Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Don’t vivify elems when putting array on stack
6661956 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.
  • Loading branch information
Father Chrysostomos committed Jan 19, 2018
1 parent bcfce88 commit fd77b29
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 4 deletions.
14 changes: 11 additions & 3 deletions pp_hot.c
Expand Up @@ -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 {
Expand All @@ -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;
Expand Down
33 changes: 32 additions & 1 deletion t/op/array.t
Expand Up @@ -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
Expand Down Expand Up @@ -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";

0 comments on commit fd77b29

Please sign in to comment.