This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Warn on always-false BIT_AND_EXPRs (PR 9944)
- From: John Levon <levon at movementarian dot org>
- To: gcc-patches at gcc dot gnu dot org, gcc at gcc dot gnu dot org
- Date: Wed, 5 Mar 2003 00:54:40 +0000
- Subject: [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);
+ */
+}