summaryrefslogtreecommitdiff
path: root/op.c
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2020-08-11 11:55:46 +0100
committerDavid Mitchell <davem@iabyn.com>2020-08-11 16:14:21 +0100
commit5b354d2a8a6fea46c62048464c6722560cb1c907 (patch)
tree3f3defd530bd7ca6b5dec4570e8703edf22ad8bc /op.c
parent1ad5a39ccaca372a3b35f5a76e16aa2aacab104a (diff)
downloadperl-5b354d2a8a6fea46c62048464c6722560cb1c907.tar.gz
list assign in list context was over-optimising
GH #17816 This code: my $x = 1; print (($x, undef) = (2 => $x)); was printing "22" when it should have been printing "21". An optimisation skips the 'common values on both sides' test when the LHS of an assign only contains a single var; as the example above shows, this is not sufficient. This was broken by v5.23.1-202-g808ce55782 This commit fixes it by counting undef's on the LHS towards the var count if they don't appear first.
Diffstat (limited to 'op.c')
-rw-r--r--op.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/op.c b/op.c
index 05f6d9d1a3..49aac853d4 100644
--- a/op.c
+++ b/op.c
@@ -15679,11 +15679,15 @@ S_aassign_scan(pTHX_ OP* o, bool rhs, int *scalars_p)
goto do_next;
case OP_UNDEF:
- /* undef counts as a scalar on the RHS:
- * (undef, $x) = ...; # only 1 scalar on LHS: always safe
+ /* undef on LHS following a var is significant, e.g.
+ * my $x = 1;
+ * @a = (($x, undef) = (2 => $x));
+ * # @a shoul be (2,1) not (2,2)
+ *
+ * undef on RHS counts as a scalar:
* ($x, $y) = (undef, $x); # 2 scalars on RHS: unsafe
*/
- if (rhs)
+ if ((!rhs && *scalars_p) || rhs)
(*scalars_p)++;
flags = AAS_SAFE_SCALAR;
break;