| 648 | } |
| 649 | |
| 650 | static ValueFlow::Value evaluate(const Token* op, const ValueFlow::Value& lhs, const ValueFlow::Value& rhs, bool removeAssign = false) |
| 651 | { |
| 652 | const std::string opStr = removeAssign ? op->str().substr(0, op->str().size() - 1) : op->str(); |
| 653 | ValueFlow::Value result; |
| 654 | if (lhs.isImpossible() && rhs.isImpossible()) |
| 655 | return ValueFlow::Value::unknown(); |
| 656 | if (lhs.isImpossible() || rhs.isImpossible()) { |
| 657 | // noninvertible |
| 658 | if (contains({"%", "/", "&", "|"}, opStr)) |
| 659 | return ValueFlow::Value::unknown(); |
| 660 | result.setImpossible(); |
| 661 | } |
| 662 | if (isNumericValue(lhs) && isNumericValue(rhs)) { |
| 663 | if (lhs.isFloatValue() || rhs.isFloatValue()) { |
| 664 | result.valueType = op->isArithmeticalOp() ? ValueFlow::Value::ValueType::FLOAT : ValueFlow::Value::ValueType::INT; |
| 665 | bool error = false; |
| 666 | result.floatValue = calculate(opStr, asFloat(lhs), asFloat(rhs), &error); |
| 667 | if (error) |
| 668 | return ValueFlow::Value::unknown(); |
| 669 | return result; |
| 670 | } |
| 671 | } |
| 672 | // Must be integral types |
| 673 | if (!isIntegralValue(lhs) && !isIntegralValue(rhs)) |
| 674 | return ValueFlow::Value::unknown(); |
| 675 | // If not the same type then one must be int |
| 676 | if (lhs.valueType != rhs.valueType && !lhs.isIntValue() && !rhs.isIntValue()) |
| 677 | return ValueFlow::Value::unknown(); |
| 678 | const bool compareOp = op->isComparisonOp(); |
| 679 | // Comparison must be the same type |
| 680 | if (compareOp && lhs.valueType != rhs.valueType) |
| 681 | return ValueFlow::Value::unknown(); |
| 682 | // Only add, subtract, and compare for non-integers |
| 683 | if (!compareOp && !contains({"+", "-"}, opStr) && !lhs.isIntValue() && !rhs.isIntValue()) |
| 684 | return ValueFlow::Value::unknown(); |
| 685 | // Both can't be iterators for non-compare |
| 686 | if (!compareOp && lhs.isIteratorValue() && rhs.isIteratorValue()) |
| 687 | return ValueFlow::Value::unknown(); |
| 688 | // Symbolic values must be in the same ring |
| 689 | if (lhs.isSymbolicValue() && rhs.isSymbolicValue() && lhs.tokvalue != rhs.tokvalue) |
| 690 | return ValueFlow::Value::unknown(); |
| 691 | if (!lhs.isIntValue() && !compareOp) { |
| 692 | result.valueType = lhs.valueType; |
| 693 | result.tokvalue = lhs.tokvalue; |
| 694 | } else if (!rhs.isIntValue() && !compareOp) { |
| 695 | result.valueType = rhs.valueType; |
| 696 | result.tokvalue = rhs.tokvalue; |
| 697 | } else { |
| 698 | result.valueType = ValueFlow::Value::ValueType::INT; |
| 699 | } |
| 700 | bool error = false; |
| 701 | result.intvalue = calculate(opStr, lhs.intvalue, rhs.intvalue, &error); |
| 702 | if (error) |
| 703 | return ValueFlow::Value::unknown(); |
| 704 | if (result.isImpossible() && opStr == "!=") { |
| 705 | if (isTrue(result)) { |
| 706 | result.intvalue = 1; |
| 707 | } else if (isFalse(result)) { |
no test coverage detected