diff options
-rw-r--r-- | gcc/cp/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/cp/method.c | 33 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/spaceship-synth-neg2.C | 25 |
3 files changed, 50 insertions, 12 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 4cb79b2..6daee41 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,9 @@ 2019-12-11 Jason Merrill <jason@redhat.com> + 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 83da20a..97c27c5 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 0000000..ecc249a --- /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" } +} |