From f6f72fc02269e009c57734fbdd4802a296fc97e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sat, 31 Jan 2009 13:57:27 +0000 Subject: [PATCH] errmsg: output severity in messages. a fix to track severity in the memory leaks check --- src/checkmemoryleak.cpp | 44 +++++++++++++++++++++++++---------------- src/checkmemoryleak.h | 8 ++++---- src/errormessage.h | 9 +++++++++ test/testmemleak.cpp | 20 +++++++++++++++++++ tools/errmsg.cpp | 1 + 5 files changed, 61 insertions(+), 21 deletions(-) diff --git a/src/checkmemoryleak.cpp b/src/checkmemoryleak.cpp index 3b585096f..434bdfe77 100644 --- a/src/checkmemoryleak.cpp +++ b/src/checkmemoryleak.cpp @@ -109,7 +109,7 @@ CheckMemoryLeakClass::AllocType CheckMemoryLeakClass::GetAllocationType(const To return New; if (Token::Match(tok2, "new %type% [")) - return NewA; + return NewArray; if (Token::Match(tok2, "fopen (")) return FOPEN; @@ -172,7 +172,7 @@ CheckMemoryLeakClass::AllocType CheckMemoryLeakClass::GetDeallocationType(const return New; if (Token::simpleMatch(tok, std::string("delete [ ] " + names + " ;").c_str())) - return NewA; + return NewArray; if (Token::simpleMatch(tok, std::string("free ( " + names + " ) ;").c_str()) || Token::simpleMatch(tok, std::string("kfree ( " + names + " ) ;").c_str())) @@ -193,7 +193,7 @@ CheckMemoryLeakClass::AllocType CheckMemoryLeakClass::GetDeallocationType(const } //-------------------------------------------------------------------------- -const char * CheckMemoryLeakClass::call_func(const Token *tok, std::list callstack, const char *varnames[], AllocType &alloctype, AllocType &dealloctype) +const char * CheckMemoryLeakClass::call_func(const Token *tok, std::list callstack, const char *varnames[], AllocType &alloctype, AllocType &dealloctype, bool &all) { // Keywords that are not function calls.. if (Token::Match(tok, "if|for|while")) @@ -266,7 +266,7 @@ const char * CheckMemoryLeakClass::call_func(const Token *tok, std::liststr() != "{")) ftok = ftok->next(); - Token *func = getcode(ftok->tokAt(1), callstack, parname, alloctype, dealloctype, false); + Token *func = getcode(ftok->tokAt(1), callstack, parname, alloctype, dealloctype, false, all); simplifycode(func); const Token *func_ = func; while (func_ && func_->str() == ";") @@ -301,11 +301,13 @@ void CheckMemoryLeakClass::MismatchError(const Token *Tok1, const std::listreportErr(ErrorMessage::resourceLeak(_tokenizer, tok, varname)); + else if (all) + _errorLogger->reportErr(ErrorMessage::memleakall(_tokenizer, tok, varname)); else _errorLogger->reportErr(ErrorMessage::memleak(_tokenizer, tok, varname)); } @@ -333,7 +335,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, bool classmember) +Token *CheckMemoryLeakClass::getcode(const Token *tok, std::list callstack, const char varname[], AllocType &alloctype, AllocType &dealloctype, bool classmember, bool &all) { const char *varnames[2]; varnames[0] = varname; @@ -407,12 +409,17 @@ Token *CheckMemoryLeakClass::getcode(const Token *tok, std::list } // If "--all" hasn't been given, don't check classes.. - if (alloc == New && ! _settings._showAll) + if (alloc == New) { if (Token::Match(tok->tokAt(3), "new %type% [(;]")) { if (isclass(tok->tokAt(4))) - alloc = No; + { + if (_settings._showAll) + all = true; + else + alloc = No; + } } } @@ -630,7 +637,7 @@ Token *CheckMemoryLeakClass::getcode(const Token *tok, std::list else { - const char *str = call_func(tok, callstack, varnames, alloctype, dealloctype); + const char *str = call_func(tok, callstack, varnames, alloctype, dealloctype, all); if (str) addtoken(str); } @@ -1144,9 +1151,11 @@ void CheckMemoryLeakClass::CheckMemoryLeak_CheckScope(const Token *Tok1, const c AllocType alloctype = No; AllocType dealloctype = No; + bool all = false; + const Token *result; - Token *tok = getcode(Tok1, callstack, varname, alloctype, dealloctype, classmember); + Token *tok = getcode(Tok1, callstack, varname, alloctype, dealloctype, classmember, all); //tok->printOut( "getcode result" ); // Simplify the code and check if freed memory is used.. @@ -1202,23 +1211,23 @@ void CheckMemoryLeakClass::CheckMemoryLeak_CheckScope(const Token *Tok1, const c if ((result = Token::findmatch(tok, "loop alloc ;")) != NULL) { - MemoryLeak(result, varname, alloctype); + MemoryLeak(result, varname, alloctype, all); } else if ((result = Token::findmatch(tok, "alloc ; if break|continue|return ;")) != NULL && Token::findmatch(tok, "dealloc ; alloc ; if continue ;") == NULL) { - MemoryLeak(result->tokAt(3), varname, alloctype); + MemoryLeak(result->tokAt(3), varname, alloctype, all); } else if (_settings._showAll && (result = Token::findmatch(tok, "alloc ; ifv break|continue|return ;")) != NULL) { - MemoryLeak(result->tokAt(3), varname, alloctype); + MemoryLeak(result->tokAt(3), varname, alloctype, all); } else if ((result = Token::findmatch(tok, "alloc ; alloc|assign|return ;")) != NULL) { - MemoryLeak(result->tokAt(2), varname, alloctype); + MemoryLeak(result->tokAt(2), varname, alloctype, all); } else if ((result = Token::findmatch(tok, "dealloc ; dealloc ;")) != NULL) @@ -1233,7 +1242,7 @@ void CheckMemoryLeakClass::CheckMemoryLeak_CheckScope(const Token *Tok1, const c const Token *last = tok; while (last->next()) last = last->next(); - MemoryLeak(last, varname, alloctype); + MemoryLeak(last, varname, alloctype, all); } // detect cases that "simplifycode" don't handle well.. @@ -1484,7 +1493,7 @@ void CheckMemoryLeakClass::CheckMemoryLeak_ClassMembers_Variable(const std::vect if (Alloc != No && Dealloc == No) { - MemoryLeak(_tokenizer->tokens(), FullVariableName.str().c_str(), Alloc); + MemoryLeak(_tokenizer->tokens(), FullVariableName.str().c_str(), Alloc, false); } } @@ -1547,8 +1556,9 @@ Token * CheckMemoryLeakClass::functionParameterCode(const Token *ftok, int param // Return the code.. AllocType alloc = No, dealloc = No; + bool all = false; std::list callstack; - Token *code = getcode(ftok, callstack, parname, alloc, dealloc, false); + Token *code = getcode(ftok, callstack, parname, alloc, dealloc, false, all); simplifycode(code); return code; } diff --git a/src/checkmemoryleak.h b/src/checkmemoryleak.h index bfbdc3925..65425990c 100644 --- a/src/checkmemoryleak.h +++ b/src/checkmemoryleak.h @@ -41,7 +41,7 @@ public: private: - enum AllocType { No, Malloc, gMalloc, New, NewA, FOPEN, POPEN }; + enum AllocType { No, Malloc, gMalloc, New, NewArray, FOPEN, POPEN }; // Extra allocation.. class AllocFunc @@ -88,12 +88,12 @@ 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, bool classmember); + Token *getcode(const Token *tok, std::list callstack, const char varname[], AllocType &alloctype, AllocType &dealloctype, bool classmember, bool &all); bool notvar(const Token *tok, const char *varnames[]); bool MatchFunctionsThatReturnArg(const Token *tok, const std::string varname); - void MemoryLeak(const Token *tok, const char varname[], AllocType alloctype); + void MemoryLeak(const Token *tok, const char varname[], AllocType alloctype, bool all); void MismatchError(const Token *Tok1, const std::list &callstack, const char varname[]); - const char * call_func(const Token *tok, std::list callstack, const char *varnames[], AllocType &alloctype, AllocType &dealloctype); + const char * call_func(const Token *tok, std::list callstack, const char *varnames[], AllocType &alloctype, AllocType &dealloctype, bool &all); AllocType GetDeallocationType(const Token *tok, const char *varnames[]); AllocType GetAllocationType(const Token *tok2); AllocType GetReallocationType(const Token *tok2); diff --git a/src/errormessage.h b/src/errormessage.h index f51e5ffc6..65b6c20c8 100644 --- a/src/errormessage.h +++ b/src/errormessage.h @@ -148,6 +148,15 @@ public: return true; } + static std::string memleakall(const Tokenizer *tokenizer, const Token *Location, const std::string &varname) + { + return msg1(tokenizer, Location) + std::string("(all) ") + "Memory leak: " + varname + ""; + } + static bool memleakall(const Settings &s) + { + return s._showAll; + } + static std::string resourceLeak(const Tokenizer *tokenizer, const Token *Location, const std::string &varname) { return msg1(tokenizer, Location) + std::string("(always) ") + "Resource leak: " + varname + ""; diff --git a/test/testmemleak.cpp b/test/testmemleak.cpp index 0ff7f00fa..65ff5c67d 100644 --- a/test/testmemleak.cpp +++ b/test/testmemleak.cpp @@ -176,6 +176,8 @@ private: TEST_CASE(freefree1); TEST_CASE(freefree2); TEST_CASE(strcat_result_assignment); + + TEST_CASE(all1); // Extra checking when --all is given } @@ -1717,6 +1719,24 @@ private: "}"); ASSERT_EQUALS(std::string(""), errout.str()); } + + + + void all1() + { + check("void foo()\n" + "{\n" + " Fred *f = new Fred;\n" + "}\n", false); + ASSERT_EQUALS(std::string(""), errout.str()); + + check("void foo()\n" + "{\n" + " Fred *f = new Fred;\n" + "}\n", true); + ASSERT_EQUALS(std::string("[test.cpp:4]: (all) Memory leak: f\n"), errout.str()); + } + }; REGISTER_TEST(TestMemleak) diff --git a/tools/errmsg.cpp b/tools/errmsg.cpp index 743f05b3d..bba9236d6 100644 --- a/tools/errmsg.cpp +++ b/tools/errmsg.cpp @@ -77,6 +77,7 @@ int main() // checkmemoryleak.cpp.. err.push_back(Message("mismatchAllocDealloc", Message::always, "Mismatching allocation and deallocation: %1", "varname")); err.push_back(Message("memleak", Message::always, "Memory leak: %1", "varname")); + err.push_back(Message("memleakall", Message::all, "Memory leak: %1", "varname")); err.push_back(Message("resourceLeak", Message::always, "Resource leak: %1", "varname")); err.push_back(Message("deallocDealloc", Message::always, "Deallocating a deallocated pointer: %1", "varname"));