summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGurusamy Sarathy <gsar@cpan.org>2002-10-30 12:58:15 -0800
committerhv <hv@crypt.org>2002-11-19 11:48:30 +0000
commit0dae17bd7971d11b90a07b6fc03ec78ab38e4db4 (patch)
treebb9953708a3910f44e857da188d9d76096cc4231
parent8af2e859c733a1615cc8dbeb3491332ed702a779 (diff)
downloadperl-0dae17bd7971d11b90a07b6fc03ec78ab38e4db4.tar.gz
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
-rw-r--r--gv.c23
-rw-r--r--pp_hot.c5
-rwxr-xr-xt/op/method.t17
3 files changed, 38 insertions, 7 deletions
diff --git a/gv.c b/gv.c
index d5cb295a2d..68bc3e9c8c 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 f4ca5f3d8b..0b3d6228c3 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 46c111946a..52fb705fb8 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(<<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",
+ );
+}