Fix bug in inlining some CORE::* subs
authorAaron Crane <arc@cpan.org>
Tue, 15 Jul 2014 17:28:42 +0000 (18:28 +0100)
committerAaron Crane <arc@cpan.org>
Fri, 1 Aug 2014 15:30:45 +0000 (16:30 +0100)
commit66c742d5709538d20fcc9da3f377be437119ba19
treec5335e376c6ba0b1b4de0125a5dafe19cecbeada
parent5e33e2aa63ba88d865ac1653a8dbc30cdafd1822
Fix bug in inlining some CORE::* subs

As of 4aaa475724fbbc4ab2427743fa4d07a12e6ce0d9, when Perl compiles code like

    BEGIN { *entangle = \&CORE::tie }
    entangle $foo, $package

the apparent call to "entangle" is replaced with an inlined invocation of
the "tie" builtin.

For unary ops, the OPf_SPECIAL flag was set on the generated inlined op iff
the op's argument was surrounded by parens. But that's incorrect for ops
which have their own interpretation of OPf_SPECIAL. In particular:

  keys, values, each
    OPf_SPECIAL is set for lvalue usage; this shows up when the compile-time
    argument is a reference to be subjected to the autoderef feature, and
    the run-time argument is an array ref. The existing tests didn't execute
    the code (and didn't combine inlining with array autoderefs), so didn't
    catch this case.

  delete, exists
    OPf_SPECIAL is set when the argument is an array element rather than a
    hash element; this doesn't directly cause any obvious problems, because
    pp_delete and pp_exists consider OPf_SPECIAL only when they've already
    determined that their argument is an array element, but it did break
    deparsing (because B::Deparse considers OPf_SPECIAL in all cases): the
    hash element argument got deparsed as an array element. Further, the
    inlining tests themselves rely on deparsing to ensure that the op was
    inlined. The existing inlining tests happened to use array elements, so
    didn't catch this problem.

This commit fixes those cases, by avoiding setting OPf_SPECIAL when inlining
an invocation of one of those ops. The list of op types is hard-coded; this
seems a little icky, but I don't see a better alternative.

I believe that no other ops are affected by this issue, but my confidence in
that statement isn't as high as it might be; it seems hard to work out
exactly which ops use OPf_SPECIAL.
op.c
t/op/coresubs.t