This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
stop lc() etc accidentally modifying in-place.
authorDavid Mitchell <davem@iabyn.com>
Sun, 20 Mar 2016 17:12:13 +0000 (17:12 +0000)
committerDavid Mitchell <davem@iabyn.com>
Thu, 24 Mar 2016 13:32:47 +0000 (13:32 +0000)
commit1921e03146ca6022defa6af5267c4dd20c0ca699
treea5b4c68425acce9ba1e07784f39151f98298d06e
parentcc4d3128555c2fbf5af7fc75854461cd87502812
stop lc() etc accidentally modifying in-place.

As an optimisation, [ul]c() and [ul]cfirst() sometimes modify their
argument in-place rather than returning a modified copy.

This should only be done when there is no possibility that the arg is
going to be reused. However, this fails:

    use List::Util qw{ first };
    my %hash = ( ASD => 1, ZXC => 2, QWE => 3, TYU => 4);
    print first { lc $_ eq 'qwe' } keys %hash;

which prints "qwe" rather than "QWE".

Bascally everything in perl that sets $_ or $a/$b and calls a code block
or function, such as map, grep, for and, sort, either copies any PADTMPs,
turns off SvTEMP, and/or bumps the reference count.

List::Util doesn't do this, and it is likely that other CPAN modules
which do "set $_ and call a block" don't either.

This has been failing since 5.20.0: perl has been in-placing if the arg is
(SvTEMP && RC==1 && !mg) (due to v5.19.7-112-g5cd5e2d).

Make the optimisation critera stricter by always copying SvTEMPs.
It still allows the optimisation if the arg is a PADTMP - I don't know
whether this is unsafe too.

Perhaps we can think of something better after 5.24?
pp.c
t/op/lc.t