On Thu, 3 Feb 2022, Jason Merrill wrote: > On 2/3/22 14:58, Patrick Palka wrote: > > When synthesizing a defaulted comparison op from > > maybe_instantiate_noexcept, we seem to be forgetting to instantiate the > > noexcept-spec afterwards. > > Hmm, there shouldn't be any need to instantiate the noexcept-spec afterwards, > it should have been set by ~comp_info.
It appears the comp_info class sets the noexcept-spec only if the comparison function hasn't been declared with an explicit noexcept-spec. Otherwise the class doesn't touch the noexcept-spec, and it remains a DEFERRED_NOEXCEPT with non-NULL DEFERRED_NOEXCEPT_PATTERN. > > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for > > trunk and perhaps 11? > > > > PR c++/96242 > > > > gcc/cp/ChangeLog: > > > > * pt.cc (maybe_instantiate_noexcept): Keep going after > > successfully synthesizing a DECL_MAYBE_DELETED fn. > > > > gcc/testsuite/ChangeLog: > > > > * g++.dg/cpp2a/spaceship-synth15.C: New test. > > --- > > gcc/cp/pt.cc | 3 ++- > > .../g++.dg/cpp2a/spaceship-synth15.C | 22 +++++++++++++++++++ > > 2 files changed, 24 insertions(+), 1 deletion(-) > > create mode 100644 gcc/testsuite/g++.dg/cpp2a/spaceship-synth15.C > > > > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc > > index 6dd64101ced..03345ed3ed3 100644 > > --- a/gcc/cp/pt.cc > > +++ b/gcc/cp/pt.cc > > @@ -25986,7 +25986,8 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t > > complain) > > ++function_depth; > > maybe_synthesize_method (fn); > > --function_depth; > > - return !DECL_MAYBE_DELETED (fn); > > + if (DECL_MAYBE_DELETED (fn)) > > + return false; > > } > > tree fntype = TREE_TYPE (fn); > > diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-synth15.C > > b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth15.C > > new file mode 100644 > > index 00000000000..00ea6c10474 > > --- /dev/null > > +++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth15.C > > @@ -0,0 +1,22 @@ > > +// PR c++/96242 > > +// { dg-do compile { target c++20 } } > > + > > +#include <compare> > > + > > +template<bool B> > > +struct X { > > + auto operator<=>(const X&) const noexcept(B) = default; > > + bool operator==(const X&) const noexcept(!B) = default; > > +}; > > + > > +X<true> x_t; > > +static_assert(noexcept(x_t <=> x_t)); > > +static_assert(noexcept(x_t < x_t)); > > +static_assert(!noexcept(x_t == x_t)); > > +static_assert(!noexcept(x_t != x_t)); > > + > > +X<false> x_f; > > +static_assert(!noexcept(x_f <=> x_f)); > > +static_assert(!noexcept(x_f < x_f)); > > +static_assert(noexcept(x_f == x_f)); > > +static_assert(noexcept(x_f != x_f)); > >