SymbolDatabase: Refactor findFunction handling. Ticket: #4494

This commit is contained in:
Robert Reif 2013-01-28 06:47:48 +01:00 committed by Daniel Marjamäki
parent 4391f0880f
commit 859793731d
15 changed files with 123 additions and 143 deletions

View File

@ -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);
}

View File

@ -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);

View File

@ -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) {

View File

@ -363,7 +363,7 @@ void CheckClass::initializeVarList(const Function &func, std::list<const Functio
if (ftok->str() != 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::list<const Functio
// Calling member function?
else if (Token::simpleMatch(ftok, "operator= (") &&
ftok->previous()->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::list<const Functio
}
// check if member function
const Function *member = symbolDatabase->findFunctionByNameAndArgsInScope(ftok, scope);
const Function *member = scope->findFunction(ftok);
// member function found
if (member && member->type != Function::eConstructor) {

View File

@ -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::list<co
// lock/unlock..
if (varid == 0) {
const Function* func = _tokenizer->getSymbolDatabase()->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::list<co
const bool dot(tok->previous()->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::list<co
if (dot)
return "use";
const Function* function = _tokenizer->getSymbolDatabase()->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<co
return ret;
}
if (varid > 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;

View File

@ -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

View File

@ -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 ')'

View File

@ -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 (") &&

View File

@ -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;

View File

@ -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

View File

@ -2330,66 +2330,13 @@ const Scope *SymbolDatabase::findVariableType(const Scope *start, const Token *t
//---------------------------------------------------------------------------
const Scope *SymbolDatabase::findFunctionScopeByToken(const Token *tok) const
{
std::list<Scope>::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<Scope>::const_iterator scope;
for (scope = scopeList.begin(); scope != scopeList.end(); ++scope) {
std::list<Function>::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<Function>::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<Function>::const_iterator i = scope->functionList.begin(); i != scope->functionList.end(); ++i) {
for (std::list<Function>::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;

View File

@ -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;

View File

@ -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..

View File

@ -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");

View File

@ -62,6 +62,36 @@ private:
found = false;
}
const Scope *findFunctionScopeByToken(const SymbolDatabase * db, const Token *tok) const {
std::list<Scope>::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<Function>::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<int, string> 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;