diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index b64ac975b..a1a1cadc1 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -1088,6 +1088,9 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const unsigned int unsigned int number_of_if = 0; + // variables that are known to be non-zero + std::set notzero; + for (; tok; tok = tok->next()) { // End of scope.. if (tok->str() == "}") { @@ -1109,12 +1112,20 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const unsigned int continue; } + // assignment with nonzero constant.. + if (Token::Match(tok, "[;{}] %var% = - %var% ;") && tok->next()->varId() > 0) + notzero.insert(tok->next()->varId()); + // Inner scope.. if (Token::simpleMatch(tok, "if (")) { // initialization / usage in condition.. if (checkIfForWhileHead(tok->next(), varid, ispointer, suppressErrors, bool(number_of_if == 0))) return true; + // checking if a not-zero variable is zero => bail out + if (Token::Match(tok, "if ( %var% )") && notzero.find(tok->tokAt(2)->varId()) != notzero.end()) + return true; // this scope is not fully analysed => return true + // goto the { tok = tok->next()->link()->next(); diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index 5549a1846..671d612fa 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -1889,6 +1889,17 @@ private: "}\n"); TODO_ASSERT_EQUALS("error", "", errout.str()); + // if goto is simplified there might be conditions that are always true + checkUninitVar2("void f() {\n" + " int i;\n" + " if (x) {\n" + " int y = -ENOMEM;\n" + " if (y != 0) return;\n" + " i++;\n" + " }\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + // for, while checkUninitVar2("void f() {\n" " int x;\n"