diff options
-rw-r--r-- | op.c | 11 | ||||
-rw-r--r-- | t/op/attrs.t | 12 |
2 files changed, 21 insertions, 2 deletions
@@ -2143,6 +2143,7 @@ S_my_kid(pTHX_ OP *o, OP *attrs, OP **imopsp) { dVAR; I32 type; + const bool stately = PL_parser && PL_parser->in_my == KEY_state; PERL_ARGS_ASSERT_MY_KID; @@ -2213,7 +2214,7 @@ S_my_kid(pTHX_ OP *o, OP *attrs, OP **imopsp) } o->op_flags |= OPf_MOD; o->op_private |= OPpLVAL_INTRO; - if (PL_parser->in_my == KEY_state) + if (stately) o->op_private |= OPpPAD_STATE; return o; } @@ -7937,7 +7938,13 @@ Perl_ck_sassign(pTHX_ OP *o) } if (kid->op_sibling) { OP *kkid = kid->op_sibling; - if (kkid->op_type == OP_PADSV + /* For state variable assignment, kkid is a list op whose op_last + is a padsv. */ + if ((kkid->op_type == OP_PADSV || + (kkid->op_type == OP_LIST && + (kkid = cLISTOPx(kkid)->op_last)->op_type == OP_PADSV + ) + ) && (kkid->op_private & OPpLVAL_INTRO) && SvPAD_STATE(*av_fetch(PL_comppad_name, kkid->op_targ, FALSE))) { const PADOFFSET target = kkid->op_targ; diff --git a/t/op/attrs.t b/t/op/attrs.t index 36d6beeee3..a8bcd6f455 100644 --- a/t/op/attrs.t +++ b/t/op/attrs.t @@ -313,4 +313,16 @@ foreach my $test (@tests) { 'Calling closure proto with no @_ that returns a lexical'; } +# [perl #68658] Attributes on stately variables +{ + package thwext; + sub MODIFY_SCALAR_ATTRIBUTES { () } + my $i = 0; + my $x_values = ''; + eval 'sub foo { use 5.01; state $x :A0 = $i++; $x_values .= $x }'; + foo(); foo(); + package main; + is $x_values, '00', 'state with attributes'; +} + done_testing(); |