Uninitialized variables: Improved checking when there are multiple if/else and a certain path causes an error
This commit is contained in:
parent
2d05cae13b
commit
f48edb63a3
|
@ -1058,11 +1058,16 @@ void CheckUninitVar::check()
|
|||
}
|
||||
}
|
||||
|
||||
bool CheckUninitVar::checkScopeForVariable(const Token *tok, const unsigned int varid)
|
||||
bool CheckUninitVar::checkScopeForVariable(const Token *tok, const unsigned int varid, bool * const possibleInit)
|
||||
{
|
||||
if (varid == 0)
|
||||
return false;
|
||||
|
||||
const bool suppressErrors(possibleInit && *possibleInit);
|
||||
|
||||
if (possibleInit)
|
||||
*possibleInit = false;
|
||||
|
||||
bool ret = false;
|
||||
|
||||
unsigned int number_of_if = 0;
|
||||
|
@ -1070,8 +1075,8 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const unsigned int
|
|||
for (; tok; tok = tok->next()) {
|
||||
// End of scope..
|
||||
if (tok->str() == "}") {
|
||||
if (number_of_if)
|
||||
return true;
|
||||
if (number_of_if && possibleInit)
|
||||
*possibleInit = true;
|
||||
|
||||
// might be a noreturn function..
|
||||
if (Token::simpleMatch(tok->tokAt(-2), ") ; }") &&
|
||||
|
@ -1085,15 +1090,11 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const unsigned int
|
|||
|
||||
// Inner scope..
|
||||
if (Token::Match(tok, "if (")) {
|
||||
if (number_of_if) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// initialization in condition..
|
||||
const Token * const endToken = tok->next()->link();
|
||||
for (const Token *tok2 = tok->tokAt(2); tok2 != endToken; tok2 = tok2->next()) {
|
||||
if (tok2->varId() == varid) {
|
||||
if (isVariableUsage(tok2))
|
||||
if (!suppressErrors && isVariableUsage(tok2))
|
||||
uninitvarError(tok2, tok2->str());
|
||||
return true;
|
||||
}
|
||||
|
@ -1104,7 +1105,8 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const unsigned int
|
|||
// goto the {
|
||||
tok = tok->next()->link()->next();
|
||||
|
||||
const bool initif = checkScopeForVariable(tok->next(), varid);
|
||||
bool possibleInitIf(number_of_if > 0);
|
||||
const bool initif = checkScopeForVariable(tok->next(), varid, &possibleInitIf);
|
||||
|
||||
// goto the }
|
||||
tok = tok->link();
|
||||
|
@ -1114,7 +1116,7 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const unsigned int
|
|||
return true; // bail out
|
||||
|
||||
if (!Token::Match(tok, "} else {")) {
|
||||
if (initif) {
|
||||
if (initif || possibleInitIf) {
|
||||
++number_of_if;
|
||||
if (number_of_if >= 2)
|
||||
return true;
|
||||
|
@ -1123,7 +1125,8 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const unsigned int
|
|||
// goto the {
|
||||
tok = tok->tokAt(2);
|
||||
|
||||
const bool initelse = checkScopeForVariable(tok->next(), varid);
|
||||
bool possibleInitElse(number_of_if > 0);
|
||||
const bool initelse = checkScopeForVariable(tok->next(), varid, &possibleInitElse);
|
||||
|
||||
// goto the }
|
||||
tok = tok->link();
|
||||
|
@ -1172,7 +1175,7 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const unsigned int
|
|||
// variable is seen..
|
||||
if (tok->varId() == varid) {
|
||||
// Use variable
|
||||
if (isVariableUsage(tok))
|
||||
if (!suppressErrors && isVariableUsage(tok))
|
||||
uninitvarError(tok, tok->str());
|
||||
|
||||
else
|
||||
|
|
|
@ -60,7 +60,7 @@ public:
|
|||
|
||||
/** Check for uninitialized variables */
|
||||
void check();
|
||||
bool checkScopeForVariable(const Token *tok, const unsigned int varid);
|
||||
bool checkScopeForVariable(const Token *tok, const unsigned int varid, bool * const possibleInit=0);
|
||||
bool isVariableUsage(const Token *vartok) const;
|
||||
|
||||
/**
|
||||
|
|
|
@ -1776,7 +1776,16 @@ private:
|
|||
" else if (y == 2) { x = 1; }\n"
|
||||
" return x;\n"
|
||||
"}\n");
|
||||
TODO_ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: x\n", "", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: x\n", errout.str());
|
||||
|
||||
checkUninitVar2("void f() {\n"
|
||||
" int x;\n"
|
||||
" if (y == 1) { x = 1; }\n"
|
||||
" else if (y == 2) { x = 1; }\n"
|
||||
" if (y == 3) { }\n" // <- ignore condition
|
||||
" return x;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("[test.cpp:6]: (error) Uninitialized variable: x\n", errout.str());
|
||||
|
||||
// initialization in condition
|
||||
checkUninitVar2("void f() {\n"
|
||||
|
|
Loading…
Reference in New Issue