This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[perl #63540] bizarre closure lossage
authorFather Chrysostomos <sprout@cpan.org>
Mon, 29 Nov 2010 14:05:35 +0000 (06:05 -0800)
committerFather Chrysostomos <sprout@cpan.org>
Mon, 29 Nov 2010 14:06:57 +0000 (06:06 -0800)
commitdbe92b04c262cab7908c1678a21a3dac03a61e15
treed05650bd0f54e6bfc66037dc8e111e0fb7245e56
parentf80c2205cb723cd2cf47ce4d256d279c74a46325
[perl #63540] bizarre closure lossage

main::b in this example shows a null op that has the if() statement
attached to it.

$ perl -MO=Concise,a,b -e 'my $x;sub a {$x}; sub b{if($x){}0}'
main::a:
3  <1> leavesub[1 ref] K/REFC,1 ->(end)
-     <@> lineseq KP ->3
1        <;> nextstate(main 2 -e:1) v ->2
2        <0> padsv[$x:FAKE:] ->3
main::b:
a  <1> leavesub[1 ref] K/REFC,1 ->(end)
-     <@> lineseq KP ->a
4        <;> nextstate(main 5 -e:1) v ->5
-        <1> null vK/1 ->8
6           <|> and(other->7) vK/1 ->8
5              <0> padsv[$x:FAKE:] s ->6
-              <@> scope vK ->-
7                 <0> stub v ->8
8        <;> nextstate(main 5 -e:1) v ->9
9        <$> const[IV 0] s ->a
-e syntax OK

Perl_op_const_sv has:

    if (type == OP_NEXTSTATE || type == OP_NULL || type == OP_PUSHMARK)
continue;

It traverses from the null to the const. The const’s op_next pointer
points to the leavesub, so it is taken to be a constant.

It returns to newATTRSUB, which turns on CvCONST without assigning a
constant value.

Later, cv_clone (called by pp_anoncode) calls op_const_sv again. The
latter returns the SV from the first PADSV it finds, which is the $x
in if($x).

This commit stops op_const_sv from skipping over null ops that
have children.
op.c
t/op/closure.t