c++: Fix deferred noexcept on constructor [PR93901].
authorJason Merrill <jason@redhat.com>
Thu, 14 May 2020 15:15:27 +0000 (11:15 -0400)
committerJason Merrill <jason@redhat.com>
Thu, 14 May 2020 20:38:30 +0000 (16:38 -0400)
My change in r10-4394 to only update clones when we actually instantiate a
deferred noexcept-spec broke this because deferred parsing updates the
primary function but not the clones.  For GCC 10 I just reverted that
change; this patch adjusts maybe_instantiate_noexcept to update only the
clone passed as the argument.

gcc/cp/ChangeLog
2020-05-14  Jason Merrill  <jason@redhat.com>

PR c++/93901
* pt.c (maybe_instantiate_noexcept): Change clone handling.

gcc/cp/ChangeLog
gcc/cp/pt.c

index 437495458e2a2ae230377c3b92a7b0de3d56948b..0a3205272a5686af1342e244d12f0bc162ab9238 100644 (file)
@@ -1,3 +1,8 @@
+2020-05-14  Jason Merrill  <jason@redhat.com>
+
+       PR c++/93901
+       * pt.c (maybe_instantiate_noexcept): Change clone handling.
+
 2020-05-14  Patrick Palka  <ppalka@redhat.com>
 
        PR c++/78446
index 61e6fa7484dfa30a036dcdf75dcf55c1b5a0243f..2a0b18f5517ae775a376389a5d574461ca6d8da8 100644 (file)
@@ -25174,7 +25174,7 @@ always_instantiate_p (tree decl)
 bool
 maybe_instantiate_noexcept (tree fn, tsubst_flags_t complain)
 {
-  tree fntype, spec, noex, clone;
+  tree fntype, spec, noex;
 
   /* Don't instantiate a noexcept-specification from template context.  */
   if (processing_template_decl
@@ -25193,8 +25193,16 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t complain)
       return !DECL_MAYBE_DELETED (fn);
     }
 
-  if (DECL_CLONED_FUNCTION_P (fn))
-    fn = DECL_CLONED_FUNCTION (fn);
+  fntype = TREE_TYPE (fn);
+  spec = TYPE_RAISES_EXCEPTIONS (fntype);
+
+  if (!spec || !TREE_PURPOSE (spec))
+    return true;
+
+  noex = TREE_PURPOSE (spec);
+  if (TREE_CODE (noex) != DEFERRED_NOEXCEPT
+      && TREE_CODE (noex) != DEFERRED_PARSE)
+    return true;
 
   tree orig_fn = NULL_TREE;
   /* For a member friend template we can get a TEMPLATE_DECL.  Let's use
@@ -25206,15 +25214,14 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t complain)
       fn = DECL_TEMPLATE_RESULT (fn);
     }
 
-  fntype = TREE_TYPE (fn);
-  spec = TYPE_RAISES_EXCEPTIONS (fntype);
-
-  if (!spec || !TREE_PURPOSE (spec))
-    return true;
-
-  noex = TREE_PURPOSE (spec);
-
-  if (TREE_CODE (noex) == DEFERRED_NOEXCEPT)
+  if (DECL_CLONED_FUNCTION_P (fn))
+    {
+      tree prime = DECL_CLONED_FUNCTION (fn);
+      if (!maybe_instantiate_noexcept (prime, complain))
+       return false;
+      spec = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (prime));
+    }
+  else if (TREE_CODE (noex) == DEFERRED_NOEXCEPT)
     {
       static hash_set<tree>* fns = new hash_set<tree>;
       bool added = false;
@@ -25284,27 +25291,19 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t complain)
 
       if (added)
        fns->remove (fn);
-
-      if (spec == error_mark_node)
-       {
-         /* 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);
-      if (orig_fn)
-       TREE_TYPE (orig_fn) = TREE_TYPE (fn);
     }
 
-  FOR_EACH_CLONE (clone, fn)
+  if (spec == error_mark_node)
     {
-      if (TREE_TYPE (clone) == fntype)
-       TREE_TYPE (clone) = TREE_TYPE (fn);
-      else
-       TREE_TYPE (clone) = build_exception_variant (TREE_TYPE (clone), spec);
+      /* 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);
+  if (orig_fn)
+    TREE_TYPE (orig_fn) = TREE_TYPE (fn);
+
   return true;
 }