summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gv.c10
-rw-r--r--pod/perldiag.pod7
-rwxr-xr-xt/op/gv.t22
3 files changed, 36 insertions, 3 deletions
diff --git a/gv.c b/gv.c
index 81b8e58df6..97c344809a 100644
--- a/gv.c
+++ b/gv.c
@@ -134,6 +134,16 @@ Perl_gv_init(pTHX_ GV *gv, HV *stash, const char *name, STRLEN len, int multi)
assert (!(proto && has_constant));
if (has_constant) {
+ /* The constant has to be a simple scalar type. */
+ switch (SvTYPE(has_constant)) {
+ case SVt_PVAV:
+ case SVt_PVHV:
+ case SVt_PVCV:
+ case SVt_PVFM:
+ case SVt_PVIO:
+ Perl_croak(aTHX_ "Cannot convert a reference to %s to typeglob",
+ sv_reftype(has_constant, 0));
+ }
SvRV_set(gv, NULL);
SvROK_off(gv);
}
diff --git a/pod/perldiag.pod b/pod/perldiag.pod
index 12041177a9..939e3d7cba 100644
--- a/pod/perldiag.pod
+++ b/pod/perldiag.pod
@@ -480,6 +480,13 @@ See L<perlfunc/pack>.
(F) An argument to pack("w",...) was negative. The BER compressed integer
format can only be used with positive integers. See L<perlfunc/pack>.
+=item Cannot convert a reference to %s to typeglob
+
+(F) You manipulated Perl's symbol table directly, stored a reference in it,
+then tried to access that symbol via conventional Perl syntax. The access
+triggers Perl to autovivify that typeglob, but it there is no legal conversion
+from that type of reference to a typeglob.
+
=item Can only compress unsigned integers in pack
(F) An argument to pack("w",...) was not an integer. The BER compressed
diff --git a/t/op/gv.t b/t/op/gv.t
index e69c1f4d11..ad2db4aa64 100755
--- a/t/op/gv.t
+++ b/t/op/gv.t
@@ -12,7 +12,7 @@ BEGIN {
use warnings;
require './test.pl';
-plan( tests => 97 );
+plan( tests => 105 );
# type coersion on assignment
$foo = 'foo';
@@ -278,7 +278,7 @@ is ($proto, "pie", "String is promoted to prototype");
# A reference to a value is used to generate a constant subroutine
foreach my $value (3, "Perl rules", \42, qr/whatever/, [1,2,3], {1=>2},
- \*STDIN, \&ok, \undef) {
+ \*STDIN, \&ok, \undef, *STDOUT) {
delete $::{oonk};
$::{oonk} = \$value;
$proto = eval 'prototype \&oonk';
@@ -287,9 +287,25 @@ foreach my $value (3, "Perl rules", \42, qr/whatever/, [1,2,3], {1=>2},
my $got = eval 'oonk';
die if $@;
- is (ref $got, ref $value, "Correct type of value");
+ is (ref $got, ref $value, "Correct type of value (" . ref($value) . ")");
is ($got, $value, "Value is correctly set");
}
+
+format =
+.
+
+foreach my $value ([1,2,3], {1=>2}, *STDOUT{IO}, \&ok, *STDOUT{FORMAT}) {
+ # *STDOUT{IO} returns a reference to a PVIO. As it's blessed, ref returns
+ # IO::Handle, which isn't what we want.
+ my $type = $value;
+ $type =~ s/.*=//;
+ $type =~ s/\(.*//;
+ delete $::{oonk};
+ $::{oonk} = $value;
+ $proto = eval 'prototype \&oonk';
+ like ($@, qr/^Cannot convert a reference to $type to typeglob/,
+ "Cannot upgrade ref-to-$type to typeglob");
+}
__END__
Perl
Rules