This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
multiconcat: keep assign for 'local $foo = "..."'
authorDavid Mitchell <davem@iabyn.com>
Tue, 4 Feb 2020 12:23:26 +0000 (12:23 +0000)
committerDavid Mitchell <davem@iabyn.com>
Tue, 4 Feb 2020 12:43:24 +0000 (12:43 +0000)
commitd5a02d973b44832f918778202d68f066c8af3963
treede83f9de5b8da590e8f7764886f34fe75e892f56
parent99c9ca9ebc1ca483167d8c51cdc3bf9e69c08dae
multiconcat: keep assign for 'local $foo = "..."'

In something like

    local $~ = "$~X";

i.e. where localising a magic variable whose previous value should be
used as part of a string concat on the RHS, don't fold the assign into
the multiconcat op. Otherwise the code execution path looks a bit like:

    local($~) = undef;
    multiconcat($~, $~, "X");

[ where multiconcat's args are (target, arg1, arg2,....) ]
and thus multiconcat sees an undef arg.

By leaving the assign out of the multiconcat, code execution now looks
like
    my $targ;
    multiconcat($targ, $~, "X");
    local($~) = $targ;

See http://nntp.perl.org/group/perl.perl5.porters/256898,
    "Bug in format introduced in 5.27.6".

Although the bug only appears with magic vars, this patch pessimises
all forms of 'local $foo = "..."', 'local $foo{bar} = "..."' etc.
Strictly speaking the bug occurs because with 'local' you end up with
two SVs (the saved one and the one currently in the glob) which both
have the same container magic and where mg_set()ing one changes the
mg_get() value of the other. Thus, vars like $!. One of the two SVs
becomes an arg of multiconcat, the other becomes its target. Part of
localising the target SV (before multiconcat is called) wipes the value
of the arg SV.
op.c
t/op/concat2.t
t/perf/opcount.t