diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index b4b54a6dc..4bcb60719 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -717,7 +717,7 @@ void CheckClass::noMemset() unsigned int varid = tok->tokAt(3)->varId(); for (const Token *lookback = tok->previous(); lookback; lookback = lookback->previous()) { - if (Token::Match(lookback, "%type% %varid%",varid)) + if (Token::Match(lookback, "%type% %varid%", varid)) { type = lookback->str(); break; @@ -731,7 +731,14 @@ void CheckClass::noMemset() // Warn if type is a class or struct that contains any std::* variables const std::string pattern2(std::string("struct|class ") + type + " {"); - for (const Token *tstruct = Token::findmatch(_tokenizer->tokens(), pattern2.c_str()); tstruct; tstruct = tstruct->next()) + const Token *tstruct = Token::findmatch(_tokenizer->tokens(), pattern2.c_str()); + + if (!tstruct) + continue; + + const std::string &typeName = tstruct->str(); + + for (; tstruct; tstruct = tstruct->next()) { if (tstruct->str() == "}") break; @@ -751,7 +758,7 @@ void CheckClass::noMemset() tstruct->str().find(":") != std::string::npos) { if (Token::Match(tstruct->next(), "std :: %type% %var% ;")) - memsetStructError(tok, tok->str(), tstruct->strAt(3)); + memsetError(tok, tok->str(), tstruct->strAt(3), typeName); else if (Token::Match(tstruct->next(), "std :: %type% <")) { @@ -779,21 +786,16 @@ void CheckClass::noMemset() // found error => report if (Token::Match(tstruct, "> %var% ;")) - memsetStructError(tok, tok->str(), typestr); + memsetError(tok, tok->str(), typestr, typeName); } } } } } -void CheckClass::memsetClassError(const Token *tok, const std::string &memfunc) +void CheckClass::memsetError(const Token *tok, const std::string &memfunc, const std::string &classname, const std::string &type) { - reportError(tok, Severity::error, "memsetClass", "Using '" + memfunc + "' on class"); -} - -void CheckClass::memsetStructError(const Token *tok, const std::string &memfunc, const std::string &classname) -{ - reportError(tok, Severity::error, "memsetStruct", "Using '" + memfunc + "' on struct that contains a 'std::" + classname + "'"); + reportError(tok, Severity::error, "memsetClass", "Using '" + memfunc + "' on " + type + " that contains a 'std::" + classname + "'"); } //--------------------------------------------------------------------------- diff --git a/lib/checkclass.h b/lib/checkclass.h index cc550c36b..2dd238f83 100644 --- a/lib/checkclass.h +++ b/lib/checkclass.h @@ -117,8 +117,7 @@ private: void uninitVarError(const Token *tok, const std::string &classname, const std::string &varname); void operatorEqVarError(const Token *tok, const std::string &classname, const std::string &varname); void unusedPrivateFunctionError(const Token *tok, const std::string &classname, const std::string &funcname); - void memsetClassError(const Token *tok, const std::string &memfunc); - void memsetStructError(const Token *tok, const std::string &memfunc, const std::string &classname); + void memsetError(const Token *tok, const std::string &memfunc, const std::string &classname, const std::string &type); void operatorEqReturnError(const Token *tok); void virtualDestructorError(const Token *tok, const std::string &Base, const std::string &Derived); void thisSubtractionError(const Token *tok); @@ -134,8 +133,7 @@ private: c.uninitVarError(0, "classname", "varname"); c.operatorEqVarError(0, "classname", ""); c.unusedPrivateFunctionError(0, "classname", "funcname"); - c.memsetClassError(0, "memfunc"); - c.memsetStructError(0, "memfunc", "classname"); + c.memsetError(0, "memfunc", "classname", "class"); c.operatorEqReturnError(0); //c.virtualDestructorError(0, "Base", "Derived"); c.thisSubtractionError(0); diff --git a/test/testclass.cpp b/test/testclass.cpp index 5bf3fb8f0..d49d5abe3 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -2908,7 +2908,52 @@ private: void memsetOnClass() { - checkNoMemset("class A\n" + checkNoMemset("class Fred\n" + "{\n" + "};\n" + "void f()\n" + "{\n" + " Fred fred;\n" + " memset(&fred, 0, sizeof(Fred));\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + + checkNoMemset("class Fred\n" + "{\n" + " std::string b; \n" + "};\n" + "void f()\n" + "{\n" + " Fred fred;\n" + " memset(&fred, 0, sizeof(Fred));\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:8]: (error) Using 'memset' on class that contains a 'std::string'\n", errout.str()); + + checkNoMemset("class Fred\n" + "{\n" + "};\n" + "void f()\n" + "{\n" + " Fred fred;\n" + " memset(&fred, 0, sizeof(fred));\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + + checkNoMemset("class Fred\n" + "{\n" + " std::string s;\n" + "};\n" + "void f()\n" + "{\n" + " Fred fred;\n" + " memset(&fred, 0, sizeof(fred));\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:8]: (error) Using 'memset' on class that contains a 'std::string'\n", errout.str()); + } + + void memsetOnStruct() + { + checkNoMemset("struct A\n" "{\n" "};\n" "void f()\n" @@ -2924,23 +2969,24 @@ private: "void f()\n" "{\n" " struct A a;\n" - " memset(&a, 0, sizeof(A));\n" + " memset(&a, 0, sizeof(struct A));\n" "}\n"); ASSERT_EQUALS("", errout.str()); - } - void memsetOnStruct() - { - checkNoMemset("class A\n" + checkNoMemset("struct A\n" "{\n" - " void g( struct sockaddr_in6& a);\n" - "private:\n" - " std::string b; \n" "};\n" "void f()\n" "{\n" - " struct sockaddr_in6 fail;\n" - " memset(&fail, 0, sizeof(struct sockaddr_in6));\n" + " struct A a;\n" + " memset(&a, 0, sizeof(A));\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + + checkNoMemset("void f()\n" + "{\n" + " struct sockaddr_in6 fail;\n" + " memset(&fail, 0, sizeof(struct sockaddr_in6));\n" "}\n"); ASSERT_EQUALS("", errout.str()); @@ -2971,13 +3017,63 @@ private: void memsetVector() { + checkNoMemset("class A\n" + "{ std::vector ints; }\n" + "\n" + "void f()\n" + "{\n" + " A a;\n" + " memset(&a, 0, sizeof(A));\n" + "}"); + ASSERT_EQUALS("[test.cpp:7]: (error) Using 'memset' on class that contains a 'std::vector'\n", errout.str()); + checkNoMemset("struct A\n" "{ std::vector ints; }\n" "\n" "void f()\n" "{\n" " A a;\n" - " memset(a, 0, sizeof(A));\n" + " memset(&a, 0, sizeof(A));\n" + "}"); + ASSERT_EQUALS("[test.cpp:7]: (error) Using 'memset' on struct that contains a 'std::vector'\n", errout.str()); + + checkNoMemset("struct A\n" + "{ std::vector ints; }\n" + "\n" + "void f()\n" + "{\n" + " A a;\n" + " memset(&a, 0, sizeof(struct A));\n" + "}"); + ASSERT_EQUALS("[test.cpp:7]: (error) Using 'memset' on struct that contains a 'std::vector'\n", errout.str()); + + checkNoMemset("struct A\n" + "{ std::vector ints; }\n" + "\n" + "void f()\n" + "{\n" + " A a;\n" + " memset(&a, 0, sizeof(a));\n" + "}"); + ASSERT_EQUALS("[test.cpp:7]: (error) Using 'memset' on struct that contains a 'std::vector'\n", errout.str()); + + checkNoMemset("class A\n" + "{ std::vector< std::vector > ints; }\n" + "\n" + "void f()\n" + "{\n" + " A a;\n" + " memset(&a, 0, sizeof(A));\n" + "}"); + ASSERT_EQUALS("[test.cpp:7]: (error) Using 'memset' on class that contains a 'std::vector'\n", errout.str()); + + checkNoMemset("struct A\n" + "{ std::vector< std::vector > ints; }\n" + "\n" + "void f()\n" + "{\n" + " A a;\n" + " memset(&a, 0, sizeof(A));\n" "}"); ASSERT_EQUALS("[test.cpp:7]: (error) Using 'memset' on struct that contains a 'std::vector'\n", errout.str()); @@ -2987,7 +3083,7 @@ private: "void f()\n" "{\n" " A a;\n" - " memset(a, 0, sizeof(A));\n" + " memset(&a, 0, sizeof(a));\n" "}"); ASSERT_EQUALS("[test.cpp:7]: (error) Using 'memset' on struct that contains a 'std::vector'\n", errout.str()); @@ -2997,7 +3093,7 @@ private: "void f()\n" "{\n" " A a;\n" - " memset(a, 0, sizeof(A));\n" + " memset(&a, 0, sizeof(A));\n" "}"); ASSERT_EQUALS("[test.cpp:7]: (error) Using 'memset' on struct that contains a 'std::vector'\n", errout.str()); }