summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2011-06-16 06:02:23 -0700
committerFather Chrysostomos <sprout@cpan.org>2011-06-16 20:17:52 -0700
commitad37a74e7dc5e204efc84791373a791f142ac7b4 (patch)
tree26f705e25b49e91c10c0ca0dff9b7c8368c0d041
parent7393165ef277e989fdf63df19ea17698bf83d8db (diff)
downloadperl-ad37a74e7dc5e204efc84791373a791f142ac7b4.tar.gz
Stop lvalue subs from copying read-only scalars
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.
-rw-r--r--pp_hot.c4
-rw-r--r--t/op/sub_lval.t13
2 files changed, 13 insertions, 4 deletions
diff --git a/pp_hot.c b/pp_hot.c
index 526adb88b9..f1c4977cd2 100644
--- 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. */
diff --git a/t/op/sub_lval.t b/t/op/sub_lval.t
index 321f5461f2..e4518ffbc9 100644
--- a/t/op/sub_lval.t
+++ b/t/op/sub_lval.t
@@ -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)' }