re PR c/77490 (bit-not (~) on boolean should be warned about)
authorMarek Polacek <polacek@redhat.com>
Sat, 24 Sep 2016 09:39:23 +0000 (09:39 +0000)
committerMarek Polacek <mpolacek@gcc.gnu.org>
Sat, 24 Sep 2016 09:39:23 +0000 (09:39 +0000)
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
gcc/c-family/ChangeLog
gcc/c-family/c.opt
gcc/c/ChangeLog
gcc/c/c-typeck.c
gcc/cp/ChangeLog
gcc/cp/typeck.c
gcc/doc/invoke.texi
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/Wbool-operation-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/Wbool-operation-1.c [new file with mode: 0644]

index 316bfaf621bedc57ea369837c850b866e9197b74..0059dd4bf63251f1513851a945e06ba87e273508 100644 (file)
@@ -1,3 +1,8 @@
+2016-09-24  Marek Polacek  <polacek@redhat.com>
+
+       PR c/77490
+       * doc/invoke.texi: Document -Wbool-operation.
+
 2016-09-23  Jakub Jelinek  <jakub@redhat.com>
 
        * hooks.c (hook_bool_bool_false, hook_bool_bool_gcc_optionsp_false,
index 3dfb39f363177029d27237c94b98d6aaeadc0812..8bcbd061407b0a4c82eb69696f44d225bfd6ea37 100644 (file)
@@ -1,3 +1,8 @@
+2016-09-24  Marek Polacek  <polacek@redhat.com>
+
+       PR c/77490
+       * c.opt (Wbool-operation): New.
+
 2016-09-21  Bernd Edlinger  <bernd.edlinger@hotmail.de>
 
        * c-common.c (c_common_truthvalue_conversion): Inhibit
index a04618d10639645cd68d811df5b0743651806163..4a9b9e88a250358a9133f500370923ff8fbd4866 100644 (file)
@@ -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.
index 283cfdacc2f33064887d2205f6e792324363f4c3..cae5c922067d99a4a4a3010799bfe1811455178a 100644 (file)
@@ -1,3 +1,9 @@
+2016-09-24  Marek Polacek  <polacek@redhat.com>
+
+       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  <jakub@redhat.com>
 
        * c-parser.c (incomplete_record_decls): Remove unnecessary
index 059ad1fc2e021c632164dcf091b1252566d1f5ca..e5c725603978dd8d5b75a0f3e4b7f697a3d49c85 100644 (file)
@@ -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);
 
index a3430bf3ad50531cdb8aee2ecb6a752e19af117c..cd5f936e3628f4708cd72408989cba10f818312a 100644 (file)
@@ -1,3 +1,9 @@
+2016-09-24  Marek Polacek  <polacek@redhat.com>
+
+       PR c/77490
+       * typeck.c (cp_build_unary_op): Warn about bit not on expressions that
+       have boolean value.
+
 2016-09-23  Jakub Jelinek  <jakub@redhat.com>
 
        Implement P0138R2, C++17 construction rules for enum class values
index b2af615d89e74a30d5bdcf0f70c302c743cf4591..0142d4a55cfee12db144e888f03d3c04d138b74a 100644 (file)
@@ -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:
index e6f503f4f97ae8aacaaf00cf3806fab7bb3af62f..a5481b5d8f97bf7773123b4ad1ad9338adb97541 100644 (file)
@@ -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
index f387022069b86e5656d3dc27778459576bebfe99..77ef74b6635e18b480691c718fc0b9df1bd28852 100644 (file)
@@ -1,3 +1,9 @@
+2016-09-24  Marek Polacek  <polacek@redhat.com>
+
+       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  <fritzoreese@gmail.com>
 
        * 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  <vogt@linux.vnet.ibm.com>
 
        * 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 (file)
index 0000000..bb72784
--- /dev/null
@@ -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 (file)
index 0000000..b24e763
--- /dev/null
@@ -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;
+}