Propagate lvalue context to && and ||
authorFather Chrysostomos <sprout@cpan.org>
Thu, 24 Oct 2013 21:45:34 +0000 (14:45 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Fri, 25 Oct 2013 00:50:19 +0000 (17:50 -0700)
I did this for the last statement in an lvalue sub (and the argument
to ‘return’ in an lvalue sub) in commit 2ec7f6f2428.

It turns out that it needs to apply in other lvaluish contexts, too:

$ ./perl -Ilib -le 'for($a||$b){$_++} print $b'
1
$ ./perl -Ilib -le 'for(pos $a || pos $b){$_++} print pos $b'
Modification of a read-only value attempted at -e line 1.

If I can assign to $b through this construct, then why not pos?

op.c
t/op/or.t

diff --git a/op.c b/op.c
index 812341d..7a35797 100644 (file)
--- a/op.c
+++ b/op.c
@@ -2298,10 +2298,8 @@ Perl_op_lvalue_flags(pTHX_ OP *o, I32 type, U32 flags)
 
     case OP_AND:
     case OP_OR:
-       if (type == OP_LEAVESUBLV) {
-           op_lvalue(cLOGOPo->op_first,             type);
-           op_lvalue(cLOGOPo->op_first->op_sibling, type);
-       }
+       op_lvalue(cLOGOPo->op_first,             type);
+       op_lvalue(cLOGOPo->op_first->op_sibling, type);
        goto nomod;
     }
 
index 5260780..7a4997b 100644 (file)
--- a/t/op/or.t
+++ b/t/op/or.t
@@ -25,7 +25,7 @@ sub FETCH {
 package main;
 require './test.pl';
 
-plan( tests => 8 );
+plan( tests => 9 );
 
 
 my ($a, $b, $c);
@@ -66,3 +66,9 @@ $c = $a || $b;
     local $TODO = 'Double FETCH';
     is($c, 1,   '   $tied || $var');
 }
+
+$y = " ";
+for (pos $x || pos $y) {
+    eval { $_++ };
+}
+is(pos($y) || $@, 1, "|| propagates lvaluish context");