diff mbox series

C++ PATCH for c++/77369, wrong noexcept handling with template type arguments

Message ID CADzB+2nZQ4YKhmFkmZD63qR6reh8vvbV5zX0p8LDeaV3FXqwfg@mail.gmail.com
State New
Headers show
Series C++ PATCH for c++/77369, wrong noexcept handling with template type arguments | expand

Commit Message

Jason Merrill Oct. 23, 2017, 7:05 p.m. UTC
In C++14 and below, the exception-specification is not part of a
function type, so we need to drop it from template arguments;
otherwise, all uses of a particular template instantiation get the
exception specification that the first use happened to have.

This patch regresses the -Wnoexcept-type warning, as in this case we
discard the exception-specification long before we get to mangling.  I
explored fixing this for a while, but it seems to require a whole new
mechanism for propagating warnings through overload resolution.  And
this warning doesn't seem to be as important as I initially thought.

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

Jason
commit 30c1bda3bd426be189e7b61844d9801605a04d49
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Oct 17 10:38:03 2017 -0400

            PR c++/77369 - wrong noexcept handling in C++14 and below
    
            * tree.c (strip_typedefs): Canonicalize TYPE_RAISES_EXCEPTIONS.
diff mbox series

Patch

diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 366f46f1506..48d40945af3 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1439,7 +1439,11 @@  strip_typedefs (tree t, bool *remove_attributes)
 	  is_variant = true;
 
 	type = strip_typedefs (TREE_TYPE (t), remove_attributes);
-	changed = type != TREE_TYPE (t) || is_variant;
+	tree canon_spec = (flag_noexcept_type
+			   ? canonical_eh_spec (TYPE_RAISES_EXCEPTIONS (t))
+			   : NULL_TREE);
+	changed = (type != TREE_TYPE (t) || is_variant
+		   || TYPE_RAISES_EXCEPTIONS (t) != canon_spec);
 
 	for (arg_node = TYPE_ARG_TYPES (t);
 	     arg_node;
@@ -1498,9 +1502,8 @@  strip_typedefs (tree t, bool *remove_attributes)
 					type_memfn_rqual (t));
 	  }
 
-	if (TYPE_RAISES_EXCEPTIONS (t))
-	  result = build_exception_variant (result,
-					    TYPE_RAISES_EXCEPTIONS (t));
+	if (canon_spec)
+	  result = build_exception_variant (result, canon_spec);
 	if (TYPE_HAS_LATE_RETURN_TYPE (t))
 	  TYPE_HAS_LATE_RETURN_TYPE (result) = 1;
       }
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept31.C b/gcc/testsuite/g++.dg/cpp0x/noexcept31.C
new file mode 100644
index 00000000000..c4c0e7dd466
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept31.C
@@ -0,0 +1,12 @@ 
+// PR c++/77369
+// { dg-do compile { target c++11 } }
+
+template<typename F> int caller(F f) noexcept(noexcept(f())) { f(); return 0; }
+
+void func1() noexcept { }
+
+void func2() { throw 1; }
+
+int instantiate_caller_with_func1 = caller(func1);
+
+static_assert( !noexcept(caller(func2)), "" );
diff --git a/gcc/testsuite/g++.dg/cpp1z/noexcept-type13.C b/gcc/testsuite/g++.dg/cpp1z/noexcept-type13.C
index 8eb3be0bd61..b51d7af2b11 100644
--- a/gcc/testsuite/g++.dg/cpp1z/noexcept-type13.C
+++ b/gcc/testsuite/g++.dg/cpp1z/noexcept-type13.C
@@ -5,7 +5,7 @@ 
 void foo () throw () {}		// { dg-bogus "mangled name" }
 
 template <class T>
-T bar (T x) { return x; }	// { dg-warning "mangled name" "" { target c++14_down } }
+T bar (T x) { return x; }
 
 void baz () {			// { dg-bogus "mangled name" }
   return (bar (foo)) ();