diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index d2716a46e..e0fc45d05 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -1107,6 +1107,42 @@ static void valueFlowBitAnd(TokenList *tokenlist) } } +static void valueFlowSameExpressions(TokenList *tokenlist) +{ + for (Token *tok = tokenlist->front(); tok; tok = tok->next()) { + if (tok->hasKnownValue()) + continue; + + if (!tok->astOperand1() || !tok->astOperand2()) + continue; + + if (tok->astOperand1()->isLiteral() || tok->astOperand2()->isLiteral()) + continue; + + if (astIsFloat(tok->astOperand1(), true) || astIsFloat(tok->astOperand2(), true)) + continue; + + ValueFlow::Value val; + + if (Token::Match(tok, "==|>=|<=|/")) { + val = ValueFlow::Value(1); + val.setKnown(); + } + + if (Token::Match(tok, "!=|>|<|%|-")) { + val = ValueFlow::Value(0); + val.setKnown(); + } + + if (!val.isKnown()) + continue; + + if (isSameExpression(tokenlist->isCPP(), false, tok->astOperand1(), tok->astOperand2(), tokenlist->getSettings()->library, true, &val.errorPath)) { + setTokenValue(tok, val, tokenlist->getSettings()); + } + } +} + static void valueFlowTerminatingCondition(TokenList *tokenlist, SymbolDatabase* symboldatabase, const Settings *settings) { const bool cpp = symboldatabase->isCPP(); @@ -4648,6 +4684,7 @@ void ValueFlow::setValues(TokenList *tokenlist, SymbolDatabase* symboldatabase, valueFlowLifetime(tokenlist, symboldatabase, errorLogger, settings); valueFlowFunctionReturn(tokenlist, errorLogger); valueFlowBitAnd(tokenlist); + valueFlowSameExpressions(tokenlist); // Temporary hack.. run valueflow until there is nothing to update or timeout expires const std::time_t timeout = std::time(0) + TIMEOUT; diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 3a4bef722..3aa9485d4 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -106,6 +106,8 @@ private: TEST_CASE(valueFlowInlineAssembly); + TEST_CASE(valueFlowSameExpression); + TEST_CASE(valueFlowUninit); TEST_CASE(valueFlowTerminatingCond); @@ -3246,6 +3248,34 @@ private: ASSERT_EQUALS(false, testValueOfX(code, 5U, 42)); } + void valueFlowSameExpression() { + const char* code; + + code = "void f(int a) {\n" + " bool x = a == a;\n" + " bool b = x;\n" + "}\n"; + ASSERT_EQUALS(true, testValueOfX(code, 3U, 1)); + + code = "void f(int a) {\n" + " bool x = a != a;\n" + " bool b = x;\n" + "}\n"; + ASSERT_EQUALS(true, testValueOfX(code, 3U, 0)); + + code = "void f(int a) {\n" + " int x = a - a;\n" + " int b = x;\n" + "}\n"; + ASSERT_EQUALS(true, testValueOfX(code, 3U, 0)); + + code = "void f(float a) {\n" + " bool x = a == a;\n" + " bool b = x;\n" + "}\n"; + ASSERT_EQUALS(false, testValueOfX(code, 3U, 1)); + } + void valueFlowUninit() { const char* code; std::list values;