Fixed #2125 (uninitialized variable: better handling of for loops)

This commit is contained in:
Daniel Marjamäki 2010-10-24 18:12:48 +02:00
parent cf86e11d05
commit b66d3c8858
4 changed files with 91 additions and 0 deletions

View File

@ -3647,6 +3647,73 @@ private:
return ExecutionPath::parseCondition(tok, checks);
}
void parseLoopBody(const Token *tok_, std::list<ExecutionPath *> &checks) const
{
for (; tok_; tok_ = tok_->next())
{
if (tok_->str() == "{")
return;
const Token &tok = *tok_;
if (Token::Match(tok.previous(), "[;{}] %var% [=[.]"))
{
if (tok.next()->str() == ".")
{
if (use_dead_pointer(checks, &tok))
{
return;
}
}
else
{
// check variable usages in rhs/index
for (const Token *tok2 = tok.tokAt(2); tok2; tok2 = tok2->next())
{
if (Token::Match(tok2, "[;)=?]"))
break;
if (Token::Match(tok2, "%var% ("))
break;
if (tok2->varId() &&
!Token::Match(tok2->previous(), "&|::") &&
!Token::simpleMatch(tok2->next(), "="))
{
// Multiple assignments..
if (Token::simpleMatch(tok2->next(), "["))
{
const Token * tok3 = tok2;
while (Token::simpleMatch(tok3->next(), "["))
tok3 = tok3->next()->link();
if (Token::simpleMatch(tok3, "] ="))
continue;
}
bool foundError;
if (tok2->previous()->str() == "*" || tok2->next()->str() == "[")
foundError = use_array_or_pointer_data(checks, tok2);
else
foundError = use(checks, tok2);
// prevent duplicate error messages
if (foundError)
{
bailOutVar(checks, tok2->varId());
}
}
}
}
// pointer aliasing?
if (Token::Match(tok.tokAt(2), "%var% ;"))
{
pointer_assignment(checks, &tok, tok.tokAt(2));
}
}
}
}
public:
/** Functions that don't handle uninitialized variables well */

View File

@ -258,6 +258,11 @@ void ExecutionPath::checkScope(const Token *tok, std::list<ExecutionPath *> &che
return;
}
if (tok->str() != "switch")
{
check->parseLoopBody(tok2->next(), checks);
}
// skip { .. }
tok2 = tok2->link();

View File

@ -112,6 +112,17 @@ public:
**/
virtual bool parseCondition(const Token &tok, std::list<ExecutionPath *> &checks);
/**
* Parse loop body
* @param tok the first token in the loop body (the token after the {)
* @param checks The execution paths
*/
virtual void parseLoopBody(const Token *tok, std::list<ExecutionPath *> &checks) const
{
(void)tok;
(void)checks;
}
/** going out of scope - all execution paths end */
virtual void end(const std::list<ExecutionPath *> & /*checks*/, const Token * /*tok*/) const
{ }

View File

@ -1754,6 +1754,14 @@ private:
"}\n");
ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: a\n", errout.str());
checkUninitVar("void f() {\n"
" int k;\n"
" for (int i = 0; i < 4; ++i) {\n"
" k = k + 2;\n"
" }\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: k\n", errout.str());
// while..
checkUninitVar("int f()\n"
"{\n"