In perl.git, the branch blead has been updated

<http://perl5.git.perl.org/perl.git/commitdiff/7799a2d155d76d9d2f3e851ca15261c8e22252c2?hp=cb0ee57a7d1f2e00a980be7c8e54b7b704cd764b>

- Log -----------------------------------------------------------------
commit 7799a2d155d76d9d2f3e851ca15261c8e22252c2
Merge: cb0ee57 2f9365d
Author: Tony Cook <t...@develop-help.com>
Date:   Mon Jan 11 09:33:34 2016 +1100

    [perl #126633] fix some corner cases in OPpASSIGN_COMMON_* handling

commit 2f9365dc3b09bdf83c00a6d176d882057608308e
Author: Dave Mitchell <da...@iabyn.com>
Date:   Thu Jan 7 11:36:10 2016 +1100

    [perl #126633] check children of OA_DANGEROUS ops for common scalars
    
    Tony Cook: added tests

M       op.c
M       t/op/aassign.t

commit 5c1db5695506e43718a1575bebb1ecf2675e3798
Author: Tony Cook <t...@develop-help.com>
Date:   Tue Dec 8 11:19:48 2015 +1100

    [perl #126633] copy anything gmagical on the right
    
    It could retrieve something we're setting on the left.

M       pp_hot.c
M       t/op/aassign.t

commit beb08a1e6d63c1eed4da66e066991eb58afccde7
Author: Tony Cook <t...@develop-help.com>
Date:   Mon Dec 7 16:24:52 2015 +1100

    [perl #126633] if we see smagic on the left copy the rest on the right

M       pp_hot.c
M       t/op/aassign.t

commit 0072721ceb719c27771e260b6e8516b947c4bb94
Author: Tony Cook <t...@develop-help.com>
Date:   Mon Dec 7 16:22:38 2015 +1100

    [perl #126633] TODO tests

M       t/op/aassign.t
-----------------------------------------------------------------------

Summary of changes:
 op.c           |  3 ++-
 pp_hot.c       | 54 +++++++++++++++++++++++++++++++++---------------------
 t/op/aassign.t | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 83 insertions(+), 22 deletions(-)

diff --git a/op.c b/op.c
index 1b78a4c..ee31adc 100644
--- a/op.c
+++ b/op.c
@@ -12343,7 +12343,8 @@ S_aassign_scan(pTHX_ OP* o, bool rhs, bool top, int 
*scalars_p)
     default:
         if (PL_opargs[o->op_type] & OA_DANGEROUS) {
             (*scalars_p) += 2;
-            return AAS_DANGEROUS;
+            flags = AAS_DANGEROUS;
+            break;
         }
 
         if (   (PL_opargs[o->op_type] & OA_TARGLEX)
diff --git a/pp_hot.c b/pp_hot.c
index b29c347..b80efae 100644
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -1110,6 +1110,7 @@ S_aassign_copy_common(pTHX_ SV **firstlelem, SV 
**lastlelem,
     SSize_t lcount = lastlelem - firstlelem + 1;
     bool marked = FALSE; /* have we marked any LHS with SVf_BREAK ? */
     bool const do_rc1 = cBOOL(PL_op->op_private & OPpASSIGN_COMMON_RC1);
+    bool copy_all = FALSE;
 
     assert(!PL_in_clean_all); /* SVf_BREAK not already in use */
     assert(firstlelem < lastlelem); /* at least 2 LH elements */
@@ -1138,6 +1139,9 @@ S_aassign_copy_common(pTHX_ SV **firstlelem, SV 
**lastlelem,
             }
 
             assert(svl);
+            if (SvSMAGICAL(svl)) {
+                copy_all = TRUE;
+            }
             if (SvTYPE(svl) == SVt_PVAV || SvTYPE(svl) == SVt_PVHV) {
                 if (!marked)
                     return;
@@ -1169,7 +1173,7 @@ S_aassign_copy_common(pTHX_ SV **firstlelem, SV 
**lastlelem,
         svr = *relem;
         assert(svr);
 
-        if (UNLIKELY(SvFLAGS(svr) & SVf_BREAK)) {
+        if (UNLIKELY(SvFLAGS(svr) & (SVf_BREAK|SVs_GMG) || copy_all)) {
 
 #ifdef DEBUGGING
             if (fake) {
@@ -1259,29 +1263,37 @@ PP(pp_aassign)
      * clobber a value on the right that's used later in the list.
      */
 
-    if ( (PL_op->op_private & (OPpASSIGN_COMMON_SCALAR|OPpASSIGN_COMMON_RC1))
-        /* at least 2 LH and RH elements, or commonality isn't an issue */
-        && (firstlelem < lastlelem && firstrelem < lastrelem)
-    ) {
-        if (PL_op->op_private & OPpASSIGN_COMMON_RC1) {
-            /* skip the scan if all scalars have a ref count of 1 */
-            for (lelem = firstlelem; lelem <= lastlelem; lelem++) {
-                sv = *lelem;
-                if (!sv || SvREFCNT(sv) == 1)
-                    continue;
-                if (SvTYPE(sv) != SVt_PVAV && SvTYPE(sv) != SVt_PVAV)
-                    goto do_scan;
-                break;
-            }
+    /* at least 2 LH and RH elements, or commonality isn't an issue */
+    if (firstlelem < lastlelem && firstrelem < lastrelem) {
+        for (relem = firstrelem+1; relem <= lastrelem; relem++) {
+            if (SvGMAGICAL(*relem))
+                goto do_scan;
         }
-        else {
-          do_scan:
-            S_aassign_copy_common(aTHX_
-                        firstlelem, lastlelem, firstrelem, lastrelem
+        for (lelem = firstlelem; lelem <= lastlelem; lelem++) {
+            if (*lelem && SvSMAGICAL(*lelem))
+                goto do_scan;
+        }
+        if ( PL_op->op_private & 
(OPpASSIGN_COMMON_SCALAR|OPpASSIGN_COMMON_RC1) ) {
+            if (PL_op->op_private & OPpASSIGN_COMMON_RC1) {
+                /* skip the scan if all scalars have a ref count of 1 */
+                for (lelem = firstlelem; lelem <= lastlelem; lelem++) {
+                    sv = *lelem;
+                    if (!sv || SvREFCNT(sv) == 1)
+                        continue;
+                    if (SvTYPE(sv) != SVt_PVAV && SvTYPE(sv) != SVt_PVAV)
+                        goto do_scan;
+                    break;
+                }
+            }
+            else {
+            do_scan:
+                S_aassign_copy_common(aTHX_
+                                      firstlelem, lastlelem, firstrelem, 
lastrelem
 #ifdef DEBUGGING
-                        , fake
+                    , fake
 #endif
-            );
+                );
+            }
         }
     }
 #ifdef DEBUGGING
diff --git a/t/op/aassign.t b/t/op/aassign.t
index 7b245cd..e1c687c 100644
--- a/t/op/aassign.t
+++ b/t/op/aassign.t
@@ -343,5 +343,53 @@ SKIP: {
     is($y, 1, 'single scalar on RHS, but two on LHS: y');
 }
 
+{ # magic handling, see #126633
+    use v5.22;
+    my $set;
+    package ArrayProxy {
+        sub TIEARRAY { bless [ $_[1] ] }
+        sub STORE { $_[0][0]->[$_[1]] = $_[2]; $set = 1 }
+        sub FETCH { $_[0][0]->[$_[1]] }
+        sub CLEAR { @{$_[0][0]} = () }
+        sub EXTEND {}
+    };
+    my @base = ( "a", "b" );
+    my @real = @base;
+    my @proxy;
+    my $temp;
+    tie @proxy, "ArrayProxy", \@real;
+    @proxy[0, 1] = @real[1, 0];
+    is($real[0], "b", "tied left first");
+    is($real[1], "a", "tied left second");
+    @real = @base;
+    @real[0, 1] = @proxy[1, 0];
+    is($real[0], "b", "tied right first");
+    is($real[1], "a", "tied right second");
+    @real = @base;
+    @proxy[0, 1] = @proxy[1, 0];
+    is($real[0], "b", "tied both first");
+    is($real[1], "a", "tied both second");
+    @real = @base;
+    ($temp, @real) = @proxy[1, 0];
+    is($real[0], "a", "scalar/array tied right");
+    @real = @base;
+    ($temp, @proxy) = @real[1, 0];
+    is($real[0], "a", "scalar/array tied left");
+    @real = @base;
+    ($temp, @proxy) = @proxy[1, 0];
+    is($real[0], "a", "scalar/array tied both");
+    $set = 0;
+    my $orig;
+    ($proxy[0], $orig) = (1, $set);
+    is($orig, 0, 'previous value of $set');
+
+    # from cpan #110278
+    use List::Util qw(min);
+    my $x = 1;
+    my $y = 2;
+    ( $x, $y ) = ( min($y), min($x) );
+    is($x, 2, "check swap for \$x");
+    is($y, 1, "check swap for \$y");
+}
 
 done_testing();

--
Perl5 Master Repository

Reply via email to