CheckIo: handle more complex variables

This commit is contained in:
Robert Reif 2013-08-23 05:35:57 +02:00 committed by Daniel Marjamäki
parent 7fc6b1344b
commit 5ce1933687
3 changed files with 52 additions and 26 deletions

View File

@ -736,28 +736,40 @@ void CheckIO::checkWrongPrintfScanfArguments()
} }
} }
// We can currently only check the type of arguments matching these simple patterns: // We currently only support string literals and variables.
// var /// @todo add non-string literals, functions, and generic expressions
// var.var
// var[...]
//
/// @todo add more complex variables, lietrals, functions, and generic expressions
bool CheckIO::getArgumentInfo(const Token * tok, const Variable **var, const Token **typeTok) const bool CheckIO::getArgumentInfo(const Token * tok, const Variable **var, const Token **typeTok) const
{ {
if (tok && (Token::Match(tok->next(), "[,)]") || if (tok) {
Token::Match(tok->next(), ". %var% [,)]") || if (tok->type() == Token::eString) {
(Token::simpleMatch(tok->next(), "[") && Token::Match(tok->linkAt(1)->next(), "[,)]")))) { *var = 0;
if (tok->next()->str() == ".") *typeTok = 0;
tok = tok->tokAt(2); return true;
} else if (tok->type() == Token::eVariable) {
const Token *varTok = 0;
for (const Token *tok1 = tok->next(); tok1; tok1 = tok1->next()) {
if (tok1->str() == "," || tok1->str() == ")") {
if (tok1->previous()->str() == "]")
varTok = tok1->linkAt(-1)->previous();
else
varTok = tok1->previous();
break;
} else if (tok1->str() == "(" || tok1->str() == "{" || tok1->str() == "[")
tok1 = tok1->link();
else if (tok1->str() == "<" && tok1->link())
tok1 = tok1->link();
else if (tok1->str() == ";")
break;
}
const Variable *variableInfo = tok->variable(); if (varTok) {
const Token *varTypeTok = variableInfo ? variableInfo->typeStartToken() : NULL; const Variable *variableInfo = varTok->variable();
*var = variableInfo;
*var = variableInfo; *typeTok = variableInfo ? variableInfo->typeStartToken() : NULL;;
*typeTok = varTypeTok; return true;
}
return true; }
} }
return false; return false;

View File

@ -9513,12 +9513,14 @@ void Tokenizer::createSymbolDatabase()
// Since it doesn't point at a fixed location it doesn't have varid // Since it doesn't point at a fixed location it doesn't have varid
if (tok->variable() != NULL && if (tok->variable() != NULL &&
tok->variable()->typeScope() && tok->variable()->typeScope() &&
Token::Match(tok, "%var% [")) { Token::Match(tok, "%var% [|.")) {
// Locate "]"
Token *tok2 = tok->next(); Token *tok2 = tok->next();
while (tok2 && tok2->str() == "[") // Locate "]"
tok2 = tok2->link()->next(); if (tok->next()->str() == "[") {
while (tok2 && tok2->str() == "[")
tok2 = tok2->link()->next();
}
Token *membertok = NULL; Token *membertok = NULL;
if (Token::Match(tok2, ". %var%")) if (Token::Match(tok2, ". %var%"))

View File

@ -796,14 +796,26 @@ private:
check("class Foo {\n" check("class Foo {\n"
" double d;\n" " double d;\n"
" struct Bar {\n"
" int i;\n"
" } bar[2];\n"
" struct Baz {\n"
" int i;\n"
" } baz;\n"
"};\n" "};\n"
"int a[10];\n" "int a[10];\n"
"Foo f[10];\n"
"void foo(const Foo* foo) {\n" "void foo(const Foo* foo) {\n"
" printf(\"%d\", foo->d);\n" " printf(\"%d %f %f %d %f %f\",\n"
" printf(\"%f\", a[0]);\n" " foo->d, foo->bar[0].i, a[0],\n"
" f[0].d, f[0].baz.i, f[0].bar[0].i);\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:6]: (warning) %d in format string (no. 1) requires a signed integer given in the argument list.\n" ASSERT_EQUALS("[test.cpp:13]: (warning) %d in format string (no. 1) requires a signed integer given in the argument list.\n"
"[test.cpp:7]: (warning) %f in format string (no. 1) requires a floating point number given in the argument list.\n", errout.str()); "[test.cpp:13]: (warning) %f in format string (no. 2) requires a floating point number given in the argument list.\n"
"[test.cpp:13]: (warning) %f in format string (no. 3) requires a floating point number given in the argument list.\n"
"[test.cpp:13]: (warning) %d in format string (no. 4) requires a signed integer given in the argument list.\n"
"[test.cpp:13]: (warning) %f in format string (no. 5) requires a floating point number given in the argument list.\n"
"[test.cpp:13]: (warning) %f in format string (no. 6) requires a floating point number given in the argument list.\n", errout.str());
} }
void testPosixPrintfScanfParameterPosition() { // #4900 - No support for parameters in format strings void testPosixPrintfScanfParameterPosition() { // #4900 - No support for parameters in format strings