summaryrefslogtreecommitdiff
path: root/op.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2012-01-28 19:14:39 -0800
committerFather Chrysostomos <sprout@cpan.org>2012-01-28 20:43:06 -0800
commit0865059d9cec0d198515152182d4283ab634748e (patch)
tree1b680fe427fe875c15229e0a912817916e167588 /op.c
parent422d6414d26e413a69e401207deaf53fb640b369 (diff)
downloadperl-0865059d9cec0d198515152182d4283ab634748e.tar.gz
[perl #109264] ->method(my(...)) forcing lvalue cx
A simple my($foo,$bar) list is flagged as an lvalue: $ ./perl -Ilib -MO=Concise -e 'my($foo,$bar)' 7 <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 1 -e:1) v:{ ->3 6 <@> list vKPM/128 ->7 3 <0> pushmark vM/128 ->4 4 <0> padsv[$foo:1,2] vM/LVINTRO ->5 5 <0> padsv[$bar:1,2] vM/LVINTRO ->6 -e syntax OK That 128 that the list op is the same flag as LVINTRO. When a method call is compiled, the list op for the argument list is itself converted into an entersub op. That LVINTRO flag is never turned off. So foo->bar(my($foo,$bar)) becomes this: $ ./perl -Ilib -MO=Concise -e 'foo->bar(my($foo,$bar))' 9 <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 1 -e:1) v:{ ->3 8 <1> entersub[t4] vKMS/LVINTRO,TARG ->9 3 <0> pushmark sM/128 ->4 4 <$> const[PV "foo"] sM/BARE ->5 5 <0> padsv[$foo:1,2] lM/LVINTRO ->6 6 <0> padsv[$bar:1,2] lM/LVINTRO ->7 7 <$> method_named[PV "bar"] ->8 -e syntax OK This was rarely a problem until commit da1dff948 added lvalue check- ing for method calls (a fifth bug fix in that commit not mentioned in the commit message). Calling the method will now result in ‘Can't modify non-lvalue subrou- tine call’ unless the method has the :lvalue attribute. Before that, this would only cause problems with lvalue methods: $ perl -le ' sub clear_queue:lvalue { warn "called"; undef } 3==main->clear_queue(my ($id, $name)) ' called at -e line 2. Can't return undef from lvalue subroutine at -e line 3. Calling it with ($id, $name) was fine, and allowed undef to be returned. Perl_localize in op.c (which is called for my, our and local) calls my() (aka Perl_my_attrs) on the list itself for my or our. Perl_my_attrs was setting flags on the list, not just on its children. So this commit modifies my_attrs not to set any flags on the list op itself. local() was not affected, as it goes through op_lvalue_flags instead of my_attrs, and op_lvalue_flags doesn’t set flags on list ops (I mean ops of type OP_LIST, not listops in general). I added tests for it anyway.
Diffstat (limited to 'op.c')
-rw-r--r--op.c1
1 files changed, 1 insertions, 0 deletions
diff --git a/op.c b/op.c
index 479d2ba10e..09f45d06ea 100644
--- a/op.c
+++ b/op.c
@@ -2402,6 +2402,7 @@ S_my_kid(pTHX_ OP *o, OP *attrs, OP **imopsp)
OP *kid;
for (kid = cLISTOPo->op_first; kid; kid = kid->op_sibling)
my_kid(kid, attrs, imopsp);
+ return o;
} else if (type == OP_UNDEF
#ifdef PERL_MAD
|| type == OP_STUB