Refactorizations:

- Replaced some indendation counters by Token::link() or usage of symbolDatabase
- Use Token::nextArgument() to jump to target parameter
This commit is contained in:
PKEuS 2012-04-21 23:05:37 +02:00
parent 6d9b4a8032
commit 710fefeef0
3 changed files with 56 additions and 117 deletions

View File

@ -495,61 +495,53 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::functionReturnType(const Token *tok,
const char *CheckMemoryLeak::functionArgAlloc(const Token *tok, unsigned int targetpar, AllocType &allocType) const const char *CheckMemoryLeak::functionArgAlloc(const Token *tok, unsigned int targetpar, AllocType &allocType) const
{ {
// Find the varid of targetpar, then locate the start of the function.. // Find the varid of targetpar, then locate the start of the function..
unsigned int parlevel = 0;
unsigned int par = 0;
unsigned int varid = 0; unsigned int varid = 0;
allocType = No; allocType = No;
while (tok) { // Locate start of arguments
if (tok->str() == "{" || tok->str() == "}") tok = Token::findsimplematch(tok, "(");
if (!tok)
return ""; return "";
if (tok->str() == "(") { // Is this the start of a function?
if (parlevel != 0) const Token* const fstart = tok->link();
if (!Token::Match(fstart, ") const| {"))
return "";
// Locate targetpar
tok = tok->next();
for (unsigned int par = 1; par < targetpar; par++) {
tok = tok->nextArgument();
if (tok == 0)
return ""; return "";
++parlevel;
++par;
} }
else if (tok->str() == ")") { while (tok) {
if (parlevel != 1) if (tok->str() == "(")
return ""; tok = tok->link();
else if (tok->str() == ",")
break;
if (Token::Match(tok, "%type% * * %var%")) {
varid = tok->tokAt(3)->varId();
break; break;
} }
else if (parlevel == 1 && tok->str() == ",") {
++par;
}
tok = tok->next(); tok = tok->next();
if (parlevel == 1 && par == targetpar && Token::Match(tok, "%type% * * %var%")) {
varid = tok->tokAt(3)->varId();
}
} }
if (varid == 0) if (varid == 0)
return ""; return "";
// Is this the start of a function? // continue in function body
if (!Token::Match(tok, ") const| {")) tok = fstart;
return "";
while (tok->str() != "{") while (tok->str() != "{")
tok = tok->next(); tok = tok->next();
// Check if pointer is allocated. // Check if pointer is allocated.
unsigned int indentlevel = 0;
int realloc = 0; int realloc = 0;
while (NULL != (tok = tok->next())) { for (const Token* const end = tok->link(); tok && tok != end; tok = tok->next()) {
if (tok->str() == "{") if (tok->varId() == varid) {
++indentlevel;
else if (tok->str() == "}") {
if (indentlevel <= 1)
break;
--indentlevel;
} else if (tok->varId() == varid) {
if (Token::Match(tok->tokAt(-3), "free ( * %varid% )", varid)) { if (Token::Match(tok->tokAt(-3), "free ( * %varid% )", varid)) {
realloc = 1; realloc = 1;
allocType = No; allocType = No;
@ -598,27 +590,21 @@ void CheckMemoryLeakInFunction::parse_noreturn()
continue; continue;
// parse this function to check if it contains an "exit" call.. // parse this function to check if it contains an "exit" call..
unsigned int indentlevel = 1; bool isNoreturn = false;
for (const Token *tok2 = scope->classStart->next(); tok2; tok2 = tok2->next()) { for (const Token *tok2 = scope->classStart->next(); tok2 != scope->classEnd; tok2 = tok2->next()) {
if (tok2->str() == "{")
++indentlevel;
else if (tok2->str() == "}") {
--indentlevel;
if (indentlevel == 0)
break;
}
if (Token::Match(tok2->previous(), "[;{}] exit (")) { if (Token::Match(tok2->previous(), "[;{}] exit (")) {
noreturn.insert(scope->className); isNoreturn = true;
break; break;
} }
} }
// This function is not a noreturn function // This function is not a noreturn function
if (indentlevel == 0) { if (isNoreturn)
noreturn.insert(scope->className);
else
notnoreturn.insert(scope->className); notnoreturn.insert(scope->className);
} }
} }
}
bool CheckMemoryLeakInFunction::notvar(const Token *tok, unsigned int varid, bool endpar) const bool CheckMemoryLeakInFunction::notvar(const Token *tok, unsigned int varid, bool endpar) const
@ -1173,10 +1159,12 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
// Loops.. // Loops..
else if ((tok->str() == "for") || (tok->str() == "while")) { else if ((tok->str() == "for") || (tok->str() == "while")) {
const Token* const end = tok->linkAt(1);
if (Token::simpleMatch(tok, "while ( true )") || if (Token::simpleMatch(tok, "while ( true )") ||
Token::simpleMatch(tok, "for ( ; ; )")) { Token::simpleMatch(tok, "for ( ; ; )")) {
addtoken(&rettail, tok, "while1"); addtoken(&rettail, tok, "while1");
tok = tok->next()->link(); tok = end;
continue; continue;
} }
@ -1189,39 +1177,30 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
if (Token::Match(tok, "while ( 0 <= %varid% )", varid) || if (Token::Match(tok, "while ( 0 <= %varid% )", varid) ||
Token::Match(tok, "while ( %varid% != -1 )", varid)) { Token::Match(tok, "while ( %varid% != -1 )", varid)) {
addtoken(&rettail, tok, "while(var)"); addtoken(&rettail, tok, "while(var)");
tok = tok->next()->link(); tok = end;
continue; continue;
} else if (Token::Match(tok, "while ( %varid% == -1 )", varid) || } else if (Token::Match(tok, "while ( %varid% == -1 )", varid) ||
Token::Match(tok, "while ( %varid% < 0 )", varid)) { Token::Match(tok, "while ( %varid% < 0 )", varid)) {
addtoken(&rettail, tok, "while(!var)"); addtoken(&rettail, tok, "while(!var)");
tok = tok->next()->link(); tok = end;
continue; continue;
} }
} }
else if (varid && Token::Match(tok, "while ( %varid% )", varid)) { else if (varid && Token::Match(tok, "while ( %varid% )", varid)) {
addtoken(&rettail, tok, "while(var)"); addtoken(&rettail, tok, "while(var)");
tok = tok->next()->link(); tok = end;
continue; continue;
} else if (varid && Token::simpleMatch(tok, "while (") && notvar(tok->tokAt(2), varid, true)) { } else if (varid && Token::simpleMatch(tok, "while (") && notvar(tok->tokAt(2), varid, true)) {
addtoken(&rettail, tok, "while(!var)"); addtoken(&rettail, tok, "while(!var)");
tok = tok->next()->link(); tok = end;
continue; continue;
} }
addtoken(&rettail, tok, "loop"); addtoken(&rettail, tok, "loop");
if (varid > 0) { if (varid > 0) {
unsigned int parlevel2 = 0; for (const Token *tok2 = tok->tokAt(2); tok2 != end; tok2 = tok2->next()) {
for (const Token *tok2 = tok->tokAt(2); tok2; tok2 = tok2->next()) {
if (tok2->str() == "(")
++parlevel2;
else if (tok2->str() == ")") {
if (parlevel2 > 0)
--parlevel2;
else
break;
}
if (notvar(tok2, varid)) { if (notvar(tok2, varid)) {
addtoken(&rettail, tok2, "!var"); addtoken(&rettail, tok2, "!var");
break; break;
@ -1259,9 +1238,7 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
// Returning a auto_ptr of this allocated variable.. // Returning a auto_ptr of this allocated variable..
if (Token::simpleMatch(tok->next(), "std :: auto_ptr <")) { if (Token::simpleMatch(tok->next(), "std :: auto_ptr <")) {
const Token *tok2 = tok->tokAt(5); const Token *tok2 = tok->linkAt(4);
while (tok2 && tok2->str() != ">")
tok2 = tok2->next();
if (Token::Match(tok2, "> ( %varid% )", varid)) { if (Token::Match(tok2, "> ( %varid% )", varid)) {
addtoken(&rettail, tok, "use"); addtoken(&rettail, tok, "use");
tok = tok2->tokAt(3); tok = tok2->tokAt(3);
@ -1313,16 +1290,10 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
// Assignment.. // Assignment..
if (varid) { if (varid) {
if (Token::simpleMatch(tok, "= {")) { if (Token::simpleMatch(tok, "= {")) {
unsigned int indentlevel2 = 0; const Token* const end2 = tok->linkAt(1);
bool use = false; bool use = false;
for (const Token *tok2 = tok; tok2; tok2 = tok2->next()) { for (const Token *tok2 = tok; tok2 != end2; tok2 = tok2->next()) {
if (tok2->str() == "{") if (tok2->varId() == varid) {
++indentlevel2;
else if (tok2->str() == "}") {
if (indentlevel2 <= 1)
break;
--indentlevel2;
} else if (tok2->varId() == varid) {
use = true; use = true;
break; break;
} }
@ -1377,15 +1348,8 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
addtoken(&rettail, tok, "exit"); addtoken(&rettail, tok, "exit");
else if (!test_white_list(tok->str())) { else if (!test_white_list(tok->str())) {
int innerParlevel = 1; const Token* const end2 = tok->linkAt(1);
for (const Token *tok2 = tok->tokAt(2); tok2; tok2 = tok2->next()) { for (const Token *tok2 = tok->tokAt(2); tok2 != end2; tok2 = tok2->next()) {
if (tok2->str() == "(")
++innerParlevel;
else if (tok2->str() == ")") {
--innerParlevel;
if (innerParlevel <= 0)
break;
}
if (tok2->varId() == varid) { if (tok2->varId() == varid) {
addtoken(&rettail, tok, "::use"); addtoken(&rettail, tok, "::use");
break; break;
@ -2787,17 +2751,8 @@ void CheckMemoryLeakStructMember::checkStructVariable(const Token * const vartok
// Check if the struct is used.. // Check if the struct is used..
bool deallocated = false; bool deallocated = false;
unsigned int parlevel = 0; const Token* const end4 = tok3->linkAt(1);
for (const Token *tok4 = tok3; tok4; tok4 = tok4->next()) { for (const Token *tok4 = tok3; tok4 != end4; tok4 = tok4->next()) {
if (tok4->str() == "(")
++parlevel;
else if (tok4->str() == ")") {
if (parlevel <= 1)
break;
--parlevel;
}
if (Token::Match(tok4, "[(,] &| %varid% [,)]", structid)) { if (Token::Match(tok4, "[(,] &| %varid% [,)]", structid)) {
/** @todo check if the function deallocates the memory */ /** @todo check if the function deallocates the memory */
deallocated = true; deallocated = true;

View File

@ -307,8 +307,7 @@ public:
const Token *tok = it; const Token *tok = it;
// Search for the start of the loop body.. // Search for the start of the loop body..
int indentlevel = 1; while (0 != (tok = tok->next())) {
while (indentlevel > 0 && 0 != (tok = tok->next())) {
if (tok->str() == "(") if (tok->str() == "(")
tok = tok->link(); tok = tok->link();
else if (tok->str() == ")") else if (tok->str() == ")")

View File

@ -735,18 +735,9 @@ private:
if (Token::Match(&tok, "( * %var% ) (") || if (Token::Match(&tok, "( * %var% ) (") ||
(Token::Match(&tok, "( *| %var% .|::") && Token::Match(tok.link()->tokAt(-2), ".|:: %var% ) ("))) { (Token::Match(&tok, "( *| %var% .|::") && Token::Match(tok.link()->tokAt(-2), ".|:: %var% ) ("))) {
// is the variable passed as a parameter to some function? // is the variable passed as a parameter to some function?
unsigned int parlevel = 0; const Token *tok2 = tok.link()->next();
for (const Token *tok2 = tok.link()->next(); tok2; tok2 = tok2->next()) { for (const Token* const end = tok2->link(); tok2 != end; tok2 = tok2->next()) {
if (tok2->str() == "(") if (tok2->varId()) {
++parlevel;
else if (tok2->str() == ")") {
if (parlevel <= 1)
break;
--parlevel;
}
else if (tok2->varId()) {
// it is possible that the variable is initialized here // it is possible that the variable is initialized here
ExecutionPath::bailOutVar(checks, tok2->varId()); ExecutionPath::bailOutVar(checks, tok2->varId());
} }
@ -905,15 +896,9 @@ private:
return; return;
if (Token::simpleMatch(tok, "if (")) { if (Token::simpleMatch(tok, "if (")) {
// bail out all variables that are used in the condition // bail out all variables that are used in the condition
unsigned int parlevel = 0; const Token* const end = tok->linkAt(1);
for (const Token *tok2 = tok->tokAt(2); tok2; tok2 = tok2->next()) { for (const Token *tok2 = tok->tokAt(2); tok2 != end; tok2 = tok2->next()) {
if (tok2->str() == "(") if (tok2->varId())
++parlevel;
else if (tok2->str() == ")") {
if (parlevel == 0)
break;
--parlevel;
} else if (tok2->varId())
ExecutionPath::bailOutVar(checks, tok2->varId()); ExecutionPath::bailOutVar(checks, tok2->varId());
} }
} }