This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Fix assertion failure with our subs and constants
authorFather Chrysostomos <sprout@cpan.org>
Mon, 1 Sep 2014 06:14:20 +0000 (23:14 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Mon, 1 Sep 2014 13:30:21 +0000 (06:30 -0700)
The code path that looks up ‘our’ subs was not vivifying GVs in
the symbol table, and it was assuming that anything it found
would be a GV.

Constants created by ‘use constant’ are stored as simple scalar refs,
when possible, instead of GVs with CVs.

So GvCV() was called on an RV, and blew up.

$ ./miniperl -Ilib -Mfeature=lexical_subs -e 'our sub foo; BEGIN { delete $::{foo}; } use constant foo=>3; warn foo()'
The lexical_subs feature is experimental at -e line 1.
Assertion failed: (SvTYPE(_gvgp) == SVt_PVGV || SvTYPE(_gvgp) == SVt_PVLV), function Perl_yylex, file toke.c, line 6566.
Abort trap: 6

t/op/lexsub.t
toke.c

index 1dfd953..efb5309 100644 (file)
@@ -7,7 +7,7 @@ BEGIN {
     *bar::is = *is;
     *bar::like = *like;
 }
-plan 129;
+plan 130;
 
 # -------------------- Errors with feature disabled -------------------- #
 
@@ -88,6 +88,14 @@ sub bar::c { 43 }
   my $y = if if if;
   is $y, 42, 'our subs from other packages override all keywords';
 }
+# Interaction with ‘use constant’
+{
+  our sub const; # symtab now has an undefined CV
+  BEGIN { delete $::{const} } # delete symtab entry; pad entry still exists
+  use constant const => 3; # symtab now has a scalar ref
+  # inlining this used to fail an assertion (parentheses necessary):
+  is(const, 3, 'our sub pointing to "use constant" constant');
+}
 
 # -------------------- state -------------------- #
 
diff --git a/toke.c b/toke.c
index 4e7ae3b..98e4b7d 100644 (file)
--- a/toke.c
+++ b/toke.c
@@ -6563,7 +6563,7 @@ Perl_yylex(pTHX)
                    rv2cv_op =
                        newCVREF(OPpMAY_RETURN_CONSTANT<<8, const_op);
                    cv = lex
-                       ? GvCV(gv)
+                       ? isGV(gv) ? GvCV(gv) : (CV *)gv
                        : rv2cv_op_cv(rv2cv_op, RV2CVOPCV_RETURN_STUB);
                }