/* Canonicalize the exception specification. */
tree cr = flag_noexcept_type ? canonical_eh_spec (raises) : NULL_TREE;
+ bool complex_eh_spec_p = (cr && cr != noexcept_true_spec
+ && !UNPARSED_NOEXCEPT_SPEC_P (cr));
- if (TYPE_STRUCTURAL_EQUALITY_P (type))
- /* Propagate structural equality. */
+ if (TYPE_STRUCTURAL_EQUALITY_P (type) || complex_eh_spec_p)
+ /* Propagate structural equality. And always use structural equality
+ for function types with a complex noexcept-spec since their identity
+ may depend on e.g. whether comparing_specializations is set. */
SET_TYPE_STRUCTURAL_EQUALITY (v);
else if (TYPE_CANONICAL (type) != type || cr != raises || late)
/* Build the underlying canonical type, since it is different
/* TYPE is a function or method type with a deferred exception
specification that has been parsed to RAISES. Fixup all the type
variants that are affected in place. Via decltype &| noexcept
- tricks, the unparsed spec could have escaped into the type system.
- The general case is hard to fixup canonical types for. */
+ tricks, the unparsed spec could have escaped into the type system. */
void
fixup_deferred_exception_variants (tree type, tree raises)
{
tree original = TYPE_RAISES_EXCEPTIONS (type);
- tree cr = flag_noexcept_type ? canonical_eh_spec (raises) : NULL_TREE;
gcc_checking_assert (UNPARSED_NOEXCEPT_SPEC_P (original));
- /* Though sucky, this walk will process the canonical variants
- first. */
- tree prev = NULL_TREE;
for (tree variant = TYPE_MAIN_VARIANT (type);
- variant; prev = variant, variant = TYPE_NEXT_VARIANT (variant))
+ variant; variant = TYPE_NEXT_VARIANT (variant))
if (TYPE_RAISES_EXCEPTIONS (variant) == original)
{
gcc_checking_assert (variant != TYPE_MAIN_VARIANT (type));
- if (!TYPE_STRUCTURAL_EQUALITY_P (variant))
- {
- cp_cv_quals var_quals = TYPE_QUALS (variant);
- cp_ref_qualifier rqual = type_memfn_rqual (variant);
-
- /* If VARIANT would become a dup (cp_check_qualified_type-wise)
- of an existing variant in the variant list of TYPE after its
- exception specification has been parsed, elide it. Otherwise,
- build_cp_fntype_variant could use it, leading to "canonical
- types differ for identical types." */
- tree v = TYPE_MAIN_VARIANT (type);
- for (; v; v = TYPE_NEXT_VARIANT (v))
- if (cp_check_qualified_type (v, variant, var_quals,
- rqual, cr, false))
- {
- /* The main variant will not match V, so PREV will never
- be null. */
- TYPE_NEXT_VARIANT (prev) = TYPE_NEXT_VARIANT (variant);
- break;
- }
- TYPE_RAISES_EXCEPTIONS (variant) = raises;
-
- if (!v)
- v = build_cp_fntype_variant (TYPE_CANONICAL (variant),
- rqual, cr, false);
- TYPE_CANONICAL (variant) = TYPE_CANONICAL (v);
- }
- else
- TYPE_RAISES_EXCEPTIONS (variant) = raises;
+ SET_TYPE_STRUCTURAL_EQUALITY (variant);
+ TYPE_RAISES_EXCEPTIONS (variant) = raises;
if (!TYPE_DEPENDENT_P (variant))
/* We no longer know that it's not type-dependent. */