In the testcase we SEGV due to infinite recursion because the
noexcept-specifier of f depends on itself.  Fixed by keeping track of
which functions we're currently trying to instantiate noexcept for.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit 7a938fed4c07c7e28008b56e6bac05376b1f99fa
Author: Jason Merrill <ja...@redhat.com>
Date:   Tue Jun 27 17:25:18 2017 -0400

            PR c++/69300 - ICE with self-referential noexcept
    
            * pt.c (maybe_instantiate_noexcept): Check for recursion.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index fa75037..047d3ba 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -22557,8 +22557,20 @@ maybe_instantiate_noexcept (tree fn)
 
   if (TREE_CODE (noex) == DEFERRED_NOEXCEPT)
     {
+      static hash_set<tree>* fns = new hash_set<tree>;
+      bool added = false;
       if (DEFERRED_NOEXCEPT_PATTERN (noex) == NULL_TREE)
        spec = get_defaulted_eh_spec (fn);
+      else if (!(added = !fns->add (fn)))
+       {
+         /* If hash_set::add returns true, the element was already there.  */
+         location_t loc = EXPR_LOC_OR_LOC (DEFERRED_NOEXCEPT_PATTERN (noex),
+                                           DECL_SOURCE_LOCATION (fn));
+         error_at (loc,
+                   "exception specification of %qD depends on itself",
+                   fn);
+         spec = noexcept_false_spec;
+       }
       else if (push_tinst_level (fn))
        {
          push_access_scope (fn);
@@ -22579,6 +22591,9 @@ maybe_instantiate_noexcept (tree fn)
       else
        spec = noexcept_false_spec;
 
+      if (added)
+       fns->remove (fn);
+
       TREE_TYPE (fn) = build_exception_variant (fntype, spec);
     }
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept30.C 
b/gcc/testsuite/g++.dg/cpp0x/noexcept30.C
new file mode 100644
index 0000000..c51e94e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept30.C
@@ -0,0 +1,12 @@
+// PR c++/69300
+// { dg-do compile { target c++11 } }
+
+template<typename A>
+struct F {
+  template<typename B>
+  void f() noexcept(&F::template f<B>) {} // { dg-error "exception 
specification" }
+};
+
+int main () {
+  F<void>().f<int>();
+}

Reply via email to