From f4c0ab5dd56d8505948076d329f7099d318bf887 Mon Sep 17 00:00:00 2001 From: PKEuS Date: Fri, 24 Mar 2017 12:19:14 +0100 Subject: [PATCH] SymbolDatabase: Match function overloads by using ValueType information by running a second pass of the function pointer assignment routine. --- lib/symboldatabase.cpp | 62 +++++++++++++++++++++++++------------ lib/symboldatabase.h | 2 +- test/testsymboldatabase.cpp | 32 +++++++++++++++++++ 3 files changed, 75 insertions(+), 21 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 04d4eb39b..dc2e3c610 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -55,7 +55,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti createSymbolDatabaseNeedInitialization(); createSymbolDatabaseVariableSymbolTable(); createSymbolDatabaseSetScopePointers(); - createSymbolDatabaseSetFunctionPointers(); + createSymbolDatabaseSetFunctionPointers(true); createSymbolDatabaseSetVariablePointers(); createSymbolDatabaseSetTypePointers(); createSymbolDatabaseEnums(); @@ -1148,27 +1148,27 @@ void SymbolDatabase::createSymbolDatabaseSetScopePointers() } } -void SymbolDatabase::createSymbolDatabaseSetFunctionPointers() +void SymbolDatabase::createSymbolDatabaseSetFunctionPointers(bool firstPass) { - // Set function definition and declaration pointers - for (std::list::iterator it = scopeList.begin(); it != scopeList.end(); ++it) { - for (std::list::const_iterator func = it->functionList.begin(); func != it->functionList.end(); ++func) { - if (func->tokenDef) - const_cast(func->tokenDef)->function(&*func); + if (firstPass) { + // Set function definition and declaration pointers + for (std::list::iterator it = scopeList.begin(); it != scopeList.end(); ++it) { + for (std::list::const_iterator func = it->functionList.begin(); func != it->functionList.end(); ++func) { + if (func->tokenDef) + const_cast(func->tokenDef)->function(&*func); - if (func->token) - const_cast(func->token)->function(&*func); + if (func->token) + const_cast(func->token)->function(&*func); + } } } // Set function call pointers for (const Token* tok = _tokenizer->list.front(); tok != _tokenizer->list.back(); tok = tok->next()) { - if (Token::Match(tok, "%name% (")) { - if (!tok->function() && tok->varId() == 0 && !isReservedName(tok->str())) { - const Function *function = findFunction(tok); - if (function) - const_cast(tok)->function(function); - } + if (!tok->function() && tok->varId() == 0 && Token::Match(tok, "%name% (") && !isReservedName(tok->str())) { + const Function *function = findFunction(tok); + if (function) + const_cast(tok)->function(function); } } @@ -4010,12 +4010,31 @@ const Function* Scope::findFunction(const Token *tok, bool requireConst) const while (argtok->astParent() && argtok->astParent() != tok->next() && argtok->astParent()->str() != ",") { argtok = argtok->astParent(); } - while (Token::Match(argtok, ".|::")) - argtok = argtok->astOperand2(); + if (argtok && argtok->valueType() && !funcarg->isArrayOrPointer()) { // TODO: Pointers + if (argtok->valueType()->type == ValueType::BOOL) { + if (funcarg->typeStartToken()->str() == "bool") + same++; + else if (Token::Match(funcarg->typeStartToken(), "wchar_t|char|short|int|long")) + fallback1++; + } else if (argtok->valueType()->isIntegral()) { + if (Token::Match(funcarg->typeStartToken(), "wchar_t|char|short|int|long")) + same++; + else if (Token::Match(funcarg->typeStartToken(), "float|double")) + fallback1++; + } else if (argtok->valueType()->isFloat()) { + if (Token::Match(funcarg->typeStartToken(), "float|double")) + same++; + else if (Token::Match(funcarg->typeStartToken(), "wchar_t|char|short|int|long")) + fallback1++; + } + } else { + while (Token::Match(argtok, ".|::")) + argtok = argtok->astOperand2(); - if (argtok) { - const Variable * callarg = check->getVariableFromVarId(argtok->varId()); - checkVariableCallMatch(callarg, funcarg, same, fallback1, fallback2); + if (argtok) { + const Variable * callarg = check->getVariableFromVarId(argtok->varId()); + checkVariableCallMatch(callarg, funcarg, same, fallback1, fallback2); + } } } } @@ -4998,6 +5017,9 @@ void SymbolDatabase::setValueTypeInTokenList() } } + // Update functions with new type information. + createSymbolDatabaseSetFunctionPointers(false); + // Update auto variables with new type information. createSymbolDatabaseSetVariablePointers(); } diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index da471c3ab..b3014ba68 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -1159,7 +1159,7 @@ private: void createSymbolDatabaseNeedInitialization(); void createSymbolDatabaseVariableSymbolTable(); void createSymbolDatabaseSetScopePointers(); - void createSymbolDatabaseSetFunctionPointers(); + void createSymbolDatabaseSetFunctionPointers(bool firstPass); void createSymbolDatabaseSetVariablePointers(); void createSymbolDatabaseSetTypePointers(); void createSymbolDatabaseEnums(); diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index a666b2f97..cf3212bc4 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -286,6 +286,7 @@ private: TEST_CASE(findFunction14); TEST_CASE(findFunction15); TEST_CASE(findFunction16); + TEST_CASE(findFunction17); TEST_CASE(noexceptFunction1); TEST_CASE(noexceptFunction2); @@ -3753,6 +3754,37 @@ private: ASSERT_EQUALS(true, f && f->function() == nullptr); } + void findFunction17() { + GET_SYMBOL_DB("void foo(int a) { }\n" + "void foo(float a) { }\n" + "void foo(void* a) { }\n" + "void foo(bool a) { }\n" + "void func(int i, float f, bool b) {\n" + " foo(i + i);\n" + " foo(f + f);\n" + " foo(!b);\n" + " foo(i > 0);\n" + " foo(f + i);\n" + "}"); + + ASSERT_EQUALS("", errout.str()); + + const Token *f = Token::findsimplematch(tokenizer.tokens(), "foo ( i + i ) ;"); + ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 1); + + f = Token::findsimplematch(tokenizer.tokens(), "foo ( f + f ) ;"); + ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 2); + + f = Token::findsimplematch(tokenizer.tokens(), "foo ( ! b ) ;"); + ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 4); + + f = Token::findsimplematch(tokenizer.tokens(), "foo ( i > 0 ) ;"); + ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 4); + + f = Token::findsimplematch(tokenizer.tokens(), "foo ( f + i ) ;"); + ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 2); + } + #define FUNC(x) const Function *x = findFunctionByName(#x, &db->scopeList.front()); \ ASSERT_EQUALS(true, x != nullptr); \