From: Gurusamy Sarathy Date: Wed, 30 Oct 2002 20:58:15 +0000 (-0800) Subject: Re: [perl #18113] UNIVERSAL::AUTOLOAD doesn't work if the stash doesn't exist yet X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=0dae17bd7971d11b90a07b6fc03ec78ab38e4db4;p=p5sagit%2Fp5-mst-13.2.git Re: [perl #18113] UNIVERSAL::AUTOLOAD doesn't work if the stash doesn't exist yet 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 --- diff --git a/gv.c b/gv.c index d5cb295..68bc3e9 100644 --- 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); diff --git a/pp_hot.c b/pp_hot.c index f4ca5f3..0b3d622 100644 --- 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 diff --git a/t/op/method.t b/t/op/method.t index 46c1119..52fb705 100755 --- a/t/op/method.t +++ b/t/op/method.t @@ -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(<$meth->[0](); +EOT + "Foo $meth->[1]", + { switches => [ '-w' ] }, + "check if UNIVERSAL::AUTOLOAD works", + ); +}