pp.c, pp_hot.c: Reorder SvXV_nomg() to fetch operands in left-to-right order

Some binary (2-operand) operators, notably arithmetic add (+) and
subtract (-), used to fetch its RHS operand first then LHS one,
so they would issue "use of uninitialized value" warnings in
right-to-left order:

 % perl -wle 'print $a + $b'
 Use of uninitialized value $b in addition (+) at -e line 1.
 Use of uninitialized value $a in addition (+) at -e line 1.
 0
 %

I think this is not intuitive for users, as "perlop" says that
"Perl has a general rule that the operands of an operator are evaluated
in left-to-right order."  (3-operand case is more surprising;
"print $a + $b + $c" will warn in the order $b, $a, $c.)

This change reverses the operand fetch order in these operators
to issue warnings in left-to-right order.

t/lib/warnings/9uninit: Reorder expected warnings in left-to-right order.

pod/perldelta.pod: Add perldelta entry for this change.
This commit is contained in:
TAKAI Kousuke 2025-02-27 00:19:53 +09:00 committed by Karl Williamson
parent d349122ed8
commit 6edc33d41c
4 changed files with 80 additions and 79 deletions

View File

@ -220,6 +220,14 @@ XXX Changes (i.e. rewording) of diagnostic messages go here
XXX Describe change here
=item *
L<Use of uninitialized value%s|perldiag/"Use of uninitialized value%s">
This warning was issued in the reverse order (right-to-left) when both
operands of a binary operator are uninitialized values. This is now
fixed to be consistent with evaluation order of operands.
=back
=head1 Utility Changes

44
pp.c
View File

@ -1483,8 +1483,8 @@ PP(pp_multiply)
} /* SvIOK(svr) */
#endif
{
NV right = SvNV_nomg(svr);
NV left = SvNV_nomg(svl);
NV right = SvNV_nomg(svr);
NV result = left * right;
#if defined(__sgi) && defined(USE_LONG_DOUBLE) && LONG_DOUBLEKIND == LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_BE_BE && NVSIZE == 16
@ -1611,8 +1611,8 @@ PP(pp_divide)
} /* one operand wasn't SvIOK */
#endif /* PERL_TRY_UV_DIVIDE */
{
NV right = SvNV_nomg(svr);
NV left = SvNV_nomg(svl);
NV right = SvNV_nomg(svr);
#if defined(NAN_COMPARE_BROKEN) && defined(Perl_isnan)
if (! Perl_isnan(right) && right == 0.0)
#else
@ -2061,14 +2061,10 @@ PP(pp_subtract)
useleft = USE_LEFT(svl);
#endif
{
NV value = SvNV_nomg(svr);
if (!useleft) {
/* left operand is undef, treat as zero - value */
TARGn(-value, 1);
goto ret;
}
TARGn(SvNV_nomg(svl) - value, 1);
/* If left operand is undef, treat as zero - value */
NV value = useleft ? SvNV_nomg(svl) : 0.0;
value -= SvNV_nomg(svr);
TARGn(value, 1);
goto ret;
}
@ -2356,8 +2352,8 @@ Perl_do_ncmp(pTHX_ SV* const left, SV * const right)
}
#endif
{
NV const rnv = SvNV_nomg(right);
NV const lnv = SvNV_nomg(left);
NV const rnv = SvNV_nomg(right);
#if defined(NAN_COMPARE_BROKEN) && defined(Perl_isnan)
if (Perl_isnan(lnv) || Perl_isnan(rnv)) {
@ -2888,8 +2884,8 @@ PP(pp_i_multiply)
if (rpp_try_AMAGIC_2(mult_amg, AMGf_assign))
return NORMAL;
IV right = SvIV_nomg(PL_stack_sp[0]);
IV left = SvIV_nomg(PL_stack_sp[-1]);
IV right = SvIV_nomg(PL_stack_sp[0]);
TARGi((IV)((UV)left * (UV)right), 1);
rpp_replace_2_1_NN(targ);
@ -2910,10 +2906,10 @@ PP(pp_i_divide)
SV *left = PL_stack_sp[-1];
{
IV num = SvIV_nomg(left);
IV value = SvIV_nomg(right);
if (value == 0)
DIE(aTHX_ "Illegal division by zero");
IV num = SvIV_nomg(left);
/* avoid FPE_INTOVF on some platforms when num is IV_MIN */
if (value == -1)
@ -2936,8 +2932,8 @@ PP(pp_i_modulo)
if (rpp_try_AMAGIC_2(modulo_amg, AMGf_assign))
return NORMAL;
IV right = SvIV_nomg(PL_stack_sp[0]);
IV left = SvIV_nomg(PL_stack_sp[-1]);
IV right = SvIV_nomg(PL_stack_sp[0]);
{
if (!right)
@ -2962,9 +2958,9 @@ PP(pp_i_add)
if (rpp_try_AMAGIC_2(add_amg, AMGf_assign))
return NORMAL;
IV right = SvIV_nomg(PL_stack_sp[0]);
SV *leftsv = PL_stack_sp[-1];
IV left = USE_LEFT(leftsv) ? SvIV_nomg(leftsv) : 0;
IV right = SvIV_nomg(PL_stack_sp[0]);
TARGi((IV)((UV)left + (UV)right), 1);
rpp_replace_2_1_NN(targ);
@ -2981,9 +2977,9 @@ PP(pp_i_subtract)
if (rpp_try_AMAGIC_2(subtr_amg, AMGf_assign))
return NORMAL;
IV right = SvIV_nomg(PL_stack_sp[0]);
SV *leftsv = PL_stack_sp[-1];
IV left = USE_LEFT(leftsv) ? SvIV_nomg(leftsv) : 0;
IV right = SvIV_nomg(PL_stack_sp[0]);
TARGi((IV)((UV)left - (UV)right), 1);
rpp_replace_2_1_NN(targ);
@ -2996,8 +2992,8 @@ PP(pp_i_lt)
if (rpp_try_AMAGIC_2(lt_amg, 0))
return NORMAL;
IV right = SvIV_nomg(PL_stack_sp[0]);
IV left = SvIV_nomg(PL_stack_sp[-1]);
IV right = SvIV_nomg(PL_stack_sp[0]);
rpp_replace_2_IMM_NN(boolSV(left < right));
return NORMAL;
@ -3009,8 +3005,8 @@ PP(pp_i_gt)
if (rpp_try_AMAGIC_2(gt_amg, 0))
return NORMAL;
IV right = SvIV_nomg(PL_stack_sp[0]);
IV left = SvIV_nomg(PL_stack_sp[-1]);
IV right = SvIV_nomg(PL_stack_sp[0]);
rpp_replace_2_IMM_NN(boolSV(left > right));
return NORMAL;
@ -3022,8 +3018,8 @@ PP(pp_i_le)
if (rpp_try_AMAGIC_2(le_amg, 0))
return NORMAL;
IV right = SvIV_nomg(PL_stack_sp[0]);
IV left = SvIV_nomg(PL_stack_sp[-1]);
IV right = SvIV_nomg(PL_stack_sp[0]);
rpp_replace_2_IMM_NN(boolSV(left <= right));
return NORMAL;
@ -3035,8 +3031,8 @@ PP(pp_i_ge)
if (rpp_try_AMAGIC_2(ge_amg, 0))
return NORMAL;
IV right = SvIV_nomg(PL_stack_sp[0]);
IV left = SvIV_nomg(PL_stack_sp[-1]);
IV right = SvIV_nomg(PL_stack_sp[0]);
rpp_replace_2_IMM_NN(boolSV(left >= right));
return NORMAL;
@ -3048,8 +3044,8 @@ PP(pp_i_eq)
if (rpp_try_AMAGIC_2(eq_amg, 0))
return NORMAL;
IV right = SvIV_nomg(PL_stack_sp[0]);
IV left = SvIV_nomg(PL_stack_sp[-1]);
IV right = SvIV_nomg(PL_stack_sp[0]);
rpp_replace_2_IMM_NN(boolSV(left == right));
return NORMAL;
@ -3061,8 +3057,8 @@ PP(pp_i_ne)
if (rpp_try_AMAGIC_2(ne_amg, 0))
return NORMAL;
IV right = SvIV_nomg(PL_stack_sp[0]);
IV left = SvIV_nomg(PL_stack_sp[-1]);
IV right = SvIV_nomg(PL_stack_sp[0]);
rpp_replace_2_IMM_NN(boolSV(left != right));
return NORMAL;
@ -3075,8 +3071,8 @@ PP(pp_i_ncmp)
if (rpp_try_AMAGIC_2(ncmp_amg, 0))
return NORMAL;
IV right = SvIV_nomg(PL_stack_sp[0]);
IV left = SvIV_nomg(PL_stack_sp[-1]);
IV right = SvIV_nomg(PL_stack_sp[0]);
{
@ -3122,8 +3118,8 @@ PP(pp_atan2)
if (rpp_try_AMAGIC_2(atan2_amg, 0))
return NORMAL;
NV right = SvNV_nomg(PL_stack_sp[0]);
NV left = SvNV_nomg(PL_stack_sp[-1]);
NV right = SvNV_nomg(PL_stack_sp[0]);
TARGn(Perl_atan2(left, right), 1);
rpp_replace_2_1_NN(targ);

View File

@ -2007,14 +2007,10 @@ PP(pp_add)
#endif
{
NV value = SvNV_nomg(svr);
if (!useleft) {
/* left operand is undef, treat as zero. + 0.0 is identity. */
TARGn(value, 1);
}
else {
TARGn(value + SvNV_nomg(svl), 1);
}
/* If left operand is undef, treat as zero. */
NV value = useleft ? SvNV_nomg(svl) : 0.0;
value += SvNV_nomg(svr);
TARGn(value, 1);
}
ret:

View File

@ -29,8 +29,8 @@ $v = $m1 + $m2;
EXPECT
Use of uninitialized value $m1 in addition (+) at - line 4.
Use of uninitialized value $m2 in addition (+) at - line 5.
Use of uninitialized value $m2 in addition (+) at - line 6.
Use of uninitialized value $m1 in addition (+) at - line 6.
Use of uninitialized value $m2 in addition (+) at - line 6.
########
use warnings 'uninitialized';
use utf8;
@ -42,8 +42,8 @@ $v = $à1 + $2;
EXPECT
Use of uninitialized value $à1 in addition (+) at - line 5.
Use of uninitialized value $2 in addition (+) at - line 6.
Use of uninitialized value $2 in addition (+) at - line 7.
Use of uninitialized value $à1 in addition (+) at - line 7.
Use of uninitialized value $2 in addition (+) at - line 7.
########
use warnings 'uninitialized';
my ($m1, $v);
@ -56,10 +56,10 @@ $v = $m1 + $g2;
EXPECT
Use of uninitialized value $g1 in addition (+) at - line 5.
Use of uninitialized value $g2 in addition (+) at - line 6.
Use of uninitialized value $g2 in addition (+) at - line 7.
Use of uninitialized value $g1 in addition (+) at - line 7.
Use of uninitialized value $g2 in addition (+) at - line 8.
Use of uninitialized value $g2 in addition (+) at - line 7.
Use of uninitialized value $m1 in addition (+) at - line 8.
Use of uninitialized value $g2 in addition (+) at - line 8.
########
use warnings 'uninitialized';
my ($m1, @ma, $v);
@ -72,8 +72,8 @@ $v = $ma[-1] + $ma[-2];
EXPECT
Use of uninitialized value $ma[5] in addition (+) at - line 4.
Use of uninitialized value $ma[6] in addition (+) at - line 5.
Use of uninitialized value $m1 in addition (+) at - line 6.
Use of uninitialized value in addition (+) at - line 6.
Use of uninitialized value $m1 in addition (+) at - line 6.
Use of uninitialized value in addition (+) at - line 7.
Use of uninitialized value in addition (+) at - line 7.
Use of uninitialized value in addition (+) at - line 8.
@ -97,14 +97,14 @@ Use of uninitialized value $mau[5] in addition (+) at - line 6.
Use of uninitialized value $mau[-5] in addition (+) at - line 7.
Use of uninitialized value $mau[6] in addition (+) at - line 8.
Use of uninitialized value $mau[-6] in addition (+) at - line 9.
Use of uninitialized value $mau[8] in addition (+) at - line 10.
Use of uninitialized value $mau[7] in addition (+) at - line 10.
Use of uninitialized value $mau[257] in addition (+) at - line 11.
Use of uninitialized value $mau[8] in addition (+) at - line 10.
Use of uninitialized value $mau[256] in addition (+) at - line 11.
Use of uninitialized value $mau[-2] in addition (+) at - line 12.
Use of uninitialized value $mau[257] in addition (+) at - line 11.
Use of uninitialized value $mau[-1] in addition (+) at - line 12.
Use of uninitialized value $mhu{"bar"} in addition (+) at - line 13.
Use of uninitialized value $mau[-2] in addition (+) at - line 12.
Use of uninitialized value $mhu{"foo"} in addition (+) at - line 13.
Use of uninitialized value $mhu{"bar"} in addition (+) at - line 13.
########
use warnings 'uninitialized';
my ($v);
@ -144,14 +144,14 @@ Use of uninitialized value $gau[8] in addition (+) at - line 6.
Use of uninitialized value $gau[-8] in addition (+) at - line 7.
Use of uninitialized value $gau[9] in addition (+) at - line 8.
Use of uninitialized value $gau[-9] in addition (+) at - line 9.
Use of uninitialized value $gau[11] in addition (+) at - line 10.
Use of uninitialized value $gau[10] in addition (+) at - line 10.
Use of uninitialized value $gau[257] in addition (+) at - line 11.
Use of uninitialized value $gau[11] in addition (+) at - line 10.
Use of uninitialized value $gau[256] in addition (+) at - line 11.
Use of uninitialized value $gau[-2] in addition (+) at - line 12.
Use of uninitialized value $gau[257] in addition (+) at - line 11.
Use of uninitialized value $gau[-1] in addition (+) at - line 12.
Use of uninitialized value $ghu{"bar"} in addition (+) at - line 13.
Use of uninitialized value $gau[-2] in addition (+) at - line 12.
Use of uninitialized value $ghu{"foo"} in addition (+) at - line 13.
Use of uninitialized value $ghu{"bar"} in addition (+) at - line 13.
########
use warnings 'uninitialized';
my ($v);
@ -173,18 +173,18 @@ $v = $mhu{$k1} + $mhu{$k2};
$v = $ghu{$k1} + $ghu{$k2};
$v = $ghu{$k1} + $ghu{$k3};
EXPECT
Use of uninitialized value $mau[20] in addition (+) at - line 14.
Use of uninitialized value $mau[10] in addition (+) at - line 14.
Use of uninitialized value $gau[20] in addition (+) at - line 15.
Use of uninitialized value $mau[20] in addition (+) at - line 14.
Use of uninitialized value $gau[10] in addition (+) at - line 15.
Use of uninitialized value in addition (+) at - line 16.
Use of uninitialized value $gau[20] in addition (+) at - line 15.
Use of uninitialized value $gau[10] in addition (+) at - line 16.
Use of uninitialized value $mhu{"bar"} in addition (+) at - line 17.
Use of uninitialized value in addition (+) at - line 16.
Use of uninitialized value $mhu{"foo"} in addition (+) at - line 17.
Use of uninitialized value $ghu{"bar"} in addition (+) at - line 18.
Use of uninitialized value $mhu{"bar"} in addition (+) at - line 17.
Use of uninitialized value $ghu{"foo"} in addition (+) at - line 18.
Use of uninitialized value in addition (+) at - line 19.
Use of uninitialized value $ghu{"bar"} in addition (+) at - line 18.
Use of uninitialized value $ghu{"foo"} in addition (+) at - line 19.
Use of uninitialized value in addition (+) at - line 19.
########
use warnings 'uninitialized';
my ($m1, $m2, @ma, %mh, $v);
@ -212,8 +212,8 @@ Use of uninitialized value $m1 in hash element at - line 10.
Use of uninitialized value $g1 in hash element at - line 11.
Use of uninitialized value $m2 in hash element at - line 12.
Use of uninitialized value $g2 in hash element at - line 13.
Use of uninitialized value $g1 in subtraction (-) at - line 15.
Use of uninitialized value $m2 in subtraction (-) at - line 15.
Use of uninitialized value $g1 in subtraction (-) at - line 15.
Use of uninitialized value $m1 in addition (+) at - line 15.
Use of uninitialized value $ga[3] in array element at - line 16.
Use of uninitialized value $ma[4] in array element at - line 17.
@ -574,31 +574,32 @@ $v = $m1 != $g1;
$v = $m1 <=> $g1;
$v = -$m1;
EXPECT
Use of uninitialized value $g1 in integer addition (+) at - line 6.
Use of uninitialized value $m1 in integer addition (+) at - line 6.
Use of uninitialized value $g1 in integer subtraction (-) at - line 7.
Use of uninitialized value $g1 in integer addition (+) at - line 6.
Use of uninitialized value $m1 in integer subtraction (-) at - line 7.
Use of uninitialized value $g1 in integer multiplication (*) at - line 8.
Use of uninitialized value $g1 in integer subtraction (-) at - line 7.
Use of uninitialized value $m1 in integer multiplication (*) at - line 8.
Use of uninitialized value $g1 in integer multiplication (*) at - line 8.
Use of uninitialized value $m1 in integer division (/) at - line 9.
Use of uninitialized value $g1 in integer division (/) at - line 9.
Use of uninitialized value $m2 in integer division (/) at - line 10.
Use of uninitialized value $g1 in integer modulus (%) at - line 11.
Use of uninitialized value $m1 in integer modulus (%) at - line 11.
Use of uninitialized value $g1 in integer modulus (%) at - line 11.
Use of uninitialized value $m2 in integer modulus (%) at - line 12.
Use of uninitialized value $g1 in integer lt (<) at - line 13.
Use of uninitialized value $m1 in integer lt (<) at - line 13.
Use of uninitialized value $g1 in integer gt (>) at - line 14.
Use of uninitialized value $g1 in integer lt (<) at - line 13.
Use of uninitialized value $m1 in integer gt (>) at - line 14.
Use of uninitialized value $g1 in integer le (<=) at - line 15.
Use of uninitialized value $g1 in integer gt (>) at - line 14.
Use of uninitialized value $m1 in integer le (<=) at - line 15.
Use of uninitialized value $g1 in integer ge (>=) at - line 16.
Use of uninitialized value $g1 in integer le (<=) at - line 15.
Use of uninitialized value $m1 in integer ge (>=) at - line 16.
Use of uninitialized value $g1 in integer eq (==) at - line 17.
Use of uninitialized value $g1 in integer ge (>=) at - line 16.
Use of uninitialized value $m1 in integer eq (==) at - line 17.
Use of uninitialized value $g1 in integer ne (!=) at - line 18.
Use of uninitialized value $g1 in integer eq (==) at - line 17.
Use of uninitialized value $m1 in integer ne (!=) at - line 18.
Use of uninitialized value $g1 in integer comparison (<=>) at - line 19.
Use of uninitialized value $g1 in integer ne (!=) at - line 18.
Use of uninitialized value $m1 in integer comparison (<=>) at - line 19.
Use of uninitialized value $g1 in integer comparison (<=>) at - line 19.
Use of uninitialized value $m1 in integer negation (-) at - line 20.
########
use warnings 'uninitialized';
@ -655,8 +656,8 @@ Use of uninitialized value $m1 in sort at - line 6.
Use of uninitialized value $g1 in sort at - line 6.
Use of uninitialized value $m1 in sort at - line 7.
Use of uninitialized value $g1 in sort at - line 7.
Use of uninitialized value $g1 in sort at - line 7.
Use of uninitialized value $m1 in sort at - line 7.
Use of uninitialized value $g1 in sort at - line 7.
Use of uninitialized value $a in subtraction (-) at - line 8.
Use of uninitialized value $b in subtraction (-) at - line 8.
Use of uninitialized value $m1 in sort at - line 9.
@ -717,36 +718,36 @@ $v = $m1 ** $g1;
$v = $m1 + $g1;
$v = $m1 - $g1;
EXPECT
Use of uninitialized value $g1 in division (/) at - line 5.
Use of uninitialized value $m1 in division (/) at - line 5.
Use of uninitialized value $g1 in division (/) at - line 5.
Use of uninitialized value $m2 in division (/) at - line 6.
Use of uninitialized value $g1 in modulus (%) at - line 7.
Use of uninitialized value $m1 in modulus (%) at - line 7.
Use of uninitialized value $m2 in modulus (%) at - line 8.
Use of uninitialized value $g1 in numeric eq (==) at - line 9.
Use of uninitialized value $m1 in numeric eq (==) at - line 9.
Use of uninitialized value $g1 in numeric ge (>=) at - line 10.
Use of uninitialized value $g1 in numeric eq (==) at - line 9.
Use of uninitialized value $m1 in numeric ge (>=) at - line 10.
Use of uninitialized value $g1 in numeric gt (>) at - line 11.
Use of uninitialized value $g1 in numeric ge (>=) at - line 10.
Use of uninitialized value $m1 in numeric gt (>) at - line 11.
Use of uninitialized value $g1 in numeric le (<=) at - line 12.
Use of uninitialized value $g1 in numeric gt (>) at - line 11.
Use of uninitialized value $m1 in numeric le (<=) at - line 12.
Use of uninitialized value $g1 in numeric lt (<) at - line 13.
Use of uninitialized value $g1 in numeric le (<=) at - line 12.
Use of uninitialized value $m1 in numeric lt (<) at - line 13.
Use of uninitialized value $g1 in multiplication (*) at - line 14.
Use of uninitialized value $g1 in numeric lt (<) at - line 13.
Use of uninitialized value $m1 in multiplication (*) at - line 14.
Use of uninitialized value $g1 in numeric comparison (<=>) at - line 15.
Use of uninitialized value $g1 in multiplication (*) at - line 14.
Use of uninitialized value $m1 in numeric comparison (<=>) at - line 15.
Use of uninitialized value $g1 in numeric ne (!=) at - line 16.
Use of uninitialized value $g1 in numeric comparison (<=>) at - line 15.
Use of uninitialized value $m1 in numeric ne (!=) at - line 16.
Use of uninitialized value $g1 in subtraction (-) at - line 17.
Use of uninitialized value $g1 in numeric ne (!=) at - line 16.
Use of uninitialized value $m1 in subtraction (-) at - line 17.
Use of uninitialized value $g1 in subtraction (-) at - line 17.
Use of uninitialized value $g1 in exponentiation (**) at - line 18.
Use of uninitialized value $m1 in exponentiation (**) at - line 18.
Use of uninitialized value $g1 in addition (+) at - line 19.
Use of uninitialized value $m1 in addition (+) at - line 19.
Use of uninitialized value $g1 in subtraction (-) at - line 20.
Use of uninitialized value $g1 in addition (+) at - line 19.
Use of uninitialized value $m1 in subtraction (-) at - line 20.
Use of uninitialized value $g1 in subtraction (-) at - line 20.
########
use warnings 'uninitialized';
sub TIESCALAR{bless[]}
@ -967,8 +968,8 @@ $v = oct $m1;
$v = oct;
$v = length; # does not warn
EXPECT
Use of uninitialized value $g1 in atan2 at - line 5.
Use of uninitialized value $m1 in atan2 at - line 5.
Use of uninitialized value $g1 in atan2 at - line 5.
Use of uninitialized value $m1 in sin at - line 6.
Use of uninitialized value $m1 in cos at - line 7.
Use of uninitialized value $m1 in rand at - line 8.
@ -1163,8 +1164,8 @@ undef $^A; $v = $^A + ${^FOO}; # should output '^A' not chr(1)
$v = $GLOB1 + 1;
$v = $GLOB2 + 1;
EXPECT
Use of uninitialized value $^FOO in addition (+) at - line 4.
Use of uninitialized value $^A in addition (+) at - line 4.
Use of uninitialized value $^FOO in addition (+) at - line 4.
Use of uninitialized value $GLOB1 in addition (+) at - line 6.
Use of uninitialized value $GLOB2 in addition (+) at - line 7.
########
@ -2150,8 +2151,8 @@ Use of uninitialized value $k in hash element at - line 9.
Use of uninitialized value $k in hash element at - line 9.
Use of uninitialized value $i in array element at - line 10.
Use of uninitialized value $k in delete at - line 10.
Use of uninitialized value $j in addition (+) at - line 11.
Use of uninitialized value $i in addition (+) at - line 11.
Use of uninitialized value $j in addition (+) at - line 11.
Use of uninitialized value $k in hash element at - line 11.
Use of uninitialized value $i in array element at - line 12.
Use of uninitialized value $k in hash element at - line 12.