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.
Tested x86_64-pc-linux-gnu, applying to trunk. gcc/cp/ChangeLog 2020-05-14 Jason Merrill <ja...@redhat.com> PR c++/93901 * pt.c (maybe_instantiate_noexcept): Change clone handling. --- gcc/cp/pt.c | 55 ++++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 28 deletions(-) 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<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; } base-commit: 3a36428b5fbc825e2d3455f5770b5d6e71c63413 -- 2.18.1