Earlier changes to defer instantiating a defaulted noexcept-specifier that
depends on yet-unparsed default member initializers broke this testcase,
where instantiation fails for another reason.  In this case there's no
reason to defer and try again later, so let's not.

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

        * pt.c (maybe_instantiate_noexcept): Only return false if defaulted.
        (regenerate_decl_from_template): Use it for noexcept-specs.
---
 gcc/cp/pt.c                             | 34 +++++++++++++++++++------
 gcc/testsuite/g++.dg/cpp0x/noexcept36.C | 22 ++++++++++++++++
 gcc/cp/ChangeLog                        |  6 +++++
 3 files changed, 54 insertions(+), 8 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept36.C

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 2ab6e273c3a..dc5c24c47a7 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -23991,12 +23991,18 @@ regenerate_decl_from_template (tree decl, tree tmpl, 
tree args)
       if (args_depth > parms_depth)
        args = get_innermost_template_args (args, parms_depth);
 
-      specs = tsubst_exception_specification (TREE_TYPE (code_pattern),
-                                             args, tf_error, NULL_TREE,
-                                             /*defer_ok*/false);
-      if (specs && specs != error_mark_node)
-       TREE_TYPE (decl) = build_exception_variant (TREE_TYPE (decl),
-                                                   specs);
+      /* Instantiate a dynamic exception-specification.  noexcept will be
+        handled below.  */
+      if (tree raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (code_pattern)))
+       if (TREE_VALUE (raises))
+         {
+           specs = tsubst_exception_specification (TREE_TYPE (code_pattern),
+                                                   args, tf_error, NULL_TREE,
+                                                   /*defer_ok*/false);
+           if (specs && specs != error_mark_node)
+             TREE_TYPE (decl) = build_exception_variant (TREE_TYPE (decl),
+                                                         specs);
+         }
 
       /* Merge parameter declarations.  */
       decl_parm = skip_artificial_parms_for (decl,
@@ -24062,6 +24068,8 @@ regenerate_decl_from_template (tree decl, tree tmpl, 
tree args)
       if (DECL_DECLARED_INLINE_P (code_pattern)
          && !DECL_DECLARED_INLINE_P (decl))
        DECL_DECLARED_INLINE_P (decl) = 1;
+
+      maybe_instantiate_noexcept (decl, tf_error);
     }
   else if (VAR_P (decl))
     {
@@ -24187,7 +24195,13 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t 
complain)
       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, complain);
+       {
+         spec = get_defaulted_eh_spec (fn, complain);
+         if (spec == error_mark_node)
+           /* This might have failed because of an unparsed DMI, so
+              let's try again later.  */
+           return false;
+       }
       else if (!(added = !fns->add (fn)))
        {
          /* If hash_set::add returns true, the element was already there.  */
@@ -24247,7 +24261,11 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t 
complain)
        fns->remove (fn);
 
       if (spec == error_mark_node)
-       return false;
+       {
+         /* This failed with a hard error, so let's go with false.  */
+         gcc_assert (seen_error ());
+         spec = noexcept_false_spec;
+       }
 
       TREE_TYPE (fn) = build_exception_variant (fntype, spec);
     }
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept36.C 
b/gcc/testsuite/g++.dg/cpp0x/noexcept36.C
new file mode 100644
index 00000000000..980a28cd207
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept36.C
@@ -0,0 +1,22 @@
+// PR c++/89571
+// { dg-do compile { target c++11 } }
+
+struct z8 {
+  constexpr static int qq /* = 0 */;  // { dg-error "initializer" }
+};
+
+template<typename T>
+struct kf {
+  kf (const kf &) noexcept (T::qq);  // { dg-error "constant" }
+};
+
+struct lk {
+  kf<z8> e1;
+};
+
+template<typename T>
+T &sc ();
+
+struct b6 {
+  decltype (lk (sc<lk> ())) zz;
+};
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 6c96c24430f..8738f2c3cf4 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2019-03-14  Jason Merrill  <ja...@redhat.com>
+
+       PR c++/89571 - ICE with ill-formed noexcept on constructor.
+       * pt.c (maybe_instantiate_noexcept): Only return false if defaulted.
+       (regenerate_decl_from_template): Use it for noexcept-specs.
+
 2019-03-14  Jason Merrill  <ja...@redhat.com>
 
        * parser.c (cp_parser_decl_specifier_seq): Support C++20

base-commit: 6f9b555b441312235713247f996b67372efb8ddd
-- 
2.20.1

Reply via email to