https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115159
--- Comment #4 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The master branch has been updated by Patrick Palka <ppa...@gcc.gnu.org>: https://gcc.gnu.org/g:3c98d06a9016a0fa3a806879bd168f13b8a606f8 commit r15-779-g3c98d06a9016a0fa3a806879bd168f13b8a606f8 Author: Patrick Palka <ppa...@redhat.com> Date: Wed May 22 17:45:04 2024 -0400 c++: canonicity of fn types w/ complex eh specs [PR115159] Here the member functions QList::g and QList::h are given the same function type by build_cp_fntype_variant since their noexcept-specs are equivalent according to cp_tree_equal. In doing so however this means that the function type of QList::h refers to a function parameter from QList::g, which ends up confusing modules streaming. I'm not sure if modules can be fixed to handle this situation, but regardless it seems weird in principle that a function parameter can escape in such a way. The analogous situation with a trailing return type and decltype auto g(QList &other) -> decltype(f(other)); auto h(QList &other) -> decltype(f(other)); behaves better because we don't canonicalize decltype, and so the function types of g and h are non-canonical and therefore not shared. In light of this, it seems natural to treat function types with complex noexcept-specs as non-canonical as well so that each such function declaration is given a unique function type node. (The main benefit of type canonicalization is to speed up repeated type comparisons, but it should be rare to repeatedly compare two otherwise compatible function types with complex noexcept-specs.) To that end, this patch strengthens the ce_exact case of comp_except_specs to require identity instead of equivalence of the noexcept-spec so that build_cp_fntype_variant doesn't reuse a variant when it shouldn't. In turn we need to use structural equality for types with a complex eh spec. This lets us get rid of the tricky handling of canonical types when updating unparsed noexcept-spec variants. PR c++/115159 gcc/cp/ChangeLog: * tree.cc (build_cp_fntype_variant): Always use structural equality for types with a complex exception specification. (fixup_deferred_exception_variants): Use structural equality for adjusted variants. * typeck.cc (comp_except_specs): Require == instead of cp_tree_equal for ce_exact noexcept-spec comparison. gcc/testsuite/ChangeLog: * g++.dg/modules/noexcept-2_a.H: New test. * g++.dg/modules/noexcept-2_b.C: New test. Reviewed-by: Jason Merrill <ja...@redhat.com>