Memory leaks: Use varid instead of varname

This commit is contained in:
Daniel Marjamäki 2009-08-19 19:42:07 +02:00
parent 2ca5caab28
commit 8b46172bcf
3 changed files with 142 additions and 109 deletions

View File

@ -53,7 +53,7 @@ bool CheckMemoryLeak::isclass(const Tokenizer *_tokenizer, const Token *tok) con
}
//---------------------------------------------------------------------------
CheckMemoryLeak::AllocType CheckMemoryLeak::getAllocationType(const Token *tok2, const char varname[]) const
CheckMemoryLeak::AllocType CheckMemoryLeak::getAllocationType(const Token *tok2, const unsigned int varid) const
{
// What we may have...
// * var = (char *)malloc(10);
@ -87,7 +87,7 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::getAllocationType(const Token *tok2,
}
// Using realloc..
if (Token::Match(tok2, (std::string("realloc ( !!") + varname).c_str()))
if (varid && Token::Match(tok2, "realloc ( %any% ,") && tok2->tokAt(2)->varId() != varid)
return Malloc;
// Does tok2 point on "g_malloc", "g_strdup", ..
@ -136,7 +136,8 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::getAllocationType(const Token *tok2,
CheckMemoryLeak::AllocType CheckMemoryLeak::getReallocationType(const Token *tok2, const char varname[])
CheckMemoryLeak::AllocType CheckMemoryLeak::getReallocationType(const Token *tok2, const unsigned int varid) const
{
// What we may have...
// * var = (char *)realloc(..;
@ -148,7 +149,7 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::getReallocationType(const Token *tok
if (! tok2)
return No;
if (! Token::Match(tok2, (std::string("%var% ( ") + varname + " [,)]").c_str()))
if (! Token::Match(tok2, "%var% ( %varid% [,)]", varid))
return No;
if (tok2->str() == "realloc")
@ -162,7 +163,44 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::getReallocationType(const Token *tok
}
CheckMemoryLeak::AllocType CheckMemoryLeak::getDeallocationType(const Token *tok, const char *varnames[])
CheckMemoryLeak::AllocType CheckMemoryLeak::getDeallocationType(const Token *tok, const unsigned int varid) const
{
if (Token::Match(tok, "delete %varid% ;", varid))
return New;
if (Token::Match(tok, "delete [ ] %varid% ;", varid))
return NewArray;
if (Token::Match(tok, "delete ( %varid% ) ;", varid))
return New;
if (Token::Match(tok, "delete [ ] ( %varid% ) ;", varid))
return NewArray;
if (Token::Match(tok, "free ( %varid% ) ;", varid) ||
Token::Match(tok, "kfree ( %varid% ) ;", varid))
return Malloc;
if (Token::Match(tok, "g_free ( %varid% ) ;", varid))
return gMalloc;
if (Token::Match(tok, "fclose ( %varid% )", varid) ||
Token::Match(tok, "fcloseall ( )"))
return File;
if (Token::Match(tok, "close ( %varid% )", varid))
return Fd;
if (Token::Match(tok, "pclose ( %varid% )", varid))
return Pipe;
if (Token::Match(tok, "closedir ( %varid% )", varid))
return Dir;
return No;
}
CheckMemoryLeak::AllocType CheckMemoryLeak::getDeallocationType(const Token *tok, const char *varnames[]) const
{
int i = 0;
std::string names;
@ -214,17 +252,17 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::getDeallocationType(const Token *tok
//--------------------------------------------------------------------------
void CheckMemoryLeak::memoryLeak(const Token *tok, const char varname[], AllocType alloctype, bool all)
void CheckMemoryLeak::memoryLeak(const Token *tok, const std::string varname, AllocType alloctype, bool all)
{
if (alloctype == CheckMemoryLeak::File ||
alloctype == CheckMemoryLeak::Pipe ||
alloctype == CheckMemoryLeak::Fd ||
alloctype == CheckMemoryLeak::Dir)
resourceLeakError(tok, varname);
resourceLeakError(tok, varname.c_str());
else if (all)
memleakallError(tok, varname);
memleakallError(tok, varname.c_str());
else
memleakError(tok, varname);
memleakError(tok, varname.c_str());
}
//---------------------------------------------------------------------------
@ -330,7 +368,7 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::functionReturnType(const Token *tok)
tok = tok ? tok->next() : 0;
// Inspect the statements..
std::string varname;
unsigned int varid = 0;
AllocType allocType = No;
while (tok)
{
@ -341,10 +379,10 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::functionReturnType(const Token *tok)
continue;
}
if (varname.empty() && Token::Match(tok, "%var% = "))
if (varid == 0 && tok->varId() && Token::Match(tok, "%var% ="))
{
varname = tok->str();
allocType = getAllocationType(tok->tokAt(2), varname.c_str());
varid = tok->varId();
allocType = getAllocationType(tok->tokAt(2), varid);
if (allocType == No)
return No;
while (tok && tok->str() != ";")
@ -355,7 +393,7 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::functionReturnType(const Token *tok)
if (tok->str() == "return")
{
if (varname.size() && Token::Match(tok->next(), (varname + " ;").c_str()))
if (varid > 0 && Token::Match(tok->next(), "%varid% ;", varid))
return allocType;
if (Token::Match(tok, "return new %type% ;"))
return New;
@ -398,27 +436,17 @@ void CheckMemoryLeakInFunction::init()
}
}
bool CheckMemoryLeakInFunction::matchFunctionsThatReturnArg(const Token *tok, const std::string &varname)
bool CheckMemoryLeakInFunction::matchFunctionsThatReturnArg(const Token *tok, const unsigned int varid) const
{
return Token::Match(tok, std::string("; " + varname + " = strcat|memcpy|memmove|strcpy ( " + varname + " ,").c_str());
return Token::Match(tok, "; %varid% = strcat|memcpy|memmove|strcpy ( %varid% ,", varid);
}
bool CheckMemoryLeakInFunction::notvar(const Token *tok, const char *varnames[], bool endpar)
bool CheckMemoryLeakInFunction::notvar(const Token *tok, const unsigned int varid, bool endpar) const
{
std::string varname;
for (int i = 0; varnames[i]; i++)
{
if (i > 0)
varname += " . ";
varname += varnames[i];
}
const std::string end(endpar ? " &&|)" : " [;)&|]");
return bool(Token::Match(tok, ("! " + varname + end).c_str()) ||
Token::Match(tok, ("! ( " + varname + " )" + end).c_str()));
return bool(Token::Match(tok, ("! %varid%" + end).c_str(), varid) ||
Token::Match(tok, ("! ( %varid% )" + end).c_str(), varid));
}
@ -450,12 +478,12 @@ static int countParameters(const Token *tok)
return -1;
}
const char * CheckMemoryLeakInFunction::call_func(const Token *tok, std::list<const Token *> callstack, const char *varnames[], AllocType &alloctype, AllocType &dealloctype, bool &all, unsigned int sz)
const char * CheckMemoryLeakInFunction::call_func(const Token *tok, std::list<const Token *> callstack, const unsigned int varid, AllocType &alloctype, AllocType &dealloctype, bool &all, unsigned int sz)
{
if (call_func_white_list.find(tok->str()) != call_func_white_list.end())
return 0;
if (getAllocationType(tok, varnames[0]) != No || getReallocationType(tok, varnames[0]) != No || getDeallocationType(tok, varnames) != No)
if (getAllocationType(tok, varid) != No || getReallocationType(tok, varid) != No || getDeallocationType(tok, varid) != No)
return 0;
if (callstack.size() > 2)
@ -484,16 +512,6 @@ const char * CheckMemoryLeakInFunction::call_func(const Token *tok, std::list<co
int par = 1;
int parlevel = 0;
std::string pattern = "[,()] ";
for (int i = 0; varnames[i]; i++)
{
if (i > 0)
pattern += " . ";
pattern += varnames[i];
}
pattern += " [,()]";
for (; tok; tok = tok->next())
{
@ -512,7 +530,7 @@ const char * CheckMemoryLeakInFunction::call_func(const Token *tok, std::list<co
{
if (tok->str() == ",")
++par;
if (Token::Match(tok, pattern.c_str()))
if (Token::Match(tok, "[,()] %varid% [,()]", varid))
{
const Token *ftok = _tokenizer->getFunctionTokenByName(funcname.c_str());
if (!ftok)
@ -525,10 +543,18 @@ const char * CheckMemoryLeakInFunction::call_func(const Token *tok, std::list<co
const char *parname = Tokenizer::getParameterName(ftok, par);
if (! parname)
return "recursive";
unsigned int parameterVarid = 0;
{
const Token *partok = Token::findmatch(ftok, parname);
if (partok)
parameterVarid = partok->varId();
}
if (parameterVarid == 0)
return "recursive";
// 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, all, sz);
Token *func = getcode(ftok->tokAt(1), callstack, parameterVarid, alloctype, dealloctype, false, all, sz);
simplifycode(func, all);
const Token *func_ = func;
while (func_ && func_->str() == ";")
@ -553,13 +579,8 @@ const char * CheckMemoryLeakInFunction::call_func(const Token *tok, std::list<co
Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Token *> callstack, const char varname[], AllocType &alloctype, AllocType &dealloctype, bool classmember, bool &all, unsigned int sz)
Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Token *> callstack, const unsigned int varid, AllocType &alloctype, AllocType &dealloctype, bool classmember, bool &all, unsigned int sz)
{
const char *varnames[2];
varnames[0] = varname;
varnames[1] = 0;
std::string varnameStr = varname;
Token *rethead = 0, *rettail = 0;
#define addtoken(_str) \
{ \
@ -610,9 +631,9 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
if (parlevel == 0 && tok->str() == ";")
addtoken(";");
if (Token::Match(tok->previous(), std::string("[(;{}] " + varnameStr + " =").c_str()))
if (Token::Match(tok->previous(), "[(;{}] %varid% =", varid))
{
AllocType alloc = getAllocationType(tok->tokAt(2), varname);
AllocType alloc = getAllocationType(tok->tokAt(2), varid);
bool realloc = false;
if (sz > 1 &&
@ -624,7 +645,7 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
if (alloc == No)
{
alloc = getReallocationType(tok->tokAt(2), varname);
alloc = getReallocationType(tok->tokAt(2), varid);
if (alloc != No)
{
addtoken("realloc");
@ -673,14 +694,14 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
if (alloc != Many && dealloctype != No && dealloctype != Many && dealloctype != alloc)
{
callstack.push_back(tok);
mismatchAllocDealloc(callstack, varname);
mismatchAllocDealloc(callstack, Token::findmatch(_tokenizer->tokens(), "%varid%", varid)->str());
callstack.pop_back();
}
alloctype = alloc;
}
else if (matchFunctionsThatReturnArg(tok->previous(), std::string(varname)))
else if (matchFunctionsThatReturnArg(tok->previous(), varid))
{
addtoken("use");
}
@ -690,13 +711,12 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
{
// is the pointer in rhs?
bool rhs = false;
std::string pattern("[=+] " + std::string(varname));
for (const Token *tok2 = tok; tok2; tok2 = tok2->next())
{
if (tok2->str() == ";")
break;
if (Token::Match(tok2, pattern.c_str()))
if (Token::Match(tok2, "[=+] %varid%", varid))
{
rhs = true;
break;
@ -709,7 +729,7 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
if (Token::Match(tok->previous(), "[;{})=] %var%"))
{
AllocType dealloc = getDeallocationType(tok, varnames);
AllocType dealloc = getDeallocationType(tok, varid);
if (dealloc != No)
{
addtoken("dealloc");
@ -720,7 +740,7 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
if (dealloc != Many && alloctype != No && alloctype != Many && alloctype != dealloc)
{
callstack.push_back(tok);
mismatchAllocDealloc(callstack, varname);
mismatchAllocDealloc(callstack, Token::findmatch(_tokenizer->tokens(), "%varid%", varid)->str());
callstack.pop_back();
}
dealloctype = dealloc;
@ -731,20 +751,20 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
// if else switch
if (tok->str() == "if")
{
if (Token::simpleMatch(tok, std::string("if ( " + varnameStr + " )").c_str()))
if (Token::Match(tok, "if ( %varid% )", varid))
{
addtoken("if(var)");
// Make sure the "use" will not be added
tok = tok->next()->link();
}
else if (Token::simpleMatch(tok, std::string("if ( " + varnameStr + " == -1 )").c_str()) ||
Token::simpleMatch(tok, std::string("if ( " + varnameStr + " < 0 )").c_str()))
else if (Token::Match(tok, "if ( %varid% == -1 )", varid) ||
Token::Match(tok, "if ( %varid% < 0 )", varid))
{
// FIXME: ensure then this variable has int type and uses as file descriptor
addtoken("if(!var)");
}
else if (Token::simpleMatch(tok, "if (") && notvar(tok->tokAt(2), varnames, true))
else if (Token::simpleMatch(tok, "if (") && notvar(tok->tokAt(2), varid, true))
{
addtoken("if(!var)");
}
@ -763,29 +783,27 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
if (parlevel <= 0)
break;
}
if (Token::Match(tok2, std::string("close|fclose|closedir ( " + varnameStr + " )").c_str()))
if (Token::Match(tok2, "close|fclose|closedir ( %varid% )", varid))
{
addtoken("dealloc");
addtoken(";");
dep = true;
break;
}
if ((tok2->str() != ".") &&
Token::simpleMatch(tok2->next(), varnameStr.c_str()) &&
!Token::simpleMatch(tok2->next(), std::string(varnameStr + " .").c_str()))
if (Token::Match(tok2, ". %varid% !!.", varid))
{
dep = true;
break;
}
}
if (Token::simpleMatch(tok, std::string("if ( ! " + varnameStr + " &&").c_str()))
if (Token::Match(tok, "if ( ! %varid% &&", varid))
{
addtoken("if(!var)");
}
else if (tok->next() &&
tok->next()->link() &&
Token::simpleMatch(tok->next()->link()->tokAt(-3), std::string("&& ! " + varnameStr).c_str()))
Token::Match(tok->next()->link()->tokAt(-3), "&& ! %varid%", varid))
{
addtoken("if(!var)");
}
@ -823,7 +841,7 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
{
addtoken("do");
}
if (isloop && notvar(tok, varnames))
if (isloop && notvar(tok, varid))
addtoken("!var");
// continue / break..
@ -849,19 +867,19 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
const Token *tok2 = tok->tokAt(5);
while (tok2 && tok2->str() != ">")
tok2 = tok2->next();
if (Token::simpleMatch(tok2, ("> ( " + varnameStr + " )").c_str()))
if (Token::Match(tok2, "> ( %varid% )", varid))
{
addtoken("use");
tok = tok2->tokAt(3);
}
}
else if (Token::Match(tok, ("return &| " + varnameStr).c_str()))
else if (Token::Match(tok, "return &| %varid%", varid))
{
addtoken("use");
}
else if (Token::Match(tok, ("return strcpy|strncpy|memcpy ( " + varnameStr).c_str()))
else if (Token::Match(tok, "return strcpy|strncpy|memcpy ( %varid%", varid))
{
addtoken("use");
tok = tok->tokAt(2);
@ -874,7 +892,7 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
if (tok2->str() == ";")
break;
if (tok2->str() == varname)
if (tok2->varId() == varid)
{
addtoken("use");
break;
@ -895,14 +913,14 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
}
// Assignment..
if (Token::Match(tok, std::string("[)=] " + varnameStr + " [+;)]").c_str()) ||
Token::Match(tok, std::string(varnameStr + " +=|-=").c_str()) ||
Token::Match(tok, std::string("+=|<< " + varnameStr + " ;").c_str()) ||
Token::Match(tok, std::string("= strcpy|strcat|memmove|memcpy ( " + varnameStr + " ,").c_str()))
if (Token::Match(tok, "[)=] %varid% [+;)]", varid) ||
Token::Match(tok, "%varid% +=|-=", varid) ||
Token::Match(tok, "+=|<< %varid% ;", varid) ||
Token::Match(tok, "= strcpy|strcat|memmove|memcpy ( %varid% ,", varid))
{
addtoken("use");
}
else if (Token::Match(tok->previous(), std::string("[;{}=(,+-*/] " + varnameStr + " [").c_str()))
else if (Token::Match(tok->previous(), "[;{}=(,+-*/] %varid% [", varid))
{
addtoken("use_");
}
@ -926,7 +944,7 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
if (parlevel <= 0)
break;
}
if (tok2->str() == varnameStr)
if (tok2->varId() == varid)
{
addtoken("::use");
break;
@ -936,17 +954,16 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
else
{
const char *str = call_func(tok, callstack, varnames, alloctype, dealloctype, all, sz);
const char *str = call_func(tok, callstack, varid, alloctype, dealloctype, all, sz);
if (str)
{
if (Token::simpleMatch(tok->tokAt(-2), (varnameStr + " =").c_str()) || std::string(str) != "alloc")
if (Token::Match(tok->tokAt(-2), "%varid% =", varid) || std::string(str) != "alloc")
addtoken(str);
}
else
{
if (getReallocationType(tok, varname) != No &&
Token::simpleMatch(tok->tokAt(2), varnameStr.c_str())
)
if (getReallocationType(tok, varid) != No &&
tok->tokAt(2)->varId() == varid)
{
addtoken("if");
addtoken("{");
@ -975,7 +992,7 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
{
if (Token::Match(tok2, "[;{]"))
break;
else if (tok2->str() == varname)
else if (tok2->varId() == varid)
{
addtoken("use");
break;
@ -985,7 +1002,7 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
}
// Linux lists..
if (Token::Match(tok, std::string("[=(,] & " + varnameStr + " [.[,)]").c_str()))
if (Token::Match(tok, "[=(,] & %varid% [.[,)]", varid))
{
addtoken("&use");
}
@ -1503,7 +1520,7 @@ void CheckMemoryLeakInFunction::simplifycode(Token *tok, bool &all)
// Check for memory leaks for a function variable.
void CheckMemoryLeakInFunction::checkScope(const Token *Tok1, const char varname[], bool classmember, unsigned int sz)
void CheckMemoryLeakInFunction::checkScope(const Token *Tok1, const std::string varname, const unsigned int varid, bool classmember, unsigned int sz)
{
std::list<const Token *> callstack;
@ -1514,7 +1531,7 @@ void CheckMemoryLeakInFunction::checkScope(const Token *Tok1, const char varname
const Token *result;
Token *tok = getcode(Tok1, callstack, varname, alloctype, dealloctype, classmember, all, sz);
Token *tok = getcode(Tok1, callstack, varid, alloctype, dealloctype, classmember, all, sz);
//tok->printOut((std::string("Checkmemoryleak: getcode result for: ") + varname).c_str());
// Simplify the code and check if freed memory is used..
@ -1553,7 +1570,7 @@ void CheckMemoryLeakInFunction::checkScope(const Token *Tok1, const char varname
if (_settings->_debug)
{
tok->printOut((std::string("Checkmemoryleak: simplifycode result for: ") + varname).c_str());
tok->printOut(("Checkmemoryleak: simplifycode result for: " + varname).c_str());
}
// If the variable is not allocated at all => no memory leak
@ -1715,19 +1732,20 @@ void CheckMemoryLeakInFunction::check()
if (Token::Match(tok, "[{};] %type% * const| %var% [;=]"))
{
const int varname_tok = (tok->tokAt(3)->str() != "const" ? 3 : 4);
checkScope(tok->next(), tok->strAt(varname_tok), classmember, sz);
const Token *vartok = tok->tokAt(tok->tokAt(3)->str() != "const" ? 3 : 4);
checkScope(tok->next(), vartok->str(), vartok->varId(), classmember, sz);
}
else if (Token::Match(tok, "[{};] %type% %type% * const| %var% [;=]"))
{
const int varname_tok = (tok->tokAt(4)->str() != "const" ? 4 : 5);
checkScope(tok->next(), tok->strAt(varname_tok), classmember, sz);
const Token *vartok = tok->tokAt(tok->tokAt(4)->str() != "const" ? 4 : 5);
checkScope(tok->next(), vartok->str(), vartok->varId(), classmember, sz);
}
else if (Token::Match(tok, "[{};] int %var% [;=]"))
{
checkScope(tok->next(), tok->strAt(2), classmember, sz);
const Token *vartok = tok->tokAt(2);
checkScope(tok->next(), vartok->str(), vartok->varId(), classmember, sz);
}
}
}
@ -1876,7 +1894,7 @@ void CheckMemoryLeakInClass::variable(const char classname[], const Token *tokVa
// Allocate..
if (indent == 0 || Token::Match(tok, (std::string(varname) + " =").c_str()))
{
AllocType alloc = getAllocationType(tok->tokAt((indent > 0) ? 2 : 3), varname);
AllocType alloc = getAllocationType(tok->tokAt((indent > 0) ? 2 : 3), 0);
if (alloc != CheckMemoryLeak::No)
{
if (Alloc != No && Alloc != alloc)

View File

@ -85,22 +85,33 @@ public:
/** What type of allocation are used.. the "Many" means that several types of allocation and deallocation are used */
enum AllocType { No, Malloc, gMalloc, New, NewArray, File, Fd, Pipe, Dir, Many };
void memoryLeak(const Token *tok, const char varname[], AllocType alloctype, bool all);
void memoryLeak(const Token *tok, const std::string varname, AllocType alloctype, bool all);
/**
* Get type of deallocation at given position
* @param tok position
* @param varnames variable names
* @return type of deallocation
*/
AllocType getDeallocationType(const Token *tok, const char *varnames[]);
AllocType getDeallocationType(const Token *tok, const char *varnames[]) const;
/**
* Get type of deallocation at given position
* @param tok position
* @param varname variable name
* @return type of deallocation
*/
AllocType getDeallocationType(const Token *tok, const unsigned int varid) const;
/**
* Get type of allocation at given position
*/
AllocType getAllocationType(const Token *tok2, const char varname[]) const;
AllocType getAllocationType(const Token *tok2, const unsigned int varid) const;
/**
* Get type of reallocation at given position
*/
AllocType getReallocationType(const Token *tok2, const char varname[]);
AllocType getReallocationType(const Token *tok2, const unsigned int varid) const;
bool isclass(const Tokenizer *_tokenizer, const Token *typestr) const;
@ -157,16 +168,16 @@ public:
private:
#endif
bool matchFunctionsThatReturnArg(const Token *tok, const std::string &varname);
bool matchFunctionsThatReturnArg(const Token *tok, const unsigned int varid) const;
/**
* Check if there is a "!var" match inside a condition
* @param tok first token to match
* @param varnames the varname
* @param varname the varname
* @param endpar if this is true the "!var" must be followed by ")"
* @return true if match
*/
bool notvar(const Token *tok, const char *varnames[], bool endpar = false);
bool notvar(const Token *tok, const unsigned int varid, bool endpar = false) const;
/**
* Inspect a function call. the call_func and getcode are recursive
@ -187,7 +198,7 @@ private:
* - "callfunc"
* - "&use"
*/
const char * call_func(const Token *tok, std::list<const Token *> callstack, const char *varnames[], AllocType &alloctype, AllocType &dealloctype, bool &all, unsigned int sz);
const char * call_func(const Token *tok, std::list<const Token *> callstack, const unsigned int varid, AllocType &alloctype, AllocType &dealloctype, bool &all, unsigned int sz);
/**
* Extract a new tokens list that is easier to parse than the "_tokenizer->tokens()", the
@ -221,7 +232,7 @@ private:
* - goto : corresponds to a "goto"
* - return : corresponds to a "return"
*/
Token *getcode(const Token *tok, std::list<const Token *> callstack, const char varname[], AllocType &alloctype, AllocType &dealloctype, bool classmember, bool &all, unsigned int sz);
Token *getcode(const Token *tok, std::list<const Token *> callstack, const unsigned int varid, AllocType &alloctype, AllocType &dealloctype, bool classmember, bool &all, unsigned int sz);
/**
* Simplify code e.g. by replacing empty "{ }" with ";"
@ -237,7 +248,7 @@ private:
* @param classmember is the scope inside a class member function
* @param sz size of type.. if the variable is a "int *" then sz should be "sizeof(int)"
*/
void checkScope(const Token *Tok1, const char varname[], bool classmember, unsigned int sz);
void checkScope(const Token *Tok1, const std::string varname, const unsigned int varid, bool classmember, unsigned int sz);
void getErrorMessages()
{

View File

@ -47,6 +47,7 @@ private:
Tokenizer tokenizer;
std::istringstream istr(code);
tokenizer.tokenize(istr, "test.cpp");
tokenizer.setVarId();
return ((const CheckMemoryLeak *)0)->functionReturnType(tokenizer.tokens());
}
@ -1725,6 +1726,9 @@ private:
Tokenizer tokenizer;
std::istringstream istr(code);
tokenizer.tokenize(istr, "test.cpp");
tokenizer.setVarId();
const unsigned int varid(Token::findmatch(tokenizer.tokens(), varname)->varId());
// getcode..
CheckMemoryLeakInFunction checkMemoryLeak;
@ -1732,7 +1736,7 @@ private:
CheckMemoryLeak::AllocType allocType, deallocType;
allocType = deallocType = CheckMemoryLeak::No;
bool all = false;
Token *tokens = checkMemoryLeak.getcode(tokenizer.tokens(), callstack, varname, allocType, deallocType, false, all, 1);
Token *tokens = checkMemoryLeak.getcode(tokenizer.tokens(), callstack, varid, allocType, deallocType, false, all, 1);
// stringify..
std::string ret;
@ -1746,8 +1750,8 @@ private:
void realloc6()
{
ASSERT_EQUALS(";;realloc;;", getcode(";buf=realloc(buf,100);", "buf"));
ASSERT_EQUALS(";;alloc;", getcode(";buf=realloc(0,100);", "buf"));
ASSERT_EQUALS(";;realloc;;", getcode("char *buf; buf=realloc(buf,100);", "buf"));
ASSERT_EQUALS(";;alloc;", getcode("char *buf; buf=realloc(0,100);", "buf"));
}
void assign()
@ -1818,7 +1822,7 @@ private:
" }\n"
" free(p);\n"
"}\n");
TODO_ASSERT_EQUALS("", errout.str());
ASSERT_EQUALS("", errout.str());
}
void cast1()