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:
Robert Reif 2013-08-27 05:46:09 +02:00 committed by Daniel Marjamäki
parent 80093f0a40
commit 228f6b1a87
4 changed files with 26 additions and 5 deletions

View File

@ -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;
} }
} }

View File

@ -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);

View File

@ -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

View File

@ -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