summaryrefslogtreecommitdiff
path: root/t/mro
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2012-11-25 22:15:33 -0800
committerFather Chrysostomos <sprout@cpan.org>2012-11-29 09:11:30 -0800
commit6e1b2de7c59099adaa1866fe94957b98fabcd9c4 (patch)
treee239ecfe943c3c05c39a4f8d78865a859e762fab /t/mro
parentb01425c33956a0b279a0f20ced4131027f2c40f4 (diff)
downloadperl-6e1b2de7c59099adaa1866fe94957b98fabcd9c4.tar.gz
Fix two minor bugs with local glob assignment
These are combined into one patch because it is hard to fix one with- out fixing the other. local *glob = $ref was ignoring the clobbered reference and not accounting for when updating ISA caches, resulting in two bugs: *Foo::ISA = *Bar::ISA; @Foo::ISA = "Baz"; sub Baz::ook { "Baz" } sub L::ook { "See" } warn Bar->ook; # Baz local *Foo::ISA = ["L"]; warn Bar->ook; # Baz @Baz::ISA = @Baz::ISA; # should have no effect warn Bar->ook; # See @Baz::ISA = "Foo::bar"; sub Foo::bar::ber { 'baz' } sub UNIVERSAL::ber { "black sheep" } warn Baz->ber; # baz local *Foo:: = \%Bar::; warn Baz->ber; # baz @Baz::ISA = @Baz::ISA; # should have no effect warn Baz->ber; # black sheep The dref variable in sv.c:S_glob_assign_ref holds the SV that needs to be freed. So during localisation it is NULL. When I was fixing up isa and mro bugs in perl 5.14, I misunderstood its purpose and thought it always contained the reference on the left. Since we need to have access to what was assigned over after the assignment, this commit changes dref always to hold the clobbered SV, and makes the SvREFCNT_dec conditional.
Diffstat (limited to 't/mro')
-rw-r--r--t/mro/isa_aliases.t10
-rw-r--r--t/mro/package_aliases.t12
2 files changed, 19 insertions, 3 deletions
diff --git a/t/mro/isa_aliases.t b/t/mro/isa_aliases.t
index abdedce120..2073e5ebe5 100644
--- a/t/mro/isa_aliases.t
+++ b/t/mro/isa_aliases.t
@@ -2,7 +2,7 @@
BEGIN { chdir 't'; @INC = '../lib'; require './test.pl' }
-plan 12;
+plan 13;
@Foogh::ISA = "Bar";
*Phoogh::ISA = *Foogh::ISA;
@@ -41,3 +41,11 @@ ok !Foo->isa("Bar"),
'!isa when another stash has claimed the @ISA via ref-to-glob assignment';
ok !Phoo->isa("Bar"),
'!isa on the stash that claimed the @ISA via ref-to-glob assignment';
+
+*Fooo::ISA = *Baro::ISA;
+@Fooo::ISA = "Bazo";
+sub Bazo::ook { "Baz" }
+sub L::ook { "See" }
+Baro->ook;
+local *Fooo::ISA = ["L"];
+is 'Baro'->ook, 'See', 'localised *ISA=$ref assignment';
diff --git a/t/mro/package_aliases.t b/t/mro/package_aliases.t
index 3bc3c8fa74..34aa2d68b9 100644
--- a/t/mro/package_aliases.t
+++ b/t/mro/package_aliases.t
@@ -10,7 +10,7 @@ BEGIN {
use strict;
use warnings;
-plan(tests => 52);
+plan(tests => 53);
{
package New;
@@ -399,4 +399,12 @@ bless [], "O:";
'isa(foo) when inheriting from "class:" after string-to-glob assignment';
}
-
+@Bazo::ISA = "Fooo::bar";
+sub Fooo::bar::ber { 'baz' }
+sub UNIVERSAL::ber { "black sheep" }
+Bazo->ber;
+local *Fooo:: = \%Baro::;
+{
+ no warnings;
+ is 'Bazo'->ber, 'black sheep', 'localised *glob=$stashref assignment';
+}