Stop lvalue subs from copying read-only scalars
authorFather Chrysostomos <sprout@cpan.org>
Thu, 16 Jun 2011 13:02:23 +0000 (06:02 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Fri, 17 Jun 2011 03:17:52 +0000 (20:17 -0700)
They were only doing so in reference context (subroutine args,
for(...)).

Explicit return already worked, but only because I didn’t write it
well.  I’m in the process of trying to merge the two.

pp_hot.c
t/op/sub_lval.t

index 526adb8..f1c4977 100644 (file)
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -2693,9 +2693,7 @@ PP(pp_leavesublv)
            for (mark = newsp + 1; mark <= SP; mark++) {
                if (SvTEMP(*mark))
                    NOOP;
-               else if (SvFLAGS(*mark) & SVs_PADTMP
-                     || (SvFLAGS(*mark) & (SVf_READONLY|SVf_FAKE))
-                          == SVf_READONLY)
+               else if (SvFLAGS(*mark) & SVs_PADTMP)
                    *mark = sv_mortalcopy(*mark);
                else {
                    /* Can be a localized value subject to deletion. */
index 321f546..e4518ff 100644 (file)
@@ -3,7 +3,7 @@ BEGIN {
     @INC = '../lib';
     require './test.pl';
 }
-plan tests=>156;
+plan tests=>158;
 
 sub a : lvalue { my $a = 34; ${\(bless \$a)} }  # Return a temporary
 sub b : lvalue { ${\shift} }
@@ -802,3 +802,14 @@ for my $sub (
     is +(&$sub)[0], 72, "sub returning pad var in list context$suffix";
 }
 continue { $suffix = ' (explicit return)' }
+
+# Returning read-only values in reference context
+$suffix = '';
+for (
+         sub :lvalue { $] }->(),
+         sub :lvalue { return $] }->()
+) {
+    is \$_, \$], 'read-only values are returned in reference context'
+                .$suffix             # (they used to be copied)
+}
+continue { $suffix = ' (explicit return)' }