diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index d7215b8bd..65899e35c 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -371,9 +371,15 @@ static const Token *getCastTypeStartToken(const Token *parent) return nullptr; } +// does the operation cause a loss of information? +static bool isNonInvertibleOperation(const Token* tok) +{ + return tok->isComparisonOp() || Token::Match(tok, "%|/|&|%or%|<<|>>"); +} + static bool isComputableValue(const Token* parent, const ValueFlow::Value& value) { - const bool noninvertible = parent->isComparisonOp() || Token::Match(parent, "%|/|&|%or%"); + const bool noninvertible = isNonInvertibleOperation(parent); if (noninvertible && value.isImpossible()) return false; if (!value.isIntValue() && !value.isFloatValue() && !value.isTokValue() && !value.isIteratorValue()) @@ -669,7 +675,7 @@ static void setTokenValue(Token* tok, ValueFlow::Value value, const Settings* se parent->astOperand1() && parent->astOperand2()) { - const bool noninvertible = parent->isComparisonOp() || Token::Match(parent, "%|/|&|%or%"); + const bool noninvertible = isNonInvertibleOperation(parent); // Skip operators with impossible values that are not invertible if (noninvertible && value.isImpossible()) diff --git a/test/testcondition.cpp b/test/testcondition.cpp index 29078d3ad..8d66c8e2e 100644 --- a/test/testcondition.cpp +++ b/test/testcondition.cpp @@ -3927,6 +3927,16 @@ private: " if (pD) {}\n" "}\n"); ASSERT_EQUALS("", errout.str()); + + // #9549 + check("void f(const uint32_t v) {\n" + " const uint32_t v16 = v >> 16;\n" + " if (v16) {\n" + " const uint32_t v8 = v16 >> 8;\n" + " if (v8) {}\n" + " }\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); } void alwaysTrueInfer() {