summaryrefslogtreecommitdiff
path: root/pp_ctl.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2011-06-22 18:37:59 -0700
committerFather Chrysostomos <sprout@cpan.org>2011-06-23 06:04:00 -0700
commit80422e24c8b2c134c9ee2ac7d87aa9f750192f20 (patch)
treee494feb847da892a228ffb382421b6cb854786a3 /pp_ctl.c
parent37395ff5f2b5fa17c5b7cebede056b6742e28e46 (diff)
downloadperl-80422e24c8b2c134c9ee2ac7d87aa9f750192f20.tar.gz
Copy PADTMPs explicitly returned from lv subs
I don’t believe this changes any observable behaviour, Devel::Peek aside. If it does, it fixes bugs. I am making this change for two reasons: • PADTMPs can be a bit buggy and letting them escape their subroutines can make the bugs harder to fix. • This brings explicit and implicit return from lvalue subroutines one step closer (for the sake of merging the code).
Diffstat (limited to 'pp_ctl.c')
-rw-r--r--pp_ctl.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/pp_ctl.c b/pp_ctl.c
index 4324253692..d40374598c 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -2226,6 +2226,7 @@ STATIC void
S_return_lvalues(pTHX_ SV **mark, SV **sp, SV **newsp, I32 gimme,
PERL_CONTEXT *cx)
{
+ const bool ref = !!(CxLVAL(cx) & OPpENTERSUB_INARGS);
if (gimme == G_SCALAR) {
if (MARK < SP) {
if (cx->blk_sub.cv && CvDEPTH(cx->blk_sub.cv) > 1) {
@@ -2260,12 +2261,14 @@ S_return_lvalues(pTHX_ SV **mark, SV **sp, SV **newsp, I32 gimme,
}
else if (gimme == G_ARRAY) {
assert (!(CxLVAL(cx) & OPpENTERSUB_DEREF));
- if (!CxLVAL(cx) || CxLVAL(cx) & OPpENTERSUB_INARGS)
+ if (ref || !CxLVAL(cx))
while (++MARK <= SP)
*++newsp =
SvTEMP(*MARK)
? *MARK
- : sv_2mortal(SvREFCNT_inc_simple_NN(*MARK));
+ : ref && SvFLAGS(*MARK) & SVs_PADTMP
+ ? sv_mortalcopy(*MARK)
+ : sv_2mortal(SvREFCNT_inc_simple_NN(*MARK));
else while (++MARK <= SP) {
*++newsp = *MARK;
}