Fix #9806 (False positive: template function can be static) (#2868)

* Include detecting variadic template functions by matching against endTok instead of startTok.
* Add argument count check for variadic (template) member functions.
This commit is contained in:
vilarion 2020-10-31 10:02:15 +01:00 committed by GitHub
parent a623168942
commit bc5ec38149
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 39 additions and 3 deletions

View File

@ -1925,7 +1925,9 @@ bool CheckClass::isMemberFunc(const Scope *scope, const Token *tok) const
else
break;
}
if (argsPassed == func.argCount() || (argsPassed < func.argCount() && argsPassed >= func.minArgCount()))
if (argsPassed == func.argCount() ||
(func.isVariadic() && argsPassed >= (func.argCount() - 1)) ||
(argsPassed < func.argCount() && argsPassed >= func.minArgCount()))
return true;
}
}

View File

@ -3681,8 +3681,8 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Scope *s
argumentList.emplace_back(nameTok, startTok, endTok, count++, AccessControl::Argument, argType, functionScope, symbolDatabase->mSettings);
if (tok->str() == ")") {
// check for a variadic function
if (Token::simpleMatch(startTok, "..."))
// check for a variadic function or a variadic template function
if (Token::simpleMatch(endTok, "..."))
isVariadic(true);
break;

View File

@ -171,6 +171,8 @@ private:
TEST_CASE(const66); // ticket #7714
TEST_CASE(const67); // ticket #9193
TEST_CASE(const68); // ticket #6471
TEST_CASE(const69); // ticket #9806
TEST_CASE(const70); // variadic template can receive more arguments than in its definition
TEST_CASE(const_handleDefaultParameters);
TEST_CASE(const_passThisToMemberOfOtherClass);
TEST_CASE(assigningPointerToPointerIsNotAConstOperation);
@ -5534,6 +5536,38 @@ private:
ASSERT_EQUALS("", errout.str());
}
void const69() { // #9806
checkConst("struct A {\n"
" int a = 0;\n"
" template <typename... Args> void call(const Args &... args) { a = 1; }\n"
" template <typename T, typename... Args> auto call(const Args &... args) -> T {\n"
" a = 2;\n"
" return T{};\n"
" }\n"
"};\n"
"\n"
"struct B : public A {\n"
" void test() {\n"
" call();\n"
" call<int>(1, 2, 3);\n"
" }\n"
"};");
ASSERT_EQUALS("", errout.str());
}
void const70() {
checkConst("struct A {\n"
" template <typename... Args> void call(Args ... args) {\n"
" func(this);\n"
" }\n"
"\n"
" void test() {\n"
" call(1, 2);\n"
" }\n"
"};");
ASSERT_EQUALS("", errout.str());
}
void const_handleDefaultParameters() {
checkConst("struct Foo {\n"
" void foo1(int i, int j = 0) {\n"