From 4e1592f8e1d6366699e05c0824fc3dc39ca7314b Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Thu, 14 May 2020 11:15:27 -0400 Subject: [PATCH] c++: Fix deferred noexcept on constructor [PR93901]. 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 PR c++/93901 * pt.c (maybe_instantiate_noexcept): Change clone handling. --- gcc/cp/ChangeLog | 5 +++++ gcc/cp/pt.c | 55 ++++++++++++++++++++++++------------------------ 2 files changed, 32 insertions(+), 28 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 437495458e2..0a3205272a5 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,8 @@ +2020-05-14 Jason Merrill + + PR c++/93901 + * pt.c (maybe_instantiate_noexcept): Change clone handling. + 2020-05-14 Patrick Palka PR c++/78446 diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 61e6fa7484d..2a0b18f5517 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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* fns = new hash_set; 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; }