summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/overload.t21
-rw-r--r--pp_hot.c13
2 files changed, 29 insertions, 5 deletions
diff --git a/lib/overload.t b/lib/overload.t
index 055daab30f..5f2e0c2902 100644
--- a/lib/overload.t
+++ b/lib/overload.t
@@ -48,7 +48,7 @@ package main;
$| = 1;
BEGIN { require './test.pl'; require './charset_tools.pl' }
-plan tests => 5362;
+plan tests => 5363;
use Scalar::Util qw(tainted);
@@ -3174,3 +3174,22 @@ package Stringify {
::is $count, $stringify, $code;
}
}
+
+# RT #133789: in multiconcat with overload, the overloaded ref returned
+# from the overload method was being assigned to the pad targ, causing
+# a delay to the freeing of the object
+
+package RT33789 {
+ use overload
+ '.' => sub { $_[0] }
+ ;
+
+ my $destroy = 0;
+ sub DESTROY { $destroy++ }
+
+ {
+ my $o = bless [];
+ my $result = '1' . ( '2' . ( '3' . ( '4' . ( '5' . $o ) ) ) );
+ }
+ ::is($destroy, 1, "RT #133789: delayed destroy");
+}
diff --git a/pp_hot.c b/pp_hot.c
index fd439a5e4b..7c6b3a8fc9 100644
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -1097,15 +1097,20 @@ PP(pp_multiconcat)
SP = toparg - stack_adj + 1;
- /* Assign result of all RHS concats (left) to LHS (targ).
+ /* Return the result of all RHS concats, unless this op includes
+ * an assign ($lex = x.y.z or expr = x.y.z), in which case copy
+ * to target (which will be $lex or expr).
* If we are appending, targ will already have been appended to in
* the loop */
- if (is_append)
- SvTAINT(targ);
- else {
+ if ( !is_append
+ && ( (PL_op->op_flags & OPf_STACKED)
+ || (PL_op->op_private & OPpTARGET_MY))
+ ) {
sv_setsv(targ, left);
SvSETMAGIC(targ);
}
+ else
+ targ = left;
SETs(targ);
RETURN;
}