summaryrefslogtreecommitdiff
path: root/hv.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2010-10-24 23:45:49 -0700
committerFather Chrysostomos <sprout@cpan.org>2010-10-24 23:45:49 -0700
commit35759254f69c7bfa698c7a24b1031806ea41bbae (patch)
tree039bd04d14a8964552b84834ef8a0b0cfc9a9529 /hv.c
parent96517a90c6cb5ea3aaf4304897cd4eb1db2d2305 (diff)
downloadperl-35759254f69c7bfa698c7a24b1031806ea41bbae.tar.gz
Rename stashes when they move around
This is yet another patch in preparation for [perl #75176] (I keep saying that.). It uses the recently-added functions hv_name_add and hv_name_delete, to add and remove names when mro_package_moved is called. mro_package_moved’s calling convention needed to change to make this work, which is the bulk of the patch. Code that was calling mro_package_moved was also doing it sometimes when it was unnecessary. If the stash being assigned over had no name, then there was no possibiiity of its being in the symbol table. This probably fixes [perl #77358] (isa warnings), though I have not tested that yet. One user-visible change this introduces is that a detached glob whose stash loses its name will no longer stringify the same way (a bit like a glob that loses its stash pointer; except that it becomes *__ANON__::foo instead of "").
Diffstat (limited to 'hv.c')
-rw-r--r--hv.c30
1 files changed, 17 insertions, 13 deletions
diff --git a/hv.c b/hv.c
index 0b347f5788..13968b4b3c 100644
--- a/hv.c
+++ b/hv.c
@@ -1016,6 +1016,23 @@ S_hv_delete_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen,
if (k_flags & HVhek_FREEKEY)
Safefree(key);
+ /* If this is a stash and the key ends with ::, then someone is
+ deleting a package. This must come before the entry is
+ actually detached from the hash, as mro_package_moved checks
+ whether the passed gv is still in the symbol table before
+ doing anything. */
+ if (HeVAL(entry) && HvNAME(hv)) {
+ if (keysv) key = SvPV(keysv, klen);
+ if (klen > 1 && key[klen-2] == ':' && key[klen-1] == ':'
+ && SvTYPE(HeVAL(entry)) == SVt_PVGV) {
+ HV * const stash = GvHV((GV *)HeVAL(entry));
+ if (stash && HvNAME(stash))
+ mro_package_moved(
+ NULL, stash, (GV *)HeVAL(entry), NULL, 0
+ );
+ }
+ }
+
if (d_flags & G_DISCARD)
sv = NULL;
else {
@@ -1037,19 +1054,6 @@ 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(NULL, stash, NULL, NULL, 0);
- }
- }
-
if (SvOOK(hv) && entry == HvAUX(hv)->xhv_eiter /* HvEITER(hv) */)
HvLAZYDEL_on(hv);
else