CheckIo: handle more complex variables
This commit is contained in:
parent
7fc6b1344b
commit
5ce1933687
|
@ -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);
|
|
||||||
|
|
||||||
const Variable *variableInfo = tok->variable();
|
|
||||||
const Token *varTypeTok = variableInfo ? variableInfo->typeStartToken() : NULL;
|
|
||||||
|
|
||||||
*var = variableInfo;
|
|
||||||
*typeTok = varTypeTok;
|
|
||||||
|
|
||||||
return true;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (varTok) {
|
||||||
|
const Variable *variableInfo = varTok->variable();
|
||||||
|
*var = variableInfo;
|
||||||
|
*typeTok = variableInfo ? variableInfo->typeStartToken() : NULL;;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -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();
|
||||||
|
// Locate "]"
|
||||||
|
if (tok->next()->str() == "[") {
|
||||||
while (tok2 && tok2->str() == "[")
|
while (tok2 && tok2->str() == "[")
|
||||||
tok2 = tok2->link()->next();
|
tok2 = tok2->link()->next();
|
||||||
|
}
|
||||||
|
|
||||||
Token *membertok = NULL;
|
Token *membertok = NULL;
|
||||||
if (Token::Match(tok2, ". %var%"))
|
if (Token::Match(tok2, ". %var%"))
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue