diff --git a/lib/library.cpp b/lib/library.cpp
index 298eeda57..3c3911889 100644
--- a/lib/library.cpp
+++ b/lib/library.cpp
@@ -556,10 +556,12 @@ Library::Error Library::loadFunction(const tinyxml2::XMLElement * const node, co
const char* argNrString = functionnode->Attribute("nr");
if (!argNrString)
return Error(MISSING_ATTRIBUTE, "nr");
- const bool bAnyArg = strcmp(argNrString, "any")==0;
- const int nr = bAnyArg ? -1 : std::atoi(argNrString);
+ const bool bAnyArg = strcmp(argNrString, "any") == 0;
+ const bool bVariadicArg = strcmp(argNrString, "variadic") == 0;
+ const int nr = (bAnyArg || bVariadicArg) ? -1 : std::atoi(argNrString);
ArgumentChecks &ac = func.argumentChecks[nr];
ac.optional = functionnode->Attribute("default") != nullptr;
+ ac.variadic = bVariadicArg;
for (const tinyxml2::XMLElement *argnode = functionnode->FirstChildElement(); argnode; argnode = argnode->NextSiblingElement()) {
const std::string argnodename = argnode->Name();
if (argnodename == "not-bool")
@@ -942,7 +944,7 @@ bool Library::matchArguments(const Token *ftok, const std::string &functionName)
if (it2->second.optional && (firstOptionalArg == -1 || firstOptionalArg > it2->first))
firstOptionalArg = it2->first;
- if (it2->second.formatstr)
+ if (it2->second.formatstr || it2->second.variadic)
return args <= callargs;
}
return (firstOptionalArg < 0) ? args == callargs : (callargs >= firstOptionalArg-1 && callargs <= args);
diff --git a/lib/library.h b/lib/library.h
index e77c347dd..6e3741302 100644
--- a/lib/library.h
+++ b/lib/library.h
@@ -223,6 +223,7 @@ public:
formatstr(false),
strz(false),
optional(false),
+ variadic(false),
iteratorInfo() {
}
@@ -232,14 +233,15 @@ public:
bool formatstr;
bool strz;
bool optional;
+ bool variadic;
std::string valid;
class IteratorInfo {
public:
- IteratorInfo() : it(false), container(0), first(false), last(false) {}
+ IteratorInfo() : container(0), it(false), first(false), last(false) {}
- bool it;
int container;
+ bool it;
bool first;
bool last;
};
diff --git a/man/manual.docbook b/man/manual.docbook
index e1e38ce14..3a1f7340c 100644
--- a/man/manual.docbook
+++ b/man/manual.docbook
@@ -5,7 +5,7 @@
Cppcheck 1.78 dev
- 2016-08-13
+ 2017-03-14
@@ -918,11 +918,9 @@ Checking pen1.c...
The arguments a function takes can be specified by
<arg> tags. Each of them takes the number of
the argument (starting from 1) in the nr attribute,
- or nr="any" for variadic arguments. Optional
- arguments can be specified by providing a default value:
- default="value". Specifying -1
- as the argument number is going to apply a check to all arguments of
- that function. The specifications for individual arguments override
+ nr="any" for arbitrary arguments, or nr="variadic" for variadic arguments.
+ Optional arguments can be specified by providing a default value:
+ default="value". The specifications for individual arguments override
this setting.
diff --git a/test/testlibrary.cpp b/test/testlibrary.cpp
index eabb8f775..8db981490 100644
--- a/test/testlibrary.cpp
+++ b/test/testlibrary.cpp
@@ -41,6 +41,7 @@ private:
TEST_CASE(function_match_var);
TEST_CASE(function_arg);
TEST_CASE(function_arg_any);
+ TEST_CASE(function_arg_variadic);
TEST_CASE(function_arg_valid);
TEST_CASE(function_arg_minsize);
TEST_CASE(function_namespace);
@@ -242,6 +243,30 @@ private:
ASSERT_EQUALS(true, library.functions["foo"].argumentChecks[-1].notuninit);
}
+ void function_arg_variadic() const {
+ const char xmldata[] = "\n"
+ "\n"
+ "\n"
+ " \n"
+ " \n"
+ "\n"
+ "";
+
+ Library library;
+ readLibrary(library, xmldata);
+ ASSERT_EQUALS(true, library.functions["foo"].argumentChecks[-1].notuninit);
+
+ TokenList tokenList(nullptr);
+ std::istringstream istr("foo(a,b,c,d,e);");
+ tokenList.createTokens(istr);
+ tokenList.front()->next()->astOperand1(tokenList.front());
+
+ ASSERT_EQUALS(false, library.isuninitargbad(tokenList.front(), 1));
+ ASSERT_EQUALS(true, library.isuninitargbad(tokenList.front(), 2));
+ ASSERT_EQUALS(true, library.isuninitargbad(tokenList.front(), 3));
+ ASSERT_EQUALS(true, library.isuninitargbad(tokenList.front(), 4));
+ }
+
void function_arg_valid() const {
const char xmldata[] = "\n"
"\n"