CheckUninitVar: Use function information from library, bailout for '?'

This commit is contained in:
PKEuS 2015-01-21 22:02:25 +01:00
parent 26fa994f14
commit 94c3c45350
2 changed files with 19 additions and 8 deletions

View File

@ -1437,6 +1437,11 @@ bool CheckUninitVar::checkScopeForVariable(const Scope* scope, const Token *tok,
return true;
}
// bailout on ternary operator. TODO: This can be solved much better. For example, if the variable is not accessed in the branches of the ternary operator, we could just continue.
if (Token::Match(tok, "?")) {
return true;
}
if (Token::Match(tok, "return|break|continue|throw|goto")) {
if (noreturn)
*noreturn = true;
@ -1729,16 +1734,16 @@ bool CheckUninitVar::isVariableUsage(const Token *vartok, bool pointer, bool all
if (arg) {
const bool address(vartok->previous()->str() == "&");
const Token *argStart = arg->typeStartToken();
while (argStart->previous() && argStart->previous()->isName())
argStart = argStart->previous();
if (!address && Token::Match(argStart, "const| struct| %type% [,)]"))
if (!address && Token::Match(argStart, "struct| %type% [,)]"))
return true;
if (!address && Token::Match(argStart, "const| struct| %type% %var% [,)]"))
return true;
if (Token::Match(argStart, "const %type% & %var% [,)]"))
if (!address && Token::Match(argStart, "struct| %type% %var% [,)]"))
return true;
if (pointer && !address && !alloc && Token::Match(argStart, "struct| %type% * %var% [,)]"))
return true;
while (argStart->previous() && argStart->previous()->isName())
argStart = argStart->previous();
if (Token::Match(argStart, "const %type% & %var% [,)]"))
return true;
if ((pointer || address) && !alloc && Token::Match(argStart, "const struct| %type% * %var% [,)]"))
return true;
if ((pointer || address) && Token::Match(argStart, "const %type% %var% [") && Token::Match(argStart->linkAt(3), "] [,)]"))
@ -1748,6 +1753,12 @@ bool CheckUninitVar::isVariableUsage(const Token *vartok, bool pointer, bool all
} else if (Token::Match(start->previous(), "if|while|for")) {
// control-flow statement reading the variable "by value"
return !alloc;
} else {
bool isnullbad = _settings->library.isnullargbad(start->previous(), argumentNumber + 1);
bool isuninitbad = _settings->library.isuninitargbad(start->previous(), argumentNumber + 1);
if (alloc)
return isnullbad && isuninitbad;
return isuninitbad;
}
}
}

View File

@ -3832,7 +3832,7 @@ private:
" FILE *f;\n"
" fgets (s, n, f);\n"
"}");
TODO_ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: f\n","", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: f\n",errout.str());
checkUninitVarB("void f(char * s, int n, FILE *f) {\n"
" fgets (s, n, f);\n"
@ -3993,7 +3993,7 @@ private:
" int nbytes;\n"
" write(STDOUT_FILENO, buf, nbytes);\n"
"}");
TODO_ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: nbytes\n", "", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: nbytes\n", errout.str());
checkUninitVarB("void no_uninitvar(char *buf, int nbytes)\n"
"{\n"