Change 14920 by ams@lustre on 2002/03/01 09:06:01

           Subject: [PATCH @14577] autoloaded DESTROY bugfix
           From: Ilya Zakharevich <[EMAIL PROTECTED]>
           Date: Tue, 26 Feb 2002 19:54:31 -0500
           Message-Id: <[EMAIL PROTECTED]>

Affected files ...

.... //depot/perl/embed.fnc#18 edit
.... //depot/perl/ext/B/B/Deparse.pm#111 edit
.... //depot/perl/gv.c#165 edit

Differences ...

==== //depot/perl/embed.fnc#18 (text) ====
Index: perl/embed.fnc
--- perl/embed.fnc.~1~  Fri Mar  1 02:15:05 2002
+++ perl/embed.fnc      Fri Mar  1 02:15:05 2002
@@ -249,6 +249,8 @@
 Ap     |GV*    |gv_fetchfile   |const char* name
 Apd    |GV*    |gv_fetchmeth   |HV* stash|const char* name|STRLEN len \
                                |I32 level
+Apd    |GV*    |gv_fetchmeth_autoload  |HV* stash|const char* name|STRLEN len \
+                               |I32 level
 Apd    |GV*    |gv_fetchmethod |HV* stash|const char* name
 Apd    |GV*    |gv_fetchmethod_autoload|HV* stash|const char* name \
                                |I32 autoload

==== //depot/perl/ext/B/B/Deparse.pm#111 (text) ====
Index: perl/ext/B/B/Deparse.pm
--- perl/ext/B/B/Deparse.pm.~1~ Fri Mar  1 02:15:05 2002
+++ perl/ext/B/B/Deparse.pm     Fri Mar  1 02:15:05 2002
@@ -968,6 +968,8 @@
     }
 }
 
+sub DESTROY {} #       Do not AUTOLOAD
+
 # $root should be the op which represents the root of whatever
 # we're sequencing here. If it's undefined, then we don't append
 # any subroutine declarations to the deparsed ops, otherwise we

==== //depot/perl/gv.c#165 (text) ====
Index: perl/gv.c
--- perl/gv.c.~1~       Fri Mar  1 02:15:05 2002
+++ perl/gv.c   Fri Mar  1 02:15:05 2002
@@ -310,6 +310,50 @@
 }
 
 /*
+=for apidoc gv_fetchmeth_autoload
+
+Same as gv_fetchmeth(), but looks for autoloaded subroutines too.
+Returns a glob for the subroutine.
+
+For an autoloaded subroutine without a GV, will create a GV even
+if C<level < 0>.  For an autoloaded subroutine without a stub, GvCV()
+of the result may be zero.
+
+=cut
+*/
+
+GV *
+Perl_gv_fetchmeth_autoload(pTHX_ HV *stash, const char *name, STRLEN len, I32 level)
+{
+    GV *gv = gv_fetchmeth(stash, name, len, level);
+
+    if (!gv) {
+       char autoload[] = "AUTOLOAD";
+       STRLEN autolen = sizeof(autoload)-1;
+       CV *cv;
+       GV **gvp;
+
+       if (!stash)
+           return Nullgv;      /* UNIVERSAL::AUTOLOAD could cause trouble */
+       if (len == autolen && strnEQ(name, autoload, autolen))
+           return Nullgv;
+       if (!(gv = gv_fetchmeth(stash, autoload, autolen, FALSE)))
+           return Nullgv;
+       cv = GvCV(gv);
+       if (!(CvROOT(cv) || CvXSUB(cv)))
+           return Nullgv;
+       /* Have an autoload */
+       if (level < 0)  /* Cannot do without a stub */
+           gv_fetchmeth(stash, name, len, 0);
+       gvp = (GV**)hv_fetch(stash, name, len, (level >= 0));
+       if (!gvp)
+           return Nullgv;
+       return *gvp;
+    }
+    return gv;
+}
+
+/*
 =for apidoc gv_fetchmethod
 
 See L<gv_fetchmethod_autoload>.
@@ -1295,12 +1339,23 @@
 
        DEBUG_o( Perl_deb(aTHX_ "Checking overloading of `%s' in package `%.256s'\n",
                     cp, HvNAME(stash)) );
-       /* don't fill the cache while looking up! */
-       gv = gv_fetchmeth(stash, cooky, l, -1);
+       /* don't fill the cache while looking up!
+          Creation of inheritance stubs in intermediate packages may
+          conflict with the logic of runtime method substitution.
+          Indeed, for inheritance A -> B -> C, if C overloads "+0",
+          then we could have created stubs for "(+0" in A and C too.
+          But if B overloads "bool", we may want to use it for
+          numifying instead of C's "+0". */
+       if (i >= DESTROY_amg)
+           gv = Perl_gv_fetchmeth_autoload(aTHX_ stash, cooky, l, 0);
+       else                            /* Autoload taken care of below */
+           gv = Perl_gv_fetchmeth(aTHX_ stash, cooky, l, -1);
         cv = 0;
         if (gv && (cv = GvCV(gv))) {
            if (GvNAMELEN(CvGV(cv)) == 3 && strEQ(GvNAME(CvGV(cv)), "nil")
                && strEQ(HvNAME(GvSTASH(CvGV(cv))), "overload")) {
+               /* This is a hack to support autoloading..., while
+                  knowing *which* methods were declared as overloaded. */
                /* GvSV contains the name of the method. */
                GV *ngv = Nullgv;
                
@@ -1328,6 +1383,9 @@
            filled = 1;
            if (i < DESTROY_amg)
                have_ovl = 1;
+       } else if (gv) {                /* Autoloaded... */
+           cv = (CV*)gv;
+           filled = 1;
        }
        amt.table[i]=(CV*)SvREFCNT_inc(cv);
     }
End of Patch.

Reply via email to