diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 6cf0a2fd8..b822eefc2 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -570,14 +570,28 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value) } } + +// Handle various constants.. +static void valueFlowSetConstantValue(const Token *tok) +{ + if ((tok->isNumber() && MathLib::isInt(tok->str())) || (tok->tokType() == Token::eChar)) { + ValueFlow::Value value(MathLib::toLongNumber(tok->str())); + value.setKnown(); + setTokenValue(const_cast(tok), value); + } + + if (tok->enumerator() && tok->enumerator()->value_known) { + ValueFlow::Value value(tok->enumerator()->value); + value.setKnown(); + setTokenValue(const_cast(tok), value); + } +} + + static void valueFlowNumber(TokenList *tokenlist) { for (Token *tok = tokenlist->front(); tok; tok = tok->next()) { - if ((tok->isNumber() && MathLib::isInt(tok->str())) || (tok->tokType() == Token::eChar)) { - ValueFlow::Value value(MathLib::toLongNumber(tok->str())); - value.setKnown(); - setTokenValue(tok, value); - } + valueFlowSetConstantValue(tok); } if (tokenlist->isCPP()) { @@ -2363,6 +2377,16 @@ static void valueFlowFunctionReturn(TokenList *tokenlist, ErrorLogger *errorLogg } } +void ValueFlow::valueFlowConstantFoldAST(const Token *expr) +{ + if (!expr || !expr->values.empty()) + return; + valueFlowConstantFoldAST(expr->astOperand1()); + valueFlowConstantFoldAST(expr->astOperand2()); + valueFlowSetConstantValue(expr); +} + + void ValueFlow::setValues(TokenList *tokenlist, SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings *settings) { for (Token *tok = tokenlist->front(); tok; tok = tok->next()) @@ -2400,3 +2424,5 @@ std::string ValueFlow::eitherTheConditionIsRedundant(const Token *condition) } return "Either the condition '" + condition->expressionString() + "' is redundant"; } + + diff --git a/lib/valueflow.h b/lib/valueflow.h index 31454d118..1beec7934 100644 --- a/lib/valueflow.h +++ b/lib/valueflow.h @@ -94,6 +94,10 @@ namespace ValueFlow { } }; + /// Constant folding of expression. This can be used before the full ValueFlow has been executed (ValueFlow::setValues). + void valueFlowConstantFoldAST(const Token *expr); + + /// Perform valueflow analysis. void setValues(TokenList *tokenlist, SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings *settings); std::string eitherTheConditionIsRedundant(const Token *condition); diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 4a613afb1..baed0d96e 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -164,11 +164,12 @@ private: } void valueFlowNumber() { - ASSERT_EQUALS(123, valueOfTok("x=123;", "123").intvalue); + ASSERT_EQUALS(123, valueOfTok("x=123;", "123").intvalue); + ASSERT_EQUALS(10, valueOfTok("enum {A=10,B=15}; x=A+0;", "+").intvalue); ASSERT_EQUALS(0, valueOfTok("x=false;", "false").intvalue); - ASSERT_EQUALS(1, valueOfTok("x=true;", "true").intvalue); - ASSERT_EQUALS(0, valueOfTok("x(NULL);", "NULL").intvalue); - ASSERT_EQUALS((int)('a'), valueOfTok("x='a';", "'a'").intvalue); + ASSERT_EQUALS(1, valueOfTok("x=true;", "true").intvalue); + ASSERT_EQUALS(0, valueOfTok("x(NULL);", "NULL").intvalue); + ASSERT_EQUALS((int)('a'), valueOfTok("x='a';", "'a'").intvalue); ASSERT_EQUALS((int)('\n'), valueOfTok("x='\\n';", "'\\n'").intvalue); }