diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 5d8b5d919..1cbf76877 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -1353,15 +1353,24 @@ static bool valueFlowForward(Token * const startToken, const Token *op2 = tok2->astOperand2(); if (!condition || !op2) // Ticket #6713 continue; - std::list::const_iterator it; - for (it = values.begin(); it != values.end(); ++it) { - const ProgramMemory programMemory(getProgramMemory(tok2, varid, *it)); - if (conditionIsTrue(condition, programMemory)) - valueFlowAST(const_cast(op2->astOperand1()), varid, *it); - else if (conditionIsFalse(condition, programMemory)) - valueFlowAST(const_cast(op2->astOperand2()), varid, *it); - else - valueFlowAST(const_cast(op2), varid, *it); + + if (condition->values.size() == 1U && condition->values.front().isKnown() && !condition->values.front().tokvalue) { + const ValueFlow::Value &condValue = condition->values.front(); + const Token *expr = (condValue.intvalue != 0) ? op2->astOperand1() : op2->astOperand2(); + std::list::const_iterator it; + for (it = values.begin(); it != values.end(); ++it) + valueFlowAST(const_cast(expr), varid, *it); + } else { + std::list::const_iterator it; + for (it = values.begin(); it != values.end(); ++it) { + const ProgramMemory programMemory(getProgramMemory(tok2, varid, *it)); + if (conditionIsTrue(condition, programMemory)) + valueFlowAST(const_cast(op2->astOperand1()), varid, *it); + else if (conditionIsFalse(condition, programMemory)) + valueFlowAST(const_cast(op2->astOperand2()), varid, *it); + else + valueFlowAST(const_cast(op2), varid, *it); + } } // Skip conditional expressions.. while (tok2->astOperand1() || tok2->astOperand2()) { diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index c2266d9bc..60a9cae16 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -805,6 +805,21 @@ private: "}\n"; ASSERT_EQUALS(false, testValueOfX(code, 4U, 0)); + // ?: + code = "void f() {\n" + " int x = 8;\n" + " a = ((x > 10) ?\n" + " x : 0);\n" // <- x is not 8 + "}"; + ASSERT_EQUALS(false, testValueOfX(code, 4U, 8)); + + code = "void f() {\n" // #6973 + " char *x = \"\";\n" + " a = ((x[0] == 'U') ?\n" + " x[1] : 0);\n" // <- x is not "" + "}"; + ASSERT_EQUALS(false, testValueOfX(code, 4U, "\"\"")); + // if/else code = "void f() {\n" " int x = 123;\n"