Regression tests for proxy subroutine glob assignment.
Nicholas Clark [Thu, 22 Dec 2005 15:43:20 +0000 (15:43 +0000)]
Fix a bug (it turns out that a typeglob isn't SvOK())
Remove stray debugging code.

p4raw-id: //depot/perl@26448

pp_hot.c
t/op/gv.t

index c625c2c..c4cd739 100644 (file)
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -132,7 +132,7 @@ PP(pp_sassign)
        if (!got_coderef && gv_type != SVt_PVGV && GIMME_V == G_VOID) {
            /* Is the target symbol table currently empty?  */
            GV *gv = gv_fetchsv(right, GV_NOINIT, SVt_PVGV);
-           if (!SvOK(gv)) {
+           if (SvTYPE(gv) != SVt_PVGV && !SvOK(gv)) {
                /* Good. Create a new proxy constant subroutine in the target.
                   The gv becomes a(nother) reference to the constant.  */
                SV *const value = SvRV(cv);
@@ -166,7 +166,6 @@ PP(pp_sassign)
                                                 SvRV(cv)));
            SvREFCNT_dec(cv);
            LEAVE;
-           PerlIO_debug("Unwrap CV\n");
        }
 
     }
index ad2db4a..aa9383f 100755 (executable)
--- a/t/op/gv.t
+++ b/t/op/gv.t
@@ -12,7 +12,7 @@ BEGIN {
 use warnings;
 
 require './test.pl';
-plan( tests => 105 );
+plan( tests => 132 );
 
 # type coersion on assignment
 $foo = 'foo';
@@ -196,7 +196,7 @@ is($j[0], 1);
 
 {
     my $w = '';
-    $SIG{__WARN__} = sub { $w = $_[0] };
+    local $SIG{__WARN__} = sub { $w = $_[0] };
     sub abc1 ();
     local *abc1 = sub { };
     is ($w, '');
@@ -267,7 +267,9 @@ EOPROG
 # There are certain space optimisations implemented via promotion rules to
 # GVs
 
-ok(!exists $::{oonk}, "no symbols of any sort to start with");
+foreach (qw (oonk ga_shloip)) {
+    ok(!exists $::{$_}, "no symbols of any sort to start with for $_");
+}
 
 # A string in place of the typeglob is promoted to the function prototype
 $::{oonk} = "pie";
@@ -291,6 +293,92 @@ foreach my $value (3, "Perl rules", \42, qr/whatever/, [1,2,3], {1=>2},
     is ($got, $value, "Value is correctly set");
 }
 
+delete $::{oonk};
+$::{oonk} = \"Value";
+
+*{"ga_shloip"} = \&{"oonk"};
+
+is (ref $::{ga_shloip}, 'SCALAR', "Export of proxy constant as is");
+is (ref $::{oonk}, 'SCALAR', "Export doesn't affect original");
+is (eval 'ga_shloip', "Value", "Constant has correct value");
+is (ref $::{ga_shloip}, 'SCALAR',
+    "Inlining of constant doesn't change represenatation");
+
+delete $::{ga_shloip};
+
+eval 'sub ga_shloip (); 1' or die $@;
+is ($::{ga_shloip}, '', "Prototype is stored as an empty string");
+
+# Check that a prototype expands.
+*{"ga_shloip"} = \&{"oonk"};
+
+is (ref $::{oonk}, 'SCALAR', "Export doesn't affect original");
+is (eval 'ga_shloip', "Value", "Constant has correct value");
+is (ref \$::{ga_shloip}, 'GLOB', "Symbol table has full typeglob");
+
+
+@::zwot = ('Zwot!');
+
+# Check that assignment to an existing typeglob works
+{
+  my $w = '';
+  local $SIG{__WARN__} = sub { $w = $_[0] };
+  *{"zwot"} = \&{"oonk"};
+  is($w, '', "Should be no warning");
+}
+
+is (ref $::{oonk}, 'SCALAR', "Export doesn't affect original");
+is (eval 'zwot', "Value", "Constant has correct value");
+is (ref \$::{zwot}, 'GLOB', "Symbol table has full typeglob");
+is (join ('!', @::zwot), 'Zwot!', "Existing array still in typeglob");
+
+sub spritsits () {
+    "Traditional";
+}
+
+# Check that assignment to an existing subroutine works
+{
+  my $w = '';
+  local $SIG{__WARN__} = sub { $w = $_[0] };
+  *{"spritsits"} = \&{"oonk"};
+  like($w, qr/^Constant subroutine main::spritsits redefined/,
+       "Redefining a constant sub should warn");
+}
+
+is (ref $::{oonk}, 'SCALAR', "Export doesn't affect original");
+is (eval 'spritsits', "Value", "Constant has correct value");
+is (ref \$::{spritsits}, 'GLOB', "Symbol table has full typeglob");
+
+my $result;
+# Check that assignment to an existing typeglob works
+{
+  my $w = '';
+  local $SIG{__WARN__} = sub { $w = $_[0] };
+  $result = *{"plunk"} = \&{"oonk"};
+  is($w, '', "Should be no warning");
+}
+
+is (ref \$result, 'GLOB',
+    "Non void assignment should still return a typeglob");
+
+is (ref $::{oonk}, 'SCALAR', "Export doesn't affect original");
+is (eval 'plunk', "Value", "Constant has correct value");
+is (ref \$::{plunk}, 'GLOB', "Symbol table has full typeglob");
+
+my $gr = eval '\*plunk' or die;
+
+{
+  my $w = '';
+  local $SIG{__WARN__} = sub { $w = $_[0] };
+  $result = *{$gr} = \&{"oonk"};
+  like($w, qr/^Constant subroutine main::plunk redefined/,
+       "Redefining a constant sub should warn");
+}
+
+is (ref $::{oonk}, 'SCALAR', "Export doesn't affect original");
+is (eval 'plunk', "Value", "Constant has correct value");
+is (ref \$::{plunk}, 'GLOB', "Symbol table has full typeglob");
+
 format =
 .