summaryrefslogtreecommitdiff
path: root/mro.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2010-10-29 20:45:34 -0700
committerFather Chrysostomos <sprout@cpan.org>2010-10-29 21:50:24 -0700
commit00169e2cdde29138824a7bf6b66d5875aaa8278d (patch)
treeaeb3b50ba3698ec9d26053d42e414fda70a983ba /mro.c
parentbc56db2a697ebe59892fabdcfa5aa910ed4f2885 (diff)
downloadperl-00169e2cdde29138824a7bf6b66d5875aaa8278d.tar.gz
Switch the core MRO code over to HvENAME
This has the side-effect of fixing these one-liners: $ perl5.13.5 -le' my $glob = \*foo::ISA; delete $::{"foo::"}; *$glob = *a' Bus error $ perl5.13.5 -le' my $glob = \*foo::ISA; delete $::{"foo::"}; *$glob = []' Bus error $ perl5.13.6 -le'sub baz; my $glob = \*foo::bar; delete $::{"foo::"}; *$glob = *baz;' Bus error $ perl5.13.6 -le'sub foo::bar; my $glob = \*foo::bar; delete $::{"foo::"}; *$glob = *baz;' Bus error In the first two cases the crash was inadvertently fixed (isn’t it nice when that happens?) in 5.13.6 (by 6f86b615fa7), but there was still a fatal error: Can't call mro_isa_changed_in() on anonymous symbol table at -e line 1. Because sv_clear calls ->DESTROY, if an object’s stash has been detached from the symbol table, mro_get_linear_isa can be called on a hash with no HvENAME. So HvNAME is used as a fallback for those cases.
Diffstat (limited to 'mro.c')
-rw-r--r--mro.c18
1 files changed, 11 insertions, 7 deletions
diff --git a/mro.c b/mro.c
index a584686997..ca38a76f59 100644
--- a/mro.c
+++ b/mro.c
@@ -215,7 +215,11 @@ S_mro_get_linear_isa_dfs(pTHX_ HV *stash, U32 level)
PERL_ARGS_ASSERT_MRO_GET_LINEAR_ISA_DFS;
assert(HvAUX(stash));
- stashhek = HvNAME_HEK(stash);
+ stashhek
+ = HvAUX(stash)->xhv_name && HvENAME_HEK_NN(stash)
+ ? HvENAME_HEK_NN(stash)
+ : HvNAME_HEK(stash);
+
if (!stashhek)
Perl_croak(aTHX_ "Can't linearize anonymous symbol table");
@@ -438,8 +442,8 @@ Perl_mro_isa_changed_in3(pTHX_ HV* stash, const char *stashname,
struct mro_meta * meta = NULL;
if(!stashname && stash) {
- stashname = HvNAME_get(stash);
- stashname_len = HvNAMELEN_get(stash);
+ stashname = HvENAME_get(stash);
+ stashname_len = HvENAMELEN_get(stash);
}
else if(!stash)
stash = gv_stashpvn(stashname, stashname_len, 0 /* don't add */);
@@ -692,7 +696,7 @@ Perl_mro_package_moved(pTHX_ HV * const stash, HV * const oldstash,
stashentry && *stashentry
&& (substash = GvHV(*stashentry))
)
- || (oldsubstash && HvNAME(oldsubstash))
+ || (oldsubstash && HvENAME_get(oldsubstash))
)
{
/* Add :: and the key (minus the trailing ::)
@@ -782,7 +786,7 @@ Perl_mro_package_moved(pTHX_ HV * const stash, HV * const oldstash,
}
set_names:
- if(oldstash && HvNAME(oldstash)) {
+ if(oldstash && HvENAME_get(oldstash)) {
if(PL_stashcache)
(void)
hv_delete(PL_stashcache, newname, newname_len, G_DISCARD);
@@ -824,8 +828,8 @@ via, C<mro::method_changed_in(classname)>.
void
Perl_mro_method_changed_in(pTHX_ HV *stash)
{
- const char * const stashname = HvNAME_get(stash);
- const STRLEN stashname_len = HvNAMELEN_get(stash);
+ const char * const stashname = HvENAME_get(stash);
+ const STRLEN stashname_len = HvENAMELEN_get(stash);
SV ** const svp = hv_fetch(PL_isarev, stashname, stashname_len, 0);
HV * const isarev = svp ? MUTABLE_HV(*svp) : NULL;