Note that can be warned on implicit utf8 upgrade
[p5sagit/p5-mst-13.2.git] / gv.c
diff --git a/gv.c b/gv.c
index 9743354..becd1e9 100644 (file)
--- a/gv.c
+++ b/gv.c
@@ -1296,9 +1296,9 @@ Perl_gv_fetchpvn_flags(pTHX_ const char *nambeg, STRLEN full_len, I32 flags,
        /* Names of length 1.  (Or 0. But name is NUL terminated, so that will
           be case '\0' in this switch statement (ie a default case)  */
        switch (*name) {
-       case '&':
-       case '`':
-       case '\'':
+       case '&':               /* $& */
+       case '`':               /* $` */
+       case '\'':              /* $' */
            if (
                sv_type == SVt_PVAV ||
                sv_type == SVt_PVHV ||
@@ -1309,17 +1309,17 @@ Perl_gv_fetchpvn_flags(pTHX_ const char *nambeg, STRLEN full_len, I32 flags,
            PL_sawampersand = TRUE;
            goto magicalize;
 
-       case ':':
+       case ':':               /* $: */
            sv_setpv(GvSVn(gv),PL_chopset);
            goto magicalize;
 
-       case '?':
+       case '?':               /* $? */
 #ifdef COMPLEX_STATUS
            SvUPGRADE(GvSVn(gv), SVt_PVLV);
 #endif
            goto magicalize;
 
-       case '!':
+       case '!':               /* $! */
            GvMULTI_on(gv);
            /* If %! has been used, automatically load Errno.pm. */
 
@@ -1330,8 +1330,8 @@ Perl_gv_fetchpvn_flags(pTHX_ const char *nambeg, STRLEN full_len, I32 flags,
                require_tie_mod(gv, "!", newSVpvs("Errno"), "TIEHASH", 1);
 
            break;
-       case '-':
-       case '+':
+       case '-':               /* $- */
+       case '+':               /* $+ */
        GvMULTI_on(gv); /* no used once warnings here */
         {
             AV* const av = GvAVn(gv);
@@ -1348,13 +1348,13 @@ Perl_gv_fetchpvn_flags(pTHX_ const char *nambeg, STRLEN full_len, I32 flags,
 
             break;
        }
-       case '*':
-       case '#':
+       case '*':               /* $* */
+       case '#':               /* $# */
            if (sv_type == SVt_PV)
                Perl_ck_warner_d(aTHX_ packWARN2(WARN_DEPRECATED, WARN_SYNTAX),
                                 "$%c is no longer supported", *name);
            break;
-       case '|':
+       case '|':               /* $| */
            sv_setiv(GvSVn(gv), (IV)(IoFLAGS(GvIOp(PL_defoutgv)) & IOf_FLUSH) != 0);
            goto magicalize;
 
@@ -1368,28 +1368,28 @@ Perl_gv_fetchpvn_flags(pTHX_ const char *nambeg, STRLEN full_len, I32 flags,
        ro_magicalize:
            SvREADONLY_on(GvSVn(gv));
            /* FALL THROUGH */
-       case '0':
-       case '1':
-       case '2':
-       case '3':
-       case '4':
-       case '5':
-       case '6':
-       case '7':
-       case '8':
-       case '9':
-       case '[':
-       case '^':
-       case '~':
-       case '=':
-       case '%':
-       case '.':
-       case '(':
-       case ')':
-       case '<':
-       case '>':
-       case '\\':
-       case '/':
+       case '0':               /* $0 */
+       case '1':               /* $1 */
+       case '2':               /* $2 */
+       case '3':               /* $3 */
+       case '4':               /* $4 */
+       case '5':               /* $5 */
+       case '6':               /* $6 */
+       case '7':               /* $7 */
+       case '8':               /* $8 */
+       case '9':               /* $9 */
+       case '[':               /* $[ */
+       case '^':               /* $^ */
+       case '~':               /* $~ */
+       case '=':               /* $= */
+       case '%':               /* $% */
+       case '.':               /* $. */
+       case '(':               /* $( */
+       case ')':               /* $) */
+       case '<':               /* $< */
+       case '>':               /* $> */
+       case '\\':              /* $\ */
+       case '/':               /* $/ */
        case '\001':    /* $^A */
        case '\003':    /* $^C */
        case '\004':    /* $^D */
@@ -1409,10 +1409,10 @@ Perl_gv_fetchpvn_flags(pTHX_ const char *nambeg, STRLEN full_len, I32 flags,
            sv_setpvs(GvSVn(gv),"\f");
            PL_formfeed = GvSVn(gv);
            break;
-       case ';':
+       case ';':               /* $; */
            sv_setpvs(GvSVn(gv),"\034");
            break;
-       case ']':
+       case ']':               /* $] */
        {
            SV * const sv = GvSVn(gv);
            if (!sv_derived_from(PL_patchlevel, "version"))
@@ -2364,13 +2364,19 @@ Perl_gv_name_set(pTHX_ GV *gv, const char *name, U32 len, U32 flags)
 /*
 =for apidoc gv_try_downgrade
 
-If C<gv> is a typeglob containing only a constant sub, and is only
-referenced from its package, and both the typeglob and the sub are
-sufficiently ordinary, replace the typeglob (in the package) with a
-placeholder that more compactly represents the same thing.  This is meant
-to be used when a placeholder has been upgraded, most likely because
-something wanted to look at a proper code object, and it has turned out
-to be a constant sub to which a proper reference is no longer required.
+If the typeglob C<gv> can be expressed more succinctly, by having
+something other than a real GV in its place in the stash, replace it
+with the optimised form.  Basic requirements for this are that C<gv>
+is a real typeglob, is sufficiently ordinary, and is only referenced
+from its package.  This function is meant to be used when a GV has been
+looked up in part to see what was there, causing upgrading, but based
+on what was found it turns out that the real GV isn't required after all.
+
+If C<gv> is a completely empty typeglob, it is deleted from the stash.
+
+If C<gv> is a typeglob containing only a sufficiently-ordinary constant
+sub, the typeglob is replaced with a scalar-reference placeholder that
+more compactly represents the same thing.
 
 =cut
 */
@@ -2383,12 +2389,19 @@ Perl_gv_try_downgrade(pTHX_ GV *gv)
     HEK *namehek;
     SV **gvp;
     PERL_ARGS_ASSERT_GV_TRY_DOWNGRADE;
-    if (SvREFCNT(gv) == 1 && SvTYPE(gv) == SVt_PVGV && !SvFAKE(gv) &&
+    if (!(SvREFCNT(gv) == 1 && SvTYPE(gv) == SVt_PVGV && !SvFAKE(gv) &&
            !SvOBJECT(gv) && !SvMAGICAL(gv) && !SvREADONLY(gv) &&
            isGV_with_GP(gv) && GvGP(gv) &&
-           GvMULTI(gv) && !GvINTRO(gv) && GvREFCNT(gv) == 1 &&
+           !GvINTRO(gv) && GvREFCNT(gv) == 1 &&
            !GvSV(gv) && !GvAV(gv) && !GvHV(gv) && !GvIOp(gv) && !GvFORM(gv) &&
-           GvEGV(gv) == gv && (stash = GvSTASH(gv)) && (cv = GvCV(gv)) &&
+           GvEGV(gv) == gv && (stash = GvSTASH(gv))))
+       return;
+    cv = GvCV(gv);
+    if (!cv) {
+       HEK *gvnhek = GvNAME_HEK(gv);
+       (void)hv_delete(stash, HEK_KEY(gvnhek),
+           HEK_UTF8(gvnhek) ? -HEK_LEN(gvnhek) : HEK_LEN(gvnhek), G_DISCARD);
+    } else if (GvMULTI(gv) && cv &&
            !SvOBJECT(cv) && !SvMAGICAL(cv) && !SvREADONLY(cv) &&
            CvSTASH(cv) == stash && CvGV(cv) == gv &&
            CvCONST(cv) && !CvMETHOD(cv) && !CvLVALUE(cv) && !CvUNIQUE(cv) &&