This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Warn on always-false BIT_AND_EXPRs (PR 9944)


A better version, against 3.3 branch CVS. It seems to work for me, with the
caveat that if (!(a ? b : c) & 0x4) is not caught as the lhs operand is
COND_EXPR.

Is this any good ?

thanks
john


Index: gcc/c-common.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/c-common.c,v
retrieving revision 1.393.2.1
diff -u -r1.393.2.1 c-common.c
--- gcc/c-common.c	19 Feb 2003 02:07:56 -0000	1.393.2.1
+++ gcc/c-common.c	5 Mar 2003 00:43:39 -0000
@@ -369,6 +369,10 @@
 
 int warn_bad_function_cast;
 
+/* Warn about always-false bitwise and with != 1 on a boolean value */
+
+int warn_boolean_bitwise_and;
+
 /* Warn about traditional constructs whose meanings changed in ANSI C.  */
 
 int warn_traditional;
@@ -6608,6 +6612,26 @@
     }
 
   (*callback) (ctx, param, param_num);
+}
+
+/* return true if the tree is known to represent a boolean value. */
+int
+boolean_value_p(expr)
+     tree expr;
+{
+  if (truth_value_p (TREE_CODE (expr)))
+     return 1;
+  /* Boolean types can be wrapped in a NOP_EXPR for integer operations.
+   * Try to peek inside */
+  if (TREE_CODE (expr) == NOP_EXPR)
+  {
+     tree tmp = TREE_OPERAND (expr, 0);
+     enum tree_code code = TREE_CODE (tmp);
+     enum tree_code typecode = TREE_CODE (TREE_TYPE (tmp));
+     /* Could be a truth expression, or an expression of boolean type */
+     return truth_value_p (code) || typecode == BOOLEAN_TYPE;
+  }
+  return 0;
 }
 
 #include "gt-c-common.h"
Index: gcc/c-common.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/c-common.h,v
retrieving revision 1.164
diff -u -r1.164 c-common.h
--- gcc/c-common.h	1 Dec 2002 17:51:44 -0000	1.164
+++ gcc/c-common.h	5 Mar 2003 00:43:40 -0000
@@ -538,6 +538,10 @@
 
 extern int warn_bad_function_cast;
 
+/* Warn about always-false bitwise and with != 1 on a boolean value */
+
+extern int warn_boolean_bitwise_and;
+
 /* Warn about traditional constructs whose meanings changed in ANSI C.  */
 
 extern int warn_traditional;
@@ -939,6 +943,7 @@
 extern bool c_promoting_integer_type_p		PARAMS ((tree));
 extern int self_promoting_args_p		PARAMS ((tree));
 extern tree strip_array_types                   PARAMS ((tree));
+extern int boolean_value_p			PARAMS ((tree));
 
 /* These macros provide convenient access to the various _STMT nodes.  */
 
Index: gcc/c-opts.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/c-opts.c,v
retrieving revision 1.24.6.1
diff -u -r1.24.6.1 c-opts.c
--- gcc/c-opts.c	21 Feb 2003 06:12:58 -0000	1.24.6.1
+++ gcc/c-opts.c	5 Mar 2003 00:43:42 -0000
@@ -127,6 +127,7 @@
   OPT("Wabi",                   CL_CXX,   OPT_Wabi)                          \
   OPT("Wall",			CL_ALL,   OPT_Wall)			     \
   OPT("Wbad-function-cast",	CL_C,     OPT_Wbad_function_cast)	     \
+  OPT("Wboolean-bitwise-and",   CL_ALL,   OPT_Wboolean_bitwise_and)          \
   OPT("Wcast-qual",		CL_ALL,   OPT_Wcast_qual)		     \
   OPT("Wchar-subscripts",	CL_ALL,   OPT_Wchar_subscripts)		     \
   OPT("Wcomment",		CL_ALL,   OPT_Wcomment)			     \
@@ -702,6 +703,7 @@
       warn_sign_compare = on;	/* Was C++ only.  */
       warn_switch = on;
       warn_strict_aliasing = on;
+      warn_boolean_bitwise_and = on;
       
       /* Only warn about unknown pragmas that are not in system
 	 headers.  */                                        
@@ -734,6 +736,10 @@
 
     case OPT_Wbad_function_cast:
       warn_bad_function_cast = on;
+      break;
+
+    case OPT_Wboolean_bitwise_and:
+      warn_boolean_bitwise_and = on;
       break;
 
     case OPT_Wcast_qual:
Index: gcc/c-typeck.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/c-typeck.c,v
retrieving revision 1.213.2.2
diff -u -r1.213.2.2 c-typeck.c
--- gcc/c-typeck.c	9 Jan 2003 12:11:34 -0000	1.213.2.2
+++ gcc/c-typeck.c	5 Mar 2003 00:43:50 -0000
@@ -2007,6 +2007,17 @@
       break;
 
     case BIT_AND_EXPR:
+      /* give a warning for (!ua & 0x4) and similar cases */
+      if (warn_boolean_bitwise_and)
+      {
+         int op0not1 = TREE_CODE (op0) == INTEGER_CST && !integer_onep (op0);
+         int op1not1 = TREE_CODE (op1) == INTEGER_CST && !integer_onep (op1);
+	 if ((op0not1 && boolean_value_p (op1)) || (op1not1 && boolean_value_p (op0)))
+            warning ("bitwise and expression is always false");
+      }
+
+      /* fallthrough */
+
     case BIT_ANDTC_EXPR:
     case BIT_IOR_EXPR:
     case BIT_XOR_EXPR:
Index: gcc/fold-const.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.227.2.1
diff -u -r1.227.2.1 fold-const.c
--- gcc/fold-const.c	16 Feb 2003 08:25:20 -0000	1.227.2.1
+++ gcc/fold-const.c	5 Mar 2003 00:43:58 -0000
@@ -74,7 +74,6 @@
 static enum tree_code swap_tree_comparison PARAMS ((enum tree_code));
 static int comparison_to_compcode PARAMS ((enum tree_code));
 static enum tree_code compcode_to_comparison PARAMS ((int));
-static int truth_value_p	PARAMS ((enum tree_code));
 static int operand_equal_for_comparison_p PARAMS ((tree, tree, tree));
 static int twoval_comparison_p	PARAMS ((tree, tree *, tree *, int *));
 static tree eval_subst		PARAMS ((tree, tree, tree, tree, tree));
@@ -1771,7 +1770,7 @@
 
 /* Return nonzero if CODE is a tree code that represents a truth value.  */
 
-static int
+int
 truth_value_p (code)
      enum tree_code code;
 {
Index: gcc/toplev.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/toplev.c,v
retrieving revision 1.690.2.8
diff -u -r1.690.2.8 toplev.c
--- gcc/toplev.c	3 Mar 2003 18:26:12 -0000	1.690.2.8
+++ gcc/toplev.c	5 Mar 2003 00:44:04 -0000
@@ -1255,6 +1255,9 @@
   { "-Wbad-function-cast",
     N_("Warn about casting functions to incompatible types") },
   { "-Wno-bad-function-cast", "" },
+  { "-Wboolean-bitwise-and",
+    N_("Warn about bitwise and expressions on boolean values that are always false") },
+  { "-Wno-boolean-bitwise-and", "" },
   { "-Wmissing-format-attribute",
     N_("Warn about functions which might be candidates for format attributes") },
   { "-Wno-missing-format-attribute", "" },
Index: gcc/tree.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/tree.h,v
retrieving revision 1.367.2.1
diff -u -r1.367.2.1 tree.h
--- gcc/tree.h	9 Jan 2003 12:11:38 -0000	1.367.2.1
+++ gcc/tree.h	5 Mar 2003 00:44:08 -0000
@@ -2915,6 +2915,8 @@
 
 extern tree build_range_type PARAMS ((tree, tree, tree));
 
+extern int truth_value_p	PARAMS ((enum tree_code));
+
 /* In alias.c */
 extern void record_component_aliases		PARAMS ((tree));
 extern HOST_WIDE_INT get_alias_set		PARAMS ((tree));
Index: gcc/cp/typeck.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/cp/typeck.c,v
retrieving revision 1.436.2.2
diff -u -r1.436.2.2 typeck.c
--- gcc/cp/typeck.c	22 Jan 2003 19:17:15 -0000	1.436.2.2
+++ gcc/cp/typeck.c	5 Mar 2003 00:44:20 -0000
@@ -3155,6 +3155,17 @@
       break;
 
     case BIT_AND_EXPR:
+      /* give a warning for (!ua & 0x4) and similar cases */
+      if (warn_boolean_bitwise_and)
+      {
+         int op0not1 = TREE_CODE (op0) == INTEGER_CST && !integer_onep (op0);
+         int op1not1 = TREE_CODE (op1) == INTEGER_CST && !integer_onep (op1);
+	 if ((op0not1 && boolean_value_p (op1)) || (op1not1 && boolean_value_p (op0)))
+            warning ("bitwise and expression is always false");
+      }
+
+      /* fallthrough */
+
     case BIT_ANDTC_EXPR:
     case BIT_IOR_EXPR:
     case BIT_XOR_EXPR:
Index: gcc/doc/invoke.texi
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/doc/invoke.texi,v
retrieving revision 1.209.2.16
diff -u -r1.209.2.16 invoke.texi
--- gcc/doc/invoke.texi	2 Mar 2003 10:17:15 -0000	1.209.2.16
+++ gcc/doc/invoke.texi	5 Mar 2003 00:44:34 -0000
@@ -211,7 +211,7 @@
 @xref{Warning Options,,Options to Request or Suppress Warnings}.
 @gccoptlist{
 -fsyntax-only  -pedantic  -pedantic-errors @gol
--w  -W  -Wall -Waggregate-return @gol
+-w  -W  -Wall -Waggregate-return -Wboolean-bitwise-and @gol
 -Wcast-align  -Wcast-qual  -Wchar-subscripts  -Wcomment @gol
 -Wconversion  -Wno-deprecated-declarations @gol
 -Wdisabled-optimization  -Wno-div-by-zero  -Werror @gol
@@ -2384,6 +2384,11 @@
 compiler is using for optimization. The warning does not catch all
 cases, but does attempt to catch the more common pitfalls. It is
 included in @option{-Wall}.
+
+ at item -Wboolean-bitwise-and
+ at opindex Wboolean-bitwise-and
+Warn when a bitwise and expression is always false due to one of
+the arguments being a boolean value, for example @samp{if (!ua & 0x4)}.
 
 @item -Wall
 @opindex Wall
--- /dev/null	2002-08-31 00:31:37.000000000 +0100
+++ gcc/testsuite/gcc.dg/Wboolean-bitwise-and.c	2003-03-05 00:49:18.000000000 +0000
@@ -0,0 +1,54 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.  */
+
+/* { dg-do compile } */
+/* { dg-options "-Wboolean-bitwise-and " } */
+
+/* John Levon, March 2003 */
+
+extern int i;
+extern int j;
+extern int k;
+
+void foo()
+{
+  int l;
+
+  l = (!i & 0x0); /* { dg-warning "bitwise and expression is always false" } */
+  l = (!i & 0x1);
+  l = (!i & 0x2); /* { dg-warning "bitwise and expression is always false" } */
+
+  l = (!!i & 0x0); /* { dg-warning "bitwise and expression is always false" } */
+  l = (!!i & 0x1);
+  l = (!!i & 0x2); /* { dg-warning "bitwise and expression is always false" } */
+
+  l = (!(i & 0x0));
+  l = (!(i & 0x1));
+  l = (!(i & 0x2));
+
+  l = (i & 0x0);
+  l = (i & 0x1);
+  l = (i & 0x2);
+
+  l = (!i | 0x0);
+
+  l = ((i && j) & 0x0); /* { dg-warning "bitwise and expression is always false" } */
+  l = ((i || j) & 0x0); /* { dg-warning "bitwise and expression is always false" } */
+  l = (!(i && j) & 0x0); /* { dg-warning "bitwise and expression is always false" } */
+  l = (!(i || j) & 0x0); /* { dg-warning "bitwise and expression is always false" } */
+
+  l = ((i && j) & 0x1);
+  l = ((i || j) & 0x1);
+  l = (!(i && j) & 0x1);
+  l = (!(i || j) & 0x1);
+
+  l = ((i && j) & k);
+  l = ((i || j) & k);
+  l = (!(i && j) & k);
+  l = (!(i || j) & k);
+
+  /*
+   * these cases not handled
+  l = ((i ? j : k) & k);
+  l = (!(i ? j : k) & k);
+  */
+}
--- /dev/null	2002-08-31 00:31:37.000000000 +0100
+++ gcc/testsuite/g++.dg/warn/boolean-bitwise-and.C	2003-03-05 00:49:41.000000000 +0000
@@ -0,0 +1,54 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.  */
+
+/* { dg-do compile } */
+/* { dg-options "-Wboolean-bitwise-and " } */
+
+/* John Levon, March 2003 */
+
+extern bool i;
+extern bool j;
+extern int k;
+
+void foo()
+{
+  int l;
+
+  l = (!i & 0x0); /* { dg-warning "bitwise and expression is always false" } */
+  l = (!i & 0x1);
+  l = (!i & 0x2); /* { dg-warning "bitwise and expression is always false" } */
+
+  l = (!!i & 0x0); /* { dg-warning "bitwise and expression is always false" } */
+  l = (!!i & 0x1);
+  l = (!!i & 0x2); /* { dg-warning "bitwise and expression is always false" } */
+
+  l = (!(i & 0x0));
+  l = (!(i & 0x1));
+  l = (!(i & 0x2));
+
+  l = (i & 0x0); /* { dg-warning "bitwise and expression is always false" } */
+  l = (i & 0x1);
+  l = (i & 0x2); /* { dg-warning "bitwise and expression is always false" } */
+
+  l = (!i | 0x0);
+
+  l = ((i && j) & 0x0); /* { dg-warning "bitwise and expression is always false" } */
+  l = ((i || j) & 0x0); /* { dg-warning "bitwise and expression is always false" } */
+  l = (!(i && j) & 0x0); /* { dg-warning "bitwise and expression is always false" } */
+  l = (!(i || j) & 0x0); /* { dg-warning "bitwise and expression is always false" } */
+
+  l = ((i && j) & 0x1);
+  l = ((i || j) & 0x1);
+  l = (!(i && j) & 0x1);
+  l = (!(i || j) & 0x1);
+
+  l = ((i && j) & k);
+  l = ((i || j) & k);
+  l = (!(i && j) & k);
+  l = (!(i || j) & k);
+
+  /*
+   * these cases not handled
+  l = ((i ? j : k) & k);
+  l = (!(i ? j : k) & k);
+  */
+}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]