1 // RUN: %clang_cc1 -std=c++2a -verify=both,ref %s -fcxx-exceptions
2 // RUN: %clang_cc1 -std=c++2a -verify=both,expected %s -fcxx-exceptions -fexperimental-new-constant-interpreter
5 struct strong_ordering
{ // both-note 6{{candidate}}
7 constexpr operator int() const { return n
; }
8 static const strong_ordering less
, equal
, greater
;
10 constexpr strong_ordering
strong_ordering::less
{-1},
11 strong_ordering::equal
{0}, strong_ordering::greater
{1};
13 struct weak_ordering
{
15 constexpr weak_ordering(int n
) : n(n
) {}
16 constexpr weak_ordering(strong_ordering o
) : n(o
.n
) {}
17 constexpr operator int() const { return n
; }
18 static const weak_ordering less
, equivalent
, greater
;
20 constexpr weak_ordering
weak_ordering::less
{-1},
21 weak_ordering::equivalent
{0}, weak_ordering::greater
{1};
23 struct partial_ordering
{
25 constexpr partial_ordering(double d
) : d(d
) {}
26 constexpr partial_ordering(strong_ordering o
) : d(o
.n
) {}
27 constexpr partial_ordering(weak_ordering o
) : d(o
.n
) {}
28 constexpr operator double() const { return d
; }
29 static const partial_ordering less
, equivalent
, greater
, unordered
;
31 constexpr partial_ordering
partial_ordering::less
{-1},
32 partial_ordering::equivalent
{0}, partial_ordering::greater
{1},
33 partial_ordering::unordered
{__builtin_nan("")};
35 static_assert(!(partial_ordering::unordered
< 0));
36 static_assert(!(partial_ordering::unordered
== 0));
37 static_assert(!(partial_ordering::unordered
> 0));
40 namespace Deletedness
{
42 std::strong_ordering
operator<=>(const A
&) const;
45 bool operator==(const B
&) const;
46 bool operator<(const B
&) const;
49 std::strong_ordering
operator<=>(const C
&) const = delete; // both-note 2{{deleted}}
52 bool operator==(const D1
&) const;
53 std::strong_ordering
operator<=>(int) const; // both-note 2{{function not viable}} both-note 2{{function (with reversed parameter order) not viable}}
54 bool operator<(int) const; // both-note 2{{function not viable}}
57 bool operator<(const D2
&) const;
58 std::strong_ordering
operator<=>(int) const; // both-note 2{{function not viable}} both-note 2{{function (with reversed parameter order) not viable}}
59 bool operator==(int) const; // both-note 2{{function not viable}}
62 bool operator==(const E
&) const;
63 bool operator<(const E
&) const = delete; // both-note 2{{deleted}}
66 std::strong_ordering
operator<=>(const F
&) const; // both-note 2{{candidate}}
67 std::strong_ordering
operator<=>(F
) const; // both-note 2{{candidate}}
70 bool operator==(const G1
&) const;
71 void operator<(const G1
&) const;
74 void operator==(const G2
&) const;
75 bool operator<(const G2
&) const;
78 void operator<=>(const H
&) const;
81 // both-note@#base {{deleted comparison function for base class 'C'}}
82 // both-note@#base {{no viable three-way comparison function for base class 'D1'}}
83 // both-note@#base {{three-way comparison cannot be synthesized because there is no viable function for '<' comparison}}
84 // both-note@#base {{no viable 'operator==' for base class 'D2'}}
85 // both-note@#base {{three-way comparison cannot be synthesized because there is no viable function for '==' comparison}}
86 // both-note@#base {{deleted comparison function for base class 'E'}}
87 // both-note@#base {{implied comparison for base class 'F' is ambiguous}}
88 template<typename T
> struct Cmp
: T
{ // #base
89 std::strong_ordering
operator<=>(const Cmp
&) const = default; // #cmp both-note 5{{here}}
95 Cmp
<A
>() <=> Cmp
<A
>(),
96 Cmp
<B
>() <=> Cmp
<B
>(),
97 Cmp
<C
>() <=> Cmp
<C
>(), // both-error {{deleted}}
98 Cmp
<D1
>() <=> Cmp
<D1
>(), // both-error {{deleted}}
99 Cmp
<D2
>() <=> Cmp
<D2
>(), // both-error {{deleted}}
100 Cmp
<E
>() <=> Cmp
<E
>(), // both-error {{deleted}}
101 Cmp
<F
>() <=> Cmp
<F
>(), // both-error {{deleted}}
102 // FIXME: The following three errors are not very good.
103 // both-error@#cmp {{value of type 'void' is not contextually convertible to 'bool'}}
104 Cmp
<G1
>() <=> Cmp
<G1
>(), // both-note-re {{in defaulted three-way comparison operator for '{{.*}}Cmp<{{.*}}G1>' first required here}}j
105 // both-error@#cmp {{value of type 'void' is not contextually convertible to 'bool'}}
106 Cmp
<G2
>() <=> Cmp
<G2
>(), // both-note-re {{in defaulted three-way comparison operator for '{{.*}}Cmp<{{.*}}G2>' first required here}}j
107 // both-error@#cmp {{no matching conversion for static_cast from 'void' to 'std::strong_ordering'}}
108 Cmp
<H
>() <=> Cmp
<H
>(), // both-note-re {{in defaulted three-way comparison operator for '{{.*}}Cmp<{{.*}}H>' first required here}}j
113 // both-note@#arr {{deleted comparison function for member 'arr'}}
114 // both-note@#arr {{no viable three-way comparison function for member 'arr'}}
115 // both-note@#arr {{three-way comparison cannot be synthesized because there is no viable function for '<' comparison}}
116 // both-note@#arr {{no viable 'operator==' for member 'arr'}}
117 // both-note@#arr {{three-way comparison cannot be synthesized because there is no viable function for '==' comparison}}
118 // both-note@#arr {{deleted comparison function for member 'arr'}}
119 // both-note@#arr {{implied comparison for member 'arr' is ambiguous}}
120 template<typename T
> struct CmpArray
{
122 std::strong_ordering
operator<=>(const CmpArray
&) const = default; // #cmparray both-note 5{{here}}
126 CmpArray
<A
>() <=> CmpArray
<A
>(),
127 CmpArray
<B
>() <=> CmpArray
<B
>(),
128 CmpArray
<C
>() <=> CmpArray
<C
>(), // both-error {{deleted}}
129 CmpArray
<D1
>() <=> CmpArray
<D1
>(), // both-error {{deleted}}
130 CmpArray
<D2
>() <=> CmpArray
<D2
>(), // both-error {{deleted}}
131 CmpArray
<E
>() <=> CmpArray
<E
>(), // both-error {{deleted}}
132 CmpArray
<F
>() <=> CmpArray
<F
>(), // both-error {{deleted}}
133 // FIXME: The following three errors are not very good.
134 // both-error@#cmparray {{value of type 'void' is not contextually convertible to 'bool'}}
135 CmpArray
<G1
>() <=> CmpArray
<G1
>(), // both-note-re {{in defaulted three-way comparison operator for '{{.*}}CmpArray<{{.*}}G1>' first required here}}j
136 // both-error@#cmparray {{value of type 'void' is not contextually convertible to 'bool'}}
137 CmpArray
<G2
>() <=> CmpArray
<G2
>(), // both-note-re {{in defaulted three-way comparison operator for '{{.*}}CmpArray<{{.*}}G2>' first required here}}j
138 // both-error@#cmparray {{no matching conversion for static_cast from 'void' to 'std::strong_ordering'}}
139 CmpArray
<H
>() <=> CmpArray
<H
>(), // both-note-re {{in defaulted three-way comparison operator for '{{.*}}CmpArray<{{.*}}H>' first required here}}j
147 std::strong_ordering
operator<=>(const A
&) const; // both-note {{here}}
149 bool operator==(const A
&) const;
150 bool operator<(const A
&) const;
153 A a
; // both-note {{would invoke a private 'operator<=>'}}
154 friend std::strong_ordering
operator<=>(const B
&, const B
&) = default; // both-warning {{deleted}} both-note{{replace 'default'}}
158 std::strong_ordering
operator<=>(const C
&); // not viable (not const)
159 bool operator==(const C
&) const; // both-note {{here}}
160 bool operator<(const C
&) const;
163 C c
; // both-note {{would invoke a private 'operator=='}}
164 friend std::strong_ordering
operator<=>(const D
&, const D
&) = default; // both-warning {{deleted}} both-note{{replace 'default'}}
168 namespace Synthesis
{
169 enum Result
{ False
, True
, Mu
};
171 constexpr bool toBool(Result R
) {
172 if (R
== Mu
) throw "should not ask this question";
178 constexpr bool operator==(const Val
&) const { return toBool(equal
); }
179 constexpr bool operator<(const Val
&) const { return toBool(less
); }
182 template<typename T
> struct Cmp
{
184 friend T
operator<=>(const Cmp
&, const Cmp
&) = default; // both-note {{deleted}}
187 template<typename T
> constexpr auto cmp(Result equal
, Result less
= Mu
, Result reverse_less
= Mu
) {
188 return Cmp
<T
>{equal
, less
} <=> Cmp
<T
>{Mu
, reverse_less
};
191 static_assert(cmp
<std::strong_ordering
>(True
) == 0);
192 static_assert(cmp
<std::strong_ordering
>(False
, True
) < 0);
193 static_assert(cmp
<std::strong_ordering
>(False
, False
) > 0);
195 static_assert(cmp
<std::weak_ordering
>(True
) == 0);
196 static_assert(cmp
<std::weak_ordering
>(False
, True
) < 0);
197 static_assert(cmp
<std::weak_ordering
>(False
, False
) > 0);
199 static_assert(cmp
<std::partial_ordering
>(True
) == 0);
200 static_assert(cmp
<std::partial_ordering
>(False
, True
) < 0);
201 static_assert(cmp
<std::partial_ordering
>(False
, False
, True
) > 0);
202 static_assert(!(cmp
<std::partial_ordering
>(False
, False
, False
) > 0));
203 static_assert(!(cmp
<std::partial_ordering
>(False
, False
, False
) == 0));
204 static_assert(!(cmp
<std::partial_ordering
>(False
, False
, False
) < 0));
206 // No synthesis is performed for a custom return type, even if it can be
207 // converted from a standard ordering.
208 struct custom_ordering
{
209 custom_ordering(std::strong_ordering o
);
211 void f(Cmp
<custom_ordering
> c
) {
212 c
<=> c
; // both-error {{deleted}}
216 namespace Preference
{
218 A(const A
&) = delete; // both-note {{deleted}}
219 // "usable" candidate that can't actually be called
220 friend void operator<=>(A
, A
); // both-note {{passing}}
221 // Callable candidates for synthesis not considered.
222 friend bool operator==(A
, A
);
223 friend bool operator<(A
, A
);
229 std::strong_ordering
operator<=>(const B
&) const = default; // both-error {{call to deleted constructor of 'A'}}
231 bool x
= B() < B(); // both-note {{in defaulted three-way comparison operator for 'B' first required here}}