Improve findFunction for function calls with function calls as arguments. (#1147)

Duplicate the existing logic for variable to variable type comparisons
for function return type to variable type comparisons.
This commit is contained in:
IOBYTE 2018-04-04 14:44:01 -04:00 committed by Daniel Marjamäki
parent b133d50ebe
commit a62c932a8f
2 changed files with 104 additions and 1 deletions

View File

@ -4224,7 +4224,33 @@ const Function* Scope::findFunction(const Token *tok, bool requireConst) const
while (argtok->astParent() && argtok->astParent() != tok->next() && argtok->astParent()->str() != ",") {
argtok = argtok->astParent();
}
if (argtok && argtok->valueType() && !funcarg->isArrayOrPointer()) { // TODO: Pointers
if (argtok && argtok->valueType() && argtok->previous()->function() && argtok->previous()->function()->retDef) {
const ValueType* valuetype = argtok->valueType();
const Function* argfunc = argtok->previous()->function();
const bool isArrayOrPointer = valuetype->pointer;
const bool ptrequals = isArrayOrPointer == funcarg->isArrayOrPointer();
const bool constEquals = !isArrayOrPointer || ((argfunc->retDef->strAt(-1) == "const") == (funcarg->typeStartToken()->strAt(-1) == "const"));
if (ptrequals && constEquals &&
argfunc->retDef->str() == funcarg->typeStartToken()->str() &&
argfunc->retDef->isUnsigned() == funcarg->typeStartToken()->isUnsigned() &&
argfunc->retDef->isLong() == funcarg->typeStartToken()->isLong()) {
same++;
} else if (isArrayOrPointer) {
if (ptrequals && constEquals && funcarg->typeStartToken()->str() == "void")
fallback1++;
else if (constEquals && funcarg->isStlStringType() && Token::Match(argfunc->retDef, "char|wchar_t"))
fallback2++;
} else if (ptrequals) {
const bool takesInt = Token::Match(funcarg->typeStartToken(), "char|short|int|long");
const bool takesFloat = Token::Match(funcarg->typeStartToken(), "float|double");
const bool passesInt = Token::Match(argfunc->retDef, "char|short|int|long");
const bool passesFloat = Token::Match(argfunc->retDef, "float|double");
if ((takesInt && passesInt) || (takesFloat && passesFloat))
fallback1++;
else if ((takesInt && passesFloat) || (takesFloat && passesInt))
fallback2++;
}
} else if (argtok && argtok->valueType() && !funcarg->isArrayOrPointer()) { // TODO: Pointers
if (argtok->valueType()->type == ValueType::BOOL) {
if (funcarg->typeStartToken()->str() == "bool")
same++;

View File

@ -305,6 +305,7 @@ private:
TEST_CASE(findFunction16);
TEST_CASE(findFunction17);
TEST_CASE(findFunction18);
TEST_CASE(findFunction19);
TEST_CASE(noexceptFunction1);
TEST_CASE(noexceptFunction2);
@ -3938,6 +3939,82 @@ private:
ASSERT_EQUALS(true, f && f->function() && f->function()->tokenDef->linenr() == 3);
}
void findFunction19() {
GET_SYMBOL_DB("class Fred {\n"
" enum E1 { e1 };\n"
" enum class E2 : unsigned short { e2 };\n"
" bool get(bool x) { return x; }\n"
" char get(char x) { return x; }\n"
" short get(short x) { return x; }\n"
" int get(int x) { return x; }\n"
" long get(long x) { return x; }\n"
" long long get(long long x) { return x; }\n"
" unsigned char get(unsigned char x) { return x; }\n"
" unsigned short get(unsigned short x) { return x; }\n"
" unsigned int get(unsigned int x) { return x; }\n"
" unsigned long get(unsigned long x) { return x; }\n"
" unsigned long long get(unsigned long long x) { return x; }\n"
" E1 get(E1 x) { return x; }\n"
" E2 get(E2 x) { return x; }\n"
" void foo() {\n"
" bool v1 = true; v1 = get(get(v1));\n"
" char v2 = '1'; v2 = get(get(v2));\n"
" short v3 = 1; v3 = get(get(v3));\n"
" int v4 = 1; v4 = get(get(v4));\n"
" long v5 = 1; v5 = get(get(v5));\n"
" long long v6 = 1; v6 = get(get(v6));\n"
" unsigned char v7 = '1'; v7 = get(get(v7));\n"
" unsigned short v8 = 1; v8 = get(get(v8));\n"
" unsigned int v9 = 1; v9 = get(get(v9));\n"
" unsigned long v10 = 1; v10 = get(get(v10));\n"
" unsigned long long v11 = 1; v11 = get(get(v11));\n"
" E1 v12 = e1; v12 = get(get(v12));\n"
" E2 v13 = E2::e2; v13 = get(get(v13));\n"
" }\n"
"};");
ASSERT_EQUALS("", errout.str());
const Token *f = Token::findsimplematch(tokenizer.tokens(), "get ( get ( v1 ) ) ;");
ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 4);
f = Token::findsimplematch(tokenizer.tokens(), "get ( get ( v2 ) ) ;");
ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 5);
f = Token::findsimplematch(tokenizer.tokens(), "get ( get ( v3 ) ) ;");
ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 6);
f = Token::findsimplematch(tokenizer.tokens(), "get ( get ( v4 ) ) ;");
ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 7);
f = Token::findsimplematch(tokenizer.tokens(), "get ( get ( v5 ) ) ;");
ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 8);
f = Token::findsimplematch(tokenizer.tokens(), "get ( get ( v6 ) ) ;");
ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 9);
f = Token::findsimplematch(tokenizer.tokens(), "get ( get ( v7 ) ) ;");
ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 10);
f = Token::findsimplematch(tokenizer.tokens(), "get ( get ( v8 ) ) ;");
ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 11);
f = Token::findsimplematch(tokenizer.tokens(), "get ( get ( v9 ) ) ;");
ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 12);
f = Token::findsimplematch(tokenizer.tokens(), "get ( get ( v10 ) ) ;");
ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 13);
f = Token::findsimplematch(tokenizer.tokens(), "get ( get ( v11 ) ) ;");
ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 14);
f = Token::findsimplematch(tokenizer.tokens(), "get ( get ( v12 ) ) ;");
ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 15);
f = Token::findsimplematch(tokenizer.tokens(), "get ( get ( v13 ) ) ;");
ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 16);
}
#define FUNC(x) const Function *x = findFunctionByName(#x, &db->scopeList.front()); \
ASSERT_EQUALS(true, x != nullptr); \
if (x) ASSERT_EQUALS(true, x->isNoExcept());