[perl #55786] [PATCH blead] Re: Overload Segfaulting
Rick Delaney [Sat, 14 Jun 2008 11:51:01 +0000 (04:51 -0700)]
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

lib/overload.pm
lib/overload.t
pp.h

index c02fddb..e5b2f97 100644 (file)
@@ -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
 
index 44ead7e..7c2476c 100644 (file)
@@ -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 7b5f322..8345af4 100644 (file)
--- 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