Library: Support variadic functions which are not a formatstr-function
This commit is contained in:
parent
263c3596d5
commit
92414b923a
|
@ -556,10 +556,12 @@ Library::Error Library::loadFunction(const tinyxml2::XMLElement * const node, co
|
||||||
const char* argNrString = functionnode->Attribute("nr");
|
const char* argNrString = functionnode->Attribute("nr");
|
||||||
if (!argNrString)
|
if (!argNrString)
|
||||||
return Error(MISSING_ATTRIBUTE, "nr");
|
return Error(MISSING_ATTRIBUTE, "nr");
|
||||||
const bool bAnyArg = strcmp(argNrString, "any")==0;
|
const bool bAnyArg = strcmp(argNrString, "any") == 0;
|
||||||
const int nr = bAnyArg ? -1 : std::atoi(argNrString);
|
const bool bVariadicArg = strcmp(argNrString, "variadic") == 0;
|
||||||
|
const int nr = (bAnyArg || bVariadicArg) ? -1 : std::atoi(argNrString);
|
||||||
ArgumentChecks &ac = func.argumentChecks[nr];
|
ArgumentChecks &ac = func.argumentChecks[nr];
|
||||||
ac.optional = functionnode->Attribute("default") != nullptr;
|
ac.optional = functionnode->Attribute("default") != nullptr;
|
||||||
|
ac.variadic = bVariadicArg;
|
||||||
for (const tinyxml2::XMLElement *argnode = functionnode->FirstChildElement(); argnode; argnode = argnode->NextSiblingElement()) {
|
for (const tinyxml2::XMLElement *argnode = functionnode->FirstChildElement(); argnode; argnode = argnode->NextSiblingElement()) {
|
||||||
const std::string argnodename = argnode->Name();
|
const std::string argnodename = argnode->Name();
|
||||||
if (argnodename == "not-bool")
|
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))
|
if (it2->second.optional && (firstOptionalArg == -1 || firstOptionalArg > it2->first))
|
||||||
firstOptionalArg = it2->first;
|
firstOptionalArg = it2->first;
|
||||||
|
|
||||||
if (it2->second.formatstr)
|
if (it2->second.formatstr || it2->second.variadic)
|
||||||
return args <= callargs;
|
return args <= callargs;
|
||||||
}
|
}
|
||||||
return (firstOptionalArg < 0) ? args == callargs : (callargs >= firstOptionalArg-1 && callargs <= args);
|
return (firstOptionalArg < 0) ? args == callargs : (callargs >= firstOptionalArg-1 && callargs <= args);
|
||||||
|
|
|
@ -223,6 +223,7 @@ public:
|
||||||
formatstr(false),
|
formatstr(false),
|
||||||
strz(false),
|
strz(false),
|
||||||
optional(false),
|
optional(false),
|
||||||
|
variadic(false),
|
||||||
iteratorInfo() {
|
iteratorInfo() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,14 +233,15 @@ public:
|
||||||
bool formatstr;
|
bool formatstr;
|
||||||
bool strz;
|
bool strz;
|
||||||
bool optional;
|
bool optional;
|
||||||
|
bool variadic;
|
||||||
std::string valid;
|
std::string valid;
|
||||||
|
|
||||||
class IteratorInfo {
|
class IteratorInfo {
|
||||||
public:
|
public:
|
||||||
IteratorInfo() : it(false), container(0), first(false), last(false) {}
|
IteratorInfo() : container(0), it(false), first(false), last(false) {}
|
||||||
|
|
||||||
bool it;
|
|
||||||
int container;
|
int container;
|
||||||
|
bool it;
|
||||||
bool first;
|
bool first;
|
||||||
bool last;
|
bool last;
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<bookinfo>
|
<bookinfo>
|
||||||
<title>Cppcheck 1.78 dev</title>
|
<title>Cppcheck 1.78 dev</title>
|
||||||
|
|
||||||
<date>2016-08-13</date>
|
<date>2017-03-14</date>
|
||||||
</bookinfo>
|
</bookinfo>
|
||||||
|
|
||||||
<chapter>
|
<chapter>
|
||||||
|
@ -918,11 +918,9 @@ Checking pen1.c...
|
||||||
<para>The arguments a function takes can be specified by
|
<para>The arguments a function takes can be specified by
|
||||||
<literal><arg></literal> tags. Each of them takes the number of
|
<literal><arg></literal> tags. Each of them takes the number of
|
||||||
the argument (starting from 1) in the <literal>nr</literal> attribute,
|
the argument (starting from 1) in the <literal>nr</literal> attribute,
|
||||||
or <literal>nr="any"</literal> for variadic arguments. Optional
|
<literal>nr="any"</literal> for arbitrary arguments, or <literal>nr="variadic"</literal> for variadic arguments.
|
||||||
arguments can be specified by providing a default value:
|
Optional arguments can be specified by providing a default value:
|
||||||
<literal>default="value"</literal>. Specifying <literal>-1</literal>
|
<literal>default="value"</literal>. The specifications for individual arguments override
|
||||||
as the argument number is going to apply a check to all arguments of
|
|
||||||
that function. The specifications for individual arguments override
|
|
||||||
this setting.</para>
|
this setting.</para>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
|
|
|
@ -41,6 +41,7 @@ private:
|
||||||
TEST_CASE(function_match_var);
|
TEST_CASE(function_match_var);
|
||||||
TEST_CASE(function_arg);
|
TEST_CASE(function_arg);
|
||||||
TEST_CASE(function_arg_any);
|
TEST_CASE(function_arg_any);
|
||||||
|
TEST_CASE(function_arg_variadic);
|
||||||
TEST_CASE(function_arg_valid);
|
TEST_CASE(function_arg_valid);
|
||||||
TEST_CASE(function_arg_minsize);
|
TEST_CASE(function_arg_minsize);
|
||||||
TEST_CASE(function_namespace);
|
TEST_CASE(function_namespace);
|
||||||
|
@ -242,6 +243,30 @@ private:
|
||||||
ASSERT_EQUALS(true, library.functions["foo"].argumentChecks[-1].notuninit);
|
ASSERT_EQUALS(true, library.functions["foo"].argumentChecks[-1].notuninit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void function_arg_variadic() const {
|
||||||
|
const char xmldata[] = "<?xml version=\"1.0\"?>\n"
|
||||||
|
"<def>\n"
|
||||||
|
"<function name=\"foo\">\n"
|
||||||
|
" <arg nr=\"1\"></arg>\n"
|
||||||
|
" <arg nr=\"variadic\"><not-uninit/></arg>\n"
|
||||||
|
"</function>\n"
|
||||||
|
"</def>";
|
||||||
|
|
||||||
|
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 {
|
void function_arg_valid() const {
|
||||||
const char xmldata[] = "<?xml version=\"1.0\"?>\n"
|
const char xmldata[] = "<?xml version=\"1.0\"?>\n"
|
||||||
"<def>\n"
|
"<def>\n"
|
||||||
|
|
Loading…
Reference in New Issue