summaryrefslogtreecommitdiff
path: root/sv.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2010-10-09 18:42:01 -0700
committerFather Chrysostomos <sprout@cpan.org>2010-10-09 18:42:40 -0700
commitc8bbf675c3e9277e1dd4b1185d91c1aef2cd2594 (patch)
treeac43f29d32d5dce5d6a0e58a2ce6bf91454604ce /sv.c
parent314655b3bf3a78f53857298857fbdc053e783117 (diff)
downloadperl-c8bbf675c3e9277e1dd4b1185d91c1aef2cd2594.tar.gz
Reset isa on stash manipulation
This only applies to glob-to-glob assignments and deletions of stash elements. Other types of stash manipulation are dealt with by subse- quent patches. It adds mro_package_moved, a private function that iterates through subpackages, calling mro_isa_changed_in on each. This is related to [perl #75176], but is not the same bug. It simply got in the way of fixing [perl #75176].
Diffstat (limited to 'sv.c')
-rw-r--r--sv.c27
1 files changed, 24 insertions, 3 deletions
diff --git a/sv.c b/sv.c
index 4178dd356d..679f0dbb98 100644
--- a/sv.c
+++ b/sv.c
@@ -3581,7 +3581,8 @@ copy-ish functions and macros use this underneath.
static void
S_glob_assign_glob(pTHX_ SV *const dstr, SV *const sstr, const int dtype)
{
- I32 mro_changes = 0; /* 1 = method, 2 = isa */
+ I32 mro_changes = 0; /* 1 = method, 2 = isa, 3 = recursive isa */
+ HV *old_stash;
PERL_ARGS_ASSERT_GLOB_ASSIGN_GLOB;
@@ -3627,8 +3628,23 @@ S_glob_assign_glob(pTHX_ SV *const dstr, SV *const sstr, const int dtype)
mro_changes = 1;
}
- if(strEQ(GvNAME((const GV *)dstr),"ISA"))
- mro_changes = 2;
+ /* We don’t need to check the name of the destination if it was not a
+ glob to begin with. */
+ if(dtype == SVt_PVGV) {
+ const char * const name = GvNAME((const GV *)dstr);
+ if(strEQ(name,"ISA"))
+ mro_changes = 2;
+ else {
+ const STRLEN len = GvNAMELEN(dstr);
+ if (len > 1 && name[len-2] == ':' && name[len-1] == ':') {
+ mro_changes = 3;
+
+ /* Set aside the old stash, so we can reset isa caches on
+ its subclasses. */
+ old_stash = GvHV(dstr);
+ }
+ }
+ }
gp_free(MUTABLE_GV(dstr));
isGV_with_GP_off(dstr);
@@ -3645,6 +3661,11 @@ S_glob_assign_glob(pTHX_ SV *const dstr, SV *const sstr, const int dtype)
}
GvMULTI_on(dstr);
if(mro_changes == 2) mro_isa_changed_in(GvSTASH(dstr));
+ else if(mro_changes == 3) {
+ const HV * const stash = GvHV(dstr);
+ if(stash && HvNAME(stash)) mro_package_moved(stash);
+ if(old_stash && HvNAME(old_stash)) mro_package_moved(old_stash);
+ }
else if(mro_changes) mro_method_changed_in(GvSTASH(dstr));
return;
}