Skip to content
Open
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
2 changes: 1 addition & 1 deletion cop.h
Original file line number Diff line number Diff line change
Expand Up @@ -1166,7 +1166,7 @@ struct context {
/* this is only set in conjunction with CXp_FOR_GV */
#define CXp_FOR_DEF 0x10 /* foreach using $_ */
/* these 3 are mutually exclusive */
#define CXp_FOR_LVREF 0x20 /* foreach using \$var */
#define CXp_FOR_LVREF 0x20 /* foreach using \our $var */
#define CXp_FOR_GV 0x40 /* foreach using package var */
#define CXp_FOR_PAD 0x80 /* foreach using lexical var */

Expand Down
56 changes: 24 additions & 32 deletions inline.h
Original file line number Diff line number Diff line change
Expand Up @@ -4317,43 +4317,35 @@ Perl_cx_poploop(pTHX_ PERL_CONTEXT *cx)
MAGIC *mg = SvMAGIC(itervar);
assert(mg);
assert(mg->mg_type == PERL_MAGIC_lvref);
if (!mg->mg_obj) {
// LV ref around a lexical, mg_len gives its pad index
SV **padslot = &PAD_SVl(mg->mg_len);
SV *oldsv = *padslot;
*padslot = origval;
SvREFCNT_dec(oldsv);
}
else {
// LV ref around a package lexical, mg_obj gives its GV
GV *gv = (GV *)mg->mg_obj;
SV *oldsv = NULL;
switch(mg->mg_private & OPpLVREF_TYPE) {
case OPpLVREF_SV:
oldsv = GvSVn(gv);
GvSVn(gv) = origval;
break;
assert(mg->mg_obj);
// LV ref around a package lexical, mg_obj gives its GV
GV *gv = (GV *)mg->mg_obj;
SV *oldsv = NULL;
switch(mg->mg_private & OPpLVREF_TYPE) {
case OPpLVREF_SV:
oldsv = GvSVn(gv);
GvSVn(gv) = origval;
break;

case OPpLVREF_AV:
oldsv = (SV *)GvAV(gv);
GvAV(gv) = (AV *)origval;
break;
case OPpLVREF_AV:
oldsv = (SV *)GvAV(gv);
GvAV(gv) = (AV *)origval;
break;

case OPpLVREF_HV:
oldsv = (SV *)GvHV(gv);
GvHV(gv) = (HV *)origval;
break;
case OPpLVREF_HV:
oldsv = (SV *)GvHV(gv);
GvHV(gv) = (HV *)origval;
break;

case OPpLVREF_CV:
oldsv = (SV *)GvCV(gv);
GvCV_set(gv, (CV *)origval);
break;
case OPpLVREF_CV:
oldsv = (SV *)GvCV(gv);
GvCV_set(gv, (CV *)origval);
break;

default:
NOT_REACHED;
}
SvREFCNT_dec(oldsv);
default:
NOT_REACHED;
}
SvREFCNT_dec(oldsv);
}
if (cx->cx_type & (CXp_FOR_GV|CXp_FOR_LVREF))
SvREFCNT_dec(cx->blk_loop.itervar_u.svp);
Expand Down
94 changes: 49 additions & 45 deletions lib/B/Deparse.t
Original file line number Diff line number Diff line change
Expand Up @@ -2622,51 +2622,6 @@ my %h;
$_ == 3 ? \$_ : $_ = \3;
$_ == 3 ? \$_ : \$x = \3;
\($_ == 3 ? $_ : $x) = \3;
for \my $topic (\$1, \$2) {
die;
}
for \state $topic (\$1, \$2) {
die;
}
for \our $topic (\$1, \$2) {
die;
}
for \$_ (\$1, \$2) {
die;
}
for \my @a ([1,2], [3,4]) {
die;
}
for \state @a ([1,2], [3,4]) {
die;
}
for \our @a ([1,2], [3,4]) {
die;
}
for \@_ ([1,2], [3,4]) {
die;
}
for \my %a ({5,6}, {7,8}) {
die;
}
for \our %a ({5,6}, {7,8}) {
die;
}
for \state %a ({5,6}, {7,8}) {
die;
}
for \%_ ({5,6}, {7,8}) {
die;
}
{
my sub a;
for \&a (sub { 9; }, sub { 10; }) {
die;
}
}
for \&a (sub { 9; }, sub { 10; }) {
die;
}
>>>>
our $x;
\$x = \$x;
Expand Down Expand Up @@ -2745,6 +2700,55 @@ my %h;
$_ == 3 ? \$_ : $_ = \3;
$_ == 3 ? \$_ : \$x = \3;
($_ == 3 ? \$_ : \$x) = \3;
####
# lvalue reference iteration
# CONTEXT use feature "state", 'refaliasing', 'lexical_subs'; no warnings 'experimental';
for \my $topic (\$1, \$2) {
die;
}
for \state $topic (\$1, \$2) {
die;
}
for \our $topic (\$1, \$2) {
die;
}
for \$_ (\$1, \$2) {
die;
}
for \my @a ([1,2], [3,4]) {
die;
}
for \state @a ([1,2], [3,4]) {
die;
}
for \our @a ([1,2], [3,4]) {
die;
}
for \@_ ([1,2], [3,4]) {
die;
}
for \my %a ({5,6}, {7,8}) {
die;
}
for \our %a ({5,6}, {7,8}) {
die;
}
for \state %a ({5,6}, {7,8}) {
die;
}
for \%_ ({5,6}, {7,8}) {
die;
}
{
my sub a;
for \&a (sub { 9; }, sub { 10; }) {
die;
}
}
for \&a (sub { 9; }, sub { 10; }) {
die;
}
>>>>
foreach \my $topic (\$1, \$2) {
die;
}
Expand Down
7 changes: 5 additions & 2 deletions op.c
Original file line number Diff line number Diff line change
Expand Up @@ -10086,11 +10086,14 @@ Perl_newFOROP(pTHX_ I32 flags, OP *sv, OP *expr, OP *block, OP *cont)
varop->op_type == OP_PADAV ||
varop->op_type == OP_PADHV));

if(varop->op_type != OP_LVREF || varop->op_private & OPpLVAL_INTRO) { /* for my \VAR */
/* Any of these ops with a non-zero ->op_targ operates on lexicals
* providing it is not OPf_STACKED */
if((varop->op_targ && !(varop->op_flags & OPf_STACKED)) || varop->op_private & OPpLVAL_INTRO) { /* for my \VAR */
/* Throw away the sv op subtree and turn this into a simple
* padoffset + OPpITER_REFALIAS flag */
iterpflags = OPpITER_REFALIAS;
enteriterpflags = OPpLVAL_INTRO;
if(varop->op_private & OPpLVAL_INTRO)
enteriterpflags = OPpLVAL_INTRO;
padoff = varop->op_targ;
varop->op_targ = 0;
op_free(sv);
Expand Down
25 changes: 10 additions & 15 deletions pp_ctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -2627,22 +2627,17 @@ PP(pp_enteriter)
MAGIC *mg = SvMAGIC(sv);
assert(mg);
assert(mg->mg_type == PERL_MAGIC_lvref);
if (!mg->mg_obj) {
// LV ref around a lexical, mg_len gives its pad index
itersave = SvREFCNT_inc_NN(PAD_SV(mg->mg_len));
}
else {
// LV ref around a package lexical, mg_obj gives its GV
GV *gv = (GV *)mg->mg_obj;
assert(SvTYPE(gv) == SVt_PVGV);
switch(mg->mg_private & OPpLVREF_TYPE) {
case OPpLVREF_SV: itersave = GvSVn(gv); break;
case OPpLVREF_AV: itersave = (SV *)GvAV(gv); break;
case OPpLVREF_HV: itersave = (SV *)GvHV(gv); break;
case OPpLVREF_CV: itersave = (SV *)GvCV(gv); break;
}
SvREFCNT_inc_void(itersave);
assert(mg->mg_obj);
// LV ref around a package lexical, mg_obj gives its GV
GV *gv = (GV *)mg->mg_obj;
assert(SvTYPE(gv) == SVt_PVGV);
switch(mg->mg_private & OPpLVREF_TYPE) {
case OPpLVREF_SV: itersave = GvSVn(gv); break;
case OPpLVREF_AV: itersave = (SV *)GvAV(gv); break;
case OPpLVREF_HV: itersave = (SV *)GvHV(gv); break;
case OPpLVREF_CV: itersave = (SV *)GvCV(gv); break;
}
SvREFCNT_inc_void(itersave);
cxflags = CXp_FOR_LVREF;
}
/* we transfer ownership of 1 ref count of itervarp from the stack
Expand Down
Loading