| 284 | } |
| 285 | |
| 286 | std::vector<ValueFlow::Value> infer(const ValuePtr<InferModel>& model, |
| 287 | const std::string& op, |
| 288 | std::list<ValueFlow::Value> lhsValues, |
| 289 | std::list<ValueFlow::Value> rhsValues) |
| 290 | { |
| 291 | std::vector<ValueFlow::Value> result; |
| 292 | auto notMatch = [&](const ValueFlow::Value& value) { |
| 293 | return !model->match(value); |
| 294 | }; |
| 295 | lhsValues.remove_if(notMatch); |
| 296 | if (lhsValues.empty()) |
| 297 | return result; |
| 298 | rhsValues.remove_if(notMatch); |
| 299 | if (rhsValues.empty()) |
| 300 | return result; |
| 301 | |
| 302 | Interval lhs = Interval::fromValues(lhsValues); |
| 303 | Interval rhs = Interval::fromValues(rhsValues); |
| 304 | |
| 305 | if (op == "-") { |
| 306 | Interval diff = lhs - rhs; |
| 307 | if (diff.isScalar()) { |
| 308 | std::vector<const ValueFlow::Value*> refs = diff.getScalarRef(); |
| 309 | ValueFlow::Value value(diff.getScalar()); |
| 310 | addToErrorPath(value, refs); |
| 311 | setValueKind(value, refs); |
| 312 | result.push_back(std::move(value)); |
| 313 | } else { |
| 314 | if (!diff.minvalue.empty()) { |
| 315 | ValueFlow::Value value(diff.minvalue.front() - 1); |
| 316 | value.setImpossible(); |
| 317 | value.bound = ValueFlow::Value::Bound::Upper; |
| 318 | addToErrorPath(value, diff.minRef); |
| 319 | result.push_back(std::move(value)); |
| 320 | } |
| 321 | if (!diff.maxvalue.empty()) { |
| 322 | ValueFlow::Value value(diff.maxvalue.front() + 1); |
| 323 | value.setImpossible(); |
| 324 | value.bound = ValueFlow::Value::Bound::Lower; |
| 325 | addToErrorPath(value, diff.maxRef); |
| 326 | result.push_back(std::move(value)); |
| 327 | } |
| 328 | } |
| 329 | } else if ((op == "!=" || op == "==") && lhs.isScalarOrEmpty() && rhs.isScalarOrEmpty()) { |
| 330 | if (lhs.isScalar() && rhs.isScalar()) { |
| 331 | std::vector<const ValueFlow::Value*> refs = Interval::merge(lhs.getScalarRef(), rhs.getScalarRef()); |
| 332 | ValueFlow::Value value(calculate(op, lhs.getScalar(), rhs.getScalar())); |
| 333 | addToErrorPath(value, refs); |
| 334 | setValueKind(value, refs); |
| 335 | result.push_back(std::move(value)); |
| 336 | } else { |
| 337 | std::vector<const ValueFlow::Value*> refs; |
| 338 | if (lhs.isScalar() && inferNotEqual(rhsValues, lhs.getScalar())) |
| 339 | refs = lhs.getScalarRef(); |
| 340 | else if (rhs.isScalar() && inferNotEqual(lhsValues, rhs.getScalar())) |
| 341 | refs = rhs.getScalarRef(); |
| 342 | if (!refs.empty()) { |
| 343 | ValueFlow::Value value(op == "!="); |
no test coverage detected