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:
|
||||
// var
|
||||
// var.var
|
||||
// var[...]
|
||||
//
|
||||
/// @todo add more complex variables, lietrals, functions, and generic expressions
|
||||
// We currently only support string literals and variables.
|
||||
/// @todo add non-string literals, functions, and generic expressions
|
||||
|
||||
bool CheckIO::getArgumentInfo(const Token * tok, const Variable **var, const Token **typeTok) const
|
||||
{
|
||||
if (tok && (Token::Match(tok->next(), "[,)]") ||
|
||||
Token::Match(tok->next(), ". %var% [,)]") ||
|
||||
(Token::simpleMatch(tok->next(), "[") && Token::Match(tok->linkAt(1)->next(), "[,)]")))) {
|
||||
if (tok->next()->str() == ".")
|
||||
tok = tok->tokAt(2);
|
||||
if (tok) {
|
||||
if (tok->type() == Token::eString) {
|
||||
*var = 0;
|
||||
*typeTok = 0;
|
||||
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();
|
||||
const Token *varTypeTok = variableInfo ? variableInfo->typeStartToken() : NULL;
|
||||
|
||||
*var = variableInfo;
|
||||
*typeTok = varTypeTok;
|
||||
|
||||
return true;
|
||||
if (varTok) {
|
||||
const Variable *variableInfo = varTok->variable();
|
||||
*var = variableInfo;
|
||||
*typeTok = variableInfo ? variableInfo->typeStartToken() : NULL;;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -9513,12 +9513,14 @@ void Tokenizer::createSymbolDatabase()
|
|||
// Since it doesn't point at a fixed location it doesn't have varid
|
||||
if (tok->variable() != NULL &&
|
||||
tok->variable()->typeScope() &&
|
||||
Token::Match(tok, "%var% [")) {
|
||||
Token::Match(tok, "%var% [|.")) {
|
||||
|
||||
// Locate "]"
|
||||
Token *tok2 = tok->next();
|
||||
while (tok2 && tok2->str() == "[")
|
||||
tok2 = tok2->link()->next();
|
||||
// Locate "]"
|
||||
if (tok->next()->str() == "[") {
|
||||
while (tok2 && tok2->str() == "[")
|
||||
tok2 = tok2->link()->next();
|
||||
}
|
||||
|
||||
Token *membertok = NULL;
|
||||
if (Token::Match(tok2, ". %var%"))
|
||||
|
|
|
@ -796,14 +796,26 @@ private:
|
|||
|
||||
check("class Foo {\n"
|
||||
" double d;\n"
|
||||
" struct Bar {\n"
|
||||
" int i;\n"
|
||||
" } bar[2];\n"
|
||||
" struct Baz {\n"
|
||||
" int i;\n"
|
||||
" } baz;\n"
|
||||
"};\n"
|
||||
"int a[10];\n"
|
||||
"Foo f[10];\n"
|
||||
"void foo(const Foo* foo) {\n"
|
||||
" printf(\"%d\", foo->d);\n"
|
||||
" printf(\"%f\", a[0]);\n"
|
||||
" printf(\"%d %f %f %d %f %f\",\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"
|
||||
"[test.cpp:7]: (warning) %f in format string (no. 1) requires a floating point number given in the argument list.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:13]: (warning) %d in format string (no. 1) requires a signed integer given in the argument list.\n"
|
||||
"[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
|
||||
|
|
Loading…
Reference in New Issue