In perl.git, the branch blead has been updated <https://perl5.git.perl.org/perl.git/commitdiff/fd77b29b3be4108adb4a74b9c274599eaf228cb3?hp=a8e51187c21fee8697b9299b5303d90883b1eba9>
- Log ----------------------------------------------------------------- commit fd77b29b3be4108adb4a74b9c274599eaf228cb3 Author: Father Chrysostomos <spr...@cpan.org> Date: Fri Jan 19 13:47:53 2018 -0800 Don’t vivify elems when putting array on stack 6661956a2 was a little too powerful, and, in addition to fixing the bug that @_ did not properly alias nonexistent elements, also broke other uses of nonexistent array elements. (See the tests added.) This commit changes it so that putting @a on the stack does not vivify all ‘holes’ in @a, but creates defelem (deferred element) scalars, but only in lvalue context. commit bcfce88b64155612fcd6af40e88805fe32c25b7f Author: Father Chrysostomos <spr...@cpan.org> Date: Fri Jan 19 12:41:15 2018 -0800 Apply the mod flag to @a in \(@a) The next commit will depend on it. ----------------------------------------------------------------------- Summary of changes: op.c | 12 ++++++++++-- pp_hot.c | 14 +++++++++++--- t/op/array.t | 33 ++++++++++++++++++++++++++++++++- 3 files changed, 53 insertions(+), 6 deletions(-) diff --git a/op.c b/op.c index 2b87f9c781..373822a349 100644 --- a/op.c +++ b/op.c @@ -4081,7 +4081,10 @@ Perl_op_lvalue_flags(pTHX_ OP *o, I32 type, U32 flags) case OP_RV2HV: if (type == OP_REFGEN && o->op_flags & OPf_PARENS) { PL_modcount = RETURN_UNLIMITED_NUMBER; - return o; /* Treat \(@foo) like ordinary list. */ + /* Treat \(@foo) like ordinary list, but still mark it as modi- + fiable since some contexts need to know. */ + o->op_flags |= OPf_MOD; + return o; } /* FALLTHROUGH */ case OP_RV2GV: @@ -4146,7 +4149,12 @@ Perl_op_lvalue_flags(pTHX_ OP *o, I32 type, U32 flags) case OP_PADHV: PL_modcount = RETURN_UNLIMITED_NUMBER; if (type == OP_REFGEN && o->op_flags & OPf_PARENS) - return o; /* Treat \(@foo) like ordinary list. */ + { + /* Treat \(@foo) like ordinary list, but still mark it as modi- + fiable since some contexts need to know. */ + o->op_flags |= OPf_MOD; + return o; + } if (scalar_mod_type(o, type)) goto nomod; if ((o->op_flags & OPf_WANT) != OPf_WANT_SCALAR diff --git a/pp_hot.c b/pp_hot.c index d479ecf218..1bc453a457 100644 --- a/pp_hot.c +++ b/pp_hot.c @@ -1163,8 +1163,12 @@ S_pushav(pTHX_ AV* const av) if (UNLIKELY(SvRMAGICAL(av))) { PADOFFSET i; for (i=0; i < (PADOFFSET)maxarg; i++) { - SV ** const svp = av_fetch(av, i, TRUE); - SP[i+1] = svp ? *svp : &PL_sv_undef; + SV ** const svp = av_fetch(av, i, FALSE); + SP[i+1] = LIKELY(svp) + ? *svp + : UNLIKELY(PL_op->op_flags & OPf_MOD) + ? newSVavdefelem(av,i,1) + : &PL_sv_undef; } } else { @@ -1173,7 +1177,11 @@ S_pushav(pTHX_ AV* const av) SV *sv = AvARRAY(av)[i]; if (!LIKELY(sv)) AvARRAY(av)[i] = sv = newSV(0); - SP[i+1] = sv; + SP[i+1] = LIKELY(sv) + ? sv + : UNLIKELY(PL_op->op_flags & OPf_MOD) + ? newSVavdefelem(av,i,1) + : &PL_sv_undef; } } SP += maxarg; diff --git a/t/op/array.t b/t/op/array.t index 3d9b9d7900..9d0bfad4ef 100644 --- a/t/op/array.t +++ b/t/op/array.t @@ -6,7 +6,7 @@ BEGIN { set_up_inc('.', '../lib'); } -plan (179); +plan (185); # # @foo, @bar, and @ary are also used from tie-stdarray after tie-ing them @@ -595,4 +595,35 @@ $#a = -1; $#a++; is join("", @r), "55", "lazy element creation with foreach"; } +{ # Some things broken by the initial fix for #8910 + (\my @a)->$#*++; + my @b = @a; + ok !exists $a[0], 'copying an array via = does not vivify elements'; + delete $a[0]; + @a[1..5] = 1..5; + $#a++; + my $count; + my @existing_elements = map { exists $a[$count++] ? $_ : () } @a; + is join(",", @existing_elements), "1,2,3,4,5", + 'map {} @a does not vivify elements'; + $#a = -1; + {local $a[3] = 12; my @foo=@a}; + is @a, 0,'unwinding localization of elem past end of array shrinks it'; + + # Again, but with a package array + package tmp; (\our @a)->$#*++; package main; + my @b = @a; + ok !exists $a[0], 'copying an array via = does not vivify elements'; + delete $a[0]; + @a[1..5] = 1..5; + $#a++; + my $count; + my @existing_elements = map { exists $a[$count++] ? $_ : () } @a; + is join(",", @existing_elements), "1,2,3,4,5", + 'map {} @a does not vivify elements'; + $#a = -1; + {local $a[3] = 12; my @foo=@a}; + is @a, 0, 'unwinding localization of elem past end of array shrinks it' +} + "We're included by lib/Tie/Array/std.t so we need to return something true"; -- Perl5 Master Repository