diff --git a/lib/checkio.cpp b/lib/checkio.cpp index 06e249e9a..a71f2c5fe 100644 --- a/lib/checkio.cpp +++ b/lib/checkio.cpp @@ -647,7 +647,7 @@ void CheckIO::checkWrongPrintfScanfArguments() case 'p': if (functionInfo && varTypeTok && varTypeTok->type() == Token::eType && varTypeTok->next()->str() != "*") invalidPrintfArgTypeError_p(tok, numFormat); - else if (variableInfo && varTypeTok && isKnownType(variableInfo, varTypeTok) && !Token::Match(varTypeTok, "short|long|int|size_t") && !variableInfo->isPointer() && !variableInfo->isArray()) + else if (variableInfo && varTypeTok && isKnownType(variableInfo, varTypeTok) && !variableInfo->isPointer() && !variableInfo->isArray()) invalidPrintfArgTypeError_p(tok, numFormat); else if (argListTok->type() == Token::eString) invalidPrintfArgTypeError_p(tok, numFormat); @@ -758,7 +758,7 @@ void CheckIO::checkWrongPrintfScanfArguments() } // We currently only support string literals, variables, and functions. -/// @todo add non-string literals, qualification, 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 { @@ -768,7 +768,11 @@ bool CheckIO::getArgumentInfo(const Token * tok, const Variable **var, const Tok *typeTok = 0; *func = 0; return true; - } else if (tok->type() == Token::eVariable || tok->type() == Token::eFunction) { + } else if (tok->type() == Token::eVariable || tok->type() == Token::eFunction || Token::Match(tok, "%type% ::")) { + while (Token::Match(tok, "%type% ::")) + tok = tok->tokAt(2); + 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()) { if (tok1->str() == "," || tok1->str() == ")") { diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index dc0ad513b..878417955 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -427,7 +427,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti tok1 = tok1->next(); if (tok1) - function.retDef = tok1->next(); + function.retDef = tok1; } const Token *end; diff --git a/test/testio.cpp b/test/testio.cpp index a3c57dffd..7261f34cf 100644 --- a/test/testio.cpp +++ b/test/testio.cpp @@ -919,12 +919,35 @@ private: check("namespace bar { int f() { return 0; } }\n" "void foo() { printf(\"%u %lu %f %lf %p\", bar::f(), bar::f(), bar::f(), bar::f(), bar::f()); }"); - TODO_ASSERT_EQUALS("[test.cpp:2]: (warning) %u in format string (no. 1) requires an unsigned integer given in the argument list.\n" - "[test.cpp:2]: (warning) %lu in format string (no. 2) requires an unsigned long integer given in the argument list.\n" - "[test.cpp:2]: (warning) %f in format string (no. 3) requires a floating point number given in the argument list.\n" - "[test.cpp:2]: (warning) %lf in format string (no. 4) requires a floating point number given in the argument list.\n" - "[test.cpp:2]: (warning) %p in format string (no. 5) requires an address given in the argument list.\n", "", errout.str()); + ASSERT_EQUALS("[test.cpp:2]: (warning) %u in format string (no. 1) requires an unsigned integer given in the argument list.\n" + "[test.cpp:2]: (warning) %lu in format string (no. 2) requires an unsigned long integer given in the argument list.\n" + "[test.cpp:2]: (warning) %f in format string (no. 3) requires a floating point number given in the argument list.\n" + "[test.cpp:2]: (warning) %lf in format string (no. 4) requires a floating point number given in the argument list.\n" + "[test.cpp:2]: (warning) %p in format string (no. 5) requires an address given in the argument list.\n", errout.str()); + check("struct Fred { int i; } f;\n" + "void foo() { printf(\"%u %lu %f %lf %p\", f.i, f.i, f.i, f.i, f.i); }"); + ASSERT_EQUALS("[test.cpp:2]: (warning) %u in format string (no. 1) requires an unsigned integer given in the argument list.\n" + "[test.cpp:2]: (warning) %lu in format string (no. 2) requires an unsigned long integer given in the argument list.\n" + "[test.cpp:2]: (warning) %f in format string (no. 3) requires a floating point number given in the argument list.\n" + "[test.cpp:2]: (warning) %lf in format string (no. 4) requires a floating point number given in the argument list.\n" + "[test.cpp:2]: (warning) %p in format string (no. 5) requires an address given in the argument list.\n", errout.str()); + + check("struct Fred { unsigned int u; } f;\n" + "void foo() { printf(\"%d %ld %f %lf %p\", f.u, f.u, f.u, f.u, f.u); }"); + ASSERT_EQUALS("[test.cpp:2]: (warning) %d in format string (no. 1) requires a signed integer given in the argument list.\n" + "[test.cpp:2]: (warning) %ld in format string (no. 2) requires a signed long integer given in the argument list.\n" + "[test.cpp:2]: (warning) %f in format string (no. 3) requires a floating point number given in the argument list.\n" + "[test.cpp:2]: (warning) %lf in format string (no. 4) requires a floating point number given in the argument list.\n" + "[test.cpp:2]: (warning) %p in format string (no. 5) requires an address given in the argument list.\n", errout.str()); + + check("struct Fred { unsigned int ui() { return 0; } } f;\n" + "void foo() { printf(\"%d %ld %f %lf %p\", f.ui(), f.ui(), f.ui(), f.ui(), f.ui()); }"); + ASSERT_EQUALS("[test.cpp:2]: (warning) %d in format string (no. 1) requires a signed integer given in the argument list.\n" + "[test.cpp:2]: (warning) %ld in format string (no. 2) requires a signed long integer given in the argument list.\n" + "[test.cpp:2]: (warning) %f in format string (no. 3) requires a floating point number given in the argument list.\n" + "[test.cpp:2]: (warning) %lf in format string (no. 4) requires a floating point number given in the argument list.\n" + "[test.cpp:2]: (warning) %p in format string (no. 5) requires an address given in the argument list.\n", errout.str()); } void testPosixPrintfScanfParameterPosition() { // #4900 - No support for parameters in format strings