This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[perl #118753] Remove erroneous elsif("") warning
authorFather Chrysostomos <sprout@cpan.org>
Tue, 20 Aug 2013 20:21:14 +0000 (13:21 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Wed, 21 Aug 2013 01:00:46 +0000 (18:00 -0700)
‘5 || foo’ gets optimised down to a plain ‘5’.  If that happens in
void context, we should not get a warning, as constant folding is not
supposed to change behaviour.

We accomplish that by flagging the constant with
OPpCONST_SHORTCIRCUIT.  The code that warns checks for the absence of
that flag first.

Commit f6f3a1fea, in order to improve line number accuracy in elsif,
changed the condition in elsif() to have a nulled COP (containing line
numbers) with the condition as its kidop.

That prevented constant folding from happening, so commit 71c4dbc37
implemented a function (search_const) to search to find a constant
below the nulled COP, but only used it to make folding happen, and did
not use it for OPpCONST_SHORTCIRCUIT.

The result was that if($foo){}elsif(""){} (mostly equivalent to
$foo ? do{} : "" && do {} internally) got folded to $foo ? do{} : ""
without OPpCONST_SHORTCIRCUIT being set on the final "".  So the warn-
ing occurs.

This commit uses search_const to set OPpCONST_SHORTCIRCUIT, and the
warning vanishes.

op.c
t/lib/warnings/op

diff --git a/op.c b/op.c
index c911b79..6776dc7 100644 (file)
--- a/op.c
+++ b/op.c
@@ -5901,8 +5901,8 @@ S_new_logop(pTHX_ I32 type, I32 flags, OP** firstp, OP** otherp)
            }
 
            *otherp = NULL;
-           if (first->op_type == OP_CONST)
-               first->op_private |= OPpCONST_SHORTCIRCUIT;
+           if (cstop->op_type == OP_CONST)
+               cstop->op_private |= OPpCONST_SHORTCIRCUIT;
            if (PL_madskills) {
                first = newUNOP(OP_NULL, 0, first);
                op_getmad(other, first, '2');
index c38bcde..6fdcf3f 100644 (file)
@@ -558,6 +558,7 @@ U;
 qq/"   \n/;
 5 || print "bad\n";    # test OPpCONST_SHORTCIRCUIT
 print "boo\n" if U;    # test OPpCONST_SHORTCIRCUIT
+if($foo){}elsif(""){}  # test OPpCONST_SHORTCIRCUIT
 no warnings 'void' ;
 "abc"; # OP_CONST
 7 ; # OP_CONST