diff --git a/gcc/range-op.cc b/gcc/range-op.cc index 5c67bce6d3a..c425c496c25 100644 --- a/gcc/range-op.cc +++ b/gcc/range-op.cc @@ -1730,6 +1730,29 @@ operator_minus::op2_range (irange &r, tree type, return fold_range (r, type, op1, lhs); } +class operator_widen_plus : public range_operator +{ +public: + virtual void wi_fold (irange &r, tree type, + const wide_int &lh_lb, + const wide_int &lh_ub, + const wide_int &rh_lb, + const wide_int &rh_ub) const; +} op_widen_plus; + +void +operator_widen_plus::wi_fold (irange &r, tree type, + const wide_int &lh_lb, + const wide_int &lh_ub, + const wide_int &rh_lb, + const wide_int &rh_ub) const +{ + wi::overflow_type ov_lb, ov_ub; + signop s = TYPE_SIGN (type); + wide_int new_lb = wi::add (lh_lb, rh_lb, s, &ov_lb); + wide_int new_ub = wi::add (lh_ub, rh_ub, s, &ov_ub); + r = int_range<2> (type, new_lb, new_ub); +} class operator_pointer_diff : public range_operator { @@ -4505,6 +4528,7 @@ integral_table::integral_table () set (ABSU_EXPR, op_absu); set (NEGATE_EXPR, op_negate); set (ADDR_EXPR, op_addr); + set (WIDEN_PLUS_EXPR, op_widen_plus); } // Instantiate a range op table for pointer operations.