Make lvalue subs copy returned PADTMPs in rvalue cx
authorFather Chrysostomos <sprout@cpan.org>
Thu, 26 Apr 2012 01:29:12 +0000 (18:29 -0700)
committerRicardo Signes <rjbs@cpan.org>
Mon, 25 Jun 2012 23:46:29 +0000 (19:46 -0400)
commit71720ae3f661a1da65efc277229e96a386817e89
tree4ec2a844038546e495237a1a4c9f0672776ed2ce
parentd6f272d0b5888beecd8cdd3904b8449f1268e0ba
Make lvalue subs copy returned PADTMPs in rvalue cx

I was trying to write a JAPH, but did not get what I expected:

$ ./perl -Ilib -e '@UNIVERSAL::ISA = CORE; print "just another "->ucfirst, "perl hacker,\n"->ucfirst'
Perl hacker,
Perl hacker,

This happened because coresubs use leavesublv, to avoid copying the
return value wastefully.

But since this is exactly the same ucfirst op being called each time
(the one in &CORE::ucfirst’s op tree), and since ucfirst uses TARG, we
end up with the same scalar.

We have the same problem with lvalue subs:

$ ./perl -Ilib -e 'sub UNIVERSAL::ucfirst :lvalue { ucfirst $_[0] } print "just another "->ucfirst, "perl hacker,\n"->ucfirst'
Perl hacker,
Perl hacker,

(This is not a regression, as 5.14 gave ‘Can't modify ucfirst in
lvalue subroutine return’.)

So ‘fixing’ coresubs would not be a solution, but a workaround.

The solution therefore is for leavesublv to copy PADTMPs in
rvalue context.

Commit 80422e24c fixed this for potential lvalue list context (i.e.,
for(lvsub()) {...}), but it wasn’t sufficient.
pp_ctl.c
t/op/coresubs.t
t/op/sub_lval.t