diff --git a/sv.c b/sv.c index 0b3d142e85e4..68b0d40e9873 100644 --- a/sv.c +++ b/sv.c @@ -2658,19 +2658,14 @@ Perl_sv_2nv_flags(pTHX_ SV *const sv, const I32 flags) SvNOK_on(sv); } else { /* value has been set. It may not be precise. */ - if ((numtype & IS_NUMBER_NEG) && (value >= (UV)IV_MIN)) { - /* 2s complement assumption for (UV)IV_MIN */ + if ((numtype & IS_NUMBER_NEG) && (value > ABS_IV_MIN)) { SvNOK_on(sv); /* Integer is too negative. */ } else { SvNOKp_on(sv); SvIOKp_on(sv); if (numtype & IS_NUMBER_NEG) { - /* -IV_MIN is undefined, but we should never reach - * this point with both IS_NUMBER_NEG and value == - * (UV)IV_MIN */ - assert(value != (UV)IV_MIN); - SvIV_set(sv, -(IV)value); + SvIV_set(sv, NEGATE_2IV(value)); } else if (value <= (UV)IV_MAX) { SvIV_set(sv, (IV)value); } else { diff --git a/t/op/numconvert.t b/t/op/numconvert.t index 4a7cc3985dbe..b1ad58785df7 100644 --- a/t/op/numconvert.t +++ b/t/op/numconvert.t @@ -281,3 +281,18 @@ sub plus_one { (shift) + 1 } is 0x1p60 - 1.0, 0x1p60 - 1, "(0x1p60 - 1) and (0x1p60 - 1.0) should be identical"; + +my @iv_min_test; +BEGIN { + @iv_min_test = ('2147483647', '2147483648', + '9223372036854775807', '9223372036854775808'); + $::additional_tests += @iv_min_test; +} + +foreach my $str (@iv_min_test) { + my $x = "-$str"; + my $y = $x + 1.23; + my $z = $x + 0; + my $w = "-$str" + 0; + is $z, $w, "previously NV-ified '-$str' has correct numeric value"; +}