diff --git a/lib/infer.cpp b/lib/infer.cpp index cad0761f68b..d264d30054f 100644 --- a/lib/infer.cpp +++ b/lib/infer.cpp @@ -409,6 +409,70 @@ ValuePtr makeIntegralInferModel() return IntegralInferModel{}; } +namespace { + struct SymbolicInferModel : InferModel { + const Token* expr; + explicit SymbolicInferModel(const Token* tok) : expr(tok) { + assert(expr->exprId() != 0); + } + bool match(const ValueFlow::Value& value) const override + { + return value.isSymbolicValue() && value.tokvalue && value.tokvalue->exprId() == expr->exprId(); + } + ValueFlow::Value yield(MathLib::bigint value) const override + { + ValueFlow::Value result(value); + result.valueType = ValueFlow::Value::ValueType::SYMBOLIC; + result.tokvalue = expr; + result.setKnown(); + return result; + } + }; +} + +ValuePtr makeSymbolicInferModel(const Token* token) +{ + return SymbolicInferModel{token}; +} + +namespace { + struct IteratorInferModel : InferModel { + virtual ValueFlow::Value::ValueType getType() const = 0; + bool match(const ValueFlow::Value& value) const override { + return value.valueType == getType(); + } + ValueFlow::Value yield(MathLib::bigint value) const override + { + ValueFlow::Value result(value); + result.valueType = getType(); + result.setKnown(); + return result; + } + }; + + struct EndIteratorInferModel : IteratorInferModel { + ValueFlow::Value::ValueType getType() const override { + return ValueFlow::Value::ValueType::ITERATOR_END; + } + }; + + struct StartIteratorInferModel : IteratorInferModel { + ValueFlow::Value::ValueType getType() const override { + return ValueFlow::Value::ValueType::ITERATOR_END; + } + }; +} + +ValuePtr makeEndIteratorInferModel() +{ + return EndIteratorInferModel{}; +} + +ValuePtr makeStartIteratorInferModel() +{ + return StartIteratorInferModel{}; +} + ValueFlow::Value inferCondition(const std::string& op, const Token* varTok, MathLib::bigint val) { if (!varTok) diff --git a/lib/infer.h b/lib/infer.h index 8d66d7da016..cb1e595295a 100644 --- a/lib/infer.h +++ b/lib/infer.h @@ -63,6 +63,11 @@ std::vector getMaxValue(const ValuePtr& model, cons ValuePtr makeIntegralInferModel(); +ValuePtr makeSymbolicInferModel(const Token* token); + +ValuePtr makeEndIteratorInferModel(); +ValuePtr makeStartIteratorInferModel(); + ValueFlow::Value inferCondition(const std::string& op, const Token* varTok, MathLib::bigint val); #endif diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 81e65c8347f..a411abb5f69 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -3877,25 +3877,6 @@ static void valueFlowSymbolicOperators(const SymbolDatabase& symboldatabase, con } } -struct SymbolicInferModel : InferModel { - const Token* expr; - explicit SymbolicInferModel(const Token* tok) : expr(tok) { - assert(expr->exprId() != 0); - } - bool match(const ValueFlow::Value& value) const override - { - return value.isSymbolicValue() && value.tokvalue && value.tokvalue->exprId() == expr->exprId(); - } - ValueFlow::Value yield(MathLib::bigint value) const override - { - ValueFlow::Value result(value); - result.valueType = ValueFlow::Value::ValueType::SYMBOLIC; - result.tokvalue = expr; - result.setKnown(); - return result; - } -}; - static void valueFlowSymbolicInfer(const SymbolDatabase& symboldatabase, const Settings& settings) { for (const Scope* scope : symboldatabase.functionScopes) { @@ -3923,11 +3904,11 @@ static void valueFlowSymbolicInfer(const SymbolDatabase& symboldatabase, const S std::vector values; { - SymbolicInferModel leftModel{tok->astOperand1()}; + auto leftModel = makeSymbolicInferModel(tok->astOperand1()); values = infer(leftModel, tok->str(), 0, tok->astOperand2()->values()); } if (values.empty()) { - SymbolicInferModel rightModel{tok->astOperand2()}; + auto rightModel = makeSymbolicInferModel(tok->astOperand2()); values = infer(rightModel, tok->str(), tok->astOperand1()->values(), 0); } for (ValueFlow::Value& value : values) { @@ -5132,32 +5113,6 @@ struct SimpleConditionHandler : ConditionHandler { } }; -struct IteratorInferModel : InferModel { - virtual ValueFlow::Value::ValueType getType() const = 0; - bool match(const ValueFlow::Value& value) const override { - return value.valueType == getType(); - } - ValueFlow::Value yield(MathLib::bigint value) const override - { - ValueFlow::Value result(value); - result.valueType = getType(); - result.setKnown(); - return result; - } -}; - -struct EndIteratorInferModel : IteratorInferModel { - ValueFlow::Value::ValueType getType() const override { - return ValueFlow::Value::ValueType::ITERATOR_END; - } -}; - -struct StartIteratorInferModel : IteratorInferModel { - ValueFlow::Value::ValueType getType() const override { - return ValueFlow::Value::ValueType::ITERATOR_END; - } -}; - static bool isIntegralOnlyOperator(const Token* tok) { return Token::Match(tok, "%|<<|>>|&|^|~|%or%"); } @@ -5193,8 +5148,8 @@ static void valueFlowInferCondition(TokenList& tokenlist, const Settings& settin continue; if (Token::Match(tok, "%comp%|-") && tok->astOperand1() && tok->astOperand2()) { if (astIsIterator(tok->astOperand1()) || astIsIterator(tok->astOperand2())) { - static const std::array, 2> iteratorModels = {EndIteratorInferModel{}, - StartIteratorInferModel{}}; + static const std::array, 2> iteratorModels = {makeEndIteratorInferModel(), + makeStartIteratorInferModel()}; for (const ValuePtr& model : iteratorModels) { std::vector result = infer(model, tok->str(), tok->astOperand1()->values(), tok->astOperand2()->values());