Uninitialized variables: Fixed false positives caused by recent commit when potentially uninitialized variable is read in condition

This commit is contained in:
Daniel Marjamäki 2011-12-26 18:32:42 +01:00
parent 481fa532a8
commit 59cd099ba7
3 changed files with 54 additions and 13 deletions

View File

@ -1113,17 +1113,9 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const unsigned int
// Inner scope.. // Inner scope..
if (Token::Match(tok, "if (")) { if (Token::Match(tok, "if (")) {
// initialization in condition.. // initialization / usage in condition..
const Token * const endToken = tok->next()->link(); if (checkIfForWhileHead(tok->next(), varid, ispointer, suppressErrors))
for (const Token *tok2 = tok->tokAt(2); tok2 != endToken; tok2 = tok2->next()) { return true;
if (tok2->varId() == varid) {
if (!suppressErrors && isVariableUsage(tok2, ispointer))
uninitvarError(tok2, tok2->str());
return true;
}
if (Token::Match(tok2, "sizeof|decltype|offsetof ("))
tok2 = tok2->next()->link();
}
// goto the { // goto the {
tok = tok->next()->link()->next(); tok = tok->next()->link()->next();
@ -1180,8 +1172,25 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const unsigned int
if (Token::Match(tok, "sizeof|offsetof|decltype (")) if (Token::Match(tok, "sizeof|offsetof|decltype ("))
tok = tok->next()->link(); tok = tok->next()->link();
// for..
if (Token::simpleMatch(tok, "for (")) {
// goto the {
const Token *tok2 = tok->next()->link()->next();
bool possibleinit = true;
bool init = checkScopeForVariable(tok2->next(), varid, ispointer, &possibleinit);
// variable is initialized in the loop..
if (possibleinit || init)
return true;
// is variable used / initialized in for-head
if (checkIfForWhileHead(tok->next(), varid, ispointer, suppressErrors))
return true;
}
// TODO: handle loops, try, etc // TODO: handle loops, try, etc
if (tok->str() == "for" || Token::simpleMatch(tok, ") {") || Token::Match(tok, "%var% {")) { if (Token::simpleMatch(tok, ") {") || Token::Match(tok, "%var% {")) {
return true; return true;
} }
@ -1210,6 +1219,23 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const unsigned int
return ret; return ret;
} }
bool CheckUninitVar::checkIfForWhileHead(const Token *startparanthesis, unsigned int varid, bool ispointer, bool suppressErrors)
{
const Token * const endpar = startparanthesis->link();
for (const Token *tok = startparanthesis->next(); tok && tok != endpar; tok = tok->next()) {
if (tok->varId() == varid) {
if (!suppressErrors && isVariableUsage(tok, ispointer))
uninitvarError(tok, tok->str());
return true;
}
if (Token::Match(tok, "sizeof|decltype|offsetof ("))
tok = tok->next()->link();
if (tok->str() == "&&")
suppressErrors = true;
}
return false;
}
bool CheckUninitVar::isVariableUsage(const Token *vartok, bool pointer) const bool CheckUninitVar::isVariableUsage(const Token *vartok, bool pointer) const
{ {
if (vartok->previous()->str() == "return") if (vartok->previous()->str() == "return")

View File

@ -61,8 +61,10 @@ public:
/** Check for uninitialized variables */ /** Check for uninitialized variables */
void check(); void check();
bool checkScopeForVariable(const Token *tok, const unsigned int varid, bool ispointer, bool * const possibleInit); bool checkScopeForVariable(const Token *tok, const unsigned int varid, bool ispointer, bool * const possibleInit);
bool checkIfForWhileHead(const Token *startparanthesis, unsigned int varid, bool ispointer, bool suppressErrors);
bool isVariableUsage(const Token *vartok, bool ispointer) const; bool isVariableUsage(const Token *vartok, bool ispointer) const;
/** /**
* @brief Uninitialized variables: analyse functions to see how they work with uninitialized variables * @brief Uninitialized variables: analyse functions to see how they work with uninitialized variables
* @param tokens [in] the token list * @param tokens [in] the token list

View File

@ -1863,7 +1863,7 @@ private:
" for (int i = 0; i < 10; i += x) {\n" " for (int i = 0; i < 10; i += x) {\n"
" }\n" " }\n"
"}\n"); "}\n");
TODO_ASSERT_EQUALS("error", "", errout.str()); ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: x\n", errout.str());
// try // try
checkUninitVar2("void f() {\n" checkUninitVar2("void f() {\n"
@ -1917,6 +1917,19 @@ private:
"}\n"); "}\n");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
checkUninitVar2("static void f(int x, int y) {\n"
" int a;\n"
" if (x == 0) { a = y; }\n"
" if (x == 0 && (a == 1)) { }\n"
"}\n");
ASSERT_EQUALS("", errout.str());
checkUninitVar2("static void f(int x, int y) {\n"
" int a;\n"
" if (x == 0 && (a == 1)) { }\n"
"}\n");
TODO_ASSERT_EQUALS("error", "", errout.str());
// asm // asm
checkUninitVar2("void f() {\n" checkUninitVar2("void f() {\n"
" int x;\n" " int x;\n"