PR c++/89571 - ICE with ill-formed noexcept on constructor.
authorJason Merrill <jason@redhat.com>
Sun, 17 Mar 2019 20:07:26 +0000 (16:07 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Sun, 17 Mar 2019 20:07:26 +0000 (16:07 -0400)
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.

* pt.c (maybe_instantiate_noexcept): Only return false if defaulted.
(regenerate_decl_from_template): Use it for noexcept-specs.

From-SVN: r269746

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

index 6c96c24..34e9c79 100644 (file)
@@ -1,3 +1,9 @@
+2019-03-17  Jason Merrill  <jason@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  <jason@redhat.com>
 
        * parser.c (cp_parser_decl_specifier_seq): Support C++20
index 2ab6e27..dc5c24c 100644 (file)
@@ -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 (file)
index 0000000..980a28c
--- /dev/null
@@ -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;
+};