summaryrefslogtreecommitdiff
path: root/ext/mro/mro.xs
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2010-11-30 22:35:16 -0800
committerFather Chrysostomos <sprout@cpan.org>2010-12-01 05:20:42 -0800
commita5cd004dbd757df2bcf9e17aab6a8ed1272157d7 (patch)
treebf8d3b1283f343bf14457a3817915f3928be043b /ext/mro/mro.xs
parentf32becadbe83ee90251793094dc804d84cef87a0 (diff)
downloadperl-a5cd004dbd757df2bcf9e17aab6a8ed1272157d7.tar.gz
[perl #68654] next::method doesn't see UNIVERSAL
This commit makes next::method retry with UNIVERSAL if it reaches the end of the MRO list.
Diffstat (limited to 'ext/mro/mro.xs')
-rw-r--r--ext/mro/mro.xs14
1 files changed, 14 insertions, 0 deletions
diff --git a/ext/mro/mro.xs b/ext/mro/mro.xs
index fb28399f77..63befa9d23 100644
--- a/ext/mro/mro.xs
+++ b/ext/mro/mro.xs
@@ -482,6 +482,7 @@ mro__nextcan(...)
const char *hvname;
I32 entries;
struct mro_meta* selfmeta;
+ bool seen_univ = FALSE;
HV* nmcache;
I32 i;
PPCODE:
@@ -612,6 +613,7 @@ mro__nextcan(...)
/* Now search the remainder of the MRO for the
same method name as the contextually enclosing
method */
+ retry:
if(entries > 0) {
while (entries--) {
SV * const linear_sv = *linear_svp++;
@@ -631,6 +633,10 @@ mro__nextcan(...)
assert(curstash);
+ if (!seen_univ && SvCUR(linear_sv) == 9
+ && strnEQ(SvPV_nolen_const(linear_sv), "UNIVERSAL", 9))
+ seen_univ = TRUE;
+
gvp = (GV**)hv_fetch(curstash, subname, subname_len, 0);
if (!gvp) continue;
@@ -652,6 +658,14 @@ mro__nextcan(...)
}
}
+ if (!seen_univ && (selfstash = gv_stashpvn("UNIVERSAL", 9, 0))) {
+ linear_av = S_mro_get_linear_isa_c3(aTHX_ selfstash, 0);
+ linear_svp = AvARRAY(linear_av);
+ entries = AvFILLp(linear_av) + 1;
+ seen_univ = TRUE;
+ goto retry;
+ }
+
(void)hv_store_ent(nmcache, sv, &PL_sv_undef, 0);
if(throw_nomethod)
Perl_croak(aTHX_ "No next::method '%s' found for %s", subname, hvname);