diff --git a/lib/astutils.cpp b/lib/astutils.cpp index a440f91af99..630d713b3a1 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -547,6 +547,26 @@ bool isDifferentKnownValues(const Token * const tok1, const Token * const tok2) return result; } +static bool isSameConstantValue(bool macro, const Token * const tok1, const Token * const tok2) +{ + if (tok1 == nullptr || tok2 == nullptr) + return false; + + if (!tok1->isNumber() || !tok2->isNumber()) + return false; + + if (macro && (tok1->isExpandedMacro() || tok2->isExpandedMacro() || tok1->isTemplateArg() || tok2->isTemplateArg())) + return false; + + const ValueType * v1 = tok1->valueType(); + const ValueType * v2 = tok2->valueType(); + + if (!v1 || !v2 || v1->sign != v2->sign || v1->type != v2->type || v1->pointer != v2->pointer) + return false; + + return isEqualKnownValue(tok1, tok2); +} + 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) @@ -568,6 +588,9 @@ bool isSameExpression(bool cpp, bool macro, const Token *tok1, const Token *tok2 } if (tok1->str() != tok2->str() && isDifferentKnownValues(tok1, tok2)) return false; + if (isSameConstantValue(macro, tok1, tok2)) + return true; + // Follow variable if (followVar && tok1->str() != tok2->str() && (Token::Match(tok1, "%var%") || Token::Match(tok2, "%var%"))) { const Token * varTok1 = followVariableExpression(tok1, cpp, tok2); diff --git a/test/testastutils.cpp b/test/testastutils.cpp index 1d9a8e138c5..77cc43d5c66 100644 --- a/test/testastutils.cpp +++ b/test/testastutils.cpp @@ -36,6 +36,7 @@ class TestAstUtils : public TestFixture { TEST_CASE(findLambdaEndToken); TEST_CASE(findLambdaStartToken); TEST_CASE(isReturnScope); + TEST_CASE(isSameExpression); TEST_CASE(isVariableChanged); TEST_CASE(isVariableChangedByFunctionCall); TEST_CASE(nextAfterAstRightmostLeaf); @@ -135,6 +136,33 @@ class TestAstUtils : public TestFixture { ASSERT_EQUALS(true, isReturnScope("void positiveTokenOffset() { return; }", 7)); } + bool isSameExpression(const char code[], const char tokStr1[], const char tokStr2[]) { + Settings settings; + Library library; + Tokenizer tokenizer(&settings, this); + std::istringstream istr(code); + tokenizer.tokenize(istr, "test.cpp"); + const Token * const tok1 = Token::findsimplematch(tokenizer.tokens(), tokStr1); + const Token * const tok2 = Token::findsimplematch(tok1->next(), tokStr2); + return ::isSameExpression(false, false, tok1, tok2, library, false, false, nullptr); + } + + void isSameExpression() { + ASSERT_EQUALS(true, isSameExpression("x = 1 + 1;", "1", "1")); + ASSERT_EQUALS(false, isSameExpression("x = 1 + 1u;", "1", "1u")); + ASSERT_EQUALS(true, isSameExpression("x = 1.0 + 1.0;", "1.0", "1.0")); + ASSERT_EQUALS(false, isSameExpression("x = 1.0f + 1.0;", "1.0f", "1.0")); + ASSERT_EQUALS(false, isSameExpression("x = 1L + 1;", "1L", "1")); + ASSERT_EQUALS(true, isSameExpression("x = 0.0f + 0x0p+0f;", "0.0f", "0x0p+0f")); + ASSERT_EQUALS(true, isSameExpression("x < x;", "x", "x")); + ASSERT_EQUALS(false, isSameExpression("x < y;", "x", "y")); + ASSERT_EQUALS(true, isSameExpression("(x + 1) < (x + 1);", "+", "+")); + ASSERT_EQUALS(false, isSameExpression("(x + 1) < (x + 1L);", "+", "+")); + ASSERT_EQUALS(true, isSameExpression("(1 + x) < (x + 1);", "+", "+")); + ASSERT_EQUALS(false, isSameExpression("(1.0l + x) < (1.0 + x);", "+", "+")); + ASSERT_EQUALS(true, isSameExpression("(0.0 + x) < (x + 0x0p+0);", "+", "+")); + } + bool isVariableChanged(const char code[], const char startPattern[], const char endPattern[]) { Settings settings; Tokenizer tokenizer(&settings, this);