Symbol database: use symbol database in the memory leaks function checking. Ticket: #2219

This commit is contained in:
Robert Reif 2010-12-08 07:49:01 +01:00 committed by Daniel Marjamäki
parent 980a90071c
commit c6e67d4aad
4 changed files with 60 additions and 58 deletions

View File

@ -563,40 +563,36 @@ void CheckMemoryLeakInFunction::parse_noreturn()
noreturn.insert("errx");
noreturn.insert("verrx");
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
{
if (tok->str() == "{")
tok = tok->link();
if (tok->str() == "(")
{
const std::string function_name((tok->previous() && tok->previous()->isName()) ? tok->strAt(-1).c_str() : "");
std::list<SymbolDatabase::SpaceInfo *>::const_iterator i;
tok = tok->link();
if (!function_name.empty() && Token::simpleMatch(tok, ") {"))
for (i = symbolDatabase->spaceInfoList.begin(); i != symbolDatabase->spaceInfoList.end(); ++i)
{
SymbolDatabase::SpaceInfo *info = *i;
// only check functions
if (info->type != SymbolDatabase::SpaceInfo::Function)
continue;
// parse this function to check if it contains an "exit" call..
unsigned int indentlevel = 0;
for (const Token *tok2 = tok->next(); tok2; tok2 = tok2->next())
unsigned int indentlevel = 1;
for (const Token *tok2 = info->classStart->next(); tok2; tok2 = tok2->next())
{
if (tok2->str() == "{")
++indentlevel;
else if (tok2->str() == "}")
{
if (indentlevel <= 1)
break;
--indentlevel;
if (indentlevel == 0)
break;
}
if (Token::Match(tok2, "[;{}] exit ("))
{
noreturn.insert(function_name);
noreturn.insert(info->className);
break;
}
}
}
}
}
}
bool CheckMemoryLeakInFunction::matchFunctionsThatReturnArg(const Token *tok, unsigned int varid) const
@ -2374,32 +2370,38 @@ void CheckMemoryLeakInFunction::checkScope(const Token *Tok1, const std::string
//---------------------------------------------------------------------------
void CheckMemoryLeakInFunction::checkReallocUsage()
{
const Token *tok = _tokenizer->tokens();
while (NULL != (tok = Token::findmatch(tok, ") const| {")))
std::list<SymbolDatabase::SpaceInfo *>::const_iterator i;
for (i = symbolDatabase->spaceInfoList.begin(); i != symbolDatabase->spaceInfoList.end(); ++i)
{
SymbolDatabase::SpaceInfo *info = *i;
// only check functions
if (info->type != SymbolDatabase::SpaceInfo::Function)
continue;
// Record the varid's of the function parameters
std::set<unsigned int> parameterVarIds;
for (const Token *tok2 = tok->link(); tok2 && tok2->str() != ")"; tok2 = tok2->next())
for (const Token *tok2 = info->classDef->next(); tok2 && tok2->str() != ")"; tok2 = tok2->next())
{
if (tok2->varId() != 0)
parameterVarIds.insert(tok2->varId());
}
while (tok->str() != "{")
tok = tok->next();
const Token *tok = info->classStart;
const Token *startOfFunction = tok;
// Search for the "var = realloc(var, 100);" pattern within this function
unsigned int indentlevel = 0;
unsigned int indentlevel = 1;
for (tok = tok->next(); tok; tok = tok->next())
{
if (tok->str() == "{")
++indentlevel;
else if (tok->str() == "}")
{
--indentlevel;
if (indentlevel == 0)
break;
--indentlevel;
}
if (tok->varId() > 0 &&
@ -2507,34 +2509,24 @@ void CheckMemoryLeakInFunction::parseFunctionScope(const Token *tok, const Token
void CheckMemoryLeakInFunction::check()
{
// Parse the tokens and fill the "noreturn"
// fill the "noreturn"
parse_noreturn();
bool classmember = false;
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
{
if (tok->str() == "(")
{
tok = tok->link();
}
std::list<SymbolDatabase::SpaceInfo *>::const_iterator i;
// Found a function scope
if (Token::Match(tok, ") const| {"))
for (i = symbolDatabase->spaceInfoList.begin(); i != symbolDatabase->spaceInfoList.end(); ++i)
{
const Token * const tok1 = tok->link();
while (tok->str() != "{")
tok = tok->next();
parseFunctionScope(tok, tok1, classmember);
tok = tok->link();
classmember = false;
SymbolDatabase::SpaceInfo *info = *i;
// only check functions
if (info->type != SymbolDatabase::SpaceInfo::Function)
continue;
}
if (tok->str() == "::")
classmember = true;
const Token *tok = info->classStart;
const Token *tok1 = info->classDef->next();
bool classmember = info->functionOf != NULL;
if (Token::Match(tok, "[;}]"))
classmember = false;
parseFunctionScope(tok, tok1, classmember);
}
}
//---------------------------------------------------------------------------

View File

@ -172,13 +172,16 @@ class CheckMemoryLeakInFunction : private Check, public CheckMemoryLeak
{
public:
/** @brief This constructor is used when registering this class */
CheckMemoryLeakInFunction() : Check(), CheckMemoryLeak(0, 0)
CheckMemoryLeakInFunction() : Check(), CheckMemoryLeak(0, 0), symbolDatabase(NULL)
{ }
/** @brief This constructor is used when running checks */
CheckMemoryLeakInFunction(const Tokenizer *tokenizr, const Settings *settings, ErrorLogger *errLog)
: Check(tokenizr, settings, errLog), CheckMemoryLeak(tokenizr, errLog)
{ }
{
// get the symbol database
symbolDatabase = tokenizr->getSymbolDatabase();
}
/** @brief run all simplified checks */
void runSimplifiedChecks(const Tokenizer *tokenizr, const Settings *settings, ErrorLogger *errLog)
@ -340,6 +343,8 @@ public:
/** Function names for functions that are "noreturn" */
std::set<std::string> noreturn;
SymbolDatabase *symbolDatabase;
};

View File

@ -218,8 +218,10 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
info->functionList.push_back(function);
const Token *tok2 = funcStart;
SpaceInfo *functionOf = info;
addNewFunction(&info, &tok2);
info->functionOf = functionOf;
tok = tok2;
}
@ -745,6 +747,7 @@ void SymbolDatabase::addFunction(SpaceInfo **info, const Token **tok, const Toke
if (func->hasBody)
{
addNewFunction(info, tok);
(*info)->functionOf = info1;
added = true;
break;
}
@ -874,7 +877,8 @@ SymbolDatabase::SpaceInfo::SpaceInfo(SymbolDatabase *check_, const Token *classD
classEnd(NULL),
nestedIn(nestedIn_),
numConstructors(0),
needInitialization(SpaceInfo::Unknown)
needInitialization(SpaceInfo::Unknown),
functionOf(NULL)
{
if (!classDef)
{

View File

@ -171,6 +171,7 @@ public:
AccessControl access;
unsigned int numConstructors;
NeedInitialization needInitialization;
SpaceInfo * functionOf; // class/struct this function belongs to
bool isClassOrStruct() const
{