From 859793731d616cac1c9465e5147d7cbeceec41e7 Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Mon, 28 Jan 2013 06:47:48 +0100 Subject: [PATCH] SymbolDatabase: Refactor findFunction handling. Ticket: #4494 --- lib/checkautovariables.cpp | 6 ++-- lib/checkautovariables.h | 3 +- lib/checkbufferoverrun.cpp | 4 +-- lib/checkclass.cpp | 6 ++-- lib/checkmemoryleak.cpp | 10 +++--- lib/checknullpointer.cpp | 2 +- lib/checkother.cpp | 12 +++---- lib/checkstl.cpp | 2 +- lib/checkuninitvar.cpp | 32 ++++++++--------- lib/checkuninitvar.h | 8 ++--- lib/symboldatabase.cpp | 67 ++++------------------------------ lib/symboldatabase.h | 20 +++++------ lib/tokenize.cpp | 3 +- test/testother.cpp | 19 +++++----- test/testsymboldatabase.cpp | 72 ++++++++++++++++++++++++++----------- 15 files changed, 123 insertions(+), 143 deletions(-) diff --git a/lib/checkautovariables.cpp b/lib/checkautovariables.cpp index 51842f237..67e39fd1a 100644 --- a/lib/checkautovariables.cpp +++ b/lib/checkautovariables.cpp @@ -222,7 +222,7 @@ void CheckAutoVariables::errorReturnAddressOfFunctionParameter(const Token *tok, //--------------------------------------------------------------------------- // return temporary? -bool CheckAutoVariables::returnTemporary(const Token *tok, const Scope *startScope) const +bool CheckAutoVariables::returnTemporary(const Token *tok) const { const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase(); @@ -230,7 +230,7 @@ bool CheckAutoVariables::returnTemporary(const Token *tok, const Scope *startSco bool retref = false; // is there such a function that returns a reference? bool retvalue = false; // is there such a function that returns a value? - const Function *function = symbolDatabase->findFunctionByNameAndArgs(tok, startScope); + const Function *function = symbolDatabase->findFunction(tok); if (function) { retref = function->tokenDef->strAt(-1) == "&"; if (!retref) { @@ -309,7 +309,7 @@ void CheckAutoVariables::returnReference() // return reference to temporary.. else if (Token::Match(tok2, "return %var% (") && Token::simpleMatch(tok2->linkAt(2), ") ;")) { - if (returnTemporary(tok2->next(), scope)) { + if (returnTemporary(tok2->next())) { // report error.. errorReturnTempReference(tok2); } diff --git a/lib/checkautovariables.h b/lib/checkautovariables.h index 37f01559d..6aa8ffddb 100644 --- a/lib/checkautovariables.h +++ b/lib/checkautovariables.h @@ -71,10 +71,9 @@ private: /** * Returning a temporary object? * @param tok pointing at the "return" token - * @param startScope indicates the function scope to be checked * @return true if a temporary object is returned */ - bool returnTemporary(const Token *tok, const Scope *startScope) const; + bool returnTemporary(const Token *tok) const; void errorReturnAddressToAutoVariable(const Token *tok); void errorReturnPointerToLocalArray(const Token *tok); diff --git a/lib/checkbufferoverrun.cpp b/lib/checkbufferoverrun.cpp index d9d3d15d5..0cc4eea69 100644 --- a/lib/checkbufferoverrun.cpp +++ b/lib/checkbufferoverrun.cpp @@ -625,7 +625,7 @@ void CheckBufferOverrun::checkFunctionParameter(const Token &tok, unsigned int p // Calling a user function? // only 1-dimensional arrays can be checked currently else if (arrayInfo.num().size() == 1) { - const Function* func = _tokenizer->getSymbolDatabase()->findFunctionByName(tok.str(), tok.scope()); + const Function* func = _tokenizer->getSymbolDatabase()->findFunction(&tok); if (func && func->hasBody) { // Get corresponding parameter.. @@ -695,7 +695,7 @@ void CheckBufferOverrun::checkFunctionParameter(const Token &tok, unsigned int p // Check 'float x[10]' arguments in declaration if (_settings->isEnabled("style")) { - const Function* func = _tokenizer->getSymbolDatabase()->findFunctionByName(tok.str(), tok.scope()); + const Function* func = _tokenizer->getSymbolDatabase()->findFunction(&tok); // If argument is '%type% a[num]' then check bounds against num if (func) { diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 73e9568c5..b891f5657 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -363,7 +363,7 @@ void CheckClass::initializeVarList(const Function &func, std::liststr() != func.name()) { initVar(ftok->str(), scope, usage); } else { // c++11 delegate constructor - const Function *member = symbolDatabase->findFunctionByNameAndArgsInScope(ftok, scope); + const Function *member = scope->findFunction(ftok); // member function found if (member) { // recursive call @@ -491,7 +491,7 @@ void CheckClass::initializeVarList(const Function &func, std::listprevious()->str() != "::") { - const Function *member = symbolDatabase->findFunctionByNameAndArgsInScope(ftok, scope); + const Function *member = scope->findFunction(ftok); // member function found if (member) { // recursive call @@ -533,7 +533,7 @@ void CheckClass::initializeVarList(const Function &func, std::listfindFunctionByNameAndArgsInScope(ftok, scope); + const Function *member = scope->findFunction(ftok); // member function found if (member && member->type != Function::eConstructor) { diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index 77faec12d..0f1d02522 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -219,7 +219,7 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::getAllocationType(const Token *tok2, tok2 = tok2->tokAt(2); // User function - const Function* func = tokenizer->getSymbolDatabase()->findFunctionByNameAndArgs(tok2, tok2->scope()); + const Function* func = tokenizer->getSymbolDatabase()->findFunction(tok2); if (func == NULL) return No; @@ -643,7 +643,7 @@ const char * CheckMemoryLeakInFunction::call_func(const Token *tok, std::listgetSymbolDatabase()->findFunctionByName(funcname, tok->scope());; + const Function* func = _tokenizer->getSymbolDatabase()->findFunction(tok); if (!func || !func->hasBody) return 0; @@ -677,6 +677,8 @@ const char * CheckMemoryLeakInFunction::call_func(const Token *tok, std::listprevious()->str() == "."); const bool eq(tok->previous()->str() == "="); + const Token *functok = tok; + tok = Token::findsimplematch(tok, "("); if (tok) tok = tok->next(); @@ -687,7 +689,7 @@ const char * CheckMemoryLeakInFunction::call_func(const Token *tok, std::listgetSymbolDatabase()->findFunctionByName(funcname, tok->scope());; + const Function* function = _tokenizer->getSymbolDatabase()->findFunction(functok); if (!function) return "use"; @@ -719,7 +721,7 @@ const char * CheckMemoryLeakInFunction::call_func(const Token *tok, std::list 0 && Token::Match(tok, "& %varid% [,()]", varid)) { - const Function *func = _tokenizer->getSymbolDatabase()->findFunctionByName(funcname, tok->scope());; + const Function *func = _tokenizer->getSymbolDatabase()->findFunction(functok); if (func == 0) continue; AllocType a; diff --git a/lib/checknullpointer.cpp b/lib/checknullpointer.cpp index bbaeacafe..f50663921 100644 --- a/lib/checknullpointer.cpp +++ b/lib/checknullpointer.cpp @@ -450,7 +450,7 @@ bool CheckNullPointer::CanFunctionAssignPointer(const Token *functiontoken, unsi unsigned int argumentNumber = 0; for (const Token *arg = functiontoken->tokAt(2); arg; arg = arg->nextArgument()) { if (Token::Match(arg, "%varid% [,)]", varid)) { - const Function* func = _tokenizer->getSymbolDatabase()->findFunctionByName(functiontoken->str(), functiontoken->scope()); + const Function* func = _tokenizer->getSymbolDatabase()->findFunction(functiontoken); if (!func) { // Unknown function unknown = true; return true; // assume that the function might assign the pointer diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 57d69a100..81280841c 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -753,7 +753,7 @@ void CheckOther::checkRedundantAssignment() } } } else if (scope->type == Scope::eSwitch) { // Avoid false positives if noreturn function is called in switch - const Function* func = symbolDatabase->findFunctionByName(tok->str(), tok->scope());; + const Function* func = symbolDatabase->findFunction(tok); if (!func || !func->hasBody) { varAssignments.clear(); memAssignments.clear(); @@ -2379,7 +2379,7 @@ void CheckOther::checkMisusedScopedObject() if (Token::Match(tok, "[;{}] %var% (") && Token::simpleMatch(tok->linkAt(2), ") ;") && symbolDatabase->isClassOrStruct(tok->next()->str()) - && !symbolDatabase->findFunctionByName(tok->strAt(1), tok->scope())) { + && !symbolDatabase->findFunction(tok->next())) { tok = tok->next(); misusedScopeObjectError(tok, tok->str()); tok = tok->next(); @@ -2422,7 +2422,7 @@ void CheckOther::checkComparisonOfFuncReturningBool() first_token = tok->previous(); } if (Token::Match(first_token, "%var% (") && !Token::Match(first_token->previous(), "::|.")) { - const Function* func = symbolDatabase->findFunctionByName(first_token->str(), first_token->scope()); + const Function* func = symbolDatabase->findFunction(first_token); if (func && func->tokenDef && func->tokenDef->strAt(-1) == "bool") { first_token_func_of_type_bool = true; } @@ -2434,7 +2434,7 @@ void CheckOther::checkComparisonOfFuncReturningBool() second_token = second_token->next(); } if (Token::Match(second_token, "%var% (") && !Token::Match(second_token->previous(), "::|.")) { - const Function* func = symbolDatabase->findFunctionByName(second_token->str(), second_token->scope()); + const Function* func = symbolDatabase->findFunction(second_token); if (func && func->tokenDef && func->tokenDef->strAt(-1) == "bool") { second_token_func_of_type_bool = true; } @@ -3657,7 +3657,7 @@ void CheckOther::checkRedundantCopy() const Token *match_end = (tok->next()->link()!=NULL)?tok->next()->link()->next():NULL; if (match_end==NULL || !Token::Match(match_end,expect_end_token)) //avoid usage like "const A a = getA()+3" break; - const Function* func = _tokenizer->getSymbolDatabase()->findFunctionByName(tok->str(), tok->scope());; + const Function* func = _tokenizer->getSymbolDatabase()->findFunction(tok); if (func && func->tokenDef->previous() && func->tokenDef->previous()->str() == "&") { redundantCopyError(var_tok,var_tok->str()); } @@ -3842,7 +3842,7 @@ void CheckOther::checkVarFuncNullUB() ftok = ftok ? ftok->previous() : NULL; if (ftok && ftok->isName()) { // If this is a variadic function then report error - const Function *f = symbolDatabase->findFunctionByName(ftok->str(), scope); + const Function *f = symbolDatabase->findFunction(ftok); if (f && f->argCount() <= argnr) { const Token *tok2 = f->argDef; tok2 = tok2 ? tok2->link() : NULL; // goto ')' diff --git a/lib/checkstl.cpp b/lib/checkstl.cpp index 4a029e91b..85d92b103 100644 --- a/lib/checkstl.cpp +++ b/lib/checkstl.cpp @@ -1211,7 +1211,7 @@ void CheckStl::string_c_str() Token::simpleMatch(tok->linkAt(4), ") . c_str ( ) ;")) { string_c_strError(tok); } else if (Token::Match(tok, "return %var% (") && Token::simpleMatch(tok->linkAt(2), ") . c_str ( ) ;")) { - const Function* func =_tokenizer->getSymbolDatabase()->findFunctionByName(tok->strAt(1), tok->scope());; + const Function* func =_tokenizer->getSymbolDatabase()->findFunction(tok->next()); if (func && Token::Match(func->tokenDef->tokAt(-3), "std :: string|wstring")) string_c_strError(tok); } else if (Token::simpleMatch(tok, "return (") && diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index f10fcf593..5063e0094 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -1183,7 +1183,7 @@ bool CheckUninitVar::checkScopeForVariable(const Scope* scope, const Token *tok, conditionAlwaysTrueOrFalse(tok, variableValue, &alwaysTrue, &alwaysFalse); // initialization / usage in condition.. - if (!alwaysTrue && checkIfForWhileHead(scope, tok->next(), var, suppressErrors, bool(number_of_if == 0), membervar)) + if (!alwaysTrue && checkIfForWhileHead(tok->next(), var, suppressErrors, bool(number_of_if == 0), membervar)) return true; // checking if a not-zero variable is zero => bail out @@ -1308,7 +1308,7 @@ bool CheckUninitVar::checkScopeForVariable(const Scope* scope, const Token *tok, // for/while.. if (Token::Match(tok, "for|while (")) { // is variable initialized in for-head (don't report errors yet)? - if (checkIfForWhileHead(scope, tok->next(), var, true, false, membervar)) + if (checkIfForWhileHead(tok->next(), var, true, false, membervar)) return true; // goto the { @@ -1316,7 +1316,7 @@ bool CheckUninitVar::checkScopeForVariable(const Scope* scope, const Token *tok, if (tok2 && tok2->str() == "{") { bool possibleinit = false; - bool init = checkLoopBody(scope, tok2, var, membervar); + bool init = checkLoopBody(tok2, var, membervar); // variable is initialized in the loop.. if (possibleinit || init) @@ -1324,7 +1324,7 @@ bool CheckUninitVar::checkScopeForVariable(const Scope* scope, const Token *tok, // is variable used in for-head? if (!suppressErrors) { - checkIfForWhileHead(scope, tok->next(), var, false, bool(number_of_if == 0), membervar); + checkIfForWhileHead(tok->next(), var, false, bool(number_of_if == 0), membervar); } // goto "}" @@ -1357,7 +1357,7 @@ bool CheckUninitVar::checkScopeForVariable(const Scope* scope, const Token *tok, } // Use variable - else if (!suppressErrors && isVariableUsage(scope, tok, var.isPointer())) + else if (!suppressErrors && isVariableUsage(tok, var.isPointer())) uninitvarError(tok, tok->str()); else @@ -1380,12 +1380,12 @@ bool CheckUninitVar::checkScopeForVariable(const Scope* scope, const Token *tok, if (isMemberVariableAssignment(tok, membervar)) return true; - if (isMemberVariableUsage(scope, tok, var.isPointer(), membervar)) + if (isMemberVariableUsage(tok, var.isPointer(), membervar)) uninitStructMemberError(tok, tok->str() + "." + membervar); } else { // Use variable - if (!suppressErrors && isVariableUsage(scope, tok, var.isPointer())) + if (!suppressErrors && isVariableUsage(tok, var.isPointer())) uninitvarError(tok, tok->str()); else @@ -1398,7 +1398,7 @@ bool CheckUninitVar::checkScopeForVariable(const Scope* scope, const Token *tok, return false; } -bool CheckUninitVar::checkIfForWhileHead(const Scope *scope, const Token *startparentheses, const Variable& var, bool suppressErrors, bool isuninit, const std::string &membervar) +bool CheckUninitVar::checkIfForWhileHead(const Token *startparentheses, const Variable& var, bool suppressErrors, bool isuninit, const std::string &membervar) { const Token * const endpar = startparentheses->link(); for (const Token *tok = startparentheses->next(); tok && tok != endpar; tok = tok->next()) { @@ -1409,7 +1409,7 @@ bool CheckUninitVar::checkIfForWhileHead(const Scope *scope, const Token *startp continue; } - if (isVariableUsage(scope, tok, var.isPointer())) { + if (isVariableUsage(tok, var.isPointer())) { if (!suppressErrors) uninitvarError(tok, tok->str()); else @@ -1425,7 +1425,7 @@ bool CheckUninitVar::checkIfForWhileHead(const Scope *scope, const Token *startp return false; } -bool CheckUninitVar::checkLoopBody(const Scope* scope, const Token *tok, const Variable& var, const std::string &membervar) +bool CheckUninitVar::checkLoopBody(const Token *tok, const Variable& var, const std::string &membervar) { const Token *usetok = NULL; @@ -1437,10 +1437,10 @@ bool CheckUninitVar::checkLoopBody(const Scope* scope, const Token *tok, const V if (isMemberVariableAssignment(tok, membervar)) return true; - if (isMemberVariableUsage(scope, tok, var.isPointer(), membervar)) + if (isMemberVariableUsage(tok, var.isPointer(), membervar)) usetok = tok; } else { - if (isVariableUsage(scope, tok, var.isPointer())) + if (isVariableUsage(tok, var.isPointer())) usetok = tok; else return true; @@ -1459,7 +1459,7 @@ bool CheckUninitVar::checkLoopBody(const Scope* scope, const Token *tok, const V return false; } -bool CheckUninitVar::isVariableUsage(const Scope* scope, const Token *vartok, bool pointer) const +bool CheckUninitVar::isVariableUsage(const Token *vartok, bool pointer) const { if (vartok->previous()->str() == "return") return true; @@ -1482,7 +1482,7 @@ bool CheckUninitVar::isVariableUsage(const Scope* scope, const Token *vartok, bo // is this a function call? if (start && Token::Match(start->previous(), "%var% (")) { // check how function handle uninitialized data arguments.. - const Function *func = _tokenizer->getSymbolDatabase()->findFunctionByNameAndArgs(start->previous(), scope); + const Function *func = _tokenizer->getSymbolDatabase()->findFunction(start->previous()); if (func) { const Variable *arg = func->getArgumentVar(argumentNumber); if (arg) { @@ -1593,14 +1593,14 @@ bool CheckUninitVar::isMemberVariableAssignment(const Token *tok, const std::str return false; } -bool CheckUninitVar::isMemberVariableUsage(const Scope *scope, const Token *tok, bool isPointer, const std::string &membervar) const +bool CheckUninitVar::isMemberVariableUsage(const Token *tok, bool isPointer, const std::string &membervar) const { if (isMemberVariableAssignment(tok, membervar)) return false; if (Token::Match(tok, "%var% . %var%") && tok->strAt(2) == membervar) return true; - else if (Token::Match(tok->previous(), "[(,] %var% [,)]") && isVariableUsage(scope, tok, isPointer)) + else if (Token::Match(tok->previous(), "[(,] %var% [,)]") && isVariableUsage(tok, isPointer)) return true; return false; diff --git a/lib/checkuninitvar.h b/lib/checkuninitvar.h index 36e31bcaa..65cf55e77 100644 --- a/lib/checkuninitvar.h +++ b/lib/checkuninitvar.h @@ -65,11 +65,11 @@ public: void check(); void checkScope(const Scope* scope); bool checkScopeForVariable(const Scope* scope, const Token *tok, const Variable& var, bool * const possibleInit, bool * const noreturn, const std::string &membervar); - bool checkIfForWhileHead(const Scope *scope, const Token *startparentheses, const Variable& var, bool suppressErrors, bool isuninit, const std::string &membervar); - bool checkLoopBody(const Scope* scope, const Token *tok, const Variable& var, const std::string &membervar); - bool isVariableUsage(const Scope* scope, const Token *vartok, bool ispointer) const; + bool checkIfForWhileHead(const Token *startparentheses, const Variable& var, bool suppressErrors, bool isuninit, const std::string &membervar); + bool checkLoopBody(const Token *tok, const Variable& var, const std::string &membervar); + bool isVariableUsage(const Token *vartok, bool ispointer) const; bool isMemberVariableAssignment(const Token *tok, const std::string &membervar) const; - bool isMemberVariableUsage(const Scope *scope, const Token *tok, bool isPointer, const std::string &membervar) const; + bool isMemberVariableUsage(const Token *tok, bool isPointer, const std::string &membervar) const; /** * @brief Uninitialized variables: analyse functions to see how they work with uninitialized variables diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index f6ae11925..859b34e42 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -2330,66 +2330,13 @@ const Scope *SymbolDatabase::findVariableType(const Scope *start, const Token *t //--------------------------------------------------------------------------- -const Scope *SymbolDatabase::findFunctionScopeByToken(const Token *tok) const -{ - std::list::const_iterator scope; - - for (scope = scopeList.begin(); scope != scopeList.end(); ++scope) { - if (scope->type == Scope::eFunction) { - if (scope->classDef == tok) - return &(*scope); - } - } - return 0; -} - -//--------------------------------------------------------------------------- - -const Function *SymbolDatabase::findFunctionByToken(const Token *tok) const -{ - std::list::const_iterator scope; - - for (scope = scopeList.begin(); scope != scopeList.end(); ++scope) { - std::list::const_iterator func; - - for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) { - if (func->token == tok) - return &(*func); - } - } - return 0; -} - -//--------------------------------------------------------------------------- - -const Function* SymbolDatabase::findFunctionByName(const std::string& str, const Scope* startScope) const -{ - const Scope* currScope = startScope; - while (currScope && currScope->isExecutable()) { - if (currScope->functionOf) - currScope = currScope->functionOf; - else - currScope = currScope->nestedIn; - } - while (currScope) { - for (std::list::const_iterator i = currScope->functionList.begin(); i != currScope->functionList.end(); ++i) { - if (i->tokenDef->str() == str) - return &*i; - } - currScope = currScope->nestedIn; - } - return 0; -} - -//--------------------------------------------------------------------------- - /** @todo This function only counts the number of arguments in the function call. It does not take into account functions with default arguments. It does not take into account argument types. This can be difficult because of promotion and conversion operators and casts and because the argument can also be a function call. */ -const Function* SymbolDatabase::findFunctionByNameAndArgsInScope(const Token *tok, const Scope *scope) const +const Function* Scope::findFunction(const Token *tok) const { - for (std::list::const_iterator i = scope->functionList.begin(); i != scope->functionList.end(); ++i) { + for (std::list::const_iterator i = functionList.begin(); i != functionList.end(); ++i) { if (i->tokenDef->str() == tok->str()) { const Function *func = &*i; if (tok->strAt(1) == "(" && tok->tokAt(2)) { @@ -2418,10 +2365,10 @@ const Function* SymbolDatabase::findFunctionByNameAndArgsInScope(const Token *to //--------------------------------------------------------------------------- -const Function* SymbolDatabase::findFunctionByNameAndArgs(const Token *tok, const Scope *startScope) const +const Function* SymbolDatabase::findFunction(const Token *tok) const { // find the scope this function is in - const Scope* currScope = startScope; + const Scope *currScope = tok->scope(); while (currScope && currScope->isExecutable()) { if (currScope->functionOf) currScope = currScope->functionOf; @@ -2470,7 +2417,7 @@ const Function* SymbolDatabase::findFunctionByNameAndArgs(const Token *tok, cons tok1 = tok1->tokAt(2); if (currScope && tok1) - return findFunctionByNameAndArgsInScope(tok1, currScope); + return currScope->findFunction(tok1); } } @@ -2482,7 +2429,7 @@ const Function* SymbolDatabase::findFunctionByNameAndArgs(const Token *tok, cons if (tok1->varId()) { const Variable *var = getVariableFromVarId(tok1->varId()); if (var && var->type()) - return findFunctionByNameAndArgsInScope(tok, var->type()); + return var->type()->findFunction(tok); } } } @@ -2490,7 +2437,7 @@ const Function* SymbolDatabase::findFunctionByNameAndArgs(const Token *tok, cons // check in enclosing scopes else { while (currScope) { - const Function *func = findFunctionByNameAndArgsInScope(tok, currScope); + const Function *func = currScope->findFunction(tok); if (func) return func; currScope = currScope->nestedIn; diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index fcada5c46..7861dfe4c 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -505,6 +505,13 @@ public: return isClassOrStruct() && classStart == NULL; } + /** + * @brief find a function + * @param tok token of function call + * @return pointer to function if found or NULL if not found + */ + const Function *findFunction(const Token *tok) const; + /** * @brief find if name is in nested list * @param name name of nested scope @@ -598,21 +605,12 @@ public: */ const Scope *findVariableType(const Scope *start, const Token *type) const; - const Scope *findFunctionScopeByToken(const Token *tok) const; - - const Function *findFunctionByToken(const Token *tok) const; - - const Function *findFunctionByName(const std::string& str, const Scope* startScope) const; - /** - * @brief find a function by name and arguments + * @brief find a function * @param tok token of function call - * @param startScope scope to start looking in * @return pointer to function if found or NULL if not found */ - const Function *findFunctionByNameAndArgs(const Token *tok, const Scope *startScope) const; - - const Function *findFunctionByNameAndArgsInScope(const Token *tok, const Scope *scope) const; + const Function *findFunction(const Token *tok) const; const Scope *findScopeByName(const std::string& name) const; diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 27a9ba8c5..9b1aad399 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -2035,7 +2035,8 @@ bool Tokenizer::tokenize(std::istream &code, } //--------------------------------------------------------------------------- -bool Tokenizer::tokenizeCondition(const std::string &code) { +bool Tokenizer::tokenizeCondition(const std::string &code) +{ assert(_settings); // Fill the map _typeSize.. diff --git a/test/testother.cpp b/test/testother.cpp index b03ed6316..b766bf05a 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -4160,7 +4160,7 @@ private: void checkComparisonOfFuncReturningBool1() { check("void f(){\n" " int temp = 4;\n" - " if(compare1() > compare2()){\n" + " if(compare1(temp) > compare2(temp)){\n" " printf(\"foo\");\n" " }\n" "}\n" @@ -4244,7 +4244,7 @@ private: void checkComparisonOfFuncReturningBool5() { check("void f(){\n" " int temp = 4;\n" - " if(compare1() > !compare2()){\n" + " if(compare1(temp) > !compare2(temp)){\n" " printf(\"foo\");\n" " }\n" "}\n" @@ -4272,7 +4272,7 @@ private: "}\n" "void f(){\n" " int temp = 4;\n" - " if(compare1() > compare2()){\n" + " if(compare1(temp) > compare2(temp)){\n" " printf(\"foo\");\n" " }\n" "}\n"); @@ -4284,7 +4284,7 @@ private: "int compare1(int temp);\n" "void f(){\n" " int temp = 4;\n" - " if(compare1() > compare2()){\n" + " if(compare1(temp) > compare2(temp)){\n" " printf(\"foo\");\n" " }\n" "}\n"); @@ -4294,18 +4294,20 @@ private: "namespace Foo {\n" " bool compare1(int temp);\n" " void f(){\n" - " if(compare1() > compare2()){\n" + " int temp = 4;\n" + " if(compare1(temp) > compare2(temp)){\n" " printf(\"foo\");\n" " }\n" " }\n" "}\n"); - ASSERT_EQUALS("[test.cpp:5]: (style) Comparison of a function returning boolean value using relational (<, >, <= or >=) operator.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:6]: (style) Comparison of a function returning boolean value using relational (<, >, <= or >=) operator.\n", errout.str()); check("int compare1(int temp);\n" "namespace Foo {\n" " bool compare1(int temp);\n" " void f(){\n" - " if(::compare1() > compare2()){\n" + " int temp = 4;\n" + " if(::compare1(temp) > compare2(temp)){\n" " printf(\"foo\");\n" " }\n" " }\n" @@ -4314,7 +4316,8 @@ private: check("bool compare1(int temp);\n" "void f(){\n" - " if(foo.compare1() > compare2()){\n" + " int temp = 4;\n" + " if(foo.compare1(temp) > compare2(temp)){\n" " printf(\"foo\");\n" " }\n" "}\n"); diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 82b90ef01..5db0e1f1b 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -62,6 +62,36 @@ private: found = false; } + const Scope *findFunctionScopeByToken(const SymbolDatabase * db, const Token *tok) const { + std::list::const_iterator scope; + + for (scope = db->scopeList.begin(); scope != db->scopeList.end(); ++scope) { + if (scope->type == Scope::eFunction) { + if (scope->classDef == tok) + return &(*scope); + } + } + return 0; + } + + const Function *findFunctionByName(const std::string& str, const Scope* startScope) const { + const Scope* currScope = startScope; + while (currScope && currScope->isExecutable()) { + if (currScope->functionOf) + currScope = currScope->functionOf; + else + currScope = currScope->nestedIn; + } + while (currScope) { + for (std::list::const_iterator i = currScope->functionList.begin(); i != currScope->functionList.end(); ++i) { + if (i->tokenDef->str() == str) + return &*i; + } + currScope = currScope->nestedIn; + } + return 0; + } + void run() { TEST_CASE(array); @@ -513,12 +543,12 @@ private: ASSERT(db && db->scopeList.size() == 2); if (db) { - const Scope *scope = db->findFunctionScopeByToken(tokenizer.tokens()->next()); + const Scope *scope = findFunctionScopeByToken(db, tokenizer.tokens()->next()); ASSERT(scope && scope->className == "func"); ASSERT(scope && scope->functionOf == 0); - const Function *function = db->findFunctionByName("func", &db->scopeList.front()); + const Function *function = findFunctionByName("func", &db->scopeList.front()); ASSERT(function && function->token->str() == "func"); ASSERT(function && function->token == tokenizer.tokens()->next()); @@ -534,12 +564,12 @@ private: ASSERT(db && db->scopeList.size() == 3); if (db) { - const Scope *scope = db->findFunctionScopeByToken(tokenizer.tokens()->tokAt(4)); + const Scope *scope = findFunctionScopeByToken(db, tokenizer.tokens()->tokAt(4)); ASSERT(scope && scope->className == "func"); ASSERT(scope && scope->functionOf && scope->functionOf == db->findScopeByName("Fred")); - const Function *function = db->findFunctionByName("func", &db->scopeList.back()); + const Function *function = findFunctionByName("func", &db->scopeList.back()); ASSERT(function && function->token->str() == "func"); ASSERT(function && function->token == tokenizer.tokens()->tokAt(4)); @@ -555,11 +585,11 @@ private: ASSERT(db && db->scopeList.size() == 2); if (db) { - const Scope *scope = db->findFunctionScopeByToken(tokenizer.tokens()->tokAt(4)); + const Scope *scope = findFunctionScopeByToken(db, tokenizer.tokens()->tokAt(4)); ASSERT(scope == NULL); - const Function *function = db->findFunctionByName("func", &db->scopeList.back()); + const Function *function = findFunctionByName("func", &db->scopeList.back()); ASSERT(function && function->token->str() == "func"); ASSERT(function && function->token == tokenizer.tokens()->tokAt(4)); @@ -574,12 +604,12 @@ private: ASSERT(db && db->scopeList.size() == 3); if (db) { - const Scope *scope = db->findFunctionScopeByToken(tokenizer.tokens()->tokAt(12)); + const Scope *scope = findFunctionScopeByToken(db, tokenizer.tokens()->tokAt(12)); ASSERT(scope && scope->className == "func"); ASSERT(scope && scope->functionOf && scope->functionOf == db->findScopeByName("Fred")); - const Function *function = db->findFunctionByName("func", &db->scopeList.back()); + const Function *function = findFunctionByName("func", &db->scopeList.back()); ASSERT(function && function->token->str() == "func"); ASSERT(function && function->token == tokenizer.tokens()->tokAt(12)); @@ -595,11 +625,11 @@ private: ASSERT(db && db->scopeList.size() == 2); if (db) { - const Scope *scope = db->findFunctionScopeByToken(tokenizer.tokens()->tokAt(3)); + const Scope *scope = findFunctionScopeByToken(db, tokenizer.tokens()->tokAt(3)); ASSERT(scope && scope->className == "func"); - const Function *function = db->findFunctionByName("func", &db->scopeList.front()); + const Function *function = findFunctionByName("func", &db->scopeList.front()); ASSERT(function && function->token->str() == "func"); ASSERT(function && function->token == tokenizer.tokens()->tokAt(3)); @@ -614,11 +644,11 @@ private: ASSERT(db && db->scopeList.size() == 3); if (db) { - const Scope *scope = db->findFunctionScopeByToken(tokenizer.tokens()->tokAt(6)); + const Scope *scope = findFunctionScopeByToken(db, tokenizer.tokens()->tokAt(6)); ASSERT(scope && scope->className == "func"); - const Function *function = db->findFunctionByName("func", &db->scopeList.back()); + const Function *function = findFunctionByName("func", &db->scopeList.back()); ASSERT(function && function->token->str() == "func"); ASSERT(function && function->token == tokenizer.tokens()->tokAt(6)); @@ -633,11 +663,11 @@ private: ASSERT(db && db->scopeList.size() == 2); if (db) { - const Scope *scope = db->findFunctionScopeByToken(tokenizer.tokens()->tokAt(6)); + const Scope *scope = findFunctionScopeByToken(db, tokenizer.tokens()->tokAt(6)); ASSERT(scope == NULL); - const Function *function = db->findFunctionByName("func", &db->scopeList.back()); + const Function *function = findFunctionByName("func", &db->scopeList.back()); ASSERT(function && function->token->str() == "func"); ASSERT(function && function->token == tokenizer.tokens()->tokAt(6)); @@ -652,11 +682,11 @@ private: ASSERT(db && db->scopeList.size() == 3); if (db) { - const Scope *scope = db->findFunctionScopeByToken(tokenizer.tokens()->tokAt(23)); + const Scope *scope = findFunctionScopeByToken(db, tokenizer.tokens()->tokAt(23)); ASSERT(scope && scope->className == "func"); - const Function *function = db->findFunctionByName("func", &db->scopeList.back()); + const Function *function = findFunctionByName("func", &db->scopeList.back()); ASSERT(function && function->token->str() == "func"); ASSERT(function && function->token == tokenizer.tokens()->tokAt(23)); @@ -686,7 +716,7 @@ private: GET_SYMBOL_DB("std::map foo() {}") // 2 scopes: Global and Function - ASSERT(db && db->scopeList.size() == 2 && db->findFunctionByName("foo", &db->scopeList.back())); + ASSERT(db && db->scopeList.size() == 2 && findFunctionByName("foo", &db->scopeList.back())); if (db) { const Scope *scope = &db->scopeList.front(); @@ -704,7 +734,7 @@ private: GET_SYMBOL_DB("void foo();\nvoid foo();\nint foo(int i);\nvoid foo() {}") // 2 scopes: Global and Function - ASSERT(db && db->scopeList.size() == 2 && db->findFunctionByName("foo", &db->scopeList.back())); + ASSERT(db && db->scopeList.size() == 2 && findFunctionByName("foo", &db->scopeList.back())); if (db) { const Scope *scope = &db->scopeList.front(); @@ -752,8 +782,8 @@ private: // 3 scopes: Global, function, if ASSERT_EQUALS(3, db->scopeList.size()); - ASSERT(db->findFunctionByName("func", &db->scopeList.back()) != NULL); - ASSERT(db->findFunctionByName("if", &db->scopeList.back()) == NULL); + ASSERT(findFunctionByName("func", &db->scopeList.back()) != NULL); + ASSERT(findFunctionByName("if", &db->scopeList.back()) == NULL); } void parseFunctionDeclarationCorrect() { @@ -1460,7 +1490,7 @@ private: unsigned int index = 0; for (const Token * tok = bar->classStart->next(); tok != bar->classEnd; tok = tok->next()) { if (Token::Match(tok, "%var% (") && !tok->varId() && Token::simpleMatch(tok->linkAt(1), ") ;")) { - const Function * function = db->findFunctionByNameAndArgs(tok, bar); + const Function * function = db->findFunction(tok); ASSERT(function != 0); if (function) { std::stringstream expected;