SymbolDatabase: Better handling of pointers in findFunction(), supporting const pointers and std::string overloads

This commit is contained in:
PKEuS 2017-02-26 11:36:04 +01:00
parent 4a27376694
commit c1d8fd7f13
2 changed files with 71 additions and 18 deletions

View File

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

View File

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