summaryrefslogtreecommitdiff
path: root/gv.c
diff options
context:
space:
mode:
authorMichael Breen <perl@mbreen.com>2010-11-30 17:48:50 +0000
committerDavid Mitchell <davem@iabyn.com>2010-12-03 12:16:06 +0000
commitbf5522a13a381257966e7ed6b731195a873b153e (patch)
tree97867c011ecfc5dc5d5d50a764fb7078ffd77828 /gv.c
parent4a039ddd5c2357bd4dadf1ccf8ad58c552671247 (diff)
downloadperl-bf5522a13a381257966e7ed6b731195a873b153e.tar.gz
[perl #71286] fallback/nomethod failures
This fixes two bugs related to overload and fallback on binary ops. First, if *either* of the args has a 'nomethod', this will now be used; previously the RH nomethod was ignored if the LH arg had fallback value of undef or 1. Second, if neither arg has a 'nomethod', then the fallback to the built-in op will now only occur if *both* args have fallback => 1; previously it would do so if the *RHS* had fallback => 1. Clearly the old behaviour was wrong, but there were two ways to fix this: (a) *both* args have fallback => 1; (b) *either* arg has fallback=> 1. It could be argued either way, but the the choice of 'both' was that classes that hadn't set 'fallback => 1' were implicitly implying that their objects aren't suitable for fallback, regardless of the presence of conversion methods.
Diffstat (limited to 'gv.c')
-rw-r--r--gv.c25
1 files changed, 19 insertions, 6 deletions
diff --git a/gv.c b/gv.c
index 9cfc70d00c..5d7837c01c 100644
--- a/gv.c
+++ b/gv.c
@@ -2076,6 +2076,7 @@ Perl_amagic_call(pTHX_ SV *left, SV *right, int method, int flags)
int postpr = 0, force_cpy = 0;
int assign = AMGf_assign & flags;
const int assignshift = assign ? 1 : 0;
+ int use_default_op = 0;
#ifdef DEBUGGING
int fl=0;
#endif
@@ -2239,9 +2240,8 @@ Perl_amagic_call(pTHX_ SV *left, SV *right, int method, int flags)
&& (cv = cvp[off=method])) { /* Method for right
* argument found */
lr=1;
- } else if (((ocvp && oamtp->fallback > AMGfallNEVER
- && (cvp=ocvp) && (lr = -1))
- || (cvp && amtp->fallback > AMGfallNEVER && (lr=1)))
+ } else if (((cvp && amtp->fallback > AMGfallNEVER)
+ || (ocvp && oamtp->fallback > AMGfallNEVER))
&& !(flags & AMGf_unary)) {
/* We look for substitution for
* comparison operations and
@@ -2269,7 +2269,17 @@ Perl_amagic_call(pTHX_ SV *left, SV *right, int method, int flags)
off = scmp_amg;
break;
}
- if ((off != -1) && (cv = cvp[off]))
+ if (off != -1) {
+ if (ocvp && (oamtp->fallback > AMGfallNEVER)) {
+ cv = ocvp[off];
+ lr = -1;
+ }
+ if (!cv && (cvp && amtp->fallback > AMGfallNEVER)) {
+ cv = cvp[off];
+ lr = 1;
+ }
+ }
+ if (cv)
postpr = 1;
else
goto not_found;
@@ -2289,7 +2299,10 @@ Perl_amagic_call(pTHX_ SV *left, SV *right, int method, int flags)
notfound = 1; lr = -1;
} else if (cvp && (cv=cvp[nomethod_amg])) {
notfound = 1; lr = 1;
- } else if ((amtp && amtp->fallback >= AMGfallYES) && !DEBUG_o_TEST) {
+ } else if ((use_default_op =
+ (!ocvp || oamtp->fallback >= AMGfallYES)
+ && (!cvp || amtp->fallback >= AMGfallYES))
+ && !DEBUG_o_TEST) {
/* Skip generating the "no method found" message. */
return NULL;
} else {
@@ -2313,7 +2326,7 @@ Perl_amagic_call(pTHX_ SV *left, SV *right, int method, int flags)
SvAMAGIC(right)?
HvNAME_get(SvSTASH(SvRV(right))):
""));
- if (amtp && amtp->fallback >= AMGfallYES) {
+ if (use_default_op) {
DEBUG_o( Perl_deb(aTHX_ "%s", SvPVX_const(msg)) );
} else {
Perl_croak(aTHX_ "%"SVf, SVfARG(msg));