diff options
-rw-r--r-- | pod/perldelta.pod | 8 | ||||
-rw-r--r-- | pp_ctl.c | 2 | ||||
-rw-r--r-- | t/op/gmagic.t | 15 |
3 files changed, 24 insertions, 1 deletions
diff --git a/pod/perldelta.pod b/pod/perldelta.pod index 944a7b874d..2b98f60e06 100644 --- a/pod/perldelta.pod +++ b/pod/perldelta.pod @@ -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 @@ -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) { diff --git a/t/op/gmagic.t b/t/op/gmagic.t index 2ec1f1126c..64e7a2aebb 100644 --- a/t/op/gmagic.t +++ b/t/op/gmagic.t @@ -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(); |