From c1d8fd7f13ef1e5ae317579be44f36ea0acaea7c Mon Sep 17 00:00:00 2001 From: PKEuS Date: Sun, 26 Feb 2017 11:36:04 +0100 Subject: [PATCH] SymbolDatabase: Better handling of pointers in findFunction(), supporting const pointers and std::string overloads --- lib/symboldatabase.cpp | 37 ++++++++++++++------------ test/testsymboldatabase.cpp | 52 +++++++++++++++++++++++++++++++++++-- 2 files changed, 71 insertions(+), 18 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index bf08217c3..6d89785c4 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -3715,10 +3715,6 @@ void Scope::findFunctionInBase(const std::string & name, size_t args, std::vecto //--------------------------------------------------------------------------- -/** @todo This function does not take into account argument types when they don't match. - This can be difficult because of promotion and conversion operators and casts - and because the argument can also be a function call. - */ const Function* Scope::findFunction(const Token *tok, bool requireConst) const { // make sure this is a function call @@ -3790,23 +3786,28 @@ const Function* Scope::findFunction(const Token *tok, bool requireConst) const if (Token::Match(arguments[j], "%var% ,|)")) { const Variable * callarg = check->getVariableFromVarId(arguments[j]->varId()); - if (callarg && callarg->isArrayOrPointer() == funcarg->isArrayOrPointer()) { - if (callarg->typeStartToken()->str() == funcarg->typeStartToken()->str() && + if (callarg) { + bool ptrequals = callarg->isArrayOrPointer() == funcarg->isArrayOrPointer(); + bool constEquals = !callarg->isArrayOrPointer() || ((callarg->typeStartToken()->strAt(-1) == "const") == (funcarg->typeStartToken()->strAt(-1) == "const")); + if (ptrequals && constEquals && + callarg->typeStartToken()->str() == funcarg->typeStartToken()->str() && callarg->typeStartToken()->isUnsigned() == funcarg->typeStartToken()->isUnsigned() && callarg->typeStartToken()->isLong() == funcarg->typeStartToken()->isLong()) { same++; } else if (callarg->isArrayOrPointer()) { - if (funcarg->typeStartToken()->str() == "void") + if (ptrequals && constEquals && funcarg->typeStartToken()->str() == "void") fallback1++; + else if (constEquals && Token::Match(callarg->typeStartToken(), "char|wchar_t") && funcarg->isStlStringType()) + fallback2++; } else if ((Token::Match(funcarg->typeStartToken(), "char|short|int|long") && - Token::Match(callarg->typeStartToken(), "char|short|int|long")) || + Token::Match(callarg->typeStartToken(), "char|short|int|long") && ptrequals) || (Token::Match(funcarg->typeStartToken(), "float|double") && - Token::Match(callarg->typeStartToken(), "float|double"))) { + Token::Match(callarg->typeStartToken(), "float|double") && ptrequals)) { fallback1++; } else if ((Token::Match(funcarg->typeStartToken(), "char|short|int|long") && - Token::Match(callarg->typeStartToken(), "float|double")) || + Token::Match(callarg->typeStartToken(), "float|double") && ptrequals) || (Token::Match(funcarg->typeStartToken(), "float|double") && - Token::Match(callarg->typeStartToken(), "char|short|int|long"))) { + Token::Match(callarg->typeStartToken(), "char|short|int|long") && ptrequals)) { fallback2++; } } @@ -3925,11 +3926,15 @@ const Function* Scope::findFunction(const Token *tok, bool requireConst) const } // check for a match with a string literal - else if (Token::Match(arguments[j], "%str% ,|)") && - funcarg->typeStartToken() != funcarg->typeEndToken() && - ((!arguments[j]->isLong() && Token::simpleMatch(funcarg->typeStartToken(), "char *")) || - (arguments[j]->isLong() && Token::simpleMatch(funcarg->typeStartToken(), "wchar_t *")))) { - same++; + else if (Token::Match(arguments[j], "%str% ,|)")) { + if (funcarg->typeStartToken() != funcarg->typeEndToken() && + ((!arguments[j]->isLong() && Token::simpleMatch(funcarg->typeStartToken(), "char *")) || + (arguments[j]->isLong() && Token::simpleMatch(funcarg->typeStartToken(), "wchar_t *")))) + same++; + else if (Token::simpleMatch(funcarg->typeStartToken(), "void *")) + fallback1++; + else if (funcarg->isStlStringType()) + fallback2++; } // check that function argument type is not mismatching diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index f698b0f58..aa459c133 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -282,6 +282,7 @@ private: TEST_CASE(findFunction11); TEST_CASE(findFunction12); TEST_CASE(findFunction13); + TEST_CASE(findFunction14); TEST_CASE(noexceptFunction1); TEST_CASE(noexceptFunction2); @@ -3494,11 +3495,13 @@ private: void findFunction12() { GET_SYMBOL_DB("void foo(std::string a) { }\n" "void foo(long long a) { }\n" - "void foo() {\n" + "void func(char* cp) {\n" " foo(0);\n" " foo(0L);\n" " foo(0.f);\n" " foo(bar());\n" + " foo(cp);\n" + " foo(\"\");\n" "}"); ASSERT_EQUALS("", errout.str()); @@ -3514,6 +3517,12 @@ private: f = Token::findsimplematch(tokenizer.tokens(), "foo ( bar ( ) ) ;"); ASSERT_EQUALS(true, f && f->function() == nullptr); + + f = Token::findsimplematch(tokenizer.tokens(), "foo ( cp ) ;"); + ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 1); + + f = Token::findsimplematch(tokenizer.tokens(), "foo ( \"\" ) ;"); + ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 1); } void findFunction13() { @@ -3522,7 +3531,7 @@ private: "void foo(long long a) { }\n" "void foo(int* a) { }\n" "void foo(void* a) { }\n" - "void func(int i, float f, int* ip, float* fp) {\n" + "void func(int i, const float f, int* ip, float* fp, char* cp) {\n" " foo(0);\n" " foo(0L);\n" " foo(0.f);\n" @@ -3533,6 +3542,8 @@ private: " foo(&f);\n" " foo(ip);\n" " foo(fp);\n" + " foo(cp);\n" + " foo(\"\");\n" "}"); ASSERT_EQUALS("", errout.str()); @@ -3566,6 +3577,43 @@ private: f = Token::findsimplematch(tokenizer.tokens(), "foo ( fp ) ;"); ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 5); + + f = Token::findsimplematch(tokenizer.tokens(), "foo ( cp ) ;"); + ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 5); + + f = Token::findsimplematch(tokenizer.tokens(), "foo ( \"\" ) ;"); + ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 5); + } + + void findFunction14() { + GET_SYMBOL_DB("void foo(int* a) { }\n" + "void foo(const int* a) { }\n" + "void foo(void* a) { }\n" + "void foo(const float a) { }\n" + "void func(int* ip, const int* cip, const char* ccp, char* cp, float f) {\n" + " foo(ip);\n" + " foo(cip);\n" + " foo(cp);\n" + " foo(ccp);\n" + " foo(f);\n" + "}"); + + ASSERT_EQUALS("", errout.str()); + + const Token *f = Token::findsimplematch(tokenizer.tokens(), "foo ( ip ) ;"); + ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 1); + + f = Token::findsimplematch(tokenizer.tokens(), "foo ( cip ) ;"); + ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 2); + + f = Token::findsimplematch(tokenizer.tokens(), "foo ( cp ) ;"); + ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 3); + + f = Token::findsimplematch(tokenizer.tokens(), "foo ( ccp ) ;"); + ASSERT_EQUALS(true, f && f->function() == nullptr); + + f = Token::findsimplematch(tokenizer.tokens(), "foo ( f ) ;"); + ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 4); } #define FUNC(x) const Function *x = findFunctionByName(#x, &db->scopeList.front()); \