Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions inline.h
Original file line number Diff line number Diff line change
Expand Up @@ -4152,6 +4152,25 @@ Perl_cx_poploop(pTHX_ PERL_CONTEXT *cx)
cx->blk_loop.itersave = NULL;
SvREFCNT_dec(cursv);
}
if (CxPADLOOP(cx)) {
/* for my ... might be multivariable. my_op->op_next will point at
* the OP_ITER whose op_targ contains the count of how many more
* variables
*/
OP *iterop = cx->blk_loop.my_op->op_next;
assert(iterop->op_type == OP_ITER);
PADOFFSET how_many = iterop->op_targ;
/* op_targ actually stores count - 1, so it's the count of additional
* vars after itervar itself */
for (SV **svp = cx->blk_loop.itervar_u.svp + 1; how_many; svp++, how_many--) {
/* we didn't store an itersave for these, but we know they are all
* scoped to the loop we have just left. It's therefore safe to store
* &PL_sv_undef there since they weren't live before or afterwards.
*/
SvREFCNT_dec(*svp);
*svp = &PL_sv_undef;
}
}
if (cx->cx_type & CXp_FOR_LVREF) {
SV *itervar = (SV *)(cx)->blk_loop.itervar_u.gv;
SV *origval = (cx)->blk_loop.itersave;
Expand Down
15 changes: 15 additions & 0 deletions t/op/for-many.t
Original file line number Diff line number Diff line change
Expand Up @@ -511,4 +511,19 @@ is($continue, 'xx', 'continue reached twice');
pass '2-var for does not crash on lexical sub calls';
}

# all foreach iteration vars are cleared in a timely manner
{
my @arrx;
my @arry;

for my ($x, $y) (\@arrx, \@arry) {
# list items are aliased; add 1 to account for \ ref in the following
refcount_is \@arrx, 2+1, 'arrx refcount 2 inside loop';
refcount_is \@arry, 2+1, 'arry refcount 2 inside loop';
}

refcount_is \@arrx, 1+1, 'arrx refcount 1 after loop';
refcount_is \@arry, 1+1, 'arry refcount 1 after loop';
}

done_testing();
Loading