https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97488

Aldy Hernandez <aldyh at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |NEW
   Last reconfirmed|                            |2020-10-19
     Ever confirmed|0                           |1

--- Comment #1 from Aldy Hernandez <aldyh at gcc dot gnu.org> ---
Confirmed.

The shift amount in operator_lshift::op1_range is > than the precision of the
type so the low_bits wrap around.

Testing the following:

diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index 30d2a4d3987..13a0ee37feb 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -1608,8 +1608,10 @@ operator_lshift::op1_range (irange &r,
       // This would be [0x42, 0xFC] aka [01000010, 11111100].

       // Ideally we do this for each subrange, but just lump them all for now.
-      unsigned low_bits = TYPE_PRECISION (utype)
-                         - TREE_INT_CST_LOW (shift_amount);
+      unsigned saturated_shift_amount = TREE_INT_CST_LOW (shift_amount);
+      if (saturated_shift_amount > TYPE_PRECISION (utype))
+       saturated_shift_amount = TYPE_PRECISION (utype);
+      unsigned low_bits = TYPE_PRECISION (utype) - saturated_shift_amount;
       wide_int up_mask = wi::mask (low_bits, true, TYPE_PRECISION (utype));
       wide_int new_ub = wi::bit_or (up_mask, r.upper_bound ());
       wide_int new_lb = wi::set_bit (r.lower_bound (), low_bits);

Reply via email to