Missing error-recovery code. While I was poking at this I also figured we don't need to iterate over the members of a union.
Tested x86_64-pc-linux-gnu, applying to trunk. * method.c (comp_info::~comp_info): Factor out of... (build_comparison_op): Here. Handle error return from build_new_op. --- gcc/cp/method.c | 33 ++++++++++++------- .../g++.dg/cpp2a/spaceship-synth-neg2.C | 25 ++++++++++++++ 2 files changed, 46 insertions(+), 12 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/spaceship-synth-neg2.C diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 83da20a0779..97c27c51ea3 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -1244,6 +1244,21 @@ struct comp_info if (noex && !expr_noexcept_p (expr, tf_none)) noex = false; } + + ~comp_info () + { + if (first_time) + { + DECL_DECLARED_CONSTEXPR_P (fndecl) = constexp || was_constexp; + tree raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fndecl)); + if (!raises || UNEVALUATED_NOEXCEPT_SPEC_P (raises)) + { + raises = noex ? noexcept_true_spec : noexcept_false_spec; + TREE_TYPE (fndecl) = build_exception_variant (TREE_TYPE (fndecl), + raises); + } + } + } }; /* Build up the definition of a defaulted comparison operator. Unlike other @@ -1282,6 +1297,7 @@ build_comparison_op (tree fndecl, tsubst_flags_t complain) if (complain & tf_error) inform (info.loc, "cannot default compare union %qT", ctype); DECL_DELETED_FN (fndecl) = true; + return; } tree compound_stmt = NULL_TREE; @@ -1335,6 +1351,11 @@ build_comparison_op (tree fndecl, tsubst_flags_t complain) NULL_TREE); tree comp = build_new_op (info.loc, code, flags, lhs_mem, rhs_mem, NULL_TREE, NULL, complain); + if (comp == error_mark_node) + { + DECL_DELETED_FN (fndecl) = true; + continue; + } comps.safe_push (comp); } if (code == SPACESHIP_EXPR && is_auto (rettype)) @@ -1430,18 +1451,6 @@ build_comparison_op (tree fndecl, tsubst_flags_t complain) finish_compound_stmt (compound_stmt); else --cp_unevaluated_operand; - - if (info.first_time) - { - DECL_DECLARED_CONSTEXPR_P (fndecl) = info.constexp || info.was_constexp; - tree raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fndecl)); - if (!raises || UNEVALUATED_NOEXCEPT_SPEC_P (raises)) - { - raises = info.noex ? noexcept_true_spec : noexcept_false_spec; - TREE_TYPE (fndecl) = build_exception_variant (TREE_TYPE (fndecl), - raises); - } - } } /* Synthesize FNDECL, a non-static member function. */ diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-synth-neg2.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth-neg2.C new file mode 100644 index 00000000000..ecc249a67b7 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth-neg2.C @@ -0,0 +1,25 @@ +// PR c++/92774 +// { dg-do compile { target c++2a } } + +#include <compare> + +template<typename T> +struct X { }; + +template<typename T> +bool operator==(const X<T>&, const X<T>&) { return true; } +template<typename T> +bool operator<(const X<T>&, const X<T>&) { return true; } + +struct Y +{ + int a; + X<int> c; + + auto operator <=>(Y const&) const = default; // { dg-error "no match" } +}; + +void f() +{ + auto x = Y() < Y(); // { dg-error "deleted" } +} base-commit: 945f2b19497eff52ef44923d291bf0fdba043299 -- 2.18.1