In perl.git, the branch blead has been updated

<http://perl5.git.perl.org/perl.git/commitdiff/a1fba7eb664f6fea65549e94672040d8e47c905e?hp=9f0564c6a634ece822d85183eb4065e894294d7f>

- Log -----------------------------------------------------------------
commit a1fba7eb664f6fea65549e94672040d8e47c905e
Author: Father Chrysostomos <[email protected]>
Date:   Wed Dec 8 16:52:08 2010 -0800

    [perl #68658] attributes turn "state" into "my"
    
    This is for two reasons:
    
    • In S_my_kid, the attribute-handling code comes before the code that
      marks the padop as being a state instead of a my, which it knows to
      do based on the value of PL_parser->in_my. The attribute-handling
      code begins by setting PL_parser->in_my to FALSE, preventing the
      code that follows from doing its job.
    
      So now PL_parser->in_my is read at the top of S_my_kid, before the
      attribute code, with the statehood recorded in a boolean. Then the
      code that marks the padop as being state checks that boolean
      instead of in_my.
    
    • A lexical variable declaration that has an attribute and is assigned
      to in the same expression compiles to something similar to:
    
        (attributes->import(... \$x ...), my $x) = 3;
    
      where the list is actually in scalar context, returning the my $x
      which is then assigned to (something that cannot be expressed
      directly in Perl syntax). So Perl_ck_sassign needs to take that list
      op into account when creating the ‘once’ op that actually makes
      state assignment work. Up till now it was just looking for a padsv
      on its LHS. This commit makes it check also for a list op whose last
      item is a padsv.
-----------------------------------------------------------------------

Summary of changes:
 op.c         |   11 +++++++++--
 t/op/attrs.t |   12 ++++++++++++
 2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/op.c b/op.c
index 13462d1..09b1bbc 100644
--- a/op.c
+++ b/op.c
@@ -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 36d6bee..a8bcd6f 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();

--
Perl5 Master Repository

Reply via email to