diff --git a/gcc/range-op-mixed.h b/gcc/range-op-mixed.h index b69e674a78b..0df300781f1 100644 --- a/gcc/range-op-mixed.h +++ b/gcc/range-op-mixed.h @@ -655,6 +655,10 @@ public: bool op1_range (irange &r, tree type, const irange &lhs, const irange &op2, relation_trio rel = TRIO_VARYING) const final override; + bool op1_range (prange &r, tree type, + const prange &lhs, const prange &op2, + relation_trio rel = TRIO_VARYING) const final override; + bool pointers_handled_p (range_op_dispatch_type, unsigned) const final override; }; class operator_bitwise_not : public range_operator diff --git a/gcc/range-op-ptr.cc b/gcc/range-op-ptr.cc index 0addd1096c2..38d9f65566f 100644 --- a/gcc/range-op-ptr.cc +++ b/gcc/range-op-ptr.cc @@ -1021,6 +1021,44 @@ operator_max::pointers_handled_p (range_op_dispatch_type type, } } +bool +operator_addr_expr::op1_range (prange &r, tree type, + const prange &lhs, + const prange &op2, + relation_trio) const +{ + if (empty_range_varying (r, type, lhs, op2)) + return true; + + // Return a non-null pointer of the LHS type (passed in op2), but only + // if we cant overflow, eitherwise a no-zero offset could wrap to zero. + // See PR 111009. + if (!lhs.undefined_p () + && !range_includes_zero_p (lhs) + && TYPE_OVERFLOW_UNDEFINED (type)) + r.set_nonzero (type); + else + r.set_varying (type); + return true; +} + +bool +operator_addr_expr::pointers_handled_p (range_op_dispatch_type type, + unsigned dispatch) const +{ + switch (type) + { + case DISPATCH_FOLD_RANGE: + // NOTE: It looks like we never generate this combination. + gcc_unreachable (); + return false; + case DISPATCH_OP1_RANGE: + return dispatch == RO_PPP; + default: + return true; + } +} + // Initialize any pointer operators to the primary table void