From: Father Chrysostomos Date: Wed, 28 Nov 2012 21:46:07 +0000 (-0800) Subject: Fix two local *ISA bugs X-Git-Tag: upstream/5.20.0~4646^2~3 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3d460042b1251a4b5e3b583fa6be358554dd3bcc;p=platform%2Fupstream%2Fperl.git Fix two local *ISA bugs These are regressions from 5.8. local *ISA was not updating isa caches. local *ISA = [] was updating caches, but scope unwinding was not. Both save_gp and leave_scope/SAVEt_GP need to check whether the glob is named ISA and call mro_isa_changed_in if appropriate. --- diff --git a/scope.c b/scope.c index c4a2222..31b990d 100644 --- a/scope.c +++ b/scope.c @@ -286,14 +286,21 @@ Perl_save_gp(pTHX_ GV *gv, I32 empty) if (empty) { GP *gp = Perl_newGP(aTHX_ gv); HV * const stash = GvSTASH(gv); - - if (GvCVu(gv) && stash && HvENAME(stash)) - mro_method_changed_in(GvSTASH(gv)); /* taking a method out of circulation ("local")*/ + bool isa_changed = 0; + + if (stash && HvENAME(stash)) { + if (GvNAMELEN(gv) == 3 && strnEQ(GvNAME(gv), "ISA", 3)) + isa_changed = TRUE; + else if (GvCVu(gv)) + /* taking a method out of circulation ("local")*/ + mro_method_changed_in(stash); + } if (GvIOp(gv) && (IoFLAGS(GvIOp(gv)) & IOf_ARGV)) { gp->gp_io = newIO(); IoFLAGS(gp->gp_io) |= IOf_ARGV|IOf_START; } GvGP_set(gv,gp); + if (isa_changed) mro_isa_changed_in(stash); } else { gp_ref(GvGP(gv)); @@ -860,9 +867,13 @@ Perl_leave_scope(pTHX_ I32 base) gv = MUTABLE_GV(SSPOPPTR); gp_free(gv); GvGP_set(gv, (GP*)ptr); - /* putting a method back into circulation ("local")*/ - if (GvCVu(gv) && (hv=GvSTASH(gv)) && HvENAME_get(hv)) + if ((hv=GvSTASH(gv)) && HvENAME_get(hv)) { + if (GvNAMELEN(gv) == 3 && strnEQ(GvNAME(gv), "ISA", 3)) + mro_isa_changed_in(hv); + else if (GvCVu(gv)) + /* putting a method back into circulation ("local")*/ gv_method_changed(gv); + } SvREFCNT_dec(gv); break; case SAVEt_FREESV: diff --git a/t/mro/basic.t b/t/mro/basic.t index cc1386c..ab34fc2 100644 --- a/t/mro/basic.t +++ b/t/mro/basic.t @@ -3,7 +3,7 @@ use strict; use warnings; -BEGIN { require q(./test.pl); } plan(tests => 55); +BEGIN { require q(./test.pl); } plan(tests => 59); require mro; @@ -353,3 +353,20 @@ is(eval { MRO_N->testfunc() }, 123); eval { local *Detached::method }; is $@, "", 'localising gv-with-cv belonging to detached package'; } + +{ + # *ISA localisation + @il::ISA = "ilsuper"; + sub ilsuper::can { "puree" } + sub il::tomatoes; + { + local *il::ISA; + is +il->can("tomatoes"), \&il::tomatoes, 'local *ISA'; + } + is "il"->can("tomatoes"), "puree", 'local *ISA unwinding'; + { + local *il::ISA = []; + is +il->can("tomatoes"), \&il::tomatoes, 'local *ISA = []'; + } + is "il"->can("tomatoes"), "puree", 'local *ISA=[] unwinding'; +}