summaryrefslogtreecommitdiff
path: root/hv.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 /hv.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 'hv.c')
-rw-r--r--hv.c38
1 files changed, 37 insertions, 1 deletions
diff --git a/hv.c b/hv.c
index a04e4c51c1..dc873ab8e8 100644
--- a/hv.c
+++ b/hv.c
@@ -692,8 +692,32 @@ Perl_hv_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen,
}
HeVAL(entry) = val;
} else if (action & HV_FETCH_ISSTORE) {
- SvREFCNT_dec(HeVAL(entry));
+ bool moving_package = FALSE;
+ SV *old_val = HeVAL(entry);
+
+ /* If this is a stash and the key ends with ::, then some-
+ one is aliasing (or moving) a package. */
+ if (HvNAME(hv)) {
+ if (keysv) key = SvPV(keysv, klen);
+ if (klen > 1
+ && key[klen-2] == ':' && key[klen-1] == ':') {
+ if(SvTYPE(old_val) == SVt_PVGV) {
+ const HV * const old_stash
+ = GvHV((GV *)old_val);
+ if(old_stash && HvNAME(old_stash))
+ mro_package_moved(old_stash);
+ }
+ moving_package = TRUE;
+ }
+ }
+
+ SvREFCNT_dec(old_val);
HeVAL(entry) = val;
+
+ if (moving_package && SvTYPE(val) == SVt_PVGV) {
+ const HV * const stash = GvHV((GV *)val);
+ if (stash && HvNAME(stash)) mro_package_moved(stash);
+ }
}
} else if (HeVAL(entry) == &PL_sv_placeholder) {
/* if we find a placeholder, we pretend we haven't found
@@ -1036,6 +1060,18 @@ S_hv_delete_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen,
HvPLACEHOLDERS(hv)++;
} else {
*oentry = HeNEXT(entry);
+
+ /* If this is a stash and the key ends with ::, then someone is
+ deleting a package. */
+ if (sv && HvNAME(hv)) {
+ if (keysv) key = SvPV(keysv, klen);
+ if (klen > 1 && key[klen-2] == ':' && key[klen-1] == ':'
+ && SvTYPE(sv) == SVt_PVGV) {
+ const HV * const stash = GvHV((GV *)sv);
+ if (stash && HvNAME(stash)) mro_package_moved(stash);
+ }
+ }
+
if (SvOOK(hv) && entry == HvAUX(hv)->xhv_eiter /* HvEITER(hv) */)
HvLAZYDEL_on(hv);
else