Uninitialized variables: better handling of for example 'a[1] = 1+a[2];'

This commit is contained in:
Daniel Marjamäki 2010-11-05 19:24:14 +01:00
parent a90a7202cb
commit 65c7b6eb8b
2 changed files with 50 additions and 34 deletions

View File

@ -360,6 +360,49 @@ private:
checks.push_back(new UninitVar(owner, vartok->varId(), vartok->str(), p, a)); checks.push_back(new UninitVar(owner, vartok->varId(), vartok->str(), p, a));
} }
/**
* Parse right hand side expression in statement
* @param tok2 start token of rhs
* @param checks the execution paths
*/
void parserhs(const Token *tok2, std::list<ExecutionPath *> &checks) const
{
// check variable usages in rhs/index
while (NULL != (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());
}
}
}
}
/** parse tokens. @sa ExecutionPath::parse */ /** parse tokens. @sa ExecutionPath::parse */
const Token *parse(const Token &tok, std::list<ExecutionPath *> &checks) const const Token *parse(const Token &tok, std::list<ExecutionPath *> &checks) const
{ {
@ -436,39 +479,13 @@ private:
} }
else else
{ {
// check variable usages in rhs/index const Token *tok2 = tok.next();
for (const Token *tok2 = tok.tokAt(2); tok2; tok2 = tok2->next()) if (tok2->str() == "[" && Token::simpleMatch(tok2->link(), "] ="))
{ {
if (Token::Match(tok2, "[;)=?]")) parserhs(tok2, checks);
break; tok2 = tok2->link()->next();
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());
}
}
} }
parserhs(tok2, checks);
} }
// pointer aliasing? // pointer aliasing?

View File

@ -381,10 +381,9 @@ private:
checkUninitVar("void f()\n" checkUninitVar("void f()\n"
"{\n" "{\n"
" int a[10];\n" " int a[10];\n"
" a[0] += 10;\n" " a[0] = 10 - a[1];\n"
"}\n"); "}\n");
TODO_ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: a\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: a\n", errout.str());
ASSERT_EQUALS("", errout.str());
// goto/setjmp/longjmp.. // goto/setjmp/longjmp..
checkUninitVar("void foo(int x)\n" checkUninitVar("void foo(int x)\n"