Skip to content

Commit

Permalink
Left overshift of negatives under use integer was still wrong.
Browse files Browse the repository at this point in the history
Follow-up on b349829: the -1 stuckiness on overshift should apply
only on right shift, not left shift (which should return zero).
  • Loading branch information
jhi committed Jul 3, 2015
1 parent f298f06 commit b69687e
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 11 deletions.
2 changes: 1 addition & 1 deletion pp.c
Expand Up @@ -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;
}
Expand Down
29 changes: 19 additions & 10 deletions t/op/bop.t
Expand Up @@ -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);
Expand Down Expand Up @@ -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.
Expand Down

0 comments on commit b69687e

Please sign in to comment.