fix #9885 (SymbolDatabase: function lookup fails calling variadic method) (#3002)

Co-authored-by: Robert Reif <reif@FX6840>
This commit is contained in:
IOBYTE 2021-01-03 05:17:32 -05:00 committed by GitHub
parent 76d5e6c7db
commit 23da5c9815
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 126 additions and 1 deletions

View File

@ -4617,7 +4617,8 @@ void Scope::findFunctionInBase(const std::string & name, nonneg int args, std::v
for (std::multimap<std::string, const Function *>::const_iterator it = base->classScope->functionMap.find(name); it != base->classScope->functionMap.end() && it->first == name; ++it) { for (std::multimap<std::string, const Function *>::const_iterator it = base->classScope->functionMap.find(name); it != base->classScope->functionMap.end() && it->first == name; ++it) {
const Function *func = it->second; const Function *func = it->second;
if (args == func->argCount() || (args < func->argCount() && args >= func->minArgCount())) { if ((func->isVariadic() && args >= (func->argCount() - 1)) ||
(args == func->argCount() || (args < func->argCount() && args >= func->minArgCount()))) {
matches.push_back(func); matches.push_back(func);
} }
} }

View File

@ -395,6 +395,7 @@ private:
TEST_CASE(findFunction30); TEST_CASE(findFunction30);
TEST_CASE(findFunction31); TEST_CASE(findFunction31);
TEST_CASE(findFunction32); // C: relax type matching TEST_CASE(findFunction32); // C: relax type matching
TEST_CASE(findFunction33); // #9885 variadic function
TEST_CASE(findFunctionContainer); TEST_CASE(findFunctionContainer);
TEST_CASE(findFunctionExternC); TEST_CASE(findFunctionExternC);
TEST_CASE(findFunctionGlobalScope); // ::foo TEST_CASE(findFunctionGlobalScope); // ::foo
@ -6065,6 +6066,129 @@ private:
ASSERT_EQUALS(1, foo->function()->tokenDef->linenr()); ASSERT_EQUALS(1, foo->function()->tokenDef->linenr());
} }
void findFunction33() {
{
GET_SYMBOL_DB("class Base {\n"
" int i{};\n"
"public:\n"
" void foo(...) const { bar(); }\n"
" int bar() const { return i; }\n"
"};\n"
"class Derived : public Base {\n"
"public:\n"
" void doIt() const {\n"
" foo();\n"
" }\n"
"};");
(void)db;
const Token *foo = Token::findsimplematch(tokenizer.tokens(), "foo ( ) ;");
ASSERT(foo);
ASSERT(foo->function());
ASSERT(foo->function()->tokenDef);
ASSERT_EQUALS(4, foo->function()->tokenDef->linenr());
}
{
GET_SYMBOL_DB("class Base {\n"
" int i{};\n"
"public:\n"
" void foo(...) const { bar(); }\n"
" int bar() const { return i; }\n"
"};\n"
"class Derived : public Base {\n"
"public:\n"
" void doIt() const {\n"
" foo(1);\n"
" }\n"
"};");
(void)db;
const Token *foo = Token::findsimplematch(tokenizer.tokens(), "foo ( 1 ) ;");
ASSERT(foo);
ASSERT(foo->function());
ASSERT(foo->function()->tokenDef);
ASSERT_EQUALS(4, foo->function()->tokenDef->linenr());
}
{
GET_SYMBOL_DB("class Base {\n"
" int i{};\n"
"public:\n"
" void foo(...) const { bar(); }\n"
" int bar() const { return i; }\n"
"};\n"
"class Derived : public Base {\n"
"public:\n"
" void doIt() const {\n"
" foo(1,2);\n"
" }\n"
"};");
(void)db;
const Token *foo = Token::findsimplematch(tokenizer.tokens(), "foo ( 1 , 2 ) ;");
ASSERT(foo);
ASSERT(foo->function());
ASSERT(foo->function()->tokenDef);
ASSERT_EQUALS(4, foo->function()->tokenDef->linenr());
}
{
GET_SYMBOL_DB("class Base {\n"
" int i{};\n"
"public:\n"
" void foo(int, ...) const { bar(); }\n"
" int bar() const { return i; }\n"
"};\n"
"class Derived : public Base {\n"
"public:\n"
" void doIt() const {\n"
" foo(1);\n"
" }\n"
"};");
(void)db;
const Token *foo = Token::findsimplematch(tokenizer.tokens(), "foo ( 1 ) ;");
ASSERT(foo);
ASSERT(foo->function());
ASSERT(foo->function()->tokenDef);
ASSERT_EQUALS(4, foo->function()->tokenDef->linenr());
}
{
GET_SYMBOL_DB("class Base {\n"
" int i{};\n"
"public:\n"
" void foo(int,...) const { bar(); }\n"
" int bar() const { return i; }\n"
"};\n"
"class Derived : public Base {\n"
"public:\n"
" void doIt() const {\n"
" foo(1,2);\n"
" }\n"
"};");
(void)db;
const Token *foo = Token::findsimplematch(tokenizer.tokens(), "foo ( 1 , 2 ) ;");
ASSERT(foo);
ASSERT(foo->function());
ASSERT(foo->function()->tokenDef);
ASSERT_EQUALS(4, foo->function()->tokenDef->linenr());
}
{
GET_SYMBOL_DB("class Base {\n"
" int i{};\n"
"public:\n"
" void foo(int,...) const { bar(); }\n"
" int bar() const { return i; }\n"
"};\n"
"class Derived : public Base {\n"
"public:\n"
" void doIt() const {\n"
" foo(1, 2, 3);\n"
" }\n"
"};");
(void)db;
const Token *foo = Token::findsimplematch(tokenizer.tokens(), "foo ( 1 , 2 , 3 ) ;");
ASSERT(foo);
ASSERT(foo->function());
ASSERT(foo->function()->tokenDef);
ASSERT_EQUALS(4, foo->function()->tokenDef->linenr());
}
}
void findFunctionContainer() { void findFunctionContainer() {
{ {
GET_SYMBOL_DB("void dostuff(std::vector<int> v);\n" GET_SYMBOL_DB("void dostuff(std::vector<int> v);\n"