SymbolDatabase: Refactor findFunction handling. Ticket: #4494
This commit is contained in:
parent
4391f0880f
commit
859793731d
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ')'
|
||||
|
|
|
@ -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 (") &&
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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..
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue