summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pod/perldelta.pod4
-rw-r--r--pp.c7
-rw-r--r--t/op/reverse.t16
3 files changed, 25 insertions, 2 deletions
diff --git a/pod/perldelta.pod b/pod/perldelta.pod
index 46f5e57092..1ea6c597ec 100644
--- a/pod/perldelta.pod
+++ b/pod/perldelta.pod
@@ -387,7 +387,9 @@ files in F<ext/> and F<lib/> are best summarized in L</Modules and Pragmata>.
=item *
-XXX
+The in-place reverse optimisation now correctly strengthens weak
+references using the L<C<sv_rvunweaken()>|perlapi/sv_rvunweaken>
+API function.
=back
diff --git a/pp.c b/pp.c
index 42bea4db70..382ee96fe9 100644
--- a/pp.c
+++ b/pp.c
@@ -5586,7 +5586,14 @@ PP(pp_reverse)
SV * const tmp = *begin;
*begin++ = *end;
*end-- = tmp;
+
+ if (tmp && SvWEAKREF(tmp))
+ sv_rvunweaken(tmp);
}
+
+ /* make sure we catch the middle element */
+ if (begin == end && *begin && SvWEAKREF(*begin))
+ sv_rvunweaken(*begin);
}
}
}
diff --git a/t/op/reverse.t b/t/op/reverse.t
index 74e6295446..fd06560fdf 100644
--- a/t/op/reverse.t
+++ b/t/op/reverse.t
@@ -6,7 +6,7 @@ BEGIN {
set_up_inc('../lib');
}
-plan tests => 23;
+plan tests => 25;
is(reverse("abc"), "cba", 'simple reverse');
@@ -91,3 +91,17 @@ use Tie::Array;
my $c = scalar reverse($b);
is($a, $c, 'Unicode string double reversal matches original');
}
+
+# in-place reversing of weak references
+SKIP: {
+ skip_if_miniperl("no dynamic loading on miniperl, no extension Scalar::Util", 2);
+ require Scalar::Util;
+ my @a = map { \(my $dummy = $_) } 1..5; # odd number of elements
+ my @r = @a[0,2]; # middle and non-middle element
+ Scalar::Util::weaken($a[0]);
+ Scalar::Util::weaken($a[2]);
+ @a = reverse @a;
+ @r = ();
+ ok defined $a[-1] && ${$a[-1]} eq '1', "in-place reverse strengthens weak reference";
+ ok defined $a[2] && ${$a[2]} eq '3', "in-place reverse strengthens weak reference in the middle";
+}