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 << " isOperator: " << func->isOperator() << std::endl;
|
||||||
std::cout << " hasLvalRefQual: " << func->hasLvalRefQualifier() << std::endl;
|
std::cout << " hasLvalRefQual: " << func->hasLvalRefQualifier() << std::endl;
|
||||||
std::cout << " hasRvalRefQual: " << func->hasRvalRefQualifier() << std::endl;
|
std::cout << " hasRvalRefQual: " << func->hasRvalRefQualifier() << std::endl;
|
||||||
|
std::cout << " isVariadic: " << func->isVariadic() << std::endl;
|
||||||
std::cout << " attributes:";
|
std::cout << " attributes:";
|
||||||
if (func->isAttributeConst())
|
if (func->isAttributeConst())
|
||||||
std::cout << " const ";
|
std::cout << " const ";
|
||||||
|
@ -2820,8 +2821,13 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Scope *s
|
||||||
|
|
||||||
argumentList.push_back(Variable(nameTok, startTok, endTok, count++, Argument, argType, functionScope, &symbolDatabase->_settings->library));
|
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;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// count default arguments
|
// count default arguments
|
||||||
|
@ -3584,7 +3590,9 @@ const Function* Scope::findFunction(const Token *tok, bool requireConst) const
|
||||||
const std::size_t args = arguments.size();
|
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) {
|
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;
|
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);
|
matches.push_back(func);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3598,6 +3606,10 @@ const Function* Scope::findFunction(const Token *tok, bool requireConst) const
|
||||||
const Function * func = matches[i];
|
const Function * func = matches[i];
|
||||||
size_t same = 0;
|
size_t same = 0;
|
||||||
for (std::size_t j = 0; j < args; ++j) {
|
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);
|
const Variable *funcarg = func->getArgumentVar(j);
|
||||||
// check for a match with a variable
|
// check for a match with a variable
|
||||||
if (Token::Match(arguments[j], "%var% ,|)")) {
|
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
|
// check that function argument type is not mismatching
|
||||||
else if (arguments[j]->str() == "&" && funcarg && funcarg->isReference()) {
|
else if (arguments[j]->str() == "&" && funcarg && funcarg->isReference()) {
|
||||||
// can't match so remove this function from possible matches
|
// 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
|
// check if all arguments matched
|
||||||
if (same == args) {
|
if ((func->isVariadic() && same == (func->argCount() - 1)) ||
|
||||||
|
(!func->isVariadic() && same == args)) {
|
||||||
if (requireConst && func->isConst())
|
if (requireConst && func->isConst())
|
||||||
return func;
|
return func;
|
||||||
|
|
||||||
|
|
|
@ -628,7 +628,8 @@ class CPPCHECKLIB Function {
|
||||||
fIsThrow = (1 << 13), /** @brief is throw */
|
fIsThrow = (1 << 13), /** @brief is throw */
|
||||||
fIsOperator = (1 << 14), /** @brief is operator */
|
fIsOperator = (1 << 14), /** @brief is operator */
|
||||||
fHasLvalRefQual = (1 << 15), /** @brief has & lvalue ref-qualifier */
|
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 {
|
bool hasRvalRefQualifier() const {
|
||||||
return getFlag(fHasRvalRefQual);
|
return getFlag(fHasRvalRefQual);
|
||||||
}
|
}
|
||||||
|
bool isVariadic() const {
|
||||||
|
return getFlag(fIsVariadic);
|
||||||
|
}
|
||||||
|
|
||||||
void hasBody(bool state) {
|
void hasBody(bool state) {
|
||||||
setFlag(fHasBody, state);
|
setFlag(fHasBody, state);
|
||||||
|
@ -818,6 +822,9 @@ public:
|
||||||
void hasRvalRefQualifier(bool state) {
|
void hasRvalRefQualifier(bool state) {
|
||||||
setFlag(fHasRvalRefQual, state);
|
setFlag(fHasRvalRefQual, state);
|
||||||
}
|
}
|
||||||
|
void isVariadic(bool state) {
|
||||||
|
setFlag(fIsVariadic, state);
|
||||||
|
}
|
||||||
|
|
||||||
const Token *tokenDef; // function name token in class definition
|
const Token *tokenDef; // function name token in class definition
|
||||||
const Token *argDef; // function argument start '(' in class definition
|
const Token *argDef; // function argument start '(' in class definition
|
||||||
|
|
|
@ -294,6 +294,8 @@ private:
|
||||||
TEST_CASE(executableScopeWithUnknownFunction);
|
TEST_CASE(executableScopeWithUnknownFunction);
|
||||||
|
|
||||||
TEST_CASE(valuetype);
|
TEST_CASE(valuetype);
|
||||||
|
|
||||||
|
TEST_CASE(variadic); // # 7453
|
||||||
}
|
}
|
||||||
|
|
||||||
void array() {
|
void array() {
|
||||||
|
@ -3694,6 +3696,37 @@ private:
|
||||||
ASSERT_EQUALS(ValueType::Type::INT, vt.type);
|
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)
|
REGISTER_TEST(TestSymbolDatabase)
|
||||||
|
|
Loading…
Reference in New Issue