errmsg: output severity in messages. a fix to track severity in the memory leaks check
This commit is contained in:
parent
25607d9f71
commit
f6f72fc022
|
@ -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<const Token *> callstack, const char *varnames[], AllocType &alloctype, AllocType &dealloctype)
|
||||
const char * CheckMemoryLeakClass::call_func(const Token *tok, std::list<const Token *> 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::list<const T
|
|||
// Check if the function deallocates the variable..
|
||||
while (ftok && (ftok->str() != "{"))
|
||||
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::list<cons
|
|||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void CheckMemoryLeakClass::MemoryLeak(const Token *tok, const char varname[], AllocType alloctype)
|
||||
void CheckMemoryLeakClass::MemoryLeak(const Token *tok, const char varname[], AllocType alloctype, bool all)
|
||||
{
|
||||
if (alloctype == CheckMemoryLeakClass::FOPEN ||
|
||||
alloctype == CheckMemoryLeakClass::POPEN)
|
||||
_errorLogger->reportErr(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<const Token *> callstack, const char varname[], AllocType &alloctype, AllocType &dealloctype, bool classmember)
|
||||
Token *CheckMemoryLeakClass::getcode(const Token *tok, std::list<const Token *> 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<const Token *>
|
|||
}
|
||||
|
||||
// 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<const Token *>
|
|||
|
||||
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<const Token *> callstack;
|
||||
Token *code = getcode(ftok, callstack, parname, alloc, dealloc, false);
|
||||
Token *code = getcode(ftok, callstack, parname, alloc, dealloc, false, all);
|
||||
simplifycode(code);
|
||||
return code;
|
||||
}
|
||||
|
|
|
@ -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<const Token *> callstack, const char varname[], AllocType &alloctype, AllocType &dealloctype, bool classmember);
|
||||
Token *getcode(const Token *tok, std::list<const Token *> 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<const Token *> &callstack, const char varname[]);
|
||||
const char * call_func(const Token *tok, std::list<const Token *> callstack, const char *varnames[], AllocType &alloctype, AllocType &dealloctype);
|
||||
const char * call_func(const Token *tok, std::list<const Token *> 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);
|
||||
|
|
|
@ -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 + "";
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"));
|
||||
|
||||
|
|
Loading…
Reference in New Issue