PR c++/69300 - ICE with self-referential noexcept
authorJason Merrill <jason@redhat.com>
Wed, 28 Jun 2017 20:02:12 +0000 (16:02 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 28 Jun 2017 20:02:12 +0000 (16:02 -0400)
* pt.c (maybe_instantiate_noexcept): Check for recursion.

From-SVN: r249757

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/testsuite/g++.dg/cpp0x/noexcept30.C [new file with mode: 0644]

index 9c21f6f363e5ebe1d7f89165cc5a1286c5a1ae85..2245ca9060c23550b84f93ef80a62c89ec292c9b 100644 (file)
@@ -1,5 +1,8 @@
 2017-06-28  Jason Merrill  <jason@redhat.com>
 
+       PR c++/69300 - ICE with self-referential noexcept
+       * pt.c (maybe_instantiate_noexcept): Check for recursion.
+
        PR c++/61022 - error with variadic template template parm
        * pt.c (convert_template_argument): Keep the TYPE_PACK_EXPANSION.
 
index fa75037aa3da24f266e085ac10d30a822c40b100..047d3baabbfeda2b2e69f8fe44cfa0f7ab6d3067 100644 (file)
@@ -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 (file)
index 0000000..c51e94e
--- /dev/null
@@ -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>();
+}