Symbol database: use symbol database in the memory leaks function checking. Ticket: #2219
This commit is contained in:
parent
980a90071c
commit
c6e67d4aad
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue