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

View File

@ -172,13 +172,16 @@ class CheckMemoryLeakInFunction : private Check, public CheckMemoryLeak
{ {
public: public:
/** @brief This constructor is used when registering this class */ /** @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 */ /** @brief This constructor is used when running checks */
CheckMemoryLeakInFunction(const Tokenizer *tokenizr, const Settings *settings, ErrorLogger *errLog) CheckMemoryLeakInFunction(const Tokenizer *tokenizr, const Settings *settings, ErrorLogger *errLog)
: Check(tokenizr, settings, errLog), CheckMemoryLeak(tokenizr, errLog) : Check(tokenizr, settings, errLog), CheckMemoryLeak(tokenizr, errLog)
{ } {
// get the symbol database
symbolDatabase = tokenizr->getSymbolDatabase();
}
/** @brief run all simplified checks */ /** @brief run all simplified checks */
void runSimplifiedChecks(const Tokenizer *tokenizr, const Settings *settings, ErrorLogger *errLog) void runSimplifiedChecks(const Tokenizer *tokenizr, const Settings *settings, ErrorLogger *errLog)
@ -340,6 +343,8 @@ public:
/** Function names for functions that are "noreturn" */ /** Function names for functions that are "noreturn" */
std::set<std::string> 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); info->functionList.push_back(function);
const Token *tok2 = funcStart; const Token *tok2 = funcStart;
SpaceInfo *functionOf = info;
addNewFunction(&info, &tok2); addNewFunction(&info, &tok2);
info->functionOf = functionOf;
tok = tok2; tok = tok2;
} }
@ -745,6 +747,7 @@ void SymbolDatabase::addFunction(SpaceInfo **info, const Token **tok, const Toke
if (func->hasBody) if (func->hasBody)
{ {
addNewFunction(info, tok); addNewFunction(info, tok);
(*info)->functionOf = info1;
added = true; added = true;
break; break;
} }
@ -874,7 +877,8 @@ SymbolDatabase::SpaceInfo::SpaceInfo(SymbolDatabase *check_, const Token *classD
classEnd(NULL), classEnd(NULL),
nestedIn(nestedIn_), nestedIn(nestedIn_),
numConstructors(0), numConstructors(0),
needInitialization(SpaceInfo::Unknown) needInitialization(SpaceInfo::Unknown),
functionOf(NULL)
{ {
if (!classDef) if (!classDef)
{ {

View File

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