From 60e457d9cad52491bbff434bf611b21f2da07ecc Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Wed, 11 Dec 2019 11:51:05 -0500 Subject: [PATCH] PR c++/92774 - ICE with implicitly deleted operator<=>. 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. * method.c (comp_info::~comp_info): Factor out of... (build_comparison_op): Here. Handle error return from build_new_op. From-SVN: r279235 --- gcc/cp/ChangeLog | 4 +++ gcc/cp/method.c | 33 ++++++++++++------- .../g++.dg/cpp2a/spaceship-synth-neg2.C | 25 ++++++++++++++ 3 files changed, 50 insertions(+), 12 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/spaceship-synth-neg2.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 4cb79b2c24e..6daee41c5d1 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,9 @@ 2019-12-11 Jason Merrill + PR c++/92774 - ICE with implicitly deleted operator<=>. + * method.c (comp_info::~comp_info): Factor out of... + (build_comparison_op): Here. Handle error return from build_new_op. + PR c++/92859 - ADL and bit-field. * name-lookup.c: Use unlowered_expr_type. 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 + +template +struct X { }; + +template +bool operator==(const X&, const X&) { return true; } +template +bool operator<(const X&, const X&) { return true; } + +struct Y +{ + int a; + X c; + + auto operator <=>(Y const&) const = default; // { dg-error "no match" } +}; + +void f() +{ + auto x = Y() < Y(); // { dg-error "deleted" } +} -- 2.30.2