This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
5.22.3-RC4 and 5.24.1-RC4 today
[perl5.git] / op.c
diff --git a/op.c b/op.c
index 2e85438..697faa7 100644 (file)
--- a/op.c
+++ b/op.c
@@ -1017,8 +1017,8 @@ Perl_op_clear(pTHX_ OP *o)
        goto clear_pmop;
 
     case OP_SPLIT:
-        if (     (o->op_private & OPpSPLIT_ASSIGN)
-            && !(o->op_flags & OPf_STACKED))
+        if (     (o->op_private & OPpSPLIT_ASSIGN) /* @array  = split */
+            && !(o->op_flags & OPf_STACKED))       /* @{expr} = split */
         {
             if (o->op_private & OPpSPLIT_LEX)
                 pad_free(cPMOPo->op_pmreplrootu.op_pmtargetoff);
@@ -4763,7 +4763,7 @@ Perl_op_convert_list(pTHX_ I32 type, I32 flags, OP *o)
     if (type != OP_SPLIT)
         /* At this point o is a LISTOP, but OP_SPLIT is a PMOP; let
          * ck_split() create a real PMOP and leave the op's type as listop
-         * for for now. Otherwise op_free() etc will crash.
+         * for now. Otherwise op_free() etc will crash.
          */
         OpTYPE_set(o, type);
 
@@ -5594,7 +5594,7 @@ S_set_haseval(pTHX)
  * constant), or convert expr into a runtime regcomp op sequence (if it's
  * not)
  *
- * Flags currently has 2 bits or meaning:
+ * Flags currently has 2 bits of meaning:
  * 1: isreg indicates that the pattern is part of a regex construct, eg
  * $x =~ /pattern/ or split /pattern/, as opposed to $x =~ $pattern or
  * split "pattern", which aren't. In the former case, expr will be a list
@@ -6568,10 +6568,10 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right)
        }
 
         /* optimise @a = split(...) into:
-            * local/my @a:  split(..., @a), where @a is not flattened
-            * other arrays: split(...)      where @a is attached to
-            *                                   the split op itself
-            */
+        * @{expr}:              split(..., @{expr}) (where @a is not flattened)
+        * @a, my @a, local @a:  split(...)          (where @a is attached to
+        *                                            the split op itself)
+        */
 
        if (   right
             && right->op_type == OP_SPLIT
@@ -6580,22 +6580,19 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right)
         {
             OP *gvop = NULL;
 
-            if (!(left->op_private & OPpLVAL_INTRO) &&
-                ( (left->op_type == OP_RV2AV &&
-                  (gvop=((UNOP*)left)->op_first)->op_type==OP_GV)
-                || left->op_type == OP_PADAV )
-                )
+            if (   (  left->op_type == OP_RV2AV
+                   && (gvop=((UNOP*)left)->op_first)->op_type==OP_GV)
+                || left->op_type == OP_PADAV)
             {
-                /* @pkg or @lex, but not 'local @pkg' nor 'my @lex' */
+                /* @pkg or @lex or local @pkg' or 'my @lex' */
                 OP *tmpop;
-                PMOP * const pm = (PMOP*)right;
                 if (gvop) {
 #ifdef USE_ITHREADS
-                    pm->op_pmreplrootu.op_pmtargetoff
+                    ((PMOP*)right)->op_pmreplrootu.op_pmtargetoff
                         = cPADOPx(gvop)->op_padix;
                     cPADOPx(gvop)->op_padix = 0;       /* steal it */
 #else
-                    pm->op_pmreplrootu.op_pmtargetgv
+                    ((PMOP*)right)->op_pmreplrootu.op_pmtargetgv
                         = MUTABLE_GV(cSVOPx(gvop)->op_sv);
                     cSVOPx(gvop)->op_sv = NULL;        /* steal it */
 #endif
@@ -6603,10 +6600,11 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right)
                         left->op_private & OPpOUR_INTRO;
                 }
                 else {
-                    pm->op_pmreplrootu.op_pmtargetoff = left->op_targ;
+                    ((PMOP*)right)->op_pmreplrootu.op_pmtargetoff = left->op_targ;
                     left->op_targ = 0; /* steal it */
                     right->op_private |= OPpSPLIT_LEX;
                 }
+                right->op_private |= left->op_private & OPpLVAL_INTRO;
 
               detach_split:
                 tmpop = cUNOPo->op_first;      /* to list (nulled) */
@@ -6622,10 +6620,8 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right)
                         /* "I don't know and I don't care." */
                 return right;
             }
-            else if (left->op_type == OP_RV2AV
-                  || left->op_type == OP_PADAV)
-            {
-                /* 'local @pkg' or 'my @lex' */
+            else if (left->op_type == OP_RV2AV) {
+                /* @{expr} */
 
                 OP *pushop = cUNOPx(cBINOPo->op_last)->op_first;
                 assert(OpSIBLING(pushop) == left);
@@ -11154,7 +11150,7 @@ Perl_ck_split(pTHX_ OP *o)
     kid = cLISTOPo->op_first;
 
     if (kid->op_type != OP_MATCH || kid->op_flags & OPf_STACKED) {
-        /* remove match expression, and replace with new optree  with
+        /* remove match expression, and replace with new optree with
          * a match op at its head */
         op_sibling_splice(o, NULL, 1, NULL);
         /* pmruntime will handle split " " behavior with flag==2 */
@@ -11173,10 +11169,10 @@ Perl_ck_split(pTHX_ OP *o)
      * into its place, then convert the match op into a split op. i.e.
      *
      *  SPLIT                    MATCH                 SPLIT(ex-MATCH)
-     *    |                        |                     |               
-     *  MATCH - A - B - C   =>     R - A - B - C   =>    R - A - B - C 
-     *    |                        |                     |               
-     *    R                        X - Y                 X - Y           
+     *    |                        |                     |
+     *  MATCH - A - B - C   =>     R - A - B - C   =>    R - A - B - C
+     *    |                        |                     |
+     *    R                        X - Y                 X - Y
      *    |
      *    X - Y
      *
@@ -12523,6 +12519,7 @@ S_aassign_scan(pTHX_ OP* o, bool rhs, bool top, int *scalars_p)
     case OP_PADAV:
     case OP_PADHV:
         (*scalars_p) += 2;
+        /* if !top, could be e.g. @a[0,1] */
         if (top && (o->op_flags & OPf_REF))
             return (o->op_private & OPpLVAL_INTRO)
                 ? AAS_MY_AGG : AAS_LEX_AGG;
@@ -12543,6 +12540,7 @@ S_aassign_scan(pTHX_ OP* o, bool rhs, bool top, int *scalars_p)
         if (cUNOPx(o)->op_first->op_type != OP_GV)
             return AAS_DANGEROUS; /* @{expr}, %{expr} */
         /* @pkg, %pkg */
+        /* if !top, could be e.g. @a[0,1] */
         if (top && (o->op_flags & OPf_REF))
             return AAS_PKG_AGG;
         return AAS_DANGEROUS;
@@ -12556,17 +12554,32 @@ S_aassign_scan(pTHX_ OP* o, bool rhs, bool top, int *scalars_p)
         return AAS_PKG_SCALAR; /* $pkg */
 
     case OP_SPLIT:
-        if (1) { /* XXX this condition is wrong - fix later
-        if (cLISTOPo->op_first->op_type == OP_PUSHRE) {
-        */
-            /* "@foo = split... " optimises away the aassign and stores its
-             * destination array in the OP_PUSHRE that precedes it.
-             * A flattened array is always dangerous.
+        if (o->op_private & OPpSPLIT_ASSIGN) {
+            /* the assign in @a = split() has been optimised away
+             * and the @a attached directly to the split op
+             * Treat the array as appearing on the RHS, i.e.
+             *    ... = (@a = split)
+             * is treated like
+             *    ... = @a;
              */
+
+            if (o->op_flags & OPf_STACKED)
+                /* @{expr} = split() - the array expression is tacked
+                 * on as an extra child to split - process kid */
+                return S_aassign_scan(aTHX_ cLISTOPo->op_last, rhs,
+                                        top, scalars_p);
+
+            /* ... else array is directly attached to split op */
             (*scalars_p) += 2;
-            return AAS_DANGEROUS;
+            if (PL_op->op_private & OPpSPLIT_LEX)
+                return (o->op_private & OPpLVAL_INTRO)
+                    ? AAS_MY_AGG : AAS_LEX_AGG;
+            else
+                return AAS_PKG_AGG;
         }
-        break;
+        (*scalars_p)++;
+        /* other args of split can't be returned */
+        return AAS_SAFE_SCALAR;
 
     case OP_UNDEF:
         /* undef counts as a scalar on the RHS: