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"