On Sun, Jun 22, 2014 at 10:33:57PM +0200, Gerald Pfeifer wrote:
> On Mon, 2 Jun 2014, Marek Polacek wrote:
> >     * c-typeck.c (parser_build_binary_op): Warn when logical not is used
> >     on the left hand side operand of a comparison. 
> 
> This...
> 
> > +/* Warn about logical not used on the left hand side operand of a 
> > comparison.
> 
> ...and this...
> 
> > +  warning_at (location, OPT_Wlogical_not_parentheses,
> > +         "logical not is only applied to the left hand side of "
> > +         "comparison");
> 
> ...does not appear consistent with the actual warning.
> 
> Why does that warning say "is _ONLY_ applied to the left hand side"?
> 
> Based on the message, I naively assumed that the code should not warn
> about
> 
>   int same(int a, int b) {
>     return !a == !b;
>   }
> 
> alas this is not the case.  (Code like this occurs in Wine where
> bool types are emulated and !!a or a comparison like above ensure
> that those emulated bools are normalized to either 0 or 1.)
> 
> 
> I understand there is ambiguity in cases like
> 
>   return !a == b;
> 
> where the warning would be approriately worded and the programmer
> might have intended !(a == b).
> 
> 
> I do recommend to either omit "only" from the text of the warning
> or not warn for cases where ! occurs on both sides of the comparison
> (and keep the text as is).

I think the latter is better, incidentally, g++ doesn't warn either.
The following one liner makes cc1 behave as cc1plus.  Thanks for the
report.

Regtested/bootstrapped on x86_64.  Joseph, is this ok?

2014-06-23  Marek Polacek  <pola...@redhat.com>

        * c-typeck.c (parser_build_binary_op): Don't call
        warn_logical_not_parentheses if the RHS is TRUTH_NOT_EXPR.

        * c-c++-common/pr49706-2.c: New test.

diff --git gcc/c/c-typeck.c gcc/c/c-typeck.c
index 63bd65e..0764630 100644
--- gcc/c/c-typeck.c
+++ gcc/c/c-typeck.c
@@ -3402,7 +3402,8 @@ parser_build_binary_op (location_t location, enum 
tree_code code,
                           code1, arg1.value, code2, arg2.value);
 
   if (warn_logical_not_paren
-      && code1 == TRUTH_NOT_EXPR)
+      && code1 == TRUTH_NOT_EXPR
+      && code2 != TRUTH_NOT_EXPR)
     warn_logical_not_parentheses (location, code, arg1.value, arg2.value);
 
   /* Warn about comparisons against string literals, with the exception
diff --git gcc/testsuite/c-c++-common/pr49706-2.c 
gcc/testsuite/c-c++-common/pr49706-2.c
index e69de29..09cc9eb 100644
--- gcc/testsuite/c-c++-common/pr49706-2.c
+++ gcc/testsuite/c-c++-common/pr49706-2.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-Wlogical-not-parentheses" } */
+
+/* Test that we don't warn if both operands of the comparison
+   are negated.  */
+
+#ifndef __cplusplus
+#define bool _Bool
+#endif
+
+bool r;
+
+int
+same (int a, int b)
+{
+  r = !a == !b;
+  r = !!a == !!b;
+  r = !!a == !b;
+  r = !a == !!b;
+}

        Marek

Reply via email to