summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRick Delaney <rick@consumercontact.com>2008-06-14 04:51:01 -0700
committerRafael Garcia-Suarez <rgarciasuarez@gmail.com>2008-06-15 15:20:41 +0000
commit49c95d583ee26e3f8629868ab6da323b7c424640 (patch)
tree86172b333c6e0880f5a4252bc2f84c971849d5a1
parentcd1a9f552fc30b37bf1b6c770f1367c112fd1b1d (diff)
downloadperl-49c95d583ee26e3f8629868ab6da323b7c424640.tar.gz
[perl #55786] [PATCH blead] Re: Overload Segfaulting
From: Rick Delaney (via RT) <perlbug-followup@perl.org> Message-ID: <rt-3.6.HEAD-22068-1213469460-652.55786-75-0@perl.org> p4raw-id: //depot/perl@34055
-rw-r--r--lib/overload.pm6
-rw-r--r--lib/overload.t18
-rw-r--r--pp.h6
3 files changed, 24 insertions, 6 deletions
diff --git a/lib/overload.pm b/lib/overload.pm
index c02fddbfab..e5b2f97b6a 100644
--- a/lib/overload.pm
+++ b/lib/overload.pm
@@ -588,7 +588,8 @@ appear as lvalue when the above code is executed.
If the copy constructor is required during the execution of some mutator,
but a method for C<'='> was not specified, it can be autogenerated as a
-string copy if the object is a plain scalar.
+string copy if the object is a plain scalar or a simple assignment if it
+is not.
=over 5
@@ -675,7 +676,8 @@ C<E<lt>=E<gt>> or C<cmp>:
=item I<Copy operator>
can be expressed in terms of an assignment to the dereferenced value, if this
-value is a scalar and not a reference.
+value is a scalar and not a reference, or simply a reference assignment
+otherwise.
=back
diff --git a/lib/overload.t b/lib/overload.t
index 44ead7ef60..7c2476cc8c 100644
--- a/lib/overload.t
+++ b/lib/overload.t
@@ -47,7 +47,7 @@ sub numify { 0 + "${$_[0]}" } # Not needed, additional overhead
package main;
$| = 1;
-use Test::More tests => 556;
+use Test::More tests => 558;
$a = new Oscalar "087";
@@ -1427,4 +1427,20 @@ foreach my $op (qw(<=> == != < <= > >=)) {
is($aref**1, $num_val, 'exponentiation of ref');
}
+{
+ package CopyConstructorFallback;
+ use overload
+ '++' => sub { "$_[0]"; $_[0] },
+ fallback => 1;
+ sub new { bless {} => shift }
+
+ package main;
+
+ my $o = CopyConstructorFallback->new;
+ my $x = $o++; # would segfault
+ my $y = ++$o;
+ is($x, $o, "copy constructor falls back to assignment (postinc)");
+ is($y, $o, "copy constructor falls back to assignment (preinc)");
+}
+
# EOF
diff --git a/pp.h b/pp.h
index 7b5f322f1c..8345af4b80 100644
--- a/pp.h
+++ b/pp.h
@@ -487,9 +487,9 @@ Does not use C<TARG>. See also C<XPUSHu>, C<mPUSHu> and C<PUSHu>.
/* SV* ref causes confusion with the member variable
changed SV* ref to SV* tmpRef */
-#define RvDEEPCP(rv) STMT_START { SV* tmpRef=SvRV(rv); \
- if (SvREFCNT(tmpRef)>1) { \
- SvRV_set(rv, AMG_CALLun(rv,copy)); \
+#define RvDEEPCP(rv) STMT_START { SV* tmpRef=SvRV(rv); SV* rv_copy; \
+ if (SvREFCNT(tmpRef)>1 && (rv_copy = AMG_CALLun(rv,copy))) { \
+ SvRV_set(rv, rv_copy); \
SvREFCNT_dec(tmpRef); \
} } STMT_END