From 9a2300e956daf1dd27e144d19ef95988ac661274 Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Sat, 24 Sep 2016 09:39:23 +0000 Subject: re PR c/77490 (bit-not (~) on boolean should be warned about) PR c/77490 * c.opt (Wbool-operation): New. * c-typeck.c (build_unary_op): Warn about bit not on expressions that have boolean value. Warn about ++/-- on booleans. * typeck.c (cp_build_unary_op): Warn about bit not on expressions that have boolean value. * doc/invoke.texi: Document -Wbool-operation. * c-c++-common/Wbool-operation-1.c: New test. * gcc.dg/Wbool-operation-1.c: New test. From-SVN: r240462 --- gcc/ChangeLog | 5 ++++ gcc/c-family/ChangeLog | 5 ++++ gcc/c-family/c.opt | 4 +++ gcc/c/ChangeLog | 6 +++++ gcc/c/c-typeck.c | 26 +++++++++++++++++++ gcc/cp/ChangeLog | 6 +++++ gcc/cp/typeck.c | 10 ++++++- gcc/doc/invoke.texi | 16 ++++++++++-- gcc/testsuite/ChangeLog | 8 +++++- gcc/testsuite/c-c++-common/Wbool-operation-1.c | 36 ++++++++++++++++++++++++++ gcc/testsuite/gcc.dg/Wbool-operation-1.c | 16 ++++++++++++ 11 files changed, 134 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/Wbool-operation-1.c create mode 100644 gcc/testsuite/gcc.dg/Wbool-operation-1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 316bfaf..0059dd4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2016-09-24 Marek Polacek + + PR c/77490 + * doc/invoke.texi: Document -Wbool-operation. + 2016-09-23 Jakub Jelinek * hooks.c (hook_bool_bool_false, hook_bool_bool_gcc_optionsp_false, diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 3dfb39f..8bcbd06 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,8 @@ +2016-09-24 Marek Polacek + + PR c/77490 + * c.opt (Wbool-operation): New. + 2016-09-21 Bernd Edlinger * c-common.c (c_common_truthvalue_conversion): Inhibit diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index a04618d..4a9b9e8 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -315,6 +315,10 @@ Wbool-compare C ObjC C++ ObjC++ Var(warn_bool_compare) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall) Warn about boolean expression compared with an integer value different from true/false. +Wbool-operation +C ObjC C++ ObjC++ Var(warn_bool_op) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall) +Warn about certain operations on boolean expressions. + Wframe-address C ObjC C++ ObjC++ Var(warn_frame_address) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall) Warn when __builtin_frame_address or __builtin_return_address is used unsafely. diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 283cfda..cae5c92 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,9 @@ +2016-09-24 Marek Polacek + + PR c/77490 + * c-typeck.c (build_unary_op): Warn about bit not on expressions that + have boolean value. Warn about ++/-- on booleans. + 2016-09-23 Jakub Jelinek * c-parser.c (incomplete_record_decls): Remove unnecessary diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 059ad1f..e5c7256 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -4196,6 +4196,22 @@ build_unary_op (location_t location, enum tree_code code, tree xarg, || (typecode == VECTOR_TYPE && !VECTOR_FLOAT_TYPE_P (TREE_TYPE (arg)))) { + tree e = arg; + + /* Warn if the expression has boolean value. */ + while (TREE_CODE (e) == COMPOUND_EXPR) + e = TREE_OPERAND (e, 1); + + if ((TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE + || truth_value_p (TREE_CODE (e))) + && warning_at (location, OPT_Wbool_operation, + "%<~%> on a boolean expression")) + { + gcc_rich_location richloc (location); + richloc.add_fixit_insert_before (location, "!"); + inform_at_rich_loc (&richloc, "did you mean to use logical " + "not?"); + } if (!noconvert) arg = default_conversion (arg); } @@ -4306,6 +4322,16 @@ build_unary_op (location_t location, enum tree_code code, tree xarg, "decrement of enumeration value is invalid in C++"); } + if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE) + { + if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) + warning_at (location, OPT_Wbool_operation, + "increment of a boolean expression"); + else + warning_at (location, OPT_Wbool_operation, + "decrement of a boolean expression"); + } + /* Ensure the argument is fully folded inside any SAVE_EXPR. */ arg = c_fully_fold (arg, false, NULL); diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a3430bf..cd5f936 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2016-09-24 Marek Polacek + + PR c/77490 + * typeck.c (cp_build_unary_op): Warn about bit not on expressions that + have boolean value. + 2016-09-23 Jakub Jelinek Implement P0138R2, C++17 construction rules for enum class values diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index b2af615..0142d4a 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -5792,6 +5792,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, bool noconvert, { /* No default_conversion here. It causes trouble for ADDR_EXPR. */ tree arg = xarg; + location_t location = EXPR_LOC_OR_LOC (arg, input_location); tree argtype = 0; const char *errstring = NULL; tree val; @@ -5853,7 +5854,14 @@ cp_build_unary_op (enum tree_code code, tree xarg, bool noconvert, arg, true))) errstring = _("wrong type argument to bit-complement"); else if (!noconvert && CP_INTEGRAL_TYPE_P (TREE_TYPE (arg))) - arg = cp_perform_integral_promotions (arg, complain); + { + /* Warn if the expression has boolean value. */ + if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE + && warning_at (location, OPT_Wbool_operation, + "%<~%> on an expression of type bool")) + inform (location, "did you mean to use logical not (%)?"); + arg = cp_perform_integral_promotions (arg, complain); + } break; case ABS_EXPR: diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index e6f503f..a5481b5 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -256,8 +256,8 @@ Objective-C and Objective-C++ Dialects}. -pedantic-errors @gol -w -Wextra -Wall -Waddress -Waggregate-return @gol -Wno-aggressive-loop-optimizations -Warray-bounds -Warray-bounds=@var{n} @gol --Wno-attributes -Wbool-compare -Wno-builtin-macro-redefined @gol --Wc90-c99-compat -Wc99-c11-compat @gol +-Wno-attributes -Wbool-compare -Wbool-operation @gol +-Wno-builtin-macro-redefined -Wc90-c99-compat -Wc99-c11-compat @gol -Wc++-compat -Wc++11-compat -Wc++14-compat -Wcast-align -Wcast-qual @gol -Wchar-subscripts -Wclobbered -Wcomment -Wconditionally-supported @gol -Wconversion -Wcoverage-mismatch -Wno-cpp -Wdangling-else -Wdate-time @gol @@ -3656,6 +3656,7 @@ Options} and @ref{Objective-C and Objective-C++ Dialect Options}. @gccoptlist{-Waddress @gol -Warray-bounds=1 @r{(only with} @option{-O2}@r{)} @gol -Wbool-compare @gol +-Wbool-operation @gol -Wc++11-compat -Wc++14-compat@gol -Wchar-subscripts @gol -Wcomment @gol @@ -4846,6 +4847,17 @@ if ((n > 1) == 2) @{ @dots{} @} @end smallexample This warning is enabled by @option{-Wall}. +@item -Wbool-operation +@opindex Wno-bool-operation +@opindex Wbool-operation +Warn about suspicious operations on expressions of a boolean type. For +instance, bitwise negation of a boolean is very likely a bug in the program. +For C, this warning also warns about incrementing or decrementing a boolean, +which rarely makes sense. (In C++, decrementing a boolean is always invalid. +Incrementing a boolean is invalid in C++1z, and deprecated otherwise.) + +This warning is enabled by @option{-Wall}. + @item -Wduplicated-cond @opindex Wno-duplicated-cond @opindex Wduplicated-cond diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f387022..77ef74b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2016-09-24 Marek Polacek + + PR c/77490 + * c-c++-common/Wbool-operation-1.c: New test. + * gcc.dg/Wbool-operation-1.c: New test. + 2016-09-23 Fritz Reese * gfortran.dg/dec_static_1.f90: New. @@ -10,7 +16,7 @@ PR fortran/48298 * gfortran.dg/negative_unit_check.f90: Update test. * gfortran.dg/dtio_14.f90: New test. - + 2016-09-23 Dominik Vogt * gcc.target/s390/hotpatch-compile-1.c: Fixed dg-error test. diff --git a/gcc/testsuite/c-c++-common/Wbool-operation-1.c b/gcc/testsuite/c-c++-common/Wbool-operation-1.c new file mode 100644 index 0000000..bb72784 --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wbool-operation-1.c @@ -0,0 +1,36 @@ +/* PR c/77490 */ +/* { dg-do compile } */ +/* { dg-options "-Wall" } */ + +#ifndef __cplusplus +# define bool _Bool +#endif + +typedef volatile bool T; +typedef int __attribute__ ((vector_size (4 * sizeof (int)))) v4si; +extern bool foo (void); + +int +fn (bool b, bool b2, T b3, int n, v4si v) +{ + int r = 0; + + r += ~b; /* { dg-warning "on an expression of type bool|on a boolean expression" } */ + r += n + ~b; /* { dg-warning "on an expression of type bool|on a boolean expression" } */ + r += ~(n == 1); /* { dg-warning "on an expression of type bool|on a boolean expression" } */ + r += ~(n || 1); /* { dg-warning "on an expression of type bool|on a boolean expression" } */ + r += ~b == 1; /* { dg-warning "on an expression of type bool|on a boolean expression" } */ + r += ~(++n, n == 1); /* { dg-warning "on an expression of type bool|on a boolean expression" } */ + r += ~(++n, n > 1); /* { dg-warning "on an expression of type bool|on a boolean expression" } */ + r += ~(++n, n && 1); /* { dg-warning "on an expression of type bool|on a boolean expression" } */ + r += (++n, ~b); /* { dg-warning "on an expression of type bool|on a boolean expression" } */ + r += ~b3; /* { dg-warning "on an expression of type bool|on a boolean expression" } */ + r += ~foo (); /* { dg-warning "on an expression of type bool|on a boolean expression" } */ + r += ~(bool) !1; /* { dg-warning "on an expression of type bool|on a boolean expression" } */ + + v = ~v; + r += ~(int) b; + r += -b; + + return r; +} diff --git a/gcc/testsuite/gcc.dg/Wbool-operation-1.c b/gcc/testsuite/gcc.dg/Wbool-operation-1.c new file mode 100644 index 0000000..b24e763 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wbool-operation-1.c @@ -0,0 +1,16 @@ +/* PR c/77490 */ +/* { dg-do compile } */ +/* { dg-options "-Wall" } */ + +int +fn (_Bool b) +{ + int r = 0; + + r += b++; /* { dg-warning "increment of a boolean expression" } */ + r += ++b; /* { dg-warning "increment of a boolean expression" } */ + r += b--; /* { dg-warning "decrement of a boolean expression" } */ + r += --b; /* { dg-warning "decrement of a boolean expression" } */ + + return r; +} -- cgit v1.1