summaryrefslogtreecommitdiff
path: root/README
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2017-01-02 16:37:27 +0000
committerDavid Mitchell <davem@iabyn.com>2017-01-02 16:52:34 +0000
commit2108cbcf2fd75bfcc7b9c01563db7063a67549cf (patch)
tree0f3918332820d329b207c64b35a6f700c0fc775b /README
parent700779a8627cf5e47eedfe20b1c2eb3c865afb11 (diff)
downloadperl-2108cbcf2fd75bfcc7b9c01563db7063a67549cf.tar.gz
Handle chop(@a =~ tr///)
RT #130198 'chop(@x =~ tr/1/1/)' crashed with an assertion failure. Ditto for chomp. There are two quirks which together cause this. First, the op tree for a tr// is different from other bind ops: $ perl -MO=Concise -e'$x =~ m/a/' 5 <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 1 -e:1) v:{ ->3 4 </> match(/"a"/) vKS ->5 - <1> ex-rv2sv sK/1 ->4 3 <#> gvsv[*x] s ->4 $ perl -MO=Concise -e'$x =~ tr/a/b/' 5 <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 1 -e:1) v:{ ->3 - <1> null vKS/2 ->5 - <1> ex-rv2sv sKRM/1 ->4 3 <#> gvsv[*x] s ->4 4 <"> trans sS ->5 Note that the argument for the match is a child of the match, while the arg of the trans is an (earlier) sibing of the trans (linked by a common null parent). The normal code path that croaks when e.g. a match is seen in an lvalue context, $ perl -e'chop(@a =~ /a/)' Can't modify pattern match (m//) in chop at -e line 1, near "/a/) is skipped, since lvalue() is only called for the first child of a null op. Fixing this is as simple as calling lvalue() on the RHS too if the RHS is a trans op. The second issue is that chop and chomp are special-cased not to flatten an array; so @b = 10..99; chop $a, @b, $c; pushes 3 items on the stack to pass to pp_chop, rather than 102. pp_chop() itself then iterates over any array args. The compiler was seeing the rv2av op in chop(@a =~ tr///) and was setting the OPf_REF (don't flatten) flag on it. Which then caused pp_trans to panic when its arg was an AV rather than a string. This second issue is now moot, since after the fix suggested above, we will have croaked before we reach the place where OPf_REF would be set. This commit adds lots of tests, since tr/a/a/ and tr/a/b/r are special-cased in terms of whether they are regarded as modifying the var they are bound to.
Diffstat (limited to 'README')
0 files changed, 0 insertions, 0 deletions