diff --git a/lib/astutils.cpp b/lib/astutils.cpp index 19e1e46e1..63f002645 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -445,6 +445,36 @@ static void followVariableExpressionError(const Token *tok1, const Token *tok2, errors->push_back(item); } +template +static void findTokenValue(const Token* const tok, Predicate pred, F f) +{ + auto x = std::find_if(tok->values().begin(), tok->values().end(), pred); + if (x != tok->values().end()) + f(*x); +} + +bool isEqualKnownValue(const Token * const tok1, const Token * const tok2) +{ + bool result = false; + findTokenValue(tok1, std::mem_fn(&ValueFlow::Value::isKnown), [&](const ValueFlow::Value& v1) { + findTokenValue(tok2, std::mem_fn(&ValueFlow::Value::isKnown), [&](const ValueFlow::Value& v2) { + result = v1.equalValue(v2); + }); + }); + return result; +} + +bool isDifferentKnownValues(const Token * const tok1, const Token * const tok2) +{ + bool result = false; + findTokenValue(tok1, std::mem_fn(&ValueFlow::Value::isKnown), [&](const ValueFlow::Value& v1) { + findTokenValue(tok2, std::mem_fn(&ValueFlow::Value::isKnown), [&](const ValueFlow::Value& v2) { + result = !v1.equalValue(v2); + }); + }); + return result; +} + bool isSameExpression(bool cpp, bool macro, const Token *tok1, const Token *tok2, const Library& library, bool pure, bool followVar, ErrorPath* errors) { if (tok1 == nullptr && tok2 == nullptr) @@ -464,6 +494,8 @@ bool isSameExpression(bool cpp, bool macro, const Token *tok1, const Token *tok2 if (Token::simpleMatch(tok2, "!") && Token::simpleMatch(tok2->astOperand1(), "!") && !Token::simpleMatch(tok2->astParent(), "=")) { return isSameExpression(cpp, macro, tok1, tok2->astOperand1()->astOperand1(), library, pure, followVar, errors); } + if (tok1->str() != tok2->str() && isDifferentKnownValues(tok1, tok2)) + return false; // Follow variable if (followVar && tok1->str() != tok2->str() && (Token::Match(tok1, "%var%") || Token::Match(tok2, "%var%"))) { const Token * varTok1 = followVariableExpression(tok1, cpp, tok2); @@ -596,16 +628,6 @@ bool isSameExpression(bool cpp, bool macro, const Token *tok1, const Token *tok2 return commutativeEquals; } -bool isEqualKnownValue(const Token * const tok1, const Token * const tok2) -{ - return tok1->hasKnownValue() && tok2->hasKnownValue() && tok1->values() == tok2->values(); -} - -bool isDifferentKnownValues(const Token * const tok1, const Token * const tok2) -{ - return tok1->hasKnownValue() && tok2->hasKnownValue() && tok1->values() != tok2->values(); -} - static bool isZeroBoundCond(const Token * const cond) { if (cond == nullptr) diff --git a/lib/valueflow.h b/lib/valueflow.h index 2bc84fbea..d9fc94dc1 100644 --- a/lib/valueflow.h +++ b/lib/valueflow.h @@ -60,7 +60,7 @@ namespace ValueFlow { {} Value(const Token *c, long long val); - bool operator==(const Value &rhs) const { + bool equalValue(const ValueFlow::Value& rhs) const { if (valueType != rhs.valueType) return false; switch (valueType) { @@ -95,6 +95,12 @@ namespace ValueFlow { if (tokvalue != rhs.tokvalue) return false; } + return true; + } + + bool operator==(const Value &rhs) const { + if (!equalValue(rhs)) + return false; return varvalue == rhs.varvalue && condition == rhs.condition && @@ -105,6 +111,10 @@ namespace ValueFlow { valueKind == rhs.valueKind; } + bool operator!=(const Value &rhs) const { + return !(*this == rhs); + } + std::string infoString() const; enum ValueType { INT, TOK, FLOAT, MOVED, UNINIT, CONTAINER_SIZE, LIFETIME, BUFFER_SIZE } valueType; diff --git a/test/testother.cpp b/test/testother.cpp index 030ca96c9..73726c00e 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -137,6 +137,7 @@ private: TEST_CASE(duplicateExpression6); // ticket #4639 TEST_CASE(duplicateExpression7); TEST_CASE(duplicateExpression8); + TEST_CASE(duplicateExpression9); // #9320 TEST_CASE(duplicateExpressionLoop); TEST_CASE(duplicateValueTernary); TEST_CASE(duplicateExpressionTernary); // #6391 @@ -4584,6 +4585,16 @@ private: ASSERT_EQUALS("", errout.str()); } + void duplicateExpression9() { + // #9320 + check("void f() {\n" + " uint16_t x = 1000;\n" + " uint8_t y = x;\n" + " if (x != y) {}\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + } + void duplicateExpressionLoop() { check("void f() {\n" " int a = 1;\n"