diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index a1a133008..f96bf2a63 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -1319,14 +1319,21 @@ void CheckClass::checkMemset() const Token *typeTok = nullptr; const Scope *type = nullptr; - if (Token::Match(arg3, "sizeof ( %type% ) )")) - typeTok = arg3->tokAt(2); - else if (Token::Match(arg3, "sizeof ( %type% :: %type% ) )")) - typeTok = arg3->tokAt(4); - else if (Token::Match(arg3, "sizeof ( struct %type% ) )")) - typeTok = arg3->tokAt(3); - else if (Token::simpleMatch(arg3, "sizeof ( * this ) )") || Token::simpleMatch(arg1, "this ,")) { - type = findFunctionOf(arg3->scope()); + const Token* sizeofTok = arg3->previous()->astOperand2(); // try to find sizeof() in argument expression + if (sizeofTok && sizeofTok->astOperand1() && Token::simpleMatch(sizeofTok->astOperand1()->previous(), "sizeof (")) + sizeofTok = sizeofTok->astOperand1(); + else if (sizeofTok && sizeofTok->astOperand2() && Token::simpleMatch(sizeofTok->astOperand2()->previous(), "sizeof (")) + sizeofTok = sizeofTok->astOperand2(); + if (Token::simpleMatch(sizeofTok, "(")) + sizeofTok = sizeofTok->previous(); + if (Token::Match(sizeofTok, "sizeof ( %type% )")) + typeTok = sizeofTok->tokAt(2); + else if (Token::Match(sizeofTok, "sizeof ( %type% :: %type% )")) + typeTok = sizeofTok->tokAt(4); + else if (Token::Match(sizeofTok, "sizeof ( struct %type% )")) + typeTok = sizeofTok->tokAt(3); + else if (Token::simpleMatch(sizeofTok, "sizeof ( * this )") || Token::simpleMatch(arg1, "this ,")) { + type = findFunctionOf(sizeofTok->scope()); } else if (Token::Match(arg1, "&|*|%var%")) { int numIndirToVariableType = 0; // Offset to the actual type in terms of dereference/addressof for (;; arg1 = arg1->next()) { diff --git a/test/testclass.cpp b/test/testclass.cpp index 010bd1b4f..0f857e2ac 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -3109,6 +3109,21 @@ private: "}"); ASSERT_EQUALS("", errout.str()); + // #8619 + checkNoMemset("struct S { std::vector m; };\n" + "void f() {\n" + " std::vector v(5);\n" + " memset(&v[0], 0, sizeof(S) * v.size());\n" + " memset(&v[0], 0, v.size() * sizeof(S));\n" + " memset(&v[0], 0, 5 * sizeof(S));\n" + " memset(&v[0], 0, sizeof(S) * 5);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:4]: (error) Using 'memset' on struct that contains a 'std::vector'.\n" + "[test.cpp:5]: (error) Using 'memset' on struct that contains a 'std::vector'.\n" + "[test.cpp:6]: (error) Using 'memset' on struct that contains a 'std::vector'.\n" + "[test.cpp:7]: (error) Using 'memset' on struct that contains a 'std::vector'.\n", + errout.str()); + // #1655 Settings s; LOAD_LIB_2(s.library, "std.cfg");