From bc5ec381490888476ce73d192f55a1315f5b426f Mon Sep 17 00:00:00 2001 From: vilarion Date: Sat, 31 Oct 2020 10:02:15 +0100 Subject: [PATCH] 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. --- lib/checkclass.cpp | 4 +++- lib/symboldatabase.cpp | 4 ++-- test/testclass.cpp | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 2c45f8e9a..60725e72f 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -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; } } diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index c1f7bb925..7c8944fb4 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -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; diff --git a/test/testclass.cpp b/test/testclass.cpp index 34a1d6104..515525c56 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -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 void call(const Args &... args) { a = 1; }\n" + " template 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(1, 2, 3);\n" + " }\n" + "};"); + ASSERT_EQUALS("", errout.str()); + } + + void const70() { + checkConst("struct A {\n" + " template 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"