Copy PADTMPs explicitly returned from lv subs
authorFather Chrysostomos <sprout@cpan.org>
Thu, 23 Jun 2011 01:37:59 +0000 (18:37 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Thu, 23 Jun 2011 13:04:00 +0000 (06:04 -0700)
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).

pp_ctl.c

index 4324253..d403745 100644 (file)
--- 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;
        }