This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PATCH RFA: C++: Avoid inappropriate -Wsign-compare warnings


Here is a better patch to address the problem described in some detail
in http://gcc.gnu.org/ml/gcc-patches/2009-06/msg01393.html .  In this
patch I simply set TREE_NO_WARNING for cases where we are using a
builtin operator and we have cast an unsigned enum type to a signed
integral type.  Then I test TREE_NO_WARNING before calling
warn_sign_compare.

Bootstrapped and g++ testsuite run on x86_64-unknown-linux-gnu.  OK for
mainline?

Ian


gcc/cp/ChangeLog:

2009-06-17  Ian Lance Taylor  <iant@google.com>

	* call.c (avoid_sign_compare_warnings): New static function.
	(build_new_op): Call it.
	* typeck.c (cp_build_binary_op): Don't call warn_sign_compare if
	TREE_NO_WARNING is set on either operand.

gcc/testsuite/ChangeLog:

2009-06-17  Ian Lance Taylor  <iant@google.com>

	* g++.dg/warn/Wsign-compare-3.C: New testcase.


Index: cp/typeck.c
===================================================================
--- cp/typeck.c	(revision 148613)
+++ cp/typeck.c	(working copy)
@@ -4018,6 +4018,8 @@ cp_build_binary_op (location_t location,
 
       if ((short_compare || code == MIN_EXPR || code == MAX_EXPR)
 	  && warn_sign_compare
+	  && !TREE_NO_WARNING (orig_op0)
+	  && !TREE_NO_WARNING (orig_op1)
 	  /* Do not warn until the template is instantiated; we cannot
 	     bound the ranges of the arguments until that point.  */
 	  && !processing_template_decl
Index: cp/call.c
===================================================================
--- cp/call.c	(revision 148613)
+++ cp/call.c	(working copy)
@@ -4045,10 +4045,32 @@ add_candidates (tree fns, const VEC(tree
     }
 }
 
+/* Even unsigned enum types promote to signed int.  We don't want to
+   issue -Wsign-compare warnings for this case.  Here ORIG_ARG is the
+   original argument and ARG is the argument after any conversions
+   have been applied.  We set TREE_NO_WARNING if we have added a cast
+   from an unsigned enum type to a signed integer type.  */
+
+static void
+avoid_sign_compare_warnings (tree orig_arg, tree arg)
+{
+  if (orig_arg != NULL_TREE
+      && arg != NULL_TREE
+      && orig_arg != arg
+      && TREE_CODE (TREE_TYPE (orig_arg)) == ENUMERAL_TYPE
+      && TYPE_UNSIGNED (TREE_TYPE (orig_arg))
+      && INTEGRAL_TYPE_P (TREE_TYPE (arg))
+      && !TYPE_UNSIGNED (TREE_TYPE (arg)))
+    TREE_NO_WARNING (arg) = 1;
+}
+
 tree
 build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3,
 	      bool *overloaded_p, tsubst_flags_t complain)
 {
+  tree orig_arg1 = arg1;
+  tree orig_arg2 = arg2;
+  tree orig_arg3 = arg3;
   struct z_candidate *candidates = 0, *cand;
   VEC(tree,gc) *arglist;
   tree fnname;
@@ -4350,6 +4372,10 @@ build_new_op (enum tree_code code, int f
     return result;
 
  builtin:
+  avoid_sign_compare_warnings (orig_arg1, arg1);
+  avoid_sign_compare_warnings (orig_arg2, arg2);
+  avoid_sign_compare_warnings (orig_arg3, arg3);
+
   switch (code)
     {
     case MODIFY_EXPR:
Index: testsuite/g++.dg/warn/Wsign-compare-3.C
===================================================================
--- testsuite/g++.dg/warn/Wsign-compare-3.C	(revision 0)
+++ testsuite/g++.dg/warn/Wsign-compare-3.C	(revision 0)
@@ -0,0 +1,13 @@
+// { dg-do compile }
+// { dg-options "-Wsign-compare" }
+
+enum E { A, B, C };
+extern void f1(int);
+void
+f2(E v1, E v2)
+{
+  for (unsigned int i = v1; i <= v2; ++i)
+    f1(i);
+  for (int i = v1; i <= v2; ++i)
+    f1(i);
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]