summaryrefslogtreecommitdiff
path: root/ext/mro
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2010-12-02 08:30:51 -0800
committerFather Chrysostomos <sprout@cpan.org>2010-12-02 08:38:57 -0800
commit1726bc11330f7a943b1e12c6dd5fa5454b90abd6 (patch)
treef76fc5c513ac2d60b26d0b8da4005620d00b805f /ext/mro
parent1245abf13f772bd2dd1d209bf07773efca954acb (diff)
downloadperl-1726bc11330f7a943b1e12c6dd5fa5454b90abd6.tar.gz
[perl #80098] Bleadperl breaks Attribute::Lexical
If @UNIVERSAL::ISA = "a"; and @a::ISA = "b"; then methods are searched for in these orders: main UNIVERSAL a b UNIVERSAL a b UNIVERSAL a b a b UNIVERSAL a b b UNIVERSAL a b For method lookup, looking at a stash twice causes no problems (except for a SUPER bug I’ve just found--to be dealt with separately). My fix to next::method in a5cd004 which made it do a second pass with UNIVERSAL the way gv_fetchmeth does did not take into account that it might return its caller (sub a::foo { return shift->next::can }), causing an infinite loop. This patch makes it check, on the second pass, whether each stash is the stash at the start of the MRO list and breaks if that is the case, so the MROs are effectively: main UNIVERSAL a b UNIVERSAL a b a b UNIVERSAL b UNIVERSAL a (which is what they are effectively already for method lookup).
Diffstat (limited to 'ext/mro')
-rw-r--r--ext/mro/mro.xs15
1 files changed, 8 insertions, 7 deletions
diff --git a/ext/mro/mro.xs b/ext/mro/mro.xs
index 63befa9d23..acccdd5a3d 100644
--- a/ext/mro/mro.xs
+++ b/ext/mro/mro.xs
@@ -482,7 +482,7 @@ mro__nextcan(...)
const char *hvname;
I32 entries;
struct mro_meta* selfmeta;
- bool seen_univ = FALSE;
+ bool searching_univ = FALSE;
HV* nmcache;
I32 i;
PPCODE:
@@ -633,9 +633,7 @@ mro__nextcan(...)
assert(curstash);
- if (!seen_univ && SvCUR(linear_sv) == 9
- && strnEQ(SvPV_nolen_const(linear_sv), "UNIVERSAL", 9))
- seen_univ = TRUE;
+ if (searching_univ && curstash == selfstash) break;
gvp = (GV**)hv_fetch(curstash, subname, subname_len, 0);
if (!gvp) continue;
@@ -658,12 +656,15 @@ mro__nextcan(...)
}
}
- if (!seen_univ && (selfstash = gv_stashpvn("UNIVERSAL", 9, 0))) {
- linear_av = S_mro_get_linear_isa_c3(aTHX_ selfstash, 0);
+ if (!searching_univ) {
+ HV * const unistash = gv_stashpvn("UNIVERSAL", 9, 0);
+ if (unistash) {
+ linear_av = S_mro_get_linear_isa_c3(aTHX_ unistash, 0);
linear_svp = AvARRAY(linear_av);
entries = AvFILLp(linear_av) + 1;
- seen_univ = TRUE;
+ searching_univ = TRUE;
goto retry;
+ }
}
(void)hv_store_ent(nmcache, sv, &PL_sv_undef, 0);