diff --git a/lib/checkio.cpp b/lib/checkio.cpp index 50d74bf99..daec23332 100644 --- a/lib/checkio.cpp +++ b/lib/checkio.cpp @@ -558,8 +558,9 @@ void CheckIO::checkWrongPrintfScanfArguments() const Variable *variableInfo; const Token *varTypeTok; const Function *functionInfo; + bool element; - if (getArgumentInfo(argListTok, &variableInfo, &varTypeTok, &functionInfo)) { + if (getArgumentInfo(argListTok, &variableInfo, &varTypeTok, &functionInfo, element)) { if (varTypeTok && varTypeTok->str() == "static") varTypeTok = varTypeTok->next(); @@ -664,7 +665,9 @@ void CheckIO::checkWrongPrintfScanfArguments() (specifier[0] == 'l' && (!varTypeTok->isLong() || varTypeTok->str() != "double")) || (specifier[0] != 'l' && varTypeTok->isLong()))) 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); else if (argListTok->type() == Token::eString) invalidPrintfArgTypeError_float(tok, numFormat, specifier); @@ -760,13 +763,14 @@ void CheckIO::checkWrongPrintfScanfArguments() // We currently only support string literals, variables, and functions. /// @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->type() == Token::eString) { *var = 0; *typeTok = 0; *func = 0; + element = false; return true; } else if (tok->type() == Token::eVariable || tok->type() == Token::eFunction || 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)) return false; 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->previous()->str() == "]") varTok = tok1->linkAt(-1)->previous(); @@ -784,6 +789,7 @@ bool CheckIO::getArgumentInfo(const Token * tok, const Variable **var, const Tok *var = 0; *typeTok = function->retDef; *func = function; + element = false; return true; } } else @@ -802,6 +808,7 @@ bool CheckIO::getArgumentInfo(const Token * tok, const Variable **var, const Tok *var = variableInfo; *typeTok = variableInfo ? variableInfo->typeStartToken() : NULL; *func = 0; + element = tok1->previous()->str() == "]"; return true; } } diff --git a/lib/checkio.h b/lib/checkio.h index 328a5464f..fe4c04742 100644 --- a/lib/checkio.h +++ b/lib/checkio.h @@ -70,7 +70,7 @@ public: void checkWrongPrintfScanfArguments(); 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.. void coutCerrMisusageError(const Token* tok, const std::string& streamName); diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index 4bf236910..f1200849a 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -334,6 +334,14 @@ public: 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. * @return true if reference, false otherwise diff --git a/test/testio.cpp b/test/testio.cpp index d28945a37..e953a0916 100644 --- a/test/testio.cpp +++ b/test/testio.cpp @@ -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); }"); 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