This commit is contained in:
parent
523c41a60b
commit
7d1423c5fb
|
@ -5442,6 +5442,23 @@ static std::string getTypeString(const Token *typeToken)
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool hasMatchingConstructor(const Scope* classScope, const ValueType* argType) {
|
||||||
|
if (!classScope || !argType)
|
||||||
|
return false;
|
||||||
|
return std::any_of(classScope->functionList.cbegin(),
|
||||||
|
classScope->functionList.cend(),
|
||||||
|
[&](const Function& f) {
|
||||||
|
if (!f.isConstructor() || f.argCount() != 1 || !f.getArgumentVar(0))
|
||||||
|
return false;
|
||||||
|
const ValueType* vt = f.getArgumentVar(0)->valueType();
|
||||||
|
return vt &&
|
||||||
|
vt->type == argType->type &&
|
||||||
|
(argType->sign == ValueType::Sign::UNKNOWN_SIGN || vt->sign == argType->sign) &&
|
||||||
|
vt->pointer == argType->pointer &&
|
||||||
|
(vt->constness & 1) >= (argType->constness & 1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const Function* Scope::findFunction(const Token *tok, bool requireConst) const
|
const Function* Scope::findFunction(const Token *tok, bool requireConst) const
|
||||||
{
|
{
|
||||||
const bool isCall = Token::Match(tok->next(), "(|{");
|
const bool isCall = Token::Match(tok->next(), "(|{");
|
||||||
|
@ -5473,6 +5490,8 @@ const Function* Scope::findFunction(const Token *tok, bool requireConst) const
|
||||||
addMatchingFunctions(nestedScope);
|
addMatchingFunctions(nestedScope);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::size_t numberOfMatchesNonBase = matches.size();
|
||||||
|
|
||||||
// check in base classes
|
// check in base classes
|
||||||
findFunctionInBase(tok->str(), args, matches);
|
findFunctionInBase(tok->str(), args, matches);
|
||||||
|
|
||||||
|
@ -5485,6 +5504,9 @@ const Function* Scope::findFunction(const Token *tok, bool requireConst) const
|
||||||
|
|
||||||
// check each function against the arguments in the function call for a match
|
// check each function against the arguments in the function call for a match
|
||||||
for (std::size_t i = 0; i < matches.size();) {
|
for (std::size_t i = 0; i < matches.size();) {
|
||||||
|
if (i > 0 && i == numberOfMatchesNonBase && fallback1Func.empty() && !fallback2Func.empty())
|
||||||
|
break;
|
||||||
|
|
||||||
bool constFallback = false;
|
bool constFallback = false;
|
||||||
const Function * func = matches[i];
|
const Function * func = matches[i];
|
||||||
size_t same = 0;
|
size_t same = 0;
|
||||||
|
@ -5592,6 +5614,9 @@ const Function* Scope::findFunction(const Token *tok, bool requireConst) const
|
||||||
else if (funcarg->isPointer() && MathLib::isNullValue(arguments[j]->str()))
|
else if (funcarg->isPointer() && MathLib::isNullValue(arguments[j]->str()))
|
||||||
fallback1++;
|
fallback1++;
|
||||||
|
|
||||||
|
else if (!funcarg->isPointer() && funcarg->type() && hasMatchingConstructor(funcarg->type()->classScope, arguments[j]->valueType()))
|
||||||
|
fallback2++;
|
||||||
|
|
||||||
// Try to evaluate the apparently more complex expression
|
// Try to evaluate the apparently more complex expression
|
||||||
else if (check->isCPP()) {
|
else if (check->isCPP()) {
|
||||||
const Token *vartok = arguments[j];
|
const Token *vartok = arguments[j];
|
||||||
|
|
|
@ -447,6 +447,7 @@ private:
|
||||||
TEST_CASE(findFunction48);
|
TEST_CASE(findFunction48);
|
||||||
TEST_CASE(findFunction49); // #11888
|
TEST_CASE(findFunction49); // #11888
|
||||||
TEST_CASE(findFunction50); // #11904 - method with same name and arguments in derived class
|
TEST_CASE(findFunction50); // #11904 - method with same name and arguments in derived class
|
||||||
|
TEST_CASE(findFunction51); // #11975 - method with same name in derived class
|
||||||
TEST_CASE(findFunctionContainer);
|
TEST_CASE(findFunctionContainer);
|
||||||
TEST_CASE(findFunctionExternC);
|
TEST_CASE(findFunctionExternC);
|
||||||
TEST_CASE(findFunctionGlobalScope); // ::foo
|
TEST_CASE(findFunctionGlobalScope); // ::foo
|
||||||
|
@ -7372,6 +7373,67 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void findFunction51() {
|
||||||
|
// Both A and B defines the method test but with different arguments.
|
||||||
|
// The call to test in B should match the method in B. The match is close enough.
|
||||||
|
{
|
||||||
|
GET_SYMBOL_DB("class A {\n"
|
||||||
|
"public:\n"
|
||||||
|
" void test(bool a = true);\n"
|
||||||
|
"};\n"
|
||||||
|
"\n"
|
||||||
|
"class B : public A {\n"
|
||||||
|
"public:\n"
|
||||||
|
" B(): b_obj(this) { b_obj->test(\"1\"); }\n"
|
||||||
|
" void test(const std::string& str_obj);\n"
|
||||||
|
" B* b_obj;\n"
|
||||||
|
"};");
|
||||||
|
const Token* call = Token::findsimplematch(tokenizer.tokens(), "test ( \"1\" ) ;");
|
||||||
|
ASSERT(call);
|
||||||
|
ASSERT(call->function());
|
||||||
|
ASSERT(call->function()->tokenDef);
|
||||||
|
ASSERT_EQUALS(9, call->function()->tokenDef->linenr());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
GET_SYMBOL_DB("struct STR { STR(const char * p); };\n"
|
||||||
|
"class A {\n"
|
||||||
|
"public:\n"
|
||||||
|
" void test(bool a = true);\n"
|
||||||
|
"};\n"
|
||||||
|
"\n"
|
||||||
|
"class B : public A {\n"
|
||||||
|
"public:\n"
|
||||||
|
" B(): b_obj(this) { b_obj->test(\"1\"); }\n"
|
||||||
|
" void test(const STR& str_obj);\n"
|
||||||
|
" B* b_obj;\n"
|
||||||
|
"};");
|
||||||
|
const Token* call = Token::findsimplematch(tokenizer.tokens(), "test ( \"1\" ) ;");
|
||||||
|
ASSERT(call);
|
||||||
|
ASSERT(call->function());
|
||||||
|
ASSERT(call->function()->tokenDef);
|
||||||
|
ASSERT_EQUALS(10, call->function()->tokenDef->linenr());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
GET_SYMBOL_DB("struct STR { STR(const char * p); };\n"
|
||||||
|
"class A {\n"
|
||||||
|
"public:\n"
|
||||||
|
" void test(bool a = true, int b = 0);\n"
|
||||||
|
"};\n"
|
||||||
|
"\n"
|
||||||
|
"class B : public A {\n"
|
||||||
|
"public:\n"
|
||||||
|
" B(): b_obj(this) { b_obj->test(\"1\"); }\n"
|
||||||
|
" void test(const STR& str_obj);\n"
|
||||||
|
" B* b_obj;\n"
|
||||||
|
"};");
|
||||||
|
const Token* call = Token::findsimplematch(tokenizer.tokens(), "test ( \"1\" ) ;");
|
||||||
|
ASSERT(call);
|
||||||
|
ASSERT(call->function());
|
||||||
|
ASSERT(call->function()->tokenDef);
|
||||||
|
ASSERT_EQUALS(10, call->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"
|
||||||
|
|
Loading…
Reference in New Issue