This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH 3.4] Warn for always-false bitwise ands
- From: John Levon <levon at movementarian dot org>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 21 Mar 2003 01:40:41 +0000
- Subject: [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 *-*-* } } */
+}