Fixed #4984 (False positive: (warning) %f in format string (no. 1) requires a floating point number given in the argument list.)
This commit is contained in:
parent
80093f0a40
commit
228f6b1a87
|
@ -558,8 +558,9 @@ void CheckIO::checkWrongPrintfScanfArguments()
|
||||||
const Variable *variableInfo;
|
const Variable *variableInfo;
|
||||||
const Token *varTypeTok;
|
const Token *varTypeTok;
|
||||||
const Function *functionInfo;
|
const Function *functionInfo;
|
||||||
|
bool element;
|
||||||
|
|
||||||
if (getArgumentInfo(argListTok, &variableInfo, &varTypeTok, &functionInfo)) {
|
if (getArgumentInfo(argListTok, &variableInfo, &varTypeTok, &functionInfo, element)) {
|
||||||
if (varTypeTok && varTypeTok->str() == "static")
|
if (varTypeTok && varTypeTok->str() == "static")
|
||||||
varTypeTok = varTypeTok->next();
|
varTypeTok = varTypeTok->next();
|
||||||
|
|
||||||
|
@ -664,7 +665,9 @@ void CheckIO::checkWrongPrintfScanfArguments()
|
||||||
(specifier[0] == 'l' && (!varTypeTok->isLong() || varTypeTok->str() != "double")) ||
|
(specifier[0] == 'l' && (!varTypeTok->isLong() || varTypeTok->str() != "double")) ||
|
||||||
(specifier[0] != 'l' && varTypeTok->isLong())))
|
(specifier[0] != 'l' && varTypeTok->isLong())))
|
||||||
invalidPrintfArgTypeError_float(tok, numFormat, specifier);
|
invalidPrintfArgTypeError_float(tok, numFormat, specifier);
|
||||||
else if (variableInfo && varTypeTok && ((isKnownType(variableInfo, varTypeTok) && !Token::Match(varTypeTok, "float|double")) || variableInfo->isPointer() || variableInfo->isArray()))
|
else if (variableInfo && varTypeTok && ((isKnownType(variableInfo, varTypeTok) && !Token::Match(varTypeTok, "float|double")) ||
|
||||||
|
(!element && variableInfo->isArrayOrPointer()) ||
|
||||||
|
(element && !variableInfo->isArrayOrPointer())))
|
||||||
invalidPrintfArgTypeError_float(tok, numFormat, specifier);
|
invalidPrintfArgTypeError_float(tok, numFormat, specifier);
|
||||||
else if (argListTok->type() == Token::eString)
|
else if (argListTok->type() == Token::eString)
|
||||||
invalidPrintfArgTypeError_float(tok, numFormat, specifier);
|
invalidPrintfArgTypeError_float(tok, numFormat, specifier);
|
||||||
|
@ -760,13 +763,14 @@ void CheckIO::checkWrongPrintfScanfArguments()
|
||||||
// We currently only support string literals, variables, and functions.
|
// We currently only support string literals, variables, and functions.
|
||||||
/// @todo add non-string literals, and generic expressions
|
/// @todo add non-string literals, and generic expressions
|
||||||
|
|
||||||
bool CheckIO::getArgumentInfo(const Token * tok, const Variable **var, const Token **typeTok, const Function **func) const
|
bool CheckIO::getArgumentInfo(const Token * tok, const Variable **var, const Token **typeTok, const Function **func, bool &element) const
|
||||||
{
|
{
|
||||||
if (tok) {
|
if (tok) {
|
||||||
if (tok->type() == Token::eString) {
|
if (tok->type() == Token::eString) {
|
||||||
*var = 0;
|
*var = 0;
|
||||||
*typeTok = 0;
|
*typeTok = 0;
|
||||||
*func = 0;
|
*func = 0;
|
||||||
|
element = false;
|
||||||
return true;
|
return true;
|
||||||
} else if (tok->type() == Token::eVariable || tok->type() == Token::eFunction || Token::Match(tok, "%type% ::")) {
|
} else if (tok->type() == Token::eVariable || tok->type() == Token::eFunction || Token::Match(tok, "%type% ::")) {
|
||||||
while (Token::Match(tok, "%type% ::"))
|
while (Token::Match(tok, "%type% ::"))
|
||||||
|
@ -774,7 +778,8 @@ bool CheckIO::getArgumentInfo(const Token * tok, const Variable **var, const Tok
|
||||||
if (!tok || !(tok->type() == Token::eVariable || tok->type() == Token::eFunction))
|
if (!tok || !(tok->type() == Token::eVariable || tok->type() == Token::eFunction))
|
||||||
return false;
|
return false;
|
||||||
const Token *varTok = 0;
|
const Token *varTok = 0;
|
||||||
for (const Token *tok1 = tok->next(); tok1; tok1 = tok1->next()) {
|
const Token *tok1 = tok->next();
|
||||||
|
for (; tok1; tok1 = tok1->next()) {
|
||||||
if (tok1->str() == "," || tok1->str() == ")") {
|
if (tok1->str() == "," || tok1->str() == ")") {
|
||||||
if (tok1->previous()->str() == "]")
|
if (tok1->previous()->str() == "]")
|
||||||
varTok = tok1->linkAt(-1)->previous();
|
varTok = tok1->linkAt(-1)->previous();
|
||||||
|
@ -784,6 +789,7 @@ bool CheckIO::getArgumentInfo(const Token * tok, const Variable **var, const Tok
|
||||||
*var = 0;
|
*var = 0;
|
||||||
*typeTok = function->retDef;
|
*typeTok = function->retDef;
|
||||||
*func = function;
|
*func = function;
|
||||||
|
element = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
|
@ -802,6 +808,7 @@ bool CheckIO::getArgumentInfo(const Token * tok, const Variable **var, const Tok
|
||||||
*var = variableInfo;
|
*var = variableInfo;
|
||||||
*typeTok = variableInfo ? variableInfo->typeStartToken() : NULL;
|
*typeTok = variableInfo ? variableInfo->typeStartToken() : NULL;
|
||||||
*func = 0;
|
*func = 0;
|
||||||
|
element = tok1->previous()->str() == "]";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ public:
|
||||||
void checkWrongPrintfScanfArguments();
|
void checkWrongPrintfScanfArguments();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool getArgumentInfo(const Token *tok, const Variable **var, const Token **typeTok, const Function **func) const;
|
bool getArgumentInfo(const Token *tok, const Variable **var, const Token **typeTok, const Function **func, bool &element) const;
|
||||||
|
|
||||||
// Reporting errors..
|
// Reporting errors..
|
||||||
void coutCerrMisusageError(const Token* tok, const std::string& streamName);
|
void coutCerrMisusageError(const Token* tok, const std::string& streamName);
|
||||||
|
|
|
@ -334,6 +334,14 @@ public:
|
||||||
return getFlag(fIsPointer);
|
return getFlag(fIsPointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is array or pointer variable.
|
||||||
|
* @return true if pointer or array, false otherwise
|
||||||
|
*/
|
||||||
|
bool isArrayOrPointer() const {
|
||||||
|
return getFlag(fIsArray) || getFlag(fIsPointer);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is reference variable.
|
* Is reference variable.
|
||||||
* @return true if reference, false otherwise
|
* @return true if reference, false otherwise
|
||||||
|
|
|
@ -1015,6 +1015,12 @@ private:
|
||||||
"void foo() { printf(\"%d %ld %u %lu %f %lf\", bar().i, bar().i, bar().i, bar().i, bar().i, bar().i); }");
|
"void foo() { printf(\"%d %ld %u %lu %f %lf\", bar().i, bar().i, bar().i, bar().i, bar().i, bar().i); }");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
// #4984
|
||||||
|
check("void f(double *x) {\n"
|
||||||
|
" printf(\"%f\", x[0]);\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void testPosixPrintfScanfParameterPosition() { // #4900 - No support for parameters in format strings
|
void testPosixPrintfScanfParameterPosition() { // #4900 - No support for parameters in format strings
|
||||||
|
|
Loading…
Reference in New Issue