Symbol database: use symbol database in the memory leaks function checking. Ticket: #2219
This commit is contained in:
parent
980a90071c
commit
c6e67d4aad
|
@ -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);
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -171,6 +171,7 @@ public:
|
|||
AccessControl access;
|
||||
unsigned int numConstructors;
|
||||
NeedInitialization needInitialization;
|
||||
SpaceInfo * functionOf; // class/struct this function belongs to
|
||||
|
||||
bool isClassOrStruct() const
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue