diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index cf7acd8f6..dc54d0657 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -1148,11 +1148,29 @@ static bool valueFlowForward(Token * const startToken, const bool condAlwaysTrue = (condTok && condTok->values.size() == 1U && condTok->values.front().isKnown() && condTok->values.front().intvalue != 0); // Should scope be skipped because variable value is checked? - std::list truevalues; + std::list truevalues, falsevalues; for (std::list::const_iterator it = values.begin(); it != values.end(); ++it) { if (condAlwaysTrue || !conditionIsFalse(condTok, getProgramMemory(tok2, varid, *it))) truevalues.push_back(*it); + if (!condAlwaysTrue && !conditionIsTrue(condTok, getProgramMemory(tok2, varid, *it))) + falsevalues.push_back(*it); } + + if (!falsevalues.empty() && Token::simpleMatch(tok2->linkAt(1)->linkAt(1), "} else {")) { + // '{' + Token * const startToken1 = tok2->linkAt(1)->linkAt(1)->tokAt(2); + + valueFlowForward(startToken1->next(), + startToken1->link(), + var, + varid, + falsevalues, + constValue, + tokenlist, + errorLogger, + settings); + } + if (truevalues.size() != values.size() || condAlwaysTrue) { // '{' Token * const startToken1 = tok2->linkAt(1)->next(); diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 751a83bb7..a07921b52 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -900,6 +900,13 @@ private: "}"; ASSERT_EQUALS(false, testValueOfX(code, 4U, 4)); + code = "void f(int y) {\n" // #3923 + " int x = 6;\n" + " if (y) { x = 0; }\n" + " else { a = x; }\n" // <- x is 6 + "}"; + ASSERT_EQUALS(true, testValueOfX(code, 4U, 6)); + code = "void f() {\n" " int x = 32;\n" " if (x>=32) return;\n"