diff --git a/src/checkmemoryleak.cpp b/src/checkmemoryleak.cpp index d0bef4b04..f4a011410 100644 --- a/src/checkmemoryleak.cpp +++ b/src/checkmemoryleak.cpp @@ -275,7 +275,7 @@ const char * CheckMemoryLeakClass::call_func(const Token *tok, std::liststr() != "{")) ftok = ftok->next(); - Token *func = getcode(ftok->tokAt(1), callstack, parname, alloctype, dealloctype); + Token *func = getcode(ftok->tokAt(1), callstack, parname, alloctype, dealloctype, false); simplifycode(func); const Token *func_ = func; while (func_ && func_->str() == ";") @@ -339,7 +339,7 @@ bool CheckMemoryLeakClass::notvar(const Token *tok, const char *varnames[]) Token::simpleMatch(tok, std::string(varname + " == 0").c_str())); } -Token *CheckMemoryLeakClass::getcode(const Token *tok, std::list callstack, const char varname[], AllocType &alloctype, AllocType &dealloctype) +Token *CheckMemoryLeakClass::getcode(const Token *tok, std::list callstack, const char varname[], AllocType &alloctype, AllocType &dealloctype, bool classmember) { const char *varnames[2]; varnames[0] = varname; @@ -605,9 +605,17 @@ Token *CheckMemoryLeakClass::getcode(const Token *tok, std::list // Investigate function calls.. if (Token::Match(tok, "%var% (")) { - const char *str = call_func(tok, callstack, varnames, alloctype, dealloctype); - if (str) - addtoken(str); + if (classmember) + { + addtoken("use"); + } + + else + { + const char *str = call_func(tok, callstack, varnames, alloctype, dealloctype); + if (str) + addtoken(str); + } } // Callback.. @@ -1108,7 +1116,7 @@ void CheckMemoryLeakClass::simplifycode(Token *tok) // Check for memory leaks for a function variable. -void CheckMemoryLeakClass::CheckMemoryLeak_CheckScope(const Token *Tok1, const char varname[]) +void CheckMemoryLeakClass::CheckMemoryLeak_CheckScope(const Token *Tok1, const char varname[], bool classmember) { std::list callstack; @@ -1117,7 +1125,7 @@ void CheckMemoryLeakClass::CheckMemoryLeak_CheckScope(const Token *Tok1, const c const Token *result; - Token *tok = getcode(Tok1, callstack, varname, alloctype, dealloctype); + Token *tok = getcode(Tok1, callstack, varname, alloctype, dealloctype, classmember); //tok->printOut( "getcode result" ); // Simplify the code and check if freed memory is used.. @@ -1258,7 +1266,7 @@ void CheckMemoryLeakClass::CheckMemoryLeak_InFunction() if (indentlevel == 0) { if (Token::Match(tok, ") {")) - infunc = !classmember; + infunc = true; else if (Token::Match(tok, "[;}]")) infunc = classmember = false; @@ -1268,10 +1276,10 @@ void CheckMemoryLeakClass::CheckMemoryLeak_InFunction() if (indentlevel > 0 && infunc) { if (Token::Match(tok, "[{};] %type% * %var% [;=]")) - CheckMemoryLeak_CheckScope(tok->next(), tok->strAt(3)); + CheckMemoryLeak_CheckScope(tok->next(), tok->strAt(3), classmember); else if (Token::Match(tok, "[{};] %type% %type% * %var% [;=]")) - CheckMemoryLeak_CheckScope(tok->next(), tok->strAt(4)); + CheckMemoryLeak_CheckScope(tok->next(), tok->strAt(4), classmember); } } } @@ -1503,7 +1511,7 @@ Token * CheckMemoryLeakClass::functionParameterCode(const Token *ftok, int param // Return the code.. AllocType alloc = No, dealloc = No; std::list callstack; - Token *code = getcode(ftok, callstack, parname, alloc, dealloc); + Token *code = getcode(ftok, callstack, parname, alloc, dealloc, false); simplifycode(code); return code; } diff --git a/src/checkmemoryleak.h b/src/checkmemoryleak.h index e4cf61f6d..00fc8473c 100644 --- a/src/checkmemoryleak.h +++ b/src/checkmemoryleak.h @@ -60,7 +60,7 @@ private: void CheckMemoryLeak_ClassMembers_ParseClass(const Token *tok1, std::vector &classname); void CheckMemoryLeak_ClassMembers(); void CheckMemoryLeak_InFunction(); - void CheckMemoryLeak_CheckScope(const Token *Tok1, const char varname[]); + void CheckMemoryLeak_CheckScope(const Token *Tok1, const char varname[], bool classmember); /** * Simplify code e.g. by replacing empty "{ }" with ";" @@ -87,7 +87,7 @@ private: * @return Newly allocated token array. Caller needs to release reserved * memory by calling Tokenizer::deleteTokens(returnValue); */ - Token *getcode(const Token *tok, std::list callstack, const char varname[], AllocType &alloctype, AllocType &dealloctype); + Token *getcode(const Token *tok, std::list callstack, const char varname[], AllocType &alloctype, AllocType &dealloctype, bool classmember); bool notvar(const Token *tok, const char *varnames[]); void MemoryLeak(const Token *tok, const char varname[], AllocType alloctype); void MismatchError(const Token *Tok1, const std::list &callstack, const char varname[]); diff --git a/test/testmemleak.cpp b/test/testmemleak.cpp index 029aef5c5..f991a5db5 100644 --- a/test/testmemleak.cpp +++ b/test/testmemleak.cpp @@ -135,6 +135,7 @@ private: TEST_CASE(class2); // TODO TEST_CASE( class3 ); TEST_CASE(class4); + TEST_CASE(class5); TEST_CASE(throw1); TEST_CASE(throw2); @@ -1234,28 +1235,43 @@ private: void class4() { - check("struct MONITOR_POST;\n" - "class MonitorClient\n" + check("struct ABC;\n" + "class Fred\n" "{\n" "private:\n" - " void addPost(MONITOR_POST *MonitorPost);\n" + " void addAbc(ABC *abc);\n" "public:\n" " void click();\n" "};\n" "\n" - "void MonitorClient::addPost(MONITOR_POST* MonitorPost)\n" + "void Fred::addAbc(ABC* abc)\n" "{\n" - " _pMonitorPosts->Add(MonitorPost);\n" + " AbcPosts->Add(abc);\n" "}\n" "\n" - "void MonitorClient::click()\n" + "void Fred::click()\n" "{\n" - " MONITOR_POST *NewMeasurePost = new MONITOR_POST;\n" - " addPost( NewMeasurePost );\n" + " ABC *p = new ABC;\n" + " addAbc( p );\n" "}\n"); ASSERT_EQUALS("", errout.str()); } + void class5() + { + check("class Fred\n" + "{\n" + "public:\n" + " void foo();\n" + "};\n" + "\n" + "void Fred::foo()\n" + "{\n" + " char *str = new char[100];\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:10]: Memory leak: str\n", errout.str()); + } +