Hi,

this message did not get listed on the gcc-patches archive.
I've got no bounce, and it just vanished, several times.

Any idea what is wrong?


Bernd.


-------- Forwarded Message --------
Subject: [PATCHv3, resent] Add a warning for suspicious use of 
conditional expressions in boolean context
Date: Thu, 15 Sep 2016 11:19:32 +0200
From: Bernd Edlinger <bernd.edlin...@hotmail.de>
To: GCC Patches <gcc-patc...@gcc.gnu.org>
CC: Jason Merrill <ja...@redhat.com>, Jeff Law <l...@redhat.com>, Joseph 
Myers <jos...@codesourcery.com>

Hi,

I send the latest version of the warning patch again, because I don't
see the previous patch submission on the gcc-patches list.  It dropped
out silently, twice :(

Don't know what went wrong, so please excuse me if this e-mail arrives
duplicate.


On 09/14/16 20:11, Jason Merrill wrote:
>>
>> Yes.  The reasoning I initially had was that it is completely
>> pointless to have something of the form "if (x ? 1 : 2)" or
>> "if (x ? 0 : 0)" because the result does not even depend on x
>> in this case.  But something like "if (x ? 4999 : 0)" looks
>> bogus but does at least not ignore x.
>>
>> If the false-positives are becoming too much of a problem here,
>> then I should of course revert to the previous heuristic again.
>
> I think we could have both, where the weaker form is part of -Wall and
> people can explicitly select the stronger form.
>


Yes, agreed.  So here is what I would think will be the first version.

It can later be extended to cover the more pedantic cases which
will not be enabled by -Wall.

I would like to send a follow-up patch for the warning on
signed-integer shift left in boolean context, which I think
should also be good for Wall.
(I already had that feature in patch version 2 but that's meanwhile
outdated).


Bootstrap and reg-testing on x86_64-pc-linux-gnu.
Is it OK for trunk?


Thanks
Bernd.


gcc:
2016-09-14  Bernd Edlinger  <bernd.edlin...@hotmail.de>

        PR c++/77434
        * doc/invoke.texi: Document -Wcond-in-bool-context.

        PR middle-end/77421
        * dwarf2out.c (output_loc_operands): Fix an assertion.

c-family:
2016-09-14  Bernd Edlinger  <bernd.edlin...@hotmail.de>

        PR c++/77434
        * c.opt (Wcond-in-bool-context): New warning.
        * c-common.c (c_common_truthvalue_conversion): Warn on integer
        constants in boolean context.

cp:
2016-09-14  Bernd Edlinger  <bernd.edlin...@hotmail.de>

        PR c++/77434
        * cvt.c (cp_convert_and_check): Suppress Wint-in-bool-context here.

testsuite:
2016-09-14  Bernd Edlinger  <bernd.edlin...@hotmail.de>

        PR c++/77434
        * c-c++-common/Wcond-in-bool-context.c: New test.
Index: gcc/builtins.c
===================================================================
--- gcc/builtins.c	(revision 240135)
+++ gcc/builtins.c	(working copy)
@@ -7887,15 +7887,18 @@ fold_builtin_classify (location_t loc, tree fndecl
 	    tree isinf_call = build_call_expr_loc (loc, isinf_fn, 1, arg);
 
 	    signbit_call = fold_build2_loc (loc, NE_EXPR, integer_type_node,
-					signbit_call, integer_zero_node);
+					    signbit_call, integer_zero_node);
 	    isinf_call = fold_build2_loc (loc, NE_EXPR, integer_type_node,
-				      isinf_call, integer_zero_node);
+					  isinf_call, integer_zero_node);
 
-	    tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node, signbit_call,
-			       integer_minus_one_node, integer_one_node);
 	    tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node,
-			       isinf_call, tmp,
-			       integer_zero_node);
+				   signbit_call, integer_minus_one_node,
+				   integer_one_node);
+	    /* Avoid a possible -Wint-in-bool-context warning in C.  */
+	    tmp = fold_build2_loc (loc, PLUS_EXPR, integer_type_node, tmp,
+				   integer_zero_node);
+	    tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node,
+				   isinf_call, tmp, integer_zero_node);
 	  }
 
 	return tmp;
Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c	(revision 240135)
+++ gcc/c-family/c-common.c	(working copy)
@@ -4652,6 +4652,19 @@ c_common_truthvalue_conversion (location_t locatio
 					       TREE_OPERAND (expr, 0));
 
     case COND_EXPR:
+      if (warn_int_in_bool_context)
+	{
+	  tree val1 = fold_for_warn (TREE_OPERAND (expr, 1));
+	  tree val2 = fold_for_warn (TREE_OPERAND (expr, 2));
+	  if (TREE_CODE (val1) == INTEGER_CST
+	      && TREE_CODE (val2) == INTEGER_CST
+	      && !integer_zerop (val1)
+	      && !integer_zerop (val2)
+	      && (!integer_onep (val1)
+		  || !integer_onep (val2)))
+	    warning_at (EXPR_LOCATION (expr), OPT_Wint_in_bool_context,
+		        "?: using integer constants in boolean context");
+	}
       /* Distribute the conversion into the arms of a COND_EXPR.  */
       if (c_dialect_cxx ())
 	{
Index: gcc/c-family/c.opt
===================================================================
--- gcc/c-family/c.opt	(revision 240135)
+++ gcc/c-family/c.opt	(working copy)
@@ -545,6 +545,10 @@ Wint-conversion
 C ObjC Var(warn_int_conversion) Init(1) Warning
 Warn about incompatible integer to pointer and pointer to integer conversions.
 
+Wint-in-bool-context
+C ObjC C++ ObjC++ Var(warn_int_in_bool_context) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
+Warn for suspicious integer expressions in boolean context.
+
 Wint-to-pointer-cast
 C ObjC C++ ObjC++ Var(warn_int_to_pointer_cast) Init(1) Warning
 Warn when there is a cast to a pointer from an integer of a different size.
Index: gcc/cp/cvt.c
===================================================================
--- gcc/cp/cvt.c	(revision 240135)
+++ gcc/cp/cvt.c	(working copy)
@@ -645,6 +645,7 @@ cp_convert_and_check (tree type, tree expr, tsubst
 	{
 	  /* Avoid bogus -Wparentheses warnings.  */
 	  warning_sentinel w (warn_parentheses);
+	  warning_sentinel c (warn_int_in_bool_context);
 	  folded_result = cp_convert (type, folded, tf_none);
 	}
       folded_result = fold_simple (folded_result);
Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(revision 240135)
+++ gcc/doc/invoke.texi	(working copy)
@@ -273,7 +273,7 @@ Objective-C and Objective-C++ Dialects}.
 -Wframe-larger-than=@var{len} -Wno-free-nonheap-object -Wjump-misses-init @gol
 -Wignored-qualifiers  -Wignored-attributes  -Wincompatible-pointer-types @gol
 -Wimplicit  -Wimplicit-function-declaration  -Wimplicit-int @gol
--Winit-self  -Winline  -Wno-int-conversion @gol
+-Winit-self  -Winline  -Wno-int-conversion  -Wint-in-bool-context @gol
 -Wno-int-to-pointer-cast -Winvalid-memory-model -Wno-invalid-offsetof @gol
 -Winvalid-pch -Wlarger-than=@var{len} @gol
 -Wlogical-op -Wlogical-not-parentheses -Wlong-long @gol
@@ -5837,6 +5837,14 @@ warning about it.
 The restrictions on @code{offsetof} may be relaxed in a future version
 of the C++ standard.
 
+@item -Wint-in-bool-context
+@opindex Wint-in-bool-context
+@opindex Wno-int-in-bool-context
+Warn for suspicious use of integer values where boolean values are expected,
+such as conditional expressions (?:) using non-boolean integer constants in
+boolean context, like @code{if (a <= b ? 2 : 3)}.
+This warning is enabled by @option{-Wall}.
+
 @item -Wno-int-to-pointer-cast
 @opindex Wno-int-to-pointer-cast
 @opindex Wint-to-pointer-cast
Index: gcc/dwarf2out.c
===================================================================
--- gcc/dwarf2out.c	(revision 240135)
+++ gcc/dwarf2out.c	(working copy)
@@ -2051,9 +2051,9 @@ output_loc_operands (dw_loc_descr_ref loc, int for
 	/* Make sure the offset has been computed and that we can encode it as
 	   an operand.  */
 	gcc_assert (die_offset > 0
-		    && die_offset <= (loc->dw_loc_opc == DW_OP_call2)
+		    && die_offset <= (loc->dw_loc_opc == DW_OP_call2
 				     ? 0xffff
-				     : 0xffffffff);
+				     : 0xffffffff));
 	dw2_asm_output_data ((loc->dw_loc_opc == DW_OP_call2) ? 2 : 4,
 			     die_offset, NULL);
       }
Index: gcc/testsuite/c-c++-common/Wint-in-bool-context.c
===================================================================
--- gcc/testsuite/c-c++-common/Wint-in-bool-context.c	(revision 0)
+++ gcc/testsuite/c-c++-common/Wint-in-bool-context.c	(working copy)
@@ -0,0 +1,32 @@
+/* PR c++/77434 */
+/* { dg-options "-Wint-in-bool-context" } */
+/* { dg-do compile } */
+
+int foo (int a, int b)
+{
+  if (a > 0 && a <= (b == 1) ? 1 : 2) /* { dg-warning "boolean context" } */
+    return 1;
+
+  if (a > 0 && a <= (b == 2) ? 1 : 1) /* { dg-bogus "boolean context" } */
+    return 2;
+
+  if (a > 0 && a <= (b == 3) ? 0 : 2) /* { dg-bogus "boolean context" } */
+    return 3;
+
+  if (a == b ? 0 : 0) /* { dg-bogus "boolean context" } */
+    return 4;
+
+  if (a == ((b ? 2|4 : 1) & 3 ? 0 : 2)) /* { dg-bogus "boolean context" } */
+    return 5;
+
+  if (a ? 1 : 1+1) /* { dg-warning "boolean context" } */
+    return 6;
+
+  if (b ? 1+1 : 1) /* { dg-warning "boolean context" } */
+    return 7;
+
+  if (__builtin_isinf_sign ((float)a/b)) /* { dg-bogus "boolean context" } */
+    return 8;
+
+  return 0;
+}

Reply via email to