diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index a596214a9..fe19d32c1 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -1396,14 +1396,7 @@ bool CheckUninitVar::checkScopeForVariable(const Scope* scope, const Token *tok, if (tok->varId() == var.varId()) { if (!membervar.empty()) { if (isMemberVariableAssignment(tok, membervar)) { - bool rhs = false; - for (const Token *tok2 = tok; tok2 && tok2->str() != ";"; tok2 = tok2->next()) { - if (tok2->str() == "=") - rhs = true; - else if (rhs && tok2->varId() == var.varId() && isMemberVariableUsage(tok2, var.isPointer(), membervar)) - uninitStructMemberError(tok2, tok2->str() + "." + membervar); - } - + checkRhs(tok, var, membervar); return true; } @@ -1419,14 +1412,8 @@ bool CheckUninitVar::checkScopeForVariable(const Scope* scope, const Token *tok, uninitvarError(tok, tok->str()); else { - if (tok->strAt(1) == "=") { - for (const Token *tok2 = tok->next(); tok2 && tok2->str() != ";"; tok2 = tok2->next()) { - if (tok2->varId() == tok->varId() && isVariableUsage(tok2, var.isPointer(), _tokenizer->isCPP())) { - uninitvarError(tok, tok->str()); - break; - } - } - } + if (tok->strAt(1) == "=") + checkRhs(tok, var, ""); // assume that variable is assigned return true; @@ -1537,6 +1524,31 @@ bool CheckUninitVar::checkLoopBody(const Token *tok, const Variable& var, const return false; } +void CheckUninitVar::checkRhs(const Token *tok, const Variable &var, const std::string &membervar) +{ + bool rhs = false; + unsigned int indent = 0; + while (tok = tok->next()) { + if (tok->str() == "=") + rhs = true; + if (rhs && tok->varId() == var.varId()) { + if (membervar.empty() && isVariableUsage(tok, var.isPointer(), _tokenizer->isCPP())) + uninitvarError(tok, tok->str()); + else if (!membervar.empty() && isMemberVariableUsage(tok, var.isPointer(), membervar)) + uninitStructMemberError(tok, tok->str() + "." + membervar); + + } else if (tok->str() == ";" || (indent==0 && tok->str() == ",")) + break; + else if (tok->str() == "(") + ++indent; + else if (tok->str() == ")") { + if (indent == 0) + break; + --indent; + } + } +} + bool CheckUninitVar::isVariableUsage(const Token *vartok, bool pointer, bool cpp) { if (vartok->previous()->str() == "return") diff --git a/lib/checkuninitvar.h b/lib/checkuninitvar.h index 661843fe7..3ba185081 100644 --- a/lib/checkuninitvar.h +++ b/lib/checkuninitvar.h @@ -60,6 +60,7 @@ public: bool checkScopeForVariable(const Scope* scope, const Token *tok, const Variable& var, bool * const possibleInit, bool * const noreturn, const std::string &membervar); bool checkIfForWhileHead(const Token *startparentheses, const Variable& var, bool suppressErrors, bool isuninit, const std::string &membervar); bool checkLoopBody(const Token *tok, const Variable& var, const std::string &membervar, const bool suppressErrors); + void checkRhs(const Token *tok, const Variable &var, const std::string &membervar); static bool isVariableUsage(const Token *vartok, bool ispointer, bool cpp); bool isMemberVariableAssignment(const Token *tok, const std::string &membervar) const; bool isMemberVariableUsage(const Token *tok, bool isPointer, const std::string &membervar) const; diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index 6ffbad6ed..a797b799e 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -2035,6 +2035,12 @@ private: "}"); ASSERT_EQUALS("", errout.str()); + checkUninitVar2("void f() {\n" + " int i;\n" + " i=f(), i!=2;\n" + "}"); + ASSERT_EQUALS("", errout.str()); + // using uninit var in condition checkUninitVar2("void f(void) {\n" " int x;\n"