Library configuration: Enable configuring the direction of arguments. (#1717)
This enhances the library configuration so the direction of function arguments can be specified (in, out, inout). isVariableChangedByFunctionCall() uses this information now to avoid guessing.
This commit is contained in:
parent
aa4265978c
commit
9a5fcddb5d
|
@ -163,6 +163,11 @@
|
|||
<text/>
|
||||
</attribute>
|
||||
</optional>
|
||||
<optional>
|
||||
<attribute name="direction">
|
||||
<ref name="ARG-DIRECTION"/>
|
||||
</attribute>
|
||||
</optional>
|
||||
|
||||
<interleave>
|
||||
<optional>
|
||||
|
@ -425,6 +430,14 @@
|
|||
<param name="maxInclusive">20</param>
|
||||
</data>
|
||||
</define>
|
||||
|
||||
<define name="ARG-DIRECTION">
|
||||
<choice>
|
||||
<value>in</value>
|
||||
<value>out</value>
|
||||
<value>inout</value>
|
||||
</choice>
|
||||
</define>
|
||||
|
||||
<define name="DATA-BOOL">
|
||||
<choice>
|
||||
|
|
16
cfg/std.cfg
16
cfg/std.cfg
|
@ -52,7 +52,7 @@
|
|||
<returnValue type="int">arg1>0?arg1:-arg1</returnValue>
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<arg nr="1" direction="in">
|
||||
<not-uninit/>
|
||||
<not-bool/>
|
||||
</arg>
|
||||
|
@ -448,10 +448,10 @@
|
|||
<returnValue type="size_t"/>
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<arg nr="1" direction="out">
|
||||
<not-null/>
|
||||
</arg>
|
||||
<arg nr="2">
|
||||
<arg nr="2" direction="in">
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<arg nr="3">
|
||||
|
@ -4115,7 +4115,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
|
|||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<formatstr/>
|
||||
<arg nr="1">
|
||||
<arg nr="1" direction="in">
|
||||
<formatstr/>
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
|
@ -4505,12 +4505,12 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
|
|||
<returnValue type="char *"/>
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<arg nr="1" direction="inout">
|
||||
<not-null/>
|
||||
<not-uninit/>
|
||||
<strz/>
|
||||
</arg>
|
||||
<arg nr="2">
|
||||
<arg nr="2" direction="in">
|
||||
<not-null/>
|
||||
<not-uninit/>
|
||||
<strz/>
|
||||
|
@ -5734,12 +5734,12 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
|
|||
<returnValue type="int"/>
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<arg nr="1" direction="out">
|
||||
<not-uninit/>
|
||||
<minsize type="strlen" arg="2"/>
|
||||
</arg>
|
||||
<formatstr/>
|
||||
<arg nr="2">
|
||||
<arg nr="2" direction="in">
|
||||
<formatstr/>
|
||||
<not-null/>
|
||||
<not-uninit/>
|
||||
|
|
|
@ -880,6 +880,16 @@ bool isVariableChangedByFunctionCall(const Token *tok, const Settings *settings,
|
|||
}
|
||||
|
||||
if (!tok->function()) {
|
||||
// Check if direction (in, out, inout) is specified in the library configuration and use that
|
||||
if (!addressOf && settings) {
|
||||
const Library::ArgumentChecks::Direction argDirection = settings->library.getArgDirection(tok, 1 + argnr);
|
||||
if (argDirection == Library::ArgumentChecks::Direction::DIR_IN)
|
||||
return false;
|
||||
else if (argDirection == Library::ArgumentChecks::Direction::DIR_OUT ||
|
||||
argDirection == Library::ArgumentChecks::Direction::DIR_INOUT)
|
||||
return true;
|
||||
}
|
||||
|
||||
// if the library says 0 is invalid
|
||||
// => it is assumed that parameter is an in parameter (TODO: this is a bad heuristic)
|
||||
if (!addressOf && settings && settings->library.isnullargbad(tok, 1+argnr))
|
||||
|
|
|
@ -581,6 +581,17 @@ Library::Error Library::loadFunction(const tinyxml2::XMLElement * const node, co
|
|||
ArgumentChecks &ac = func.argumentChecks[nr];
|
||||
ac.optional = functionnode->Attribute("default") != nullptr;
|
||||
ac.variadic = bVariadicArg;
|
||||
const char * const argDirection = functionnode->Attribute("direction");
|
||||
if (argDirection) {
|
||||
const size_t argDirLen = strlen(argDirection);
|
||||
if (!strncmp(argDirection, "in", argDirLen)) {
|
||||
ac.direction = ArgumentChecks::Direction::DIR_IN;
|
||||
} else if (!strncmp(argDirection, "out", argDirLen)) {
|
||||
ac.direction = ArgumentChecks::Direction::DIR_OUT;
|
||||
} else if (!strncmp(argDirection, "inout", argDirLen)) {
|
||||
ac.direction = ArgumentChecks::Direction::DIR_INOUT;
|
||||
}
|
||||
}
|
||||
for (const tinyxml2::XMLElement *argnode = functionnode->FirstChildElement(); argnode; argnode = argnode->NextSiblingElement()) {
|
||||
const std::string argnodename = argnode->Name();
|
||||
if (argnodename == "not-bool")
|
||||
|
|
|
@ -227,7 +227,8 @@ public:
|
|||
strz(false),
|
||||
optional(false),
|
||||
variadic(false),
|
||||
iteratorInfo() {
|
||||
iteratorInfo(),
|
||||
direction(DIR_UNKNOWN) {
|
||||
}
|
||||
|
||||
bool notbool;
|
||||
|
@ -259,6 +260,9 @@ public:
|
|||
int arg2;
|
||||
};
|
||||
std::vector<MinSize> minsizes;
|
||||
|
||||
enum Direction { DIR_IN, DIR_OUT, DIR_INOUT, DIR_UNKNOWN };
|
||||
Direction direction;
|
||||
};
|
||||
|
||||
|
||||
|
@ -320,6 +324,11 @@ public:
|
|||
return arg ? &arg->minsizes : nullptr;
|
||||
}
|
||||
|
||||
ArgumentChecks::Direction getArgDirection(const Token *ftok, int argnr) const {
|
||||
const ArgumentChecks *arg = getarg(ftok, argnr);
|
||||
return arg ? arg->direction : ArgumentChecks::Direction::DIR_UNKNOWN;
|
||||
}
|
||||
|
||||
bool markupFile(const std::string &path) const;
|
||||
|
||||
bool processMarkupAfterCode(const std::string &path) const;
|
||||
|
|
Loading…
Reference in New Issue