This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Call get-magic on temp returned under recursion
authorFather Chrysostomos <sprout@cpan.org>
Fri, 22 Jul 2011 19:14:28 +0000 (12:14 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Fri, 22 Jul 2011 19:15:02 +0000 (12:15 -0700)
This fixes a regression introduced in 5.15.0.

Commit 767eda44 made autovivification work with scalars returned from
lvalue subs.  In doing so, as it made entersub an autovivifying op,
it had to add SvGETMAGIC calls to pp_return and pp_leavesub.  (See
767eda44’s commit message for details.)  In one spot in pp_return,
the SvGETMAGIC call was added to the wrong branch of an if/else con-
dition, causing a regression.  Explicitly returning from a recursive
subroutine call in autovivifying context would not call get-magic on
the returned value.

pod/perldelta.pod
pp_ctl.c
t/op/gmagic.t

index 944a7b8..2b98f60 100644 (file)
@@ -372,6 +372,14 @@ a tied operand when doing a symbolic dereference (looking up a variable by
 name, which is not permitted under C<use strict 'refs'>).  Only C<&{}> did
 not have this problem.  This has been fixed.
 
+=item *
+
+A minor regression introduced in 5.15.0 has been fixed.  Dereferencing a
+magical mortal (e.g., the return value of C<delete> on a tied hash element)
+explicitly returned from a subroutine called recursively was not calling
+C<FETCH>.  This would affect code like C<@{ foo() }> where the C<foo> sub
+contains C<return delete $hash{elem}> and is calling itself.
+
 =back
 
 =head1 Known Problems
index 533ff5f..7f4371f 100644 (file)
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -2499,13 +2499,13 @@ PP(pp_return)
                        *++newsp = SvREFCNT_inc(*SP);
                        FREETMPS;
                        sv_2mortal(*newsp);
+                       if (gmagic) SvGETMAGIC(*newsp);
                    }
                    else {
                        sv = SvREFCNT_inc(*SP); /* FREETMPS could clobber it */
                        FREETMPS;
                        *++newsp = sv_mortalcopy(sv);
                        SvREFCNT_dec(sv);
-                       if (gmagic) SvGETMAGIC(sv);
                    }
                }
                else if (SvTEMP(*SP) && SvREFCNT(*SP) == 1) {
index 2ec1f11..64e7a2a 100644 (file)
@@ -81,6 +81,21 @@ ok($wgot == 0, 'a plain *foo causes no set-magic');
   () = sub { return delete $_{elem} }->()->[3];
   expected_tie_calls $tied_to, 1, 0,
       'mortal magic var is explicitly returned in autoviv context';
+
+  $tied_to = tie $_{elem}, "Tie::Monitor";
+  my $rsub;
+  $rsub = sub { if ($_[0]) { delete $_{elem} } else { &$rsub(1)->[3] } };
+  &$rsub;
+  expected_tie_calls $tied_to, 1, 0,
+     'mortal magic var is implicitly returned in autoviv context';
+
+  $tied_to = tie $_{elem}, "Tie::Monitor";
+  $rsub = sub {
+    if ($_[0]) { return delete $_{elem} } else { &$rsub(1)->[3] }
+  };
+  &$rsub;
+  expected_tie_calls $tied_to, 1, 0,
+      'mortal magic var is explicitly returned in autoviv context';
 }
 
 done_testing();