Uninitialized variables: check more variables

This commit is contained in:
Daniel Marjamäki 2011-12-26 14:01:46 +01:00
parent f48edb63a3
commit 8eb067358c
3 changed files with 36 additions and 11 deletions

View File

@ -1049,16 +1049,31 @@ void CheckUninitVar::check()
// only check functions // only check functions
if (func_scope->type == Scope::eFunction) { if (func_scope->type == Scope::eFunction) {
for (const Token *tok = func_scope->classStart; tok && tok != func_scope->classEnd; tok = tok->next()) { for (const Token *tok = func_scope->classStart; tok && tok != func_scope->classEnd; tok = tok->next()) {
// Variable declaration..
if (Token::Match(tok, "[;{}] %type% %var% ;") && tok->next()->isStandardType()) { if (Token::Match(tok, "[;{}] %type% !!;")) {
checkScopeForVariable(tok->tokAt(3), tok->tokAt(2)->varId()); bool stdtype = false;
bool pointer = false;
tok = tok->next();
while (tok->isName() || tok->str() == "*") {
if (tok->isStandardType())
stdtype = true;
else if (tok->str() == "*")
pointer = true;
else if (tok->isName() && tok->next()->str() == ";") {
if (stdtype || pointer || _tokenizer->isC())
checkScopeForVariable(tok->next(), tok->varId(), pointer, NULL);
break;
} else if (!tok->isName())
break;
tok = tok->next();
}
} }
} }
} }
} }
} }
bool CheckUninitVar::checkScopeForVariable(const Token *tok, const unsigned int varid, bool * const possibleInit) bool CheckUninitVar::checkScopeForVariable(const Token *tok, const unsigned int varid, bool ispointer, bool * const possibleInit)
{ {
if (varid == 0) if (varid == 0)
return false; return false;
@ -1094,7 +1109,7 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const unsigned int
const Token * const endToken = tok->next()->link(); const Token * const endToken = tok->next()->link();
for (const Token *tok2 = tok->tokAt(2); tok2 != endToken; tok2 = tok2->next()) { for (const Token *tok2 = tok->tokAt(2); tok2 != endToken; tok2 = tok2->next()) {
if (tok2->varId() == varid) { if (tok2->varId() == varid) {
if (!suppressErrors && isVariableUsage(tok2)) if (!suppressErrors && isVariableUsage(tok2, ispointer))
uninitvarError(tok2, tok2->str()); uninitvarError(tok2, tok2->str());
return true; return true;
} }
@ -1106,7 +1121,7 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const unsigned int
tok = tok->next()->link()->next(); tok = tok->next()->link()->next();
bool possibleInitIf(number_of_if > 0); bool possibleInitIf(number_of_if > 0);
const bool initif = checkScopeForVariable(tok->next(), varid, &possibleInitIf); const bool initif = checkScopeForVariable(tok->next(), varid, ispointer, &possibleInitIf);
// goto the } // goto the }
tok = tok->link(); tok = tok->link();
@ -1126,7 +1141,7 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const unsigned int
tok = tok->tokAt(2); tok = tok->tokAt(2);
bool possibleInitElse(number_of_if > 0); bool possibleInitElse(number_of_if > 0);
const bool initelse = checkScopeForVariable(tok->next(), varid, &possibleInitElse); const bool initelse = checkScopeForVariable(tok->next(), varid, ispointer, &possibleInitElse);
// goto the } // goto the }
tok = tok->link(); tok = tok->link();
@ -1175,7 +1190,7 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const unsigned int
// variable is seen.. // variable is seen..
if (tok->varId() == varid) { if (tok->varId() == varid) {
// Use variable // Use variable
if (!suppressErrors && isVariableUsage(tok)) if (!suppressErrors && isVariableUsage(tok, ispointer))
uninitvarError(tok, tok->str()); uninitvarError(tok, tok->str());
else else
@ -1187,7 +1202,7 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const unsigned int
return ret; return ret;
} }
bool CheckUninitVar::isVariableUsage(const Token *vartok) const bool CheckUninitVar::isVariableUsage(const Token *vartok, bool pointer) const
{ {
if (vartok->previous()->str() == "return") if (vartok->previous()->str() == "return")
return true; return true;
@ -1203,6 +1218,10 @@ bool CheckUninitVar::isVariableUsage(const Token *vartok) const
} }
} }
bool unknown = false;
if (pointer && CheckNullPointer::isPointerDeRef(vartok, unknown))
return true;
if (Token::Match(vartok->next(), "++|--|%op%")) if (Token::Match(vartok->next(), "++|--|%op%"))
return true; return true;

View File

@ -60,8 +60,8 @@ public:
/** Check for uninitialized variables */ /** Check for uninitialized variables */
void check(); void check();
bool checkScopeForVariable(const Token *tok, const unsigned int varid, bool * const possibleInit=0); bool checkScopeForVariable(const Token *tok, const unsigned int varid, bool ispointer, bool * const possibleInit);
bool isVariableUsage(const Token *vartok) 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

View File

@ -1733,6 +1733,12 @@ private:
"}"); "}");
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: x\n", errout.str()); ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: x\n", errout.str());
checkUninitVar2("void f() {\n"
" struct ABC *abc;\n"
" abc->a = 0;\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: abc\n", errout.str());
// using uninit var in condition // using uninit var in condition
checkUninitVar2("void f() {\n" checkUninitVar2("void f() {\n"
" int x;\n" " int x;\n"