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;
|
return New;
|
||||||
|
|
||||||
if (Token::Match(tok2, "new %type% ["))
|
if (Token::Match(tok2, "new %type% ["))
|
||||||
return NewA;
|
return NewArray;
|
||||||
|
|
||||||
if (Token::Match(tok2, "fopen ("))
|
if (Token::Match(tok2, "fopen ("))
|
||||||
return FOPEN;
|
return FOPEN;
|
||||||
|
@ -172,7 +172,7 @@ CheckMemoryLeakClass::AllocType CheckMemoryLeakClass::GetDeallocationType(const
|
||||||
return New;
|
return New;
|
||||||
|
|
||||||
if (Token::simpleMatch(tok, std::string("delete [ ] " + names + " ;").c_str()))
|
if (Token::simpleMatch(tok, std::string("delete [ ] " + names + " ;").c_str()))
|
||||||
return NewA;
|
return NewArray;
|
||||||
|
|
||||||
if (Token::simpleMatch(tok, std::string("free ( " + names + " ) ;").c_str()) ||
|
if (Token::simpleMatch(tok, std::string("free ( " + names + " ) ;").c_str()) ||
|
||||||
Token::simpleMatch(tok, std::string("kfree ( " + 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..
|
// Keywords that are not function calls..
|
||||||
if (Token::Match(tok, "if|for|while"))
|
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..
|
// Check if the function deallocates the variable..
|
||||||
while (ftok && (ftok->str() != "{"))
|
while (ftok && (ftok->str() != "{"))
|
||||||
ftok = ftok->next();
|
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);
|
simplifycode(func);
|
||||||
const Token *func_ = func;
|
const Token *func_ = func;
|
||||||
while (func_ && func_->str() == ";")
|
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 ||
|
if (alloctype == CheckMemoryLeakClass::FOPEN ||
|
||||||
alloctype == CheckMemoryLeakClass::POPEN)
|
alloctype == CheckMemoryLeakClass::POPEN)
|
||||||
_errorLogger->reportErr(ErrorMessage::resourceLeak(_tokenizer, tok, varname));
|
_errorLogger->reportErr(ErrorMessage::resourceLeak(_tokenizer, tok, varname));
|
||||||
|
else if (all)
|
||||||
|
_errorLogger->reportErr(ErrorMessage::memleakall(_tokenizer, tok, varname));
|
||||||
else
|
else
|
||||||
_errorLogger->reportErr(ErrorMessage::memleak(_tokenizer, tok, varname));
|
_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::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];
|
const char *varnames[2];
|
||||||
varnames[0] = varname;
|
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 "--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 (Token::Match(tok->tokAt(3), "new %type% [(;]"))
|
||||||
{
|
{
|
||||||
if (isclass(tok->tokAt(4)))
|
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
|
else
|
||||||
{
|
{
|
||||||
const char *str = call_func(tok, callstack, varnames, alloctype, dealloctype);
|
const char *str = call_func(tok, callstack, varnames, alloctype, dealloctype, all);
|
||||||
if (str)
|
if (str)
|
||||||
addtoken(str);
|
addtoken(str);
|
||||||
}
|
}
|
||||||
|
@ -1144,9 +1151,11 @@ void CheckMemoryLeakClass::CheckMemoryLeak_CheckScope(const Token *Tok1, const c
|
||||||
AllocType alloctype = No;
|
AllocType alloctype = No;
|
||||||
AllocType dealloctype = No;
|
AllocType dealloctype = No;
|
||||||
|
|
||||||
|
bool all = false;
|
||||||
|
|
||||||
const Token *result;
|
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" );
|
//tok->printOut( "getcode result" );
|
||||||
|
|
||||||
// Simplify the code and check if freed memory is used..
|
// 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)
|
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
|
else if ((result = Token::findmatch(tok, "alloc ; if break|continue|return ;")) != NULL
|
||||||
&& Token::findmatch(tok, "dealloc ; alloc ; if continue ;") == 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)
|
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)
|
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)
|
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;
|
const Token *last = tok;
|
||||||
while (last->next())
|
while (last->next())
|
||||||
last = last->next();
|
last = last->next();
|
||||||
MemoryLeak(last, varname, alloctype);
|
MemoryLeak(last, varname, alloctype, all);
|
||||||
}
|
}
|
||||||
|
|
||||||
// detect cases that "simplifycode" don't handle well..
|
// 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)
|
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..
|
// Return the code..
|
||||||
AllocType alloc = No, dealloc = No;
|
AllocType alloc = No, dealloc = No;
|
||||||
|
bool all = false;
|
||||||
std::list<const Token *> callstack;
|
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);
|
simplifycode(code);
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
enum AllocType { No, Malloc, gMalloc, New, NewA, FOPEN, POPEN };
|
enum AllocType { No, Malloc, gMalloc, New, NewArray, FOPEN, POPEN };
|
||||||
|
|
||||||
// Extra allocation..
|
// Extra allocation..
|
||||||
class AllocFunc
|
class AllocFunc
|
||||||
|
@ -88,12 +88,12 @@ private:
|
||||||
* @return Newly allocated token array. Caller needs to release reserved
|
* @return Newly allocated token array. Caller needs to release reserved
|
||||||
* memory by calling Tokenizer::deleteTokens(returnValue);
|
* 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 notvar(const Token *tok, const char *varnames[]);
|
||||||
bool MatchFunctionsThatReturnArg(const Token *tok, const std::string varname);
|
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[]);
|
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 GetDeallocationType(const Token *tok, const char *varnames[]);
|
||||||
AllocType GetAllocationType(const Token *tok2);
|
AllocType GetAllocationType(const Token *tok2);
|
||||||
AllocType GetReallocationType(const Token *tok2);
|
AllocType GetReallocationType(const Token *tok2);
|
||||||
|
|
|
@ -148,6 +148,15 @@ public:
|
||||||
return true;
|
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)
|
static std::string resourceLeak(const Tokenizer *tokenizer, const Token *Location, const std::string &varname)
|
||||||
{
|
{
|
||||||
return msg1(tokenizer, Location) + std::string("(always) ") + "Resource leak: " + varname + "";
|
return msg1(tokenizer, Location) + std::string("(always) ") + "Resource leak: " + varname + "";
|
||||||
|
|
|
@ -176,6 +176,8 @@ private:
|
||||||
TEST_CASE(freefree1);
|
TEST_CASE(freefree1);
|
||||||
TEST_CASE(freefree2);
|
TEST_CASE(freefree2);
|
||||||
TEST_CASE(strcat_result_assignment);
|
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());
|
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)
|
REGISTER_TEST(TestMemleak)
|
||||||
|
|
|
@ -77,6 +77,7 @@ int main()
|
||||||
// checkmemoryleak.cpp..
|
// checkmemoryleak.cpp..
|
||||||
err.push_back(Message("mismatchAllocDealloc", Message::always, "Mismatching allocation and deallocation: %1", "varname"));
|
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("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("resourceLeak", Message::always, "Resource leak: %1", "varname"));
|
||||||
err.push_back(Message("deallocDealloc", Message::always, "Deallocating a deallocated pointer: %1", "varname"));
|
err.push_back(Message("deallocDealloc", Message::always, "Deallocating a deallocated pointer: %1", "varname"));
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue