From 711d0d7a33fe0f445611935dd5ba3d83fbf6e029 Mon Sep 17 00:00:00 2001 From: PKEuS Date: Sat, 16 Feb 2013 11:02:43 -0800 Subject: [PATCH] Warn about memset(this, 0, sizeof(*this)); (#1285) --- lib/checkclass.cpp | 27 ++++++++++++++++++++------- test/testclass.cpp | 9 +++++++++ 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index c2b357f28..98722c48e 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -797,6 +797,16 @@ void CheckClass::unusedPrivateFunctionError(const Token *tok, const std::string // ClassCheck: Check that memset is not used on classes //--------------------------------------------------------------------------- +const Scope* findFunctionOf(const Scope* scope) +{ + while (scope) { + if (scope->type == Scope::eFunction) + return scope->functionOf; + scope = scope->nestedIn; + } + return 0; +} + void CheckClass::noMemset() { const std::size_t functions = symbolDatabase->functionScopes.size(); @@ -813,27 +823,30 @@ void CheckClass::noMemset() arg3 = arg3->nextArgument(); const Token *typeTok = 0; + const Scope *type = 0; 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::Match(arg1, "&| %var% ,")) { + else if (Token::simpleMatch(arg3, "sizeof ( * this ) )") || Token::simpleMatch(arg1, "this ,")) { + type = findFunctionOf(arg3->scope()); + } else if (Token::Match(arg1, "&| %var% ,")) { const Variable *var = arg1->str() == "&" ? arg1->next()->variable() : arg1->variable(); - if (var && (var->typeStartToken() == var->typeEndToken() || Token::Match(var->typeStartToken(), "%type% :: %type%")) - && (arg1->str() == "&" || var->isPointer() || var->isArray())) - typeTok = var->typeEndToken(); + if (var && (arg1->str() == "&" || var->isPointer() || var->isArray())) + type = var->type(); } // No type defined => The tokens didn't match - if (!typeTok) + if (!typeTok && !type) continue; - if (typeTok->str() == "(") + if (typeTok && typeTok->str() == "(") typeTok = typeTok->next(); - const Scope *type = symbolDatabase->findVariableType(&(*scope), typeTok); + if (!type) + type = symbolDatabase->findVariableType(&(*scope), typeTok); if (type) checkMemsetType(&(*scope), tok, type); diff --git a/test/testclass.cpp b/test/testclass.cpp index 3231a470b..9c5059e9d 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -2014,6 +2014,15 @@ private: "}\n"); ASSERT_EQUALS("[test.cpp:8]: (error) Using 'memset' on class that contains a 'std::string'.\n", errout.str()); + checkNoMemset("class Fred {\n" + " std::string b;\n" + " void f();\n" + "};\n" + "void Fred::f() {\n" + " memset(this, 0, sizeof(*this));\n" + "}"); + ASSERT_EQUALS("[test.cpp:6]: (error) Using 'memset' on class that contains a 'std::string'.\n", errout.str()); + checkNoMemset("class Fred\n" "{\n" "};\n"