Skip to content

Commit

Permalink
ck_refassign: selectively copy OPpPAD_INTRO/STATE
Browse files Browse the repository at this point in the history
Previously this function unconditionally copied the OPpLVAL_INTRO and
OPpPAD_STATE flags from the LH var op to the refassign op, even when those
flag bits weren't used or meant something different.

This commit makes the copying more selective.

It also makes clear by code comments and asserts, that the refassign
op uses bit 6, OPpPAD_STATE, to mean either that or OPpOUR_INTRO
depending on the type of LHS.

I couldn't think of any test that would would break under the old regime,
but this future-proofs the code against new flags and meanings.
  • Loading branch information
iabyn committed Aug 19, 2015
1 parent 92792a1 commit b13702a
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 1 deletion.
11 changes: 10 additions & 1 deletion op.c
Original file line number Diff line number Diff line change
Expand Up @@ -10466,20 +10466,27 @@ Perl_ck_refassign(pTHX_ OP *o)
assert (left);
assert (left->op_type == OP_SREFGEN);

o->op_private = varop->op_private & (OPpLVAL_INTRO|OPpPAD_STATE);
o->op_private = 0;
/* we use OPpPAD_STATE in refassign to mean either of those things,
* and the code assumes the two flags occupy the same bit position
* in the various ops below */
assert(OPpPAD_STATE == OPpOUR_INTRO);

switch (varop->op_type) {
case OP_PADAV:
o->op_private |= OPpLVREF_AV;
goto settarg;
case OP_PADHV:
o->op_private |= OPpLVREF_HV;
/* FALLTHROUGH */
case OP_PADSV:
settarg:
o->op_private |= (varop->op_private & (OPpLVAL_INTRO|OPpPAD_STATE));
o->op_targ = varop->op_targ;
varop->op_targ = 0;
PAD_COMPNAME_GEN_set(o->op_targ, PERL_INT_MAX);
break;

case OP_RV2AV:
o->op_private |= OPpLVREF_AV;
goto checkgv;
Expand All @@ -10489,6 +10496,7 @@ Perl_ck_refassign(pTHX_ OP *o)
/* FALLTHROUGH */
case OP_RV2SV:
checkgv:
o->op_private |= (varop->op_private & (OPpLVAL_INTRO|OPpOUR_INTRO));
if (cUNOPx(varop)->op_first->op_type != OP_GV) goto bad;
detach_and_stack:
/* Point varop to its GV kid, detached. */
Expand All @@ -10511,6 +10519,7 @@ Perl_ck_refassign(pTHX_ OP *o)
}
case OP_AELEM:
case OP_HELEM:
o->op_private |= (varop->op_private & OPpLVAL_INTRO);
o->op_private |= OPpLVREF_ELEM;
op_null(varop);
stacked = TRUE;
Expand Down
6 changes: 6 additions & 0 deletions regen/op_private
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,11 @@ addbits($_, 7 => qw(OPpPV_IS_UTF8 UTF)) for qw(last redo next goto dump);



# note that for refassign, this bit can mean either OPpPAD_STATE or
# OPpOUR_INTRO depending on the type of the LH child, .e.g.
# \our $foo = ...
# \state $foo = ...

addbits($_, 6 => qw(OPpPAD_STATE STATE)) for qw(padav padhv padsv lvavref
lvref refassign pushmark);

Expand Down Expand Up @@ -748,6 +753,7 @@ addbits($_,
3 OPpLVREF_CV CV
)],
},
#6 => qw(OPpPAD_STATE STATE),
#7 => qw(OPpLVAL_INTRO LVINTRO),
) for 'refassign', 'lvref';

Expand Down

0 comments on commit b13702a

Please sign in to comment.