diff options
author | Ben Morrow <ben@morrow.me.uk> | 2009-01-04 20:04:39 +0000 |
---|---|---|
committer | Rafael Garcia-Suarez <rgarciasuarez@gmail.com> | 2009-06-21 13:34:02 +0200 |
commit | f1c32fec87699aee2eeb638f44135f21217d2127 (patch) | |
tree | ae959bd8a01e1f3be88d953735345836f56d0f66 /hv.c | |
parent | d018fae575c7e183deffddccedc84f1f5d7ddacb (diff) | |
download | perl-f1c32fec87699aee2eeb638f44135f21217d2127.tar.gz |
When a glob is deleted, mark its sub as ANON.
Diffstat (limited to 'hv.c')
-rw-r--r-- | hv.c | 43 |
1 files changed, 41 insertions, 2 deletions
@@ -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. */ |