* 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:
parent
a623168942
commit
bc5ec38149
|
@ -1925,7 +1925,9 @@ bool CheckClass::isMemberFunc(const Scope *scope, const Token *tok) const
|
||||||
else
|
else
|
||||||
break;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
argumentList.emplace_back(nameTok, startTok, endTok, count++, AccessControl::Argument, argType, functionScope, symbolDatabase->mSettings);
|
||||||
|
|
||||||
if (tok->str() == ")") {
|
if (tok->str() == ")") {
|
||||||
// check for a variadic function
|
// check for a variadic function or a variadic template function
|
||||||
if (Token::simpleMatch(startTok, "..."))
|
if (Token::simpleMatch(endTok, "..."))
|
||||||
isVariadic(true);
|
isVariadic(true);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -171,6 +171,8 @@ private:
|
||||||
TEST_CASE(const66); // ticket #7714
|
TEST_CASE(const66); // ticket #7714
|
||||||
TEST_CASE(const67); // ticket #9193
|
TEST_CASE(const67); // ticket #9193
|
||||||
TEST_CASE(const68); // ticket #6471
|
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_handleDefaultParameters);
|
||||||
TEST_CASE(const_passThisToMemberOfOtherClass);
|
TEST_CASE(const_passThisToMemberOfOtherClass);
|
||||||
TEST_CASE(assigningPointerToPointerIsNotAConstOperation);
|
TEST_CASE(assigningPointerToPointerIsNotAConstOperation);
|
||||||
|
@ -5534,6 +5536,38 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
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() {
|
void const_handleDefaultParameters() {
|
||||||
checkConst("struct Foo {\n"
|
checkConst("struct Foo {\n"
|
||||||
" void foo1(int i, int j = 0) {\n"
|
" void foo1(int i, int j = 0) {\n"
|
||||||
|
|
Loading…
Reference in New Issue