From: Rick Delaney Date: Sat, 14 Jun 2008 11:51:01 +0000 (-0700) Subject: [perl #55786] [PATCH blead] Re: Overload Segfaulting X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=49c95d583ee26e3f8629868ab6da323b7c424640;p=p5sagit%2Fp5-mst-13.2.git [perl #55786] [PATCH blead] Re: Overload Segfaulting From: Rick Delaney (via RT) Message-ID: p4raw-id: //depot/perl@34055 --- diff --git a/lib/overload.pm b/lib/overload.pm index c02fddb..e5b2f97 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> or C: =item I 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 44ead7e..7c2476c 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 7b5f322..8345af4 100644 --- a/pp.h +++ b/pp.h @@ -487,9 +487,9 @@ Does not use C. See also C, C and C. /* 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