diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 3b0964c87..545c9e69e 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -5493,6 +5493,32 @@ ValueFlow::Value inferCondition(std::string op, MathLib::bigint val, const Token return ValueFlow::Value{}; } +struct IteratorInferModel : InferModel { + virtual ValueFlow::Value::ValueType getType() const = 0; + virtual bool match(const ValueFlow::Value& value) const OVERRIDE { + return value.valueType == getType(); + } + virtual ValueFlow::Value yield(MathLib::bigint value) const OVERRIDE + { + ValueFlow::Value result(value); + result.valueType = getType(); + result.setKnown(); + return result; + } +}; + +struct EndIteratorInferModel : IteratorInferModel { + virtual ValueFlow::Value::ValueType getType() const OVERRIDE { + return ValueFlow::Value::ValueType::ITERATOR_END; + } +}; + +struct StartIteratorInferModel : IteratorInferModel { + virtual ValueFlow::Value::ValueType getType() const OVERRIDE { + return ValueFlow::Value::ValueType::ITERATOR_END; + } +}; + static void valueFlowInferCondition(TokenList* tokenlist, const Settings* settings) { @@ -5511,10 +5537,22 @@ static void valueFlowInferCondition(TokenList* tokenlist, value.bound = ValueFlow::Value::Bound::Point; setTokenValue(tok, value, settings); } else if (Token::Match(tok, "%comp%|-") && tok->astOperand1() && tok->astOperand2()) { - std::vector result = - infer(IntegralInferModel{}, tok->str(), tok->astOperand1()->values(), tok->astOperand2()->values()); - for (const ValueFlow::Value& value : result) { - setTokenValue(tok, value, settings); + if (astIsIterator(tok->astOperand1()) || astIsIterator(tok->astOperand2())) { + for (ValuePtr model : + std::vector>{EndIteratorInferModel{}, StartIteratorInferModel{}}) { + std::vector result = + infer(model, tok->str(), tok->astOperand1()->values(), tok->astOperand2()->values()); + for (ValueFlow::Value value : result) { + value.valueType = ValueFlow::Value::ValueType::INT; + setTokenValue(tok, value, settings); + } + } + } else { + std::vector result = + infer(IntegralInferModel{}, tok->str(), tok->astOperand1()->values(), tok->astOperand2()->values()); + for (const ValueFlow::Value& value : result) { + setTokenValue(tok, value, settings); + } } } } diff --git a/test/testcondition.cpp b/test/testcondition.cpp index f50848b53..74e345dea 100644 --- a/test/testcondition.cpp +++ b/test/testcondition.cpp @@ -4115,6 +4115,16 @@ private: " if( s.size() < 3 ) return;\n" "}\n"); ASSERT_EQUALS("", errout.str()); + + // #10226 + check("int f(std::vector::iterator it, const std::vector& vector) {\n" + " if (!(it != vector.end() && it != vector.begin()))\n" + " throw 0;\n" + " if (it != vector.end() && *it == 0)\n" + " return -1;\n" + " return *it;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:4]: (style) Condition 'it!=vector.end()' is always true\n", errout.str()); } void alwaysTrueLoop()