This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Left overshift of negatives under use integer was still wrong.
authorJarkko Hietaniemi <jhi@iki.fi>
Fri, 3 Jul 2015 13:32:13 +0000 (09:32 -0400)
committerJarkko Hietaniemi <jhi@iki.fi>
Fri, 3 Jul 2015 13:40:12 +0000 (09:40 -0400)
Follow-up on b3498293: the -1 stuckiness on overshift should apply
only on right shift, not left shift (which should return zero).

pp.c
t/op/bop.t

diff --git a/pp.c b/pp.c
index 1e46dd1..4542868 100644 (file)
--- a/pp.c
+++ b/pp.c
@@ -1926,7 +1926,7 @@ static IV S_iv_shift(IV iv, int shift, bool left)
        left = !left;
    }
    if (shift >= IV_BITS) {
-       return iv < 0 ? -1 : 0;
+       return iv < 0 && !left ? -1 : 0;
    }
    return left ? iv << shift : iv >> shift;
 }
index 4225d4c..409c91b 100644 (file)
@@ -15,7 +15,7 @@ BEGIN {
 # If you find tests are failing, please try adding names to tests to track
 # down where the failure is, and supply your new names as a patch.
 # (Just-in-time test naming)
-plan tests => 192 + (10*13*2) + 5 + 25;
+plan tests => 192 + (10*13*2) + 5 + 29;
 
 # numerics
 ok ((0xdead & 0xbeef) == 0x9ead);
@@ -621,25 +621,34 @@ is $^A, "123", '~v0 clears vstring magic on retval';
     # not necessarily the ideal behavior, but that is what is happening.
     if ($w == 64) {
         no warnings "portable";
-        is(-1 << 1, 0xFFFF_FFFF_FFFF_FFFE, "neg UV (sic) left shift");
-        is(-1 >> 1, 0x7FFF_FFFF_FFFF_FFFF, "neg UV (sic) right right");
+        is(-1 << 1, 0xFFFF_FFFF_FFFF_FFFE,
+           "neg UV (sic) left shift  = 0xFF..E");
+        is(-1 >> 1, 0x7FFF_FFFF_FFFF_FFFF,
+           "neg UV (sic) right right = 0x7F..F");
     } elsif ($w == 32) {
         no warnings "portable";
-        is(-1 << 1, 0xFFFF_FFFE, "neg left shift");
-        is(-1 >> 1, 0x7FFF_FFFF, "neg right right");
+        is(-1 << 1, 0xFFFF_FFFE, "neg left shift  == 0xFF..E");
+        is(-1 >> 1, 0x7FFF_FFFF, "neg right right == 0x7F..F");
     }
 
     {
         # 'use integer' means use IVs instead of UVs.
         use integer;
 
-        is(1 << 1, 2, "IV 1 left shift 1");
-        is(1 >> 1, 0, "IV 1 right shift 1");
+        # No surprises here.
+        is(1 << 1, 2, "IV 1 left shift 1  == 2");
+        is(1 >> 1, 0, "IV 1 right shift 1 == 0");
 
-        # Even for negative for IVs, left shift is multiplication.
-        is(-1 <<      1, -2, "IV -1 left shift       1 == -2");
+        # The left overshift should behave like without 'use integer',
+        # that is, return zero.
+        is(1 << $w,     0, "IV 1 left shift $w     == 0");
+        is(1 << $w + 1, 0, "IV 1 left shift $w + 1 == 0");
+        is(-1 << $w,     0, "IV -1 left shift $w     == 0");
+        is(-1 << $w + 1, 0, "IV -1 left shift $w + 1 == 0");
 
-        # But right shift displays the stuckiness to -1.
+        # Even for negative IVs, left shift is multiplication.
+        # But right shift should display the stuckiness to -1.
+        is(-1 <<      1, -2, "IV -1 left shift       1 == -2");
         is(-1 >>      1, -1, "IV -1 right shift      1 == -1");
 
         # As for UVs, negative shifting means the reverse shift.