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/>
|
<text/>
|
||||||
</attribute>
|
</attribute>
|
||||||
</optional>
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<attribute name="direction">
|
||||||
|
<ref name="ARG-DIRECTION"/>
|
||||||
|
</attribute>
|
||||||
|
</optional>
|
||||||
|
|
||||||
<interleave>
|
<interleave>
|
||||||
<optional>
|
<optional>
|
||||||
|
@ -425,6 +430,14 @@
|
||||||
<param name="maxInclusive">20</param>
|
<param name="maxInclusive">20</param>
|
||||||
</data>
|
</data>
|
||||||
</define>
|
</define>
|
||||||
|
|
||||||
|
<define name="ARG-DIRECTION">
|
||||||
|
<choice>
|
||||||
|
<value>in</value>
|
||||||
|
<value>out</value>
|
||||||
|
<value>inout</value>
|
||||||
|
</choice>
|
||||||
|
</define>
|
||||||
|
|
||||||
<define name="DATA-BOOL">
|
<define name="DATA-BOOL">
|
||||||
<choice>
|
<choice>
|
||||||
|
|
16
cfg/std.cfg
16
cfg/std.cfg
|
@ -52,7 +52,7 @@
|
||||||
<returnValue type="int">arg1>0?arg1:-arg1</returnValue>
|
<returnValue type="int">arg1>0?arg1:-arg1</returnValue>
|
||||||
<noreturn>false</noreturn>
|
<noreturn>false</noreturn>
|
||||||
<leak-ignore/>
|
<leak-ignore/>
|
||||||
<arg nr="1">
|
<arg nr="1" direction="in">
|
||||||
<not-uninit/>
|
<not-uninit/>
|
||||||
<not-bool/>
|
<not-bool/>
|
||||||
</arg>
|
</arg>
|
||||||
|
@ -448,10 +448,10 @@
|
||||||
<returnValue type="size_t"/>
|
<returnValue type="size_t"/>
|
||||||
<noreturn>false</noreturn>
|
<noreturn>false</noreturn>
|
||||||
<leak-ignore/>
|
<leak-ignore/>
|
||||||
<arg nr="1">
|
<arg nr="1" direction="out">
|
||||||
<not-null/>
|
<not-null/>
|
||||||
</arg>
|
</arg>
|
||||||
<arg nr="2">
|
<arg nr="2" direction="in">
|
||||||
<not-uninit/>
|
<not-uninit/>
|
||||||
</arg>
|
</arg>
|
||||||
<arg nr="3">
|
<arg nr="3">
|
||||||
|
@ -4115,7 +4115,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
|
||||||
<noreturn>false</noreturn>
|
<noreturn>false</noreturn>
|
||||||
<leak-ignore/>
|
<leak-ignore/>
|
||||||
<formatstr/>
|
<formatstr/>
|
||||||
<arg nr="1">
|
<arg nr="1" direction="in">
|
||||||
<formatstr/>
|
<formatstr/>
|
||||||
<not-uninit/>
|
<not-uninit/>
|
||||||
</arg>
|
</arg>
|
||||||
|
@ -4505,12 +4505,12 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
|
||||||
<returnValue type="char *"/>
|
<returnValue type="char *"/>
|
||||||
<noreturn>false</noreturn>
|
<noreturn>false</noreturn>
|
||||||
<leak-ignore/>
|
<leak-ignore/>
|
||||||
<arg nr="1">
|
<arg nr="1" direction="inout">
|
||||||
<not-null/>
|
<not-null/>
|
||||||
<not-uninit/>
|
<not-uninit/>
|
||||||
<strz/>
|
<strz/>
|
||||||
</arg>
|
</arg>
|
||||||
<arg nr="2">
|
<arg nr="2" direction="in">
|
||||||
<not-null/>
|
<not-null/>
|
||||||
<not-uninit/>
|
<not-uninit/>
|
||||||
<strz/>
|
<strz/>
|
||||||
|
@ -5734,12 +5734,12 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
|
||||||
<returnValue type="int"/>
|
<returnValue type="int"/>
|
||||||
<noreturn>false</noreturn>
|
<noreturn>false</noreturn>
|
||||||
<leak-ignore/>
|
<leak-ignore/>
|
||||||
<arg nr="1">
|
<arg nr="1" direction="out">
|
||||||
<not-uninit/>
|
<not-uninit/>
|
||||||
<minsize type="strlen" arg="2"/>
|
<minsize type="strlen" arg="2"/>
|
||||||
</arg>
|
</arg>
|
||||||
<formatstr/>
|
<formatstr/>
|
||||||
<arg nr="2">
|
<arg nr="2" direction="in">
|
||||||
<formatstr/>
|
<formatstr/>
|
||||||
<not-null/>
|
<not-null/>
|
||||||
<not-uninit/>
|
<not-uninit/>
|
||||||
|
|
|
@ -880,6 +880,16 @@ bool isVariableChangedByFunctionCall(const Token *tok, const Settings *settings,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tok->function()) {
|
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
|
// if the library says 0 is invalid
|
||||||
// => it is assumed that parameter is an in parameter (TODO: this is a bad heuristic)
|
// => it is assumed that parameter is an in parameter (TODO: this is a bad heuristic)
|
||||||
if (!addressOf && settings && settings->library.isnullargbad(tok, 1+argnr))
|
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];
|
ArgumentChecks &ac = func.argumentChecks[nr];
|
||||||
ac.optional = functionnode->Attribute("default") != nullptr;
|
ac.optional = functionnode->Attribute("default") != nullptr;
|
||||||
ac.variadic = bVariadicArg;
|
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()) {
|
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")
|
||||||
|
|
|
@ -227,7 +227,8 @@ public:
|
||||||
strz(false),
|
strz(false),
|
||||||
optional(false),
|
optional(false),
|
||||||
variadic(false),
|
variadic(false),
|
||||||
iteratorInfo() {
|
iteratorInfo(),
|
||||||
|
direction(DIR_UNKNOWN) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool notbool;
|
bool notbool;
|
||||||
|
@ -259,6 +260,9 @@ public:
|
||||||
int arg2;
|
int arg2;
|
||||||
};
|
};
|
||||||
std::vector<MinSize> minsizes;
|
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;
|
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 markupFile(const std::string &path) const;
|
||||||
|
|
||||||
bool processMarkupAfterCode(const std::string &path) const;
|
bool processMarkupAfterCode(const std::string &path) const;
|
||||||
|
|
Loading…
Reference in New Issue