This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[perl #78634] Conflict in defining constant INIT
authorFather Chrysostomos <sprout@cpan.org>
Fri, 26 Nov 2010 15:22:47 +0000 (07:22 -0800)
committerFather Chrysostomos <sprout@cpan.org>
Fri, 26 Nov 2010 17:39:51 +0000 (09:39 -0800)
When gv_init tries to turn a constant named INIT into a CV, the auto-
matic special processing of the INIT ‘block’ kicks in, which removes
the CV from the GV.

This should not happen with gv_init, as $::{INIT} = \5 is supposed
to be equivalent to *INIT = sub(){5}, which does not do that.

This commit makes gv_init check for that, increase the reference
count, and reassign the CV. It does not stop the CV from being called
as a special block, but it is harmless to call a constant CV.

gv.c
t/op/blocks.t

diff --git a/gv.c b/gv.c
index b2cb5a4..f51839e 100644 (file)
--- a/gv.c
+++ b/gv.c
@@ -317,6 +317,9 @@ Perl_gv_init(pTHX_ GV *gv, HV *stash, const char *name, STRLEN len, int multi)
 
            /* newCONSTSUB takes ownership of the reference from us.  */
            cv = newCONSTSUB(stash, (name0 ? name0 : name), has_constant);
+           /* In case op.c:S_process_special_blocks stole it: */
+           if (!GvCV(gv))
+               GvCV(gv) = SvREFCNT_inc_simple_NN(cv);
            assert(GvCV(gv) == cv); /* newCONSTSUB should have set this */
            if (name0)
                Safefree(name0);
index 717be4c..8460371 100644 (file)
@@ -6,7 +6,7 @@ BEGIN {
     require './test.pl';
 }
 
-plan tests => 4;
+plan tests => 5;
 
 my @expect = qw(
 b1
@@ -109,3 +109,7 @@ SCRIPT3
 fresh_perl_is(<<'SCRIPT70614', "still here",{switches => [''], stdin => '', stderr => 1 },'eval-UNITCHECK-eval (bug 70614)');
 eval "UNITCHECK { eval 0 }"; print "still here";
 SCRIPT70614
+
+# [perl #78634] Make sure block names can be used as constants.
+use constant INIT => 5;
+::is INIT, 5, 'constant named after a special block';