On Wed, Aug 20, 2014 at 02:36:21PM -0400, Jason Merrill wrote:
> Could we set current.lhs_type to TRUTH_NOT_EXPR when we see a ! rather than
> track nots in two separate local variables?

Good point.  So like the following?  I haven't had time to run the full
regtest/bootstrap cycle yet, but at least the -Wlogical-not-parentheses
testcases and dg.exp pass.

2014-08-20  Marek Polacek  <pola...@redhat.com>

        PR c++/62199
        * parser.c (cp_parser_binary_expression): Check each LHS if it's
        preceded with logical not.  Handle logical not of constants.

        * c-c++-common/pr62199.c: New test.

diff --git gcc/cp/parser.c gcc/cp/parser.c
index 9053bfa..18705ee 100644
--- gcc/cp/parser.c
+++ gcc/cp/parser.c
@@ -8071,6 +8071,8 @@ cp_parser_binary_expression (cp_parser* parser, bool 
cast_p,
 
       /* We used the operator token.  */
       cp_lexer_consume_token (parser->lexer);
+      if (cp_lexer_next_token_is (parser->lexer, CPP_NOT))
+       current.lhs_type = TRUTH_NOT_EXPR;
 
       /* For "false && x" or "true || x", x will never be executed;
         disable warnings while evaluating it.  */
@@ -8098,6 +8100,7 @@ cp_parser_binary_expression (cp_parser* parser, bool 
cast_p,
          *sp = current;
          ++sp;
          current.lhs = rhs;
+         parenthesized_not_lhs_warn = current.lhs_type == TRUTH_NOT_EXPR;
          current.lhs_type = rhs_type;
          current.prec = new_prec;
          new_prec = lookahead_prec;
@@ -8126,8 +8129,17 @@ cp_parser_binary_expression (cp_parser* parser, bool 
cast_p,
 
       if (warn_logical_not_paren
          && parenthesized_not_lhs_warn)
-       warn_logical_not_parentheses (current.loc, current.tree_type,
-                                     TREE_OPERAND (current.lhs, 0), rhs);
+       {
+         tree lhs;
+         /* If the LHS was !CST, we have true/false now.  Convert it
+            to integer type, otherwise we wouldn't warn.  */
+         if (TREE_CODE (current.lhs) == INTEGER_CST)
+           lhs = convert (integer_type_node, current.lhs);
+         else
+           lhs = TREE_OPERAND (current.lhs, 0);
+         warn_logical_not_parentheses (current.loc, current.tree_type,
+                                       lhs, rhs);
+       }
 
       overload = NULL;
       /* ??? Currently we pass lhs_type == ERROR_MARK and rhs_type ==
diff --git gcc/testsuite/c-c++-common/pr62199.c 
gcc/testsuite/c-c++-common/pr62199.c
index e69de29..51078c8 100644
--- gcc/testsuite/c-c++-common/pr62199.c
+++ gcc/testsuite/c-c++-common/pr62199.c
@@ -0,0 +1,22 @@
+/* PR c++/62199 */
+/* { dg-do compile } */
+/* { dg-options "-Wlogical-not-parentheses" } */
+
+int r;
+void
+foo (int a)
+{
+  r = a > 0 || !a >= 2; /* { dg-warning "19:logical not is only applied to the 
left hand side of comparison" } */
+  r = !a || a == 10;
+  r = !a && !a < 4; /* { dg-warning "16:logical not is only applied to the 
left hand side of comparison" } */
+  r = !a > 0 && a < 6; /* { dg-warning "10:logical not is only applied to the 
left hand side of comparison" } */
+  r = a + (!a < 12); /* { dg-warning "15:logical not is only applied to the 
left hand side of comparison" } */
+  r = a == 7 || !a < 12; /* { dg-warning "20:logical not is only applied to 
the left hand side of comparison" } */
+  r = (a == 7 * a > 0) || !a < 2; /* { dg-warning "30:logical not is only 
applied to the left hand side of comparison" } */
+  r = (1 > !a) || (!42 > a); /* { dg-warning "24:logical not is only applied 
to the left hand side of comparison" } */
+  r = (!5 > a); /* { dg-warning "11:logical not is only applied to the left 
hand side of comparison" } */
+  r = (!0 > a); /* { dg-warning "11:logical not is only applied to the left 
hand side of comparison" } */
+  r = (!-5 > a); /* { dg-warning "12:logical not is only applied to the left 
hand side of comparison" } */
+  r = (!(5 + 3) > a); /* { dg-warning "17:logical not is only applied to the 
left hand side of comparison" } */
+  r = (!(5 - a) > a); /* { dg-warning "17:logical not is only applied to the 
left hand side of comparison" } */
+}

        Marek

Reply via email to