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 3.4] Warn for always-false bitwise ands


See the testsuite examples. Comments ?

Bootstrapped on i686-pc-linux-gnu and tested
with dg.exp

regards,
john

gcc/ChangeLog

2003-03-21  John Levon  <levon at movementarian dot org>

	PR c/9944
	* c-common.c (boolean_value_p): New. Add
	warn_boolean_bitwise_and.

	* c-common.h (boolean_value_p): New. Declare
	warn_boolean_bitwise_and.

	* c-opts.c (COMMAND_LINE_OPTIONS): Add
	-Wboolean-bitwise-and.
	(c_common_decode_option): Add to -Wall.
	[OPT_Wboolean_bitwise_and]: Handle.

	* toplev.c (documented_lang_options): Add
	-Wboolean-bitwise-and, -Wnoboolean-bitwise-and.

	* c-typeck.c (build_binary_op) [BIT_AND_EXPR]:
	Give warning if warn_boolean_bitwise_and.

	* fold-const.c (truth_value_p): Make non-static.

	* tree.h (truth_value_p): Declare.

	* doc/invoke.texi: Document -Wboolean-bitwise-and.

	* testsuite/gcc.dg/Wboolean-bitwise-and-1.c:
	* testsuite/gcc.dg/Wboolean-bitwise-and-2.c:
	* testsuite/g++.dg/warn/boolean-bitwise-and-1.c:
	* testsuite/g++.dg/warn/boolean-bitwise-and-2.c:
	Add.

gcc/cp/ChangeLog

2003-03-21  John Levon  <levon at movementarian dot org>

	* typeck.c (build_binary_op) [BIT_AND_EXPR]:
	Give warning if warn_boolean_bitwise_and.
	

The patch itself

Index: gcc/c-common.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/c-common.c,v
retrieving revision 1.405
diff -u -p -r1.405 c-common.c
--- gcc/c-common.c	11 Mar 2003 06:42:17 -0000	1.405
+++ gcc/c-common.c	21 Mar 2003 00:16:14 -0000
@@ -394,6 +394,10 @@ int flag_noniso_default_format_attribute
 
 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;
@@ -6230,6 +6234,26 @@ check_function_arguments_recurse (callba
     }
 
   (*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.174
diff -u -p -r1.174 c-common.h
--- gcc/c-common.h	19 Mar 2003 20:34:01 -0000	1.174
+++ gcc/c-common.h	21 Mar 2003 00:16:16 -0000
@@ -568,6 +568,10 @@ extern int flag_noniso_default_format_at
 
 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;
@@ -969,6 +973,7 @@ extern HOST_WIDE_INT c_common_get_alias_
 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.39
diff -u -p -r1.39 c-opts.c
--- gcc/c-opts.c	17 Mar 2003 06:41:06 -0000	1.39
+++ gcc/c-opts.c	21 Mar 2003 00:16:18 -0000
@@ -174,6 +174,7 @@ static void finish_options PARAMS ((void
   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)			     \
@@ -807,6 +808,7 @@ c_common_decode_option (argc, argv)
       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.  */                                        
@@ -839,6 +841,10 @@ c_common_decode_option (argc, argv)
 
     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.226
diff -u -p -r1.226 c-typeck.c
--- gcc/c-typeck.c	17 Mar 2003 21:16:07 -0000	1.226
+++ gcc/c-typeck.c	21 Mar 2003 00:16:25 -0000
@@ -2022,6 +2022,20 @@ build_binary_op (code, orig_op0, orig_op
       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.238
diff -u -p -r1.238 fold-const.c
--- gcc/fold-const.c	22 Feb 2003 04:16:16 -0000	1.238
+++ gcc/fold-const.c	21 Mar 2003 00:16:33 -0000
@@ -77,7 +77,6 @@ static enum tree_code invert_tree_compar
 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));
@@ -1822,7 +1821,7 @@ compcode_to_comparison (code)
 
 /* 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.735
diff -u -p -r1.735 toplev.c
--- gcc/toplev.c	12 Mar 2003 00:19:37 -0000	1.735
+++ gcc/toplev.c	21 Mar 2003 00:16:39 -0000
@@ -1293,6 +1293,9 @@ documented_lang_options[] =
   { "-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.385
diff -u -p -r1.385 tree.h
--- gcc/tree.h	2 Mar 2003 21:18:15 -0000	1.385
+++ gcc/tree.h	21 Mar 2003 00:16:44 -0000
@@ -2933,6 +2933,9 @@ extern tree strip_float_extensions			PAR
 /* In convert.c */
 extern tree strip_float_extensions			PARAMS ((tree));
 
+/* In fold-const.c.  */
+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.453
diff -u -p -r1.453 typeck.c
--- gcc/cp/typeck.c	18 Mar 2003 04:10:45 -0000	1.453
+++ gcc/cp/typeck.c	21 Mar 2003 00:18:25 -0000
@@ -3328,6 +3328,20 @@ build_binary_op (code, orig_op0, orig_op
       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.255
diff -u -p -r1.255 invoke.texi
--- gcc/doc/invoke.texi	11 Mar 2003 06:42:20 -0000	1.255
+++ gcc/doc/invoke.texi	21 Mar 2003 00:18:39 -0000
@@ -212,7 +212,7 @@ in the following sections.
 @xref{Warning Options,,Options to Request or Suppress Warnings}.
 @gccoptlist{
 -fsyntax-only  -pedantic  -pedantic-errors @gol
--w  -Wextra  -Wall  -Waggregate-return @gol
+-w  -Wextra  -Wall  -Waggregate-return -Wbitwise-boolean-and @gol
 -Wcast-align  -Wcast-qual  -Wchar-subscripts  -Wcomment @gol
 -Wconversion  -Wno-deprecated-declarations @gol
 -Wdisabled-optimization  -Wno-div-by-zero  -Werror @gol
@@ -2398,6 +2398,11 @@ It warns about code which might break th
 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
diff -u -p Wboolean-bitwise-and-1.c
--- /dev/null	2002-08-31 00:31:37.000000000 +0100
+++ gcc/testsuite/gcc.dg/Wboolean-bitwise-and-1.c	2003-03-20 16:38:32.000000000 +0000
@@ -0,0 +1,48 @@
+/* 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);
+}
diff -u -p Wboolean-bitwise-and-2.c
--- /dev/null	2002-08-31 00:31:37.000000000 +0100
+++ gcc/testsuite/gcc.dg/Wboolean-bitwise-and-2.c	2003-03-20 22:33:43.000000000 +0000
@@ -0,0 +1,18 @@
+/* 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 ? j : k) & 4);
+  /* this case (COND_EXPR with the negation folded in) not handled */
+  l = (!(i ? j : k) & 4); /* { dg-warning "bitwise and expression is always false" "" { xfail *-*-* } } */
+}
diff -u -p boolean-bitwise-and-1.C
--- /dev/null	2002-08-31 00:31:37.000000000 +0100
+++ gcc/testsuite/g++.dg/warn/boolean-bitwise-and-1.C	2003-03-20 16:38:32.000000000 +0000
@@ -0,0 +1,48 @@
+/* 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)); /* { 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 && 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);
+}
diff -u -p boolean-bitwise-and-2.C
--- /dev/null	2002-08-31 00:31:37.000000000 +0100
+++ gcc/testsuite/g++.dg/warn/boolean-bitwise-and-2.C	2003-03-20 22:33:39.000000000 +0000
@@ -0,0 +1,22 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.  */
+
+/* { dg-do compile } */
+/* { dg-options "-Wboolean-bitwise-and " } */
+
+/* John Levon, March 2003 */
+
+extern bool i;
+extern int j;
+extern int k;
+extern bool m;
+extern bool n;
+
+void foo()
+{
+  int l;
+  l = ((i ? j : k) & 4);
+  /* these cases (COND_EXPR with the negation folded in) not handled */
+  l = (!(i ? j : k) & 4); /* { dg-warning "bitwise and expression is always false" "" { xfail *-*-* } } */
+  l = ((i ? m : n) & 4); /* { dg-warning "bitwise and expression is always false" "" { xfail *-*-* } } */
+  l = (!(i ? m : n) & 4); /* { dg-warning "bitwise and expression is always false" "" { xfail *-*-* } } */
+}


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