Uninitialized variables: Fixed false positives caused by recent commit when potentially uninitialized variable is read in condition
This commit is contained in:
parent
481fa532a8
commit
59cd099ba7
|
@ -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")
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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"
|
||||||
|
|
Loading…
Reference in New Issue