aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/g++.dg/cpp2a/spaceship-p1186.C
blob: a979fcb65dfdd603d003806a4ace5ad4eabc1d5e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// PR c++/96299
// P1186R3
// { dg-do compile { target c++20 } }

#include <compare>

struct H {
  bool operator==(H const &) const;
  bool operator<(H const &) const;
};

// Can't deduce category from op< and op==.
struct A {
  int i;
  char c;
  H h;				// { dg-error "operator<=>" }
  auto operator<=>(A const &) const = default;
};

// OK, explicit return type tells us how to interpret op</==.
struct B {
  int i;
  char c;
  H h;
  std::strong_ordering operator<=>(B const &) const = default;
};

struct C {
  bool operator<(C const &) const;
};

// C's op< isn't enough, need op== as well.
struct D {
  C c;				// { dg-error "operator<=>" }
  std::strong_ordering operator<=>(D const &) const = default;
};

struct E {
  std::partial_ordering operator<=>(E const &) const;
};

// Can't use a weak op<=> to build a strong op<=>.
struct F {
  E e;				// { dg-error "strong_ordering" }
  H h;
  std::strong_ordering operator<=>(F const &) const = default;
};

struct G {
  std::strong_ordering operator<=>(G const &) const;
};

// OK, uses op<=> for g and op</op== for h.
struct I {
  G g;
  H h;
  std::partial_ordering operator<=>(I const &) const = default;
};

template <class T>
struct J {
  T t;				// { dg-error "no match|ambiguous" }
  auto operator<=>(J const &) const = default;
};

template <class T>
struct K {
  T t;				// { dg-error "no match" }
  std::partial_ordering operator<=>(K const &) const = default;
};

template <class T>
struct M {
  T t;				// { dg-error "no match|strong_ordering" }
  std::strong_ordering operator<=>(M const &) const = default;
};

// Test that we don't fall back to </== if <=> is ambiguous.
struct N {
  bool operator==(N const &) const;
  bool operator<(N const &) const;
};
template <class T>
std::partial_ordering operator<=>(N const &, T&&);
template <class T>
std::partial_ordering operator<=>(T&&, N const &);

void
foo (A &a1, A &a2, B &b1, B &b2, D& d1, D& d2, F& f1, F& f2, I& i1, I& i2)
{
  auto a = a1 < a2;		// { dg-error "deleted" }
  auto b = b1 < b2;
  auto d = d1 < d2;		// { dg-error "deleted" }
  auto f = f1 < f2;		// { dg-error "deleted" }
  auto i = i1 < i2;

  auto j1 = J<int>() < J<int>();
  auto j2 = J<H>() < J<H>();	// { dg-error "deleted" }
  auto j3 = J<C>() < J<C>();	// { dg-error "deleted" }
  auto j4 = J<E>() < J<E>();
  auto j5 = J<G>() < J<G>();
  auto j6 = J<N>() < J<N>();	// { dg-error "deleted" }

  auto k1 = K<int>() < K<int>();
  auto k2 = K<H>() < K<H>();
  auto k3 = K<C>() < K<C>();	// { dg-error "deleted" }
  auto k4 = K<E>() < K<E>();
  auto k5 = K<G>() < K<G>();
  auto k6 = K<N>() < K<N>();	// { dg-error "deleted" }

  auto m1 = M<int>() < M<int>();
  auto m2 = M<H>() < M<H>();
  auto m3 = M<C>() < M<C>();	// { dg-error "deleted" }
  auto m4 = M<E>() < M<E>();	// { dg-error "deleted" }
  auto m5 = M<G>() < M<G>();
  auto m6 = M<N>() < M<N>();	// { dg-error "deleted" }
}