On Wed, Aug 11, 2021 at 09:42:56AM -0400, Jason Merrill wrote: > Checking CLASS_TYPE_P && decl_in_std_namespace (TYPE_MAIN_DECL) before > looking at the name makes sense to me.
CLASS_TYPE_P is cheap, but isn't decl_in_std_namespace, especially when it needs to walk inline namespaces, better done only if we get a match, so like below? Though I can do it even in the first if if you think it is better... 2021-08-11 Jakub Jelinek <ja...@redhat.com> gcc/cp/ PR c++/94162 * method.c (cat_tag_for): Return cc_last for !CLASS_TYPE_P or for classes not in std namespace. gcc/testsuite/ PR c++/99429 * g++.dg/cpp2a/spaceship-synth11.C: New test. PR c++/94162 * g++.dg/cpp2a/spaceship-synth-neg6.C: New test. --- gcc/cp/method.c.jj 2021-08-09 15:03:00.923206463 +0200 +++ gcc/cp/method.c 2021-08-11 15:52:27.157437691 +0200 @@ -1029,10 +1029,13 @@ is_cat (tree type, comp_cat_tag tag) static comp_cat_tag cat_tag_for (tree type) { + if (!CLASS_TYPE_P (type)) + return cc_last; for (int i = 0; i < cc_last; ++i) { comp_cat_tag tag = (comp_cat_tag)i; - if (is_cat (type, tag)) + if (is_cat (type, tag) + && decl_in_std_namespace_p (TYPE_MAIN_DECL (type))) return tag; } return cc_last; --- gcc/testsuite/g++.dg/cpp2a/spaceship-synth11.C.jj 2021-08-11 15:49:05.267204333 +0200 +++ gcc/testsuite/g++.dg/cpp2a/spaceship-synth11.C 2021-08-11 15:49:05.267204333 +0200 @@ -0,0 +1,29 @@ +// PR c++/99429 +// { dg-do compile { target c++20 } } + +namespace std { +struct strong_ordering { + int _v; + constexpr strong_ordering (int v) :_v(v) {} + constexpr operator int (void) const { return _v; } + static const strong_ordering less; + static const strong_ordering equal; + static const strong_ordering greater; +}; +constexpr strong_ordering strong_ordering::less = -1; +constexpr strong_ordering strong_ordering::equal = 0; +constexpr strong_ordering strong_ordering::greater = 1; +} + +template <unsigned long N> +struct duration { + static constexpr const long period = N; + constexpr duration (void) = default; + constexpr duration (const duration& d) = default; + constexpr bool operator== (const duration& d) const = default; + constexpr bool operator<=> (const duration& d) const = default; + long _d; +}; + +using nanoseconds = duration<1>; +using microseconds = duration<nanoseconds::period * 1000>; --- gcc/testsuite/g++.dg/cpp2a/spaceship-synth-neg6.C.jj 2021-08-11 15:49:05.268204320 +0200 +++ gcc/testsuite/g++.dg/cpp2a/spaceship-synth-neg6.C 2021-08-11 15:49:05.268204320 +0200 @@ -0,0 +1,11 @@ +// PR c++/94162 +// { dg-do compile { target c++20 } } + +#include <compare> + +struct S { + int a; // { dg-error "three-way comparison of 'S::a' has type 'std::strong_ordering', which does not convert to 'int\\*'" } + int *operator<=>(const S&) const = default; +}; + +bool b = S{} < S{}; // { dg-error "use of deleted function 'constexpr int\\* S::operator<=>\\\(const S&\\\) const'" } Jakub