This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[perl #97076] Fix mad+threads bareword strict exemption
authorFather Chrysostomos <sprout@cpan.org>
Tue, 16 Aug 2011 05:30:07 +0000 (22:30 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Tue, 16 Aug 2011 06:04:29 +0000 (23:04 -0700)
As reported in the ticket this was broken by:

commit eb796c7f1a47acbd996034731639c1bb76e31a19
Author: Gerard Goossen <gerard@ggoossen.net>
Date:   Tue Aug 9 20:35:06 2011 +0200

    Move bareword checking from the peephole optimizer to finalize_optree. Fixes [perl #95998]

    The bareword checking is moved from the peephole optimizer to finalize_optree.
    newRANGE needs additional bareword checking because the constants may
    be optimized away by 'gen_constant_list'.
    The OPpCONST_STRICT flag is removed after giving an error about a
    bareword to prevent giving multiple errors about the same bareword.

In some cases, like pipe(foo,bar), the bareword was subject to strict
'subs' even though it was meant to be exempt.

A backtrace revealed that it happened in S_finalize_op when called
recursively from this block:

#if defined(PERL_MAD) && defined(USE_ITHREADS)
    {
/* Make sure mad ops are also thread-safe */
MADPROP *mp = o->op_madprop;
while (mp) {
    if (mp->mad_type == MAD_OP && mp->mad_vlen) {
OP *prop_op = (OP *) mp->mad_val;
/* We only need "Relocate sv to the pad for thread safety.", but this
   easiest way to make sure it traverses everything */
finalize_op(prop_op);
    }
    mp = mp->mad_next;
}
    }
#endif

That comment about only needing to relocate the sv to the pad is
telling.  If that’s the only reason for the recursive call, then
we don’t want that recursive call doing strict checking.  So this
commit simply turns off the strict flag, which should be safe, since
S_no_bareword_allowed does the same thing itself.

op.c

diff --git a/op.c b/op.c
index 92fed2b..ae599ad 100644 (file)
--- a/op.c
+++ b/op.c
@@ -1474,6 +1474,8 @@ S_finalize_op(pTHX_ OP* o)
                OP *prop_op = (OP *) mp->mad_val;
                /* We only need "Relocate sv to the pad for thread safety.", but this
                   easiest way to make sure it traverses everything */
+               if (prop_op->op_type == OP_CONST)
+                   cSVOPx(prop_op)->op_private &= ~OPpCONST_STRICT;
                finalize_op(prop_op);
            }
            mp = mp->mad_next;