Fixed #7458 (SymbolDatabase: Wrong overloaded function is picked)
This commit is contained in:
parent
41526ef3a8
commit
891e21b478
|
@ -2466,6 +2466,7 @@ void SymbolDatabase::printOut(const char *title) const
|
|||
std::cout << " isOperator: " << func->isOperator() << std::endl;
|
||||
std::cout << " hasLvalRefQual: " << func->hasLvalRefQualifier() << std::endl;
|
||||
std::cout << " hasRvalRefQual: " << func->hasRvalRefQualifier() << std::endl;
|
||||
std::cout << " isVariadic: " << func->isVariadic() << std::endl;
|
||||
std::cout << " attributes:";
|
||||
if (func->isAttributeConst())
|
||||
std::cout << " const ";
|
||||
|
@ -2820,9 +2821,14 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Scope *s
|
|||
|
||||
argumentList.push_back(Variable(nameTok, startTok, endTok, count++, Argument, argType, functionScope, &symbolDatabase->_settings->library));
|
||||
|
||||
if (tok->str() == ")")
|
||||
if (tok->str() == ")") {
|
||||
// check for a variadic function
|
||||
if (Token::simpleMatch(startTok, ". . ."))
|
||||
isVariadic(true);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// count default arguments
|
||||
for (const Token* tok = argDef->next(); tok && tok != argDef->link(); tok = tok->next()) {
|
||||
|
@ -3584,7 +3590,9 @@ const Function* Scope::findFunction(const Token *tok, bool requireConst) const
|
|||
const std::size_t args = arguments.size();
|
||||
for (std::multimap<std::string, const Function *>::const_iterator it = functionMap.find(tok->str()); it != functionMap.end() && it->first == tok->str(); ++it) {
|
||||
const Function *func = it->second;
|
||||
if (args == func->argCount() || (args < func->argCount() && args >= func->minArgCount())) {
|
||||
if (args == func->argCount() ||
|
||||
(func->isVariadic() && args >= (func->argCount() - 1)) ||
|
||||
(args < func->argCount() && args >= func->minArgCount())) {
|
||||
matches.push_back(func);
|
||||
}
|
||||
}
|
||||
|
@ -3598,6 +3606,10 @@ const Function* Scope::findFunction(const Token *tok, bool requireConst) const
|
|||
const Function * func = matches[i];
|
||||
size_t same = 0;
|
||||
for (std::size_t j = 0; j < args; ++j) {
|
||||
// don't check variadic arguments
|
||||
if (func->isVariadic() && j > (func->argCount() - 1)) {
|
||||
break;
|
||||
}
|
||||
const Variable *funcarg = func->getArgumentVar(j);
|
||||
// check for a match with a variable
|
||||
if (Token::Match(arguments[j], "%var% ,|)")) {
|
||||
|
@ -3682,6 +3694,13 @@ 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() &&
|
||||
Token::Match(funcarg->typeStartToken(), "char|wchar *")) {
|
||||
same++;
|
||||
}
|
||||
|
||||
// check that function argument type is not mismatching
|
||||
else if (arguments[j]->str() == "&" && funcarg && funcarg->isReference()) {
|
||||
// can't match so remove this function from possible matches
|
||||
|
@ -3692,7 +3711,8 @@ const Function* Scope::findFunction(const Token *tok, bool requireConst) const
|
|||
}
|
||||
|
||||
// check if all arguments matched
|
||||
if (same == args) {
|
||||
if ((func->isVariadic() && same == (func->argCount() - 1)) ||
|
||||
(!func->isVariadic() && same == args)) {
|
||||
if (requireConst && func->isConst())
|
||||
return func;
|
||||
|
||||
|
|
|
@ -628,7 +628,8 @@ class CPPCHECKLIB Function {
|
|||
fIsThrow = (1 << 13), /** @brief is throw */
|
||||
fIsOperator = (1 << 14), /** @brief is operator */
|
||||
fHasLvalRefQual = (1 << 15), /** @brief has & lvalue ref-qualifier */
|
||||
fHasRvalRefQual = (1 << 16) /** @brief has && rvalue ref-qualifier */
|
||||
fHasRvalRefQual = (1 << 16), /** @brief has && rvalue ref-qualifier */
|
||||
fIsVariadic = (1 << 17) /** @brief is variadic */
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -766,6 +767,9 @@ public:
|
|||
bool hasRvalRefQualifier() const {
|
||||
return getFlag(fHasRvalRefQual);
|
||||
}
|
||||
bool isVariadic() const {
|
||||
return getFlag(fIsVariadic);
|
||||
}
|
||||
|
||||
void hasBody(bool state) {
|
||||
setFlag(fHasBody, state);
|
||||
|
@ -818,6 +822,9 @@ public:
|
|||
void hasRvalRefQualifier(bool state) {
|
||||
setFlag(fHasRvalRefQual, state);
|
||||
}
|
||||
void isVariadic(bool state) {
|
||||
setFlag(fIsVariadic, state);
|
||||
}
|
||||
|
||||
const Token *tokenDef; // function name token in class definition
|
||||
const Token *argDef; // function argument start '(' in class definition
|
||||
|
|
|
@ -294,6 +294,8 @@ private:
|
|||
TEST_CASE(executableScopeWithUnknownFunction);
|
||||
|
||||
TEST_CASE(valuetype);
|
||||
|
||||
TEST_CASE(variadic); // # 7453
|
||||
}
|
||||
|
||||
void array() {
|
||||
|
@ -3694,6 +3696,37 @@ private:
|
|||
ASSERT_EQUALS(ValueType::Type::INT, vt.type);
|
||||
}
|
||||
}
|
||||
|
||||
void variadic() { // #7453
|
||||
{
|
||||
GET_SYMBOL_DB("CBase* create(const char *c1, ...);\n"
|
||||
"int create(COther& ot, const char *c1, ...);\n"
|
||||
"int foo(COther & ot)\n"
|
||||
"{\n"
|
||||
" CBase* cp1 = create(\"AAAA\", 44, (char*)0);\n"
|
||||
" CBase* cp2 = create(ot, \"AAAA\", 44, (char*)0);\n"
|
||||
"}");
|
||||
|
||||
const Token *f = Token::findsimplematch(tokenizer.tokens(), "create ( \"AAAA\"");
|
||||
ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 1);
|
||||
f = Token::findsimplematch(tokenizer.tokens(), "create ( ot");
|
||||
ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 2);
|
||||
}
|
||||
{
|
||||
GET_SYMBOL_DB("int create(COther& ot, const char *c1, ...);\n"
|
||||
"CBase* create(const char *c1, ...);\n"
|
||||
"int foo(COther & ot)\n"
|
||||
"{\n"
|
||||
" CBase* cp1 = create(\"AAAA\", 44, (char*)0);\n"
|
||||
" CBase* cp2 = create(ot, \"AAAA\", 44, (char*)0);\n"
|
||||
"}");
|
||||
|
||||
const Token *f = Token::findsimplematch(tokenizer.tokens(), "create ( \"AAAA\"");
|
||||
ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 2);
|
||||
f = Token::findsimplematch(tokenizer.tokens(), "create ( ot");
|
||||
ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_TEST(TestSymbolDatabase)
|
||||
|
|
Loading…
Reference in New Issue