]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Fix too-large or negative right shift of negative numbers
authorHannes Domani <ssbssa@yahoo.de>
Tue, 11 Jun 2024 18:32:59 +0000 (20:32 +0200)
committerHannes Domani <ssbssa@yahoo.de>
Tue, 11 Jun 2024 18:36:34 +0000 (20:36 +0200)
As seen in these test failures:

print -1 >> -1
warning: right shift count is negative
$N = 0
(gdb) FAIL: gdb.base/bitshift.exp: lang=c: neg lhs/rhs: print -1 >> -1
print -4 >> -2
warning: right shift count is negative
$N = 0
(gdb) FAIL: gdb.base/bitshift.exp: lang=c: neg lhs/rhs: print -4 >> -2

Fixed by restoring the logic from before the switch to gmp.

Approved-By: Tom Tromey <tom@tromey.com>
gdb/testsuite/gdb.base/bitshift.exp
gdb/valarith.c

index 17f6b78fed20e44bc9c26d180d323d45645550ce..d6e252102d9cc28b15087fe3cf485f02cd6ecd3f 100644 (file)
@@ -348,6 +348,7 @@ proc test_shifts {} {
            test_shift $lang "print -3 >> 1" " = -2"
            test_shift $lang "print -8 >> 1" " = -4"
            test_shift $lang "print [make_int64 $lang -8] >> 1" " = -4"
+           test_rshift_tl $lang "print -8 >> 100" " = -1"
        }
 
        # Make sure an unsigned 64-bit value with high bit set isn't
index 7034fa6096b454d335981480122ef6805fd69eb0..6160b0e4438e3d634bee6294173ae7dabb425e3d 100644 (file)
@@ -1303,7 +1303,21 @@ scalar_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
          {
            unsigned long nbits;
            if (!check_valid_shift_count (op, result_type, type2, v2, nbits))
-             v = 0;
+             {
+               /* Pretend the too-large shift was decomposed in a
+                  number of smaller shifts.  An arithmetic signed
+                  right shift of a negative number always yields -1
+                  with such semantics.  This is the right thing to
+                  do for Go, and we might as well do it for
+                  languages where it is undefined.  Also, pretend a
+                  shift by a negative number was a shift by the
+                  negative number cast to unsigned, which is the
+                  same as shifting by a too-large number.  */
+               if (v1 < 0 && !result_type->is_unsigned ())
+                 v = -1;
+               else
+                 v = 0;
+             }
            else
              v = v1 >> nbits;
          }