int filled = 0, have_ovl = 0;
int i, lim = 1;
- /* Work with "fallback" key, which we assume to be first in PL_AMG_names */
+ /* The first key in PL_AMG_names is the overloadedness indicator, which
+ allows us to skip overloading entries for non-overloaded classes. */
/* Try to find via inheritance. */
GV *gv = gv_fetchmeth_pvn(stash, PL_AMG_names[0], 2, -1, 0);
- SV * const sv = gv ? GvSV(gv) : NULL;
CV* cv;
if (!gv)
lim = DESTROY_amg; /* Skip overloading entries. */
-#ifdef PERL_DONT_CREATE_GVSV
- else if (!sv) {
+
+ else {
+
+ /* The "fallback" key is special-cased here, being absent from the
+ list in PL_AMG_names. */
+
+ SV *sv;
+ gv = gv_fetchmeth_pvn(stash, "(fallback", 9, -1, 0);
+
+ if (!gv || !(sv = GvSV(gv)))
NOOP; /* Equivalent to !SvTRUE and !SvOK */
- }
-#endif
- else if (SvTRUE(sv))
+ else if (SvTRUE(sv))
amt.fallback=AMGfallYES;
- else if (SvOK(sv))
+ else if (SvOK(sv))
amt.fallback=AMGfallNEVER;
+ }
for (i = 1; i < lim; i++)
amt.table[i] = NULL;
my %arg = @_;
my ($sub, $fb);
$ {$package . "::OVERLOAD"}{dummy}++; # Register with magic by touching.
- $fb = ${$package . "::()"}; # preserve old fallback value RT#68196
*{$package . "::()"} = \&nil; # Make it findable via fetchmethod.
for (keys %arg) {
if ($_ eq 'fallback') {
- $fb = $arg{$_};
+ for my $sym (*{$package . "::(fallback"}) {
+ *$sym = \&nil; # Make it findable via fetchmethod.
+ $$sym = $arg{$_};
+ }
} else {
warnings::warnif("overload arg '$_' is invalid")
unless $ops_seen{$_};
*{$package . "::(" . $_} = \&{ $sub };
}
}
- ${$package . "::()"} = $fb; # Make it findable too (fallback only).
}
sub import {
${$package . "::OVERLOAD"}{dummy}++; # Upgrade the table
shift;
for (@_) {
- if ($_ eq 'fallback') {
- undef $ {$package . "::()"};
- } else {
delete $ {$package . "::"}{"(" . $_};
- }
}
}
=back
-Note that since the value of the C<fallback> key is not a subroutine,
-its inheritance is not governed by the above rules. In the current
-implementation, the value of C<fallback> in the first overloaded
-ancestor is used, but this is accidental and subject to change.
+Note that in Perl version prior to 5.18 inheritance of the C<fallback> key
+was not governed by the above rules. The value of C<fallback> in the first
+overloaded ancestor was used. This was fixed in 5.18 to follow the usual
+rules of inheritance.
=head2 Run-time Overloading
=item *
+This bug was fixed in Perl 5.18, but may still trip you up if you are using
+older versions:
+
For the purpose of inheritance every overloaded package behaves as if
C<fallback> is present (possibly undefined). This may create
interesting effects if some package is not overloaded, but inherits
$| = 1;
BEGIN { require './test.pl' }
-plan tests => 5048;
+plan tests => 5050;
use Scalar::Util qw(tainted);
'no overload "fallback" does not stop overload from working';
ok !eval { () = $a eq 'mpizeli'; 1 },
'no overload "fallback" resets fallback to undef on overloaded class';
+{ package ent; use overload fallback => 0, abs => sub{};
+ our@ISA = 'huorn';
+ package huorn;
+ use overload fallback => 1;
+ package ent;
+ no overload "fallback"; # disable previous declaration
+}
+$a = bless [], ent::;
+is eval {"$a"}, overload::StrVal($a),
+ 'no overload undoes fallback declaration completetly'
+ or diag $@;
+
+# inherited fallback
+{
+ package pervyy;
+ our @ISA = 'vtoryy';
+ use overload "abs" =>=> sub {};
+ package vtoryy;
+ use overload fallback => 1, 'sin' =>=> sub{}
+}
+$a = bless [], pervyy::;
+is eval {"$a"}, overload::StrVal($a),
+ 'fallback is inherited by classes that have their own overloading'
+ or diag $@;
{ # undefining the overload stash -- KEEP THIS TEST LAST
package ant;