This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[perl #127333] add warning for until(assignment)
authorDan Collins <dcollinsn@gmail.com>
Tue, 7 Jun 2016 01:04:46 +0000 (21:04 -0400)
committerTony Cook <tony@develop-help.com>
Tue, 7 Jun 2016 04:43:48 +0000 (14:43 +1000)
while ($a = 1) emits a warning "Found = in conditional, should be ==".
However, until ($a = 1) does not. The parser breaks down until
(condition) into while (!(condition)), which defeats the check in
S_scalarboolean, since it is looking for a conditional that /is/ an
assignment, but we have a conditional that is a thinly veiled assignment.

A similar bug is [perl #127122]. That bug was fixed by treating
unless (a) {b} else {c} as if (a) {c} else {b}, instead of treating it
as if (!a) {b} else {c}. That approach will not work here.

Instead, the test in S_scalarboolean has been widened. It previously
looked for an OP_SASSIGN with op_first OP_CONST, it now also detects an
OP_NOT surrounding that construct.

Tests for both while() and until() were also added to t/lib/warnings/op.

op.c
t/lib/warnings/op

diff --git a/op.c b/op.c
index 128cdc4..6986610 100644 (file)
--- a/op.c
+++ b/op.c
@@ -1532,8 +1532,11 @@ S_scalarboolean(pTHX_ OP *o)
 {
     PERL_ARGS_ASSERT_SCALARBOOLEAN;
 
-    if (o->op_type == OP_SASSIGN && cBINOPo->op_first->op_type == OP_CONST
-     && !(cBINOPo->op_first->op_flags & OPf_SPECIAL)) {
+    if ((o->op_type == OP_SASSIGN && cBINOPo->op_first->op_type == OP_CONST &&
+         !(cBINOPo->op_first->op_flags & OPf_SPECIAL)) ||
+        (o->op_type == OP_NOT     && cUNOPo->op_first->op_type == OP_SASSIGN &&
+         cBINOPx(cUNOPo->op_first)->op_first->op_type == OP_CONST &&
+         !(cBINOPx(cUNOPo->op_first)->op_first->op_flags & OPf_SPECIAL))) {
        if (ckWARN(WARN_SYNTAX)) {
            const line_t oldline = CopLINE(PL_curcop);
 
index cf7a798..cc0cf46 100644 (file)
@@ -134,6 +134,28 @@ Found = in conditional, should be == at - line 3.
 Found = in conditional, should be == at - line 4.
 ########
 # op.c
+# NAME while with assignment as condition
+use warnings 'syntax';
+1 while $a = 0;
+while ($a = 0) {
+    1;
+}
+EXPECT
+Found = in conditional, should be == at - line 3.
+Found = in conditional, should be == at - line 4.
+########
+# op.c
+# NAME until with assignment as condition
+use warnings 'syntax';
+1 until $a = 1;
+until ($a = 1) {
+    1;
+}
+EXPECT
+Found = in conditional, should be == at - line 3.
+Found = in conditional, should be == at - line 4.
+########
+# op.c
 use warnings 'syntax' ;
 @a[3];
 @a{3};