diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index 7cb89a27a..92d3127cc 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -1079,7 +1079,7 @@ void CheckUninitVar::checkScope(const Scope* scope) while (tok && tok->str() != ";") tok = tok->next(); if (stdtype || i->isPointer()) - checkScopeForVariable(tok, *i, NULL); + checkScopeForVariable(tok, *i, NULL, NULL); } for (std::list::const_iterator i = scope->nestedList.begin(); i != scope->nestedList.end(); ++i) { @@ -1088,7 +1088,7 @@ void CheckUninitVar::checkScope(const Scope* scope) } } -bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var, bool * const possibleInit) +bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var, bool * const possibleInit, bool * const noreturn) { const bool suppressErrors(possibleInit && *possibleInit); @@ -1117,7 +1117,7 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var // Unconditional inner scope.. if (tok->str() == "{" && Token::Match(tok->previous(), "[;{}]")) { - if (checkScopeForVariable(tok->next(), var, possibleInit)) + if (checkScopeForVariable(tok->next(), var, possibleInit, NULL)) return true; tok = tok->link(); continue; @@ -1144,7 +1144,8 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var break; if (tok->str() == "{") { bool possibleInitIf(number_of_if > 0 || suppressErrors); - const bool initif = checkScopeForVariable(tok->next(), var, &possibleInitIf); + bool noreturnIf = false; + const bool initif = checkScopeForVariable(tok->next(), var, &possibleInitIf, &noreturnIf); // goto the } tok = tok->link(); @@ -1160,7 +1161,8 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var tok = tok->tokAt(2); bool possibleInitElse(number_of_if > 0 || suppressErrors); - const bool initelse = checkScopeForVariable(tok->next(), var, &possibleInitElse); + bool noreturnElse = false; + const bool initelse = checkScopeForVariable(tok->next(), var, &possibleInitElse, NULL); // goto the } tok = tok->link(); @@ -1168,6 +1170,9 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var if (initif && initelse) return true; + if ((initif && noreturnElse) || (initelse && noreturnIf)) + return true; + if (initif || initelse || possibleInitElse) ++number_of_if; } @@ -1203,7 +1208,7 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var if (tok2 && tok2->str() == "{") { bool possibleinit = true; - bool init = checkScopeForVariable(tok2->next(), var, &possibleinit); + bool init = checkScopeForVariable(tok2->next(), var, &possibleinit, NULL); // variable is initialized in the loop.. if (possibleinit || init) @@ -1213,6 +1218,9 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var if (!suppressErrors) { checkIfForWhileHead(tok->next(), var, false, bool(number_of_if == 0)); } + + // goto "}" + tok = tok2->link(); } } @@ -1226,9 +1234,12 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var return true; } - if (Token::Match(tok, "return|break|continue|throw|goto")) - ret = true; - else if (ret && tok->str() == ";") + if (Token::Match(tok, "return|break|continue|throw|goto")) { + if (noreturn) + *noreturn = true; + else + ret = true; + } else if (tok->str() == "goto") return true; // variable is seen.. diff --git a/lib/checkuninitvar.h b/lib/checkuninitvar.h index 915d5ce7c..e5c72d83f 100644 --- a/lib/checkuninitvar.h +++ b/lib/checkuninitvar.h @@ -64,7 +64,7 @@ public: /** Check for uninitialized variables */ void check(); void checkScope(const Scope* scope); - bool checkScopeForVariable(const Token *tok, const Variable& var, bool * const possibleInit); + bool checkScopeForVariable(const Token *tok, const Variable& var, bool * const possibleInit, bool * const noreturn); bool checkIfForWhileHead(const Token *startparanthesis, const Variable& var, bool suppressErrors, bool isuninit); bool isVariableUsage(const Token *vartok, bool ispointer) const; diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index 88f968231..d00712014 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -2077,13 +2077,18 @@ private: checkUninitVar2("void f() {\n" " int x;\n" " if (y == 1) { return; }\n" - " if (y == 2) { break; }\n" - " if (y == 3) { continue; }\n" " else { x = 1; }\n" " return x;\n" "}\n"); ASSERT_EQUALS("", errout.str()); + checkUninitVar2("void f() {\n" + " int x;\n" + " if (y == 1) { return; }\n" + " return x;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: x\n", errout.str()); + checkUninitVar2("void f() {\n" " int x;\n" " return;\n" @@ -2109,7 +2114,7 @@ private: " if (foo) break;\n" " return x;\n" "}\n"); - TODO_ASSERT_EQUALS("error", "", errout.str()); + ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: x\n", errout.str()); // if goto is simplified there might be conditions that are always true checkUninitVar2("void f() {\n"