This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Stop alloc_LOGOP from always setting OPf_KIDS
authorFather Chrysostomos <sprout@cpan.org>
Mon, 8 Jan 2018 04:46:54 +0000 (20:46 -0800)
committerFather Chrysostomos <sprout@cpan.org>
Mon, 8 Jan 2018 16:18:44 +0000 (08:18 -0800)
Commit v5.21.1-125-g3253bf8, which added the function, caused entertry
to get a kid op.  Before:

$ perl5.20.1 -MO=Concise -eeval{}
5  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 2 -e:1) v:{ ->3
4     <@> leavetry vK ->5
3        <|> entertry(other->4) v ->6
6        <0> stub v ->4
-e syntax OK

Notice entertry has no K.  After:

$ perl5.22.0 -MO=Concise -eeval{}
5  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 1 -e:1) v:{ ->3
4     <@> leavetry vK ->5
3        <|> entertry(other->4) vK ->6
6        <0> stub v ->4
-e syntax OK

This time it has a K, but it has no kid ops.

This causes problems for a patch I am working on, because one
can no longer depend on cUNOPo->op_first being non-null when
o->op_flags & OPf_KIDS.

alloc_LOGOP should only set the KIDS flag if it actually has kids.

op.c

diff --git a/op.c b/op.c
index 8b91f60..ace79ad 100644 (file)
--- a/op.c
+++ b/op.c
@@ -1545,7 +1545,8 @@ Perl_alloc_LOGOP(pTHX_ I32 type, OP *first, OP* other)
     OpTYPE_set(logop, type);
     logop->op_first = first;
     logop->op_other = other;
-    logop->op_flags = OPf_KIDS;
+    if (first)
+        logop->op_flags = OPf_KIDS;
     while (kid && OpHAS_SIBLING(kid))
         kid = OpSIBLING(kid);
     if (kid)