diff mbox

C++ PATCH for c++/59231 (missed warning in template instantiation)

Message ID 530E5AD6.9090707@redhat.com
State New
Headers show

Commit Message

Jason Merrill Feb. 26, 2014, 9:21 p.m. UTC
As discussed in the PR, I think my earlier suggestion to use 
c_inhibit_evaluation_warnings to suppress undesirable warnings from 
template instantiations was wrong.  That flag should only be used for 
suppressing warnings that are irrelevant because the expression is never 
evaluated, which may or may not be the case during template instantiation.

Instead, this patch suppresses specific warning flags during template 
substitution: warn_div_by_zero, warn_type_limits, and warn_useless_cast.

This is may well produce more warnings from template-heavy code.

Tested x86_64-pc-linux-gnu, applying to trunk.
diff mbox

Patch

commit 04b9e92db4acaa442552e87b18682c7b01275017
Author: Jason Merrill <jason@redhat.com>
Date:   Wed Feb 26 13:49:23 2014 -0500

    	PR c++/59231
    	PR c++/11586
    	PR c++/14710
    	PR c++/57132
    gcc/
    	* c-common.c (shorten_compare): Don't check
    	c_inhibit_evaluation_warnings.
    gcc/cp/
    	* pt.c (struct warning_sentinel): New.
    	(tsubst_copy_and_build): Use it instead of
    	c_inhibit_evaluation_warnings.

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index e23a9df..abd96fb 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -4218,8 +4218,7 @@  shorten_compare (location_t loc, tree *op0_ptr, tree *op1_ptr,
 	  type = c_common_unsigned_type (type);
 	}
 
-      if (TREE_CODE (primop0) != INTEGER_CST
-	  && c_inhibit_evaluation_warnings == 0)
+      if (TREE_CODE (primop0) != INTEGER_CST)
 	{
 	  if (val == truthvalue_false_node)
 	    warning_at (loc, OPT_Wtype_limits,
@@ -4299,7 +4298,6 @@  shorten_compare (location_t loc, tree *op0_ptr, tree *op1_ptr,
 	     warning.  */
 	  bool warn = 
 	    warn_type_limits && !in_system_header_at (loc)
-	    && c_inhibit_evaluation_warnings == 0
 	    && !(TREE_CODE (primop0) == INTEGER_CST
 		 && !TREE_OVERFLOW (convert (c_common_signed_type (type),
 					     primop0)))
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 1f5a2b7..8126905 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -1,4 +1,4 @@ 
-/* Handle parameterized types (templates) for GNU C++.
+/* Handle parameterized types (templates) for GNU -*- C++ -*-.
    Copyright (C) 1992-2014 Free Software Foundation, Inc.
    Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing.
    Rewritten by Jason Merrill (jason@cygnus.com).
@@ -14063,6 +14063,16 @@  tsubst_non_call_postfix_expression (tree t, tree args,
   return t;
 }
 
+/* Sentinel to disable certain warnings during template substitution.  */
+
+struct warning_sentinel {
+  int &flag;
+  int val;
+  warning_sentinel(int& flag, bool suppress=true)
+    : flag(flag), val(flag) { if (suppress) flag = 0; }
+  ~warning_sentinel() { flag = val; }
+};
+
 /* Like tsubst but deals with expressions and performs semantic
    analysis.  FUNCTION_P is true if T is the "F" in "F (ARGS)".  */
 
@@ -14229,7 +14239,7 @@  tsubst_copy_and_build (tree t,
 
 	op = RECUR (TREE_OPERAND (t, 0));
 
-	++c_inhibit_evaluation_warnings;
+	warning_sentinel s(warn_useless_cast);
 	switch (TREE_CODE (t))
 	  {
 	  case CAST_EXPR:
@@ -14250,7 +14260,6 @@  tsubst_copy_and_build (tree t,
 	  default:
 	    gcc_unreachable ();
 	  }
-	--c_inhibit_evaluation_warnings;
 
 	RETURN (r);
       }
@@ -14325,11 +14334,9 @@  tsubst_copy_and_build (tree t,
     case MEMBER_REF:
     case DOTSTAR_EXPR:
       {
-	tree r;
-
-	++c_inhibit_evaluation_warnings;
-
-	r = build_x_binary_op
+	warning_sentinel s1(warn_type_limits);
+	warning_sentinel s2(warn_div_by_zero);
+	tree r = build_x_binary_op
 	  (input_location, TREE_CODE (t),
 	   RECUR (TREE_OPERAND (t, 0)),
 	   (TREE_NO_WARNING (TREE_OPERAND (t, 0))
@@ -14344,8 +14351,6 @@  tsubst_copy_and_build (tree t,
 	if (EXPR_P (r) && TREE_NO_WARNING (t))
 	  TREE_NO_WARNING (r) = TREE_NO_WARNING (t);
 
-	--c_inhibit_evaluation_warnings;
-
 	RETURN (r);
       }
 
@@ -14460,11 +14465,8 @@  tsubst_copy_and_build (tree t,
 
     case MODOP_EXPR:
       {
-	tree r;
-
-	++c_inhibit_evaluation_warnings;
-
-	r = build_x_modify_expr
+	warning_sentinel s(warn_div_by_zero);
+	tree r = build_x_modify_expr
 	  (EXPR_LOCATION (t),
 	   RECUR (TREE_OPERAND (t, 0)),
 	   TREE_CODE (TREE_OPERAND (t, 1)),
@@ -14479,8 +14481,6 @@  tsubst_copy_and_build (tree t,
 	if (TREE_NO_WARNING (t))
 	  TREE_NO_WARNING (r) = TREE_NO_WARNING (t);
 
-	--c_inhibit_evaluation_warnings;
-
 	RETURN (r);
       }
 
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 5fc0e6b..1e14b63 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -6282,8 +6282,7 @@  void
 maybe_warn_about_useless_cast (tree type, tree expr, tsubst_flags_t complain)
 {
   if (warn_useless_cast
-      && complain & tf_warning
-      && c_inhibit_evaluation_warnings == 0)
+      && complain & tf_warning)
     {
       if (REFERENCE_REF_P (expr))
 	expr = TREE_OPERAND (expr, 0);
diff --git a/gcc/testsuite/g++.dg/cilk-plus/AN/array_test2_tplt.cc b/gcc/testsuite/g++.dg/cilk-plus/AN/array_test2_tplt.cc
index 87c37e1..041c052 100644
--- a/gcc/testsuite/g++.dg/cilk-plus/AN/array_test2_tplt.cc
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/array_test2_tplt.cc
@@ -1,5 +1,5 @@ 
 /* { dg-do run } */
-/* { dg-options "-fcilkplus" } */
+/* { dg-options "-fcilkplus -Wno-overflow" } */
 
 #include <cstdlib>
 #include <string.h>
diff --git a/gcc/testsuite/g++.dg/cpp0x/overflow1.C b/gcc/testsuite/g++.dg/cpp0x/overflow1.C
index 7033e9c..b8591b4 100644
--- a/gcc/testsuite/g++.dg/cpp0x/overflow1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/overflow1.C
@@ -1,3 +1,5 @@ 
+// { dg-prune-output "-Woverflow" }
+
 template <long long i>
 struct Fib
 {
diff --git a/gcc/testsuite/g++.dg/warn/Wsign-compare-7.C b/gcc/testsuite/g++.dg/warn/Wsign-compare-7.C
new file mode 100644
index 0000000..51f13f6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wsign-compare-7.C
@@ -0,0 +1,18 @@ 
+// PR c++/59231
+// { dg-options "-Wsign-compare" }
+
+template<class X, class Y>
+bool equals(X x, Y y)
+{
+    return (x == y);		// { dg-warning "signed" }
+}
+
+int main()
+{
+  unsigned long x = 2;
+  signed int y = 2;
+
+  if(!equals (x, y))
+    return 1;
+  return 0;
+}