diff --git a/lib/checkother.cpp b/lib/checkother.cpp index d2fb534b1..a9fecb2a6 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -3647,6 +3647,73 @@ private: return ExecutionPath::parseCondition(tok, checks); } + void parseLoopBody(const Token *tok_, std::list &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 */ diff --git a/lib/executionpath.cpp b/lib/executionpath.cpp index d40aa924e..29cea75ba 100644 --- a/lib/executionpath.cpp +++ b/lib/executionpath.cpp @@ -258,6 +258,11 @@ void ExecutionPath::checkScope(const Token *tok, std::list &che return; } + if (tok->str() != "switch") + { + check->parseLoopBody(tok2->next(), checks); + } + // skip { .. } tok2 = tok2->link(); diff --git a/lib/executionpath.h b/lib/executionpath.h index c9d0462d8..e501be1d1 100644 --- a/lib/executionpath.h +++ b/lib/executionpath.h @@ -112,6 +112,17 @@ public: **/ virtual bool parseCondition(const Token &tok, std::list &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 &checks) const + { + (void)tok; + (void)checks; + } + /** going out of scope - all execution paths end */ virtual void end(const std::list & /*checks*/, const Token * /*tok*/) const { } diff --git a/test/testother.cpp b/test/testother.cpp index 48c1b7396..833cadec2 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -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"