Fixed #2125 (uninitialized variable: better handling of for loops)
This commit is contained in:
parent
cf86e11d05
commit
b66d3c8858
|
@ -3647,6 +3647,73 @@ private:
|
||||||
return ExecutionPath::parseCondition(tok, checks);
|
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:
|
public:
|
||||||
|
|
||||||
/** Functions that don't handle uninitialized variables well */
|
/** Functions that don't handle uninitialized variables well */
|
||||||
|
|
|
@ -258,6 +258,11 @@ void ExecutionPath::checkScope(const Token *tok, std::list<ExecutionPath *> &che
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tok->str() != "switch")
|
||||||
|
{
|
||||||
|
check->parseLoopBody(tok2->next(), checks);
|
||||||
|
}
|
||||||
|
|
||||||
// skip { .. }
|
// skip { .. }
|
||||||
tok2 = tok2->link();
|
tok2 = tok2->link();
|
||||||
|
|
||||||
|
|
|
@ -112,6 +112,17 @@ public:
|
||||||
**/
|
**/
|
||||||
virtual bool parseCondition(const Token &tok, std::list<ExecutionPath *> &checks);
|
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 */
|
/** going out of scope - all execution paths end */
|
||||||
virtual void end(const std::list<ExecutionPath *> & /*checks*/, const Token * /*tok*/) const
|
virtual void end(const std::list<ExecutionPath *> & /*checks*/, const Token * /*tok*/) const
|
||||||
{ }
|
{ }
|
||||||
|
|
|
@ -1754,6 +1754,14 @@ private:
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: a\n", errout.str());
|
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..
|
// while..
|
||||||
checkUninitVar("int f()\n"
|
checkUninitVar("int f()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
|
|
Loading…
Reference in New Issue