summaryrefslogtreecommitdiff
path: root/hv.c
diff options
context:
space:
mode:
authorBen Morrow <ben@morrow.me.uk>2009-01-04 20:04:39 +0000
committerRafael Garcia-Suarez <rgarciasuarez@gmail.com>2009-06-21 13:34:02 +0200
commitf1c32fec87699aee2eeb638f44135f21217d2127 (patch)
treeae959bd8a01e1f3be88d953735345836f56d0f66 /hv.c
parentd018fae575c7e183deffddccedc84f1f5d7ddacb (diff)
downloadperl-f1c32fec87699aee2eeb638f44135f21217d2127.tar.gz
When a glob is deleted, mark its sub as ANON.
Diffstat (limited to 'hv.c')
-rw-r--r--hv.c43
1 files changed, 41 insertions, 2 deletions
diff --git a/hv.c b/hv.c
index ebb10fbd34..ab22584f3c 100644
--- a/hv.c
+++ b/hv.c
@@ -1468,8 +1468,8 @@ Perl_hv_free_ent(pTHX_ HV *hv, register HE *entry)
if (!entry)
return;
val = HeVAL(entry);
- if (val && isGV(val) && isGV_with_GP(val) && GvCVu(val) && HvNAME_get(hv))
- mro_method_changed_in(hv); /* deletion of method from stash */
+ if (HvNAME(hv) && anonymise_cv(HvNAME(hv), val) && GvCVu(val))
+ mro_method_changed_in(hv);
SvREFCNT_dec(val);
if (HeKLEN(entry) == HEf_SVKEY) {
SvREFCNT_dec(HeKEY_sv(entry));
@@ -1482,6 +1482,29 @@ Perl_hv_free_ent(pTHX_ HV *hv, register HE *entry)
del_HE(entry);
}
+static I32
+S_anonymise_cv(const char *stash, SV *val)
+{
+ CV *cv;
+
+ PERL_ARGS_ASSERT_ANONYMISE_CV;
+
+ if (val && isGV(val) && isGV_with_GP(val) && (cv = GvCV(val))) {
+ if ((SV *)CvGV(cv) == val) {
+ SV *gvname;
+ GV *anongv;
+
+ gvname = newSVpvf("%s::__ANON__", stash ? stash : "__ANON__");
+ anongv = gv_fetchsv(gvname, GV_ADDMULTI, SVt_PVCV);
+ SvREFCNT_dec(gvname);
+ CvGV(cv) = anongv;
+ CvANON_on(cv);
+ return 1;
+ }
+ }
+ return 0;
+}
+
void
Perl_hv_delayfree_ent(pTHX_ HV *hv, register HE *entry)
{
@@ -1646,6 +1669,22 @@ S_hfreeentries(pTHX_ HV *hv)
if (!orig_array)
return;
+ if (HvNAME(hv) && orig_array != NULL) {
+ /* symbol table: make all the contained subs ANON */
+ STRLEN i;
+ XPVHV *xhv = (XPVHV*)SvANY(hv);
+
+ for (i = 0; i <= xhv->xhv_max; i++) {
+ HE *entry = (HvARRAY(hv))[i];
+ for (; entry; entry = HeNEXT(entry)) {
+ SV *val = HeVAL(entry);
+ /* we need to put the subs in the __ANON__ symtable, as
+ * this one is being cleared. */
+ anonymise_cv(NULL, val);
+ }
+ }
+ }
+
if (SvOOK(hv)) {
/* If the hash is actually a symbol table with a name, look after the
name. */