c++: Fix ICE on defaulted spaceship with pointer return type [PR94162]

The spaceship-synth-neg6.C testcase ICEs because we call cat_tag_for
on the explicit return type, but pointer types don't have
TYPE_LINKAGE_IDENTIFIER.  The patch fixes that by checking for
CLASS_TYPE_P only and also adds verification that it is in std
namespace, so we don't return non-cc_last for my_namespace::partial_ordering.

The g++.dg/cpp2a/spaceship-synth11.C testcase is from a PR that has been
fixed with r12-619-gfc178519771db508c03611cff4a1466cf67fce1d (but
not backported to 11).

2021-08-12  Jakub Jelinek  <jakub@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.
This commit is contained in:
Jakub Jelinek 2021-08-12 09:16:13 +02:00
parent c84f79e9e3
commit 9b7ab853bf
3 changed files with 42 additions and 0 deletions

View File

@ -1029,6 +1029,8 @@ is_cat (tree type, comp_cat_tag tag)
static comp_cat_tag
cat_tag_for (tree type)
{
if (!CLASS_TYPE_P (type) || !decl_in_std_namespace_p (TYPE_MAIN_DECL (type)))
return cc_last;
for (int i = 0; i < cc_last; ++i)
{
comp_cat_tag tag = (comp_cat_tag)i;

View File

@ -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'" }

View File

@ -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>;