public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* C/C++ PATCH for c/77423 (bogus warning with -Wlogical-not-parentheses)
@ 2016-09-02 15:14 Marek Polacek
  2016-09-05 10:51 ` Bernd Schmidt
  0 siblings, 1 reply; 17+ messages in thread
From: Marek Polacek @ 2016-09-02 15:14 UTC (permalink / raw)
  To: GCC Patches, Joseph Myers, Jason Merrill

Martin reported that -Wlogical-not-parentheses issues a bogus warning
for bit operations on booleans, because the warning didn't take integer
promotions into account.  The following patch ought to fix this problem.

It's not exactly trivial because I had to handle even more complex
expressions and comparison.  I am aware that given what I do with
CONVERT_EXPR_P in expr_has_boolean_operands_p, it's possible to construct
a pathological testcase where the C FE would warn, but C++ FE wouldn't.
But I'm not convinced it's worth complicating this code further.

I also fixed -Wlogical-not-parentheses wording in docs, following Martin's
suggestion.

Bootstrapped/regtested on x86_64-linux and ppc64-linux, ok for trunk?

2016-09-02  Marek Polacek  <polacek@redhat.com>

	PR c/77423
	* doc/invoke.texi: Update -Wlogical-not-parentheses documentation.

	* c-common.c (bool_promoted_to_int_p): New function.
	(expr_has_boolean_operands_p): New function.
	(warn_logical_not_parentheses): Return if expr_has_boolean_operands_p.
	(maybe_warn_bool_compare): Use bool_promoted_to_int_p.

	* c-c++-common/Wlogical-not-parentheses-3.c: New test.

diff --git gcc/c-family/c-common.c gcc/c-family/c-common.c
index 399ba97..fbc8fb0 100644
--- gcc/c-family/c-common.c
+++ gcc/c-family/c-common.c
@@ -1479,6 +1479,36 @@ warn_tautological_cmp (location_t loc, enum tree_code code, tree lhs, tree rhs)
     }
 }
 
+/* Return true iff T is a boolean promoted to int.  */
+
+static bool
+bool_promoted_to_int_p (tree t)
+{
+  return (CONVERT_EXPR_P (t)
+	  && TREE_TYPE (t) == integer_type_node
+	  && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == BOOLEAN_TYPE);
+}
+
+/* Return true iff EXPR only contains boolean operands, or comparisons.  */
+
+static bool
+expr_has_boolean_operands_p (tree expr)
+{
+  STRIP_NOPS (expr);
+
+  if (CONVERT_EXPR_P (expr))
+    return bool_promoted_to_int_p (expr);
+  else if (UNARY_CLASS_P (expr))
+    return expr_has_boolean_operands_p (TREE_OPERAND (expr, 0));
+  else if (BINARY_CLASS_P (expr))
+    return (expr_has_boolean_operands_p (TREE_OPERAND (expr, 0))
+	    && expr_has_boolean_operands_p (TREE_OPERAND (expr, 1)));
+  else if (COMPARISON_CLASS_P (expr))
+    return true;
+  else
+    return false;
+}
+
 /* Warn about logical not used on the left hand side operand of a comparison.
    This function assumes that the LHS is inside of TRUTH_NOT_EXPR.
    Do not warn if RHS is of a boolean type, a logical operator, or
@@ -1494,6 +1524,10 @@ warn_logical_not_parentheses (location_t location, enum tree_code code,
       || truth_value_p (TREE_CODE (rhs)))
     return;
 
+  /* Don't warn for expression like !x == ~(bool1 | bool2).  */
+  if (expr_has_boolean_operands_p (rhs))
+    return;
+
   /* Don't warn for !x == 0 or !y != 0, those are equivalent to
      !(x == 0) or !(y != 0).  */
   if ((code == EQ_EXPR || code == NE_EXPR)
@@ -12405,9 +12439,7 @@ maybe_warn_bool_compare (location_t loc, enum tree_code code, tree op0,
 	 don't want to warn here.  */
       tree noncst = TREE_CODE (op0) == INTEGER_CST ? op1 : op0;
       /* Handle booleans promoted to integers.  */
-      if (CONVERT_EXPR_P (noncst)
-	  && TREE_TYPE (noncst) == integer_type_node
-	  && TREE_CODE (TREE_TYPE (TREE_OPERAND (noncst, 0))) == BOOLEAN_TYPE)
+      if (bool_promoted_to_int_p (noncst))
 	/* Warn.  */;
       else if (TREE_CODE (TREE_TYPE (noncst)) != BOOLEAN_TYPE
 	       && !truth_value_p (TREE_CODE (noncst)))
diff --git gcc/doc/invoke.texi gcc/doc/invoke.texi
index 87da1f1..38d55d4 100644
--- gcc/doc/invoke.texi
+++ gcc/doc/invoke.texi
@@ -5437,8 +5437,8 @@ if (a < 0 && a < 0) @{ @dots{} @}
 @opindex Wlogical-not-parentheses
 @opindex Wno-logical-not-parentheses
 Warn about logical not used on the left hand side operand of a comparison.
-This option does not warn if the RHS operand is of a boolean type.  Its
-purpose is to detect suspicious code like the following:
+This option does not warn if the right operand is considered to be a Boolean
+expression.  Its purpose is to detect suspicious code like the following:
 @smallexample
 int a;
 @dots{}
diff --git gcc/testsuite/c-c++-common/Wlogical-not-parentheses-3.c gcc/testsuite/c-c++-common/Wlogical-not-parentheses-3.c
index e69de29..00aa747 100644
--- gcc/testsuite/c-c++-common/Wlogical-not-parentheses-3.c
+++ gcc/testsuite/c-c++-common/Wlogical-not-parentheses-3.c
@@ -0,0 +1,31 @@
+/* PR c/77423 */
+/* { dg-do compile } */
+/* { dg-options "-Wlogical-not-parentheses" } */
+
+#ifndef __cplusplus
+# define bool _Bool
+#endif
+
+int
+f (int a, bool b, bool c)
+{
+  int r = 0;
+
+  r += !a == (b | c);
+  r += !a == (b ^ c);
+  r += !a == (b & c);
+  r += !a == ~b;
+  r += !a == ~(int) b;
+  r += !a == ((b & c) | c);
+  r += !a == ((b & c) | (b ^ c));
+  r += !a == (int) (b ^ c);
+  r += !a == (int) ~b;
+  r += !a == ~~b;
+  r += !a == ~(b | c);
+  r += !a == ~(b | (a == 1));
+  r += !a == ~(a == 1);
+
+  r += !a == ((b & c) | (b ^ a)); /* { dg-warning "logical not is only applied to the left hand side of comparison" } */
+
+  return r;
+}

	Marek

^ permalink raw reply	[flat|nested] 17+ messages in thread
* Re: C/C++ PATCH for c/77423 (bogus warning with -Wlogical-not-parentheses)
@ 2016-09-02 15:51 Bernd Edlinger
  2016-09-05 14:08 ` Marek Polacek
  0 siblings, 1 reply; 17+ messages in thread
From: Bernd Edlinger @ 2016-09-02 15:51 UTC (permalink / raw)
  To: Marek Polacek; +Cc: Joseph Myers, gcc-patches

Hi,

 > +  r += !a == ~b;
 > +  r += !a == ~(int) b;

I don't understand why ~b should not be warned at -Wall.

Frankly I don't even understand why the above statements are
completely optimized away.

r += !a == ~b;
is optimized away, but

b = ~b;
r += !a == b;

Is not.  Why?



Bernd.

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2016-09-16  9:03 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-02 15:14 C/C++ PATCH for c/77423 (bogus warning with -Wlogical-not-parentheses) Marek Polacek
2016-09-05 10:51 ` Bernd Schmidt
2016-09-05 10:57   ` Marek Polacek
2016-09-05 16:12     ` Bernd Schmidt
2016-09-05 16:44       ` Sandra Loosemore
2016-09-06  9:08         ` Marek Polacek
2016-09-02 15:51 Bernd Edlinger
2016-09-05 14:08 ` Marek Polacek
2016-09-05 14:28   ` Bernd Edlinger
2016-09-05 14:39     ` Marek Polacek
2016-09-05 15:03       ` Bernd Edlinger
2016-09-05 16:46       ` Joseph Myers
2016-09-05 17:03         ` Bernd Edlinger
2016-09-15 19:55       ` Jeff Law
2016-09-16  9:05         ` Marek Polacek
2016-09-05 15:01     ` Eric Gallager
2016-09-05 15:08       ` Bernd Edlinger

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).