Re: [perl #18113] UNIVERSAL::AUTOLOAD doesn't work if the stash doesn't exist yet
Gurusamy Sarathy [Wed, 30 Oct 2002 20:58:15 +0000 (12:58 -0800)]
Date: Wed, 30 Oct 2002 20:58:15 -0800
Message-Id: <200210310458.g9V4wFK00513@smtp3.ActiveState.com>
Date: Wed, 30 Oct 2002 21:56:22 -0800
Message-Id: <200210310556.g9V5uMK05748@smtp3.ActiveState.com>
Date: Wed, 30 Oct 2002 22:55:30 -0800
Message-Id: <200210310655.g9V6tUK10959@smtp3.ActiveState.com>

p4raw-id: //depot/perl@18159

gv.c
pp_hot.c
t/op/method.t

diff --git a/gv.c b/gv.c
index d5cb295..68bc3e9 100644 (file)
--- a/gv.c
+++ b/gv.c
@@ -394,6 +394,10 @@ Perl_gv_fetchmethod_autoload(pTHX_ HV *stash, const char *name, I32 autoload)
     register const char *nend;
     const char *nsplit = 0;
     GV* gv;
+    HV* ostash = stash;
+
+    if (stash && SvTYPE(stash) < SVt_PVHV)
+       stash = Nullhv;
 
     for (nend = name; *nend; nend++) {
        if (*nend == '\'')
@@ -426,6 +430,7 @@ Perl_gv_fetchmethod_autoload(pTHX_ HV *stash, const char *name, I32 autoload)
                gv_stashpvn(origname, nsplit - origname - 7, FALSE))
              stash = gv_stashpvn(origname, nsplit - origname, TRUE);
        }
+       ostash = stash;
     }
 
     gv = gv_fetchmeth(stash, name, nend - name, 0);
@@ -433,7 +438,7 @@ Perl_gv_fetchmethod_autoload(pTHX_ HV *stash, const char *name, I32 autoload)
        if (strEQ(name,"import") || strEQ(name,"unimport"))
            gv = (GV*)&PL_sv_yes;
        else if (autoload)
-           gv = gv_autoload4(stash, name, nend - name, TRUE);
+           gv = gv_autoload4(ostash, name, nend - name, TRUE);
     }
     else if (autoload) {
        CV* cv = GvCV(gv);
@@ -468,11 +473,19 @@ Perl_gv_autoload4(pTHX_ HV *stash, const char *name, STRLEN len, I32 method)
     HV* varstash;
     GV* vargv;
     SV* varsv;
+    char *packname = "";
 
-    if (!stash)
-       return Nullgv;  /* UNIVERSAL::AUTOLOAD could cause trouble */
     if (len == autolen && strnEQ(name, autoload, autolen))
        return Nullgv;
+    if (stash) {
+       if (SvTYPE(stash) < SVt_PVHV) {
+           packname = SvPV_nolen((SV*)stash);
+           stash = Nullhv;
+       }
+       else {
+           packname = HvNAME(stash);
+       }
+    }
     if (!(gv = gv_fetchmeth(stash, autoload, autolen, FALSE)))
        return Nullgv;
     cv = GvCV(gv);
@@ -487,7 +500,7 @@ Perl_gv_autoload4(pTHX_ HV *stash, const char *name, STRLEN len, I32 method)
        (GvCVGEN(gv) || GvSTASH(gv) != stash))
        Perl_warner(aTHX_ packWARN2(WARN_DEPRECATED, WARN_SYNTAX),
          "Use of inherited AUTOLOAD for non-method %s::%.*s() is deprecated",
-            HvNAME(stash), (int)len, name);
+            packname, (int)len, name);
 
     if (CvXSUB(cv)) {
         /* rather than lookup/init $AUTOLOAD here
@@ -515,7 +528,7 @@ Perl_gv_autoload4(pTHX_ HV *stash, const char *name, STRLEN len, I32 method)
        gv_init(vargv, varstash, autoload, autolen, FALSE);
     LEAVE;
     varsv = GvSV(vargv);
-    sv_setpv(varsv, HvNAME(stash));
+    sv_setpv(varsv, packname);
     sv_catpvn(varsv, "::", 2);
     sv_catpvn(varsv, name, len);
     SvTAINTED_off(varsv);
index f4ca5f3..0b3d622 100644 (file)
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -2820,6 +2820,7 @@ S_method_common(pTHX_ SV* meth, U32* hashp)
     char* name;
     STRLEN namelen;
     char* packname = 0;
+    SV *packsv = Nullsv;
     STRLEN packlen;
 
     name = SvPV(meth, namelen);
@@ -2855,6 +2856,8 @@ S_method_common(pTHX_ SV* meth, U32* hashp)
            }
            /* assume it's a package name */
            stash = gv_stashpvn(packname, packlen, FALSE);
+           if (!stash)
+               packsv = sv;
            goto fetch;
        }
        /* it _is_ a filehandle name -- replace with a reference */
@@ -2887,7 +2890,7 @@ S_method_common(pTHX_ SV* meth, U32* hashp)
        }
     }
 
-    gv = gv_fetchmethod(stash, name);
+    gv = gv_fetchmethod(stash ? stash : (HV*)packsv, name);
 
     if (!gv) {
        /* This code tries to figure out just what went wrong with
index 46c1119..52fb705 100755 (executable)
@@ -10,7 +10,7 @@ BEGIN {
     require "test.pl";
 }
 
-print "1..75\n";
+print "1..78\n";
 
 @A::ISA = 'B';
 @B::ISA = 'C';
@@ -277,3 +277,18 @@ sub Bminor::test {
 Bminor->test('y', 'z');
 is("@X", "Amajor Bminor x y Bminor Bminor y z");
 
+package main;
+for my $meth (['Bar', 'Foo::Bar'],
+             ['SUPER::Bar', 'main::SUPER::Bar'],
+             ['Xyz::SUPER::Bar', 'Xyz::SUPER::Bar'])
+{
+    fresh_perl_is(<<EOT,
+package UNIVERSAL; sub AUTOLOAD { my \$c = shift; print "\$c \$AUTOLOAD\\n" }
+package Xyz;
+package main; Foo->$meth->[0]();
+EOT
+       "Foo $meth->[1]",
+       { switches => [ '-w' ] },
+       "check if UNIVERSAL::AUTOLOAD works",
+    );
+}