This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Fix assert fail with my $x; sub() {$x}
authorFather Chrysostomos <sprout@cpan.org>
Mon, 17 Nov 2014 02:23:34 +0000 (18:23 -0800)
committerFather Chrysostomos <sprout@cpan.org>
Mon, 17 Nov 2014 02:23:34 +0000 (18:23 -0800)
If $x is not referenced or used in lvalue context elsewhere, then the
constant sub can actually share the same scalar as the enclosing sub’s
pad.  It doesn’t need to copy.  And we don’t in that case, as of
v5.21.5-421-g04472a8.  But we need to make sure the PADTMP flag is
turned off at scope exit if the pad has the only reference to the sub.
(The PADTMP flag has been turned on as of v5.21.5-391-g5543332.)

scope.c
t/op/const-optree.t

diff --git a/scope.c b/scope.c
index 43e2e03..8e13071 100644 (file)
--- a/scope.c
+++ b/scope.c
@@ -1076,6 +1076,7 @@ Perl_leave_scope(pTHX_ I32 base)
                         SvFLAGS(sv) &=~ (SVf_OK|SVf_IVisUV|SVf_UTF8);
                         break;
                     }
+                    SvPADTMP_off(sv);
                     SvPADSTALE_on(sv); /* mark as no longer live */
                 }
                 else { /* Someone has a claim on this, so abandon it. */
index aa5bee6..0b961d1 100644 (file)
@@ -8,7 +8,7 @@ BEGIN {
     require './test.pl';
     @INC = '../lib';
 }
-plan 166;
+plan 167;
 
 # @tests is an array of hash refs, each of which can have various keys:
 #
@@ -476,3 +476,10 @@ for \%_ (@tests) {
 
     &{$_{finally} or next}
 }
+
+# This used to fail an assertion in leave_scope.  For some reason, it did
+# not fail within the framework above.
+sub  { my $x = "x"; my $sub = sub () { $x }; undef $sub; } ->();
+pass("No assertion failure when turning on PADSTALE on lexical shared by"
+    ." erstwhile constant");
+