Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 42 additions & 4 deletions lib/valueflow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5459,6 +5459,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)
{
Expand All @@ -5477,10 +5503,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<ValueFlow::Value> 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<InferModel> model :
std::vector<ValuePtr<InferModel>>{EndIteratorInferModel{}, StartIteratorInferModel{}}) {
std::vector<ValueFlow::Value> 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<ValueFlow::Value> result =
infer(IntegralInferModel{}, tok->str(), tok->astOperand1()->values(), tok->astOperand2()->values());
for (const ValueFlow::Value& value : result) {
setTokenValue(tok, value, settings);
}
}
}
}
Expand Down
10 changes: 10 additions & 0 deletions test/testcondition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4115,6 +4115,16 @@ class TestCondition : public TestFixture {
" if( s.size() < 3 ) return;\n"
"}\n");
ASSERT_EQUALS("", errout.str());

// #10226
check("int f(std::vector<int>::iterator it, const std::vector<int>& 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()
Expand Down