1 // RUN: %clang_cc1 -std=c++2a -verify %s
2 // RUN: %clang_cc1 -std=c++2a -Wc++23-default-comp-relaxed-constexpr -verify=expected,extension %s
4 // This test is for [class.compare.default]p3 as modified and renumbered to p4
6 // Also covers modifications made by P2448R2 and extension warnings
9 struct strong_ordering
{
11 constexpr operator int() const { return n
; }
12 static const strong_ordering less
, equal
, greater
;
14 constexpr strong_ordering
strong_ordering::less
= {-1};
15 constexpr strong_ordering
strong_ordering::equal
= {0};
16 constexpr strong_ordering
strong_ordering::greater
= {1};
21 friend constexpr std::strong_ordering
operator<=>(const A
&, const A
&) = default;
24 constexpr bool (*test_a_not_found
)(const A
&, const A
&) = &operator==; // expected-error {{undeclared}}
26 constexpr bool operator==(const A
&, const A
&) noexcept
;
27 constexpr bool (*test_a
)(const A
&, const A
&) noexcept
= &operator==;
28 static_assert((*test_a
)(A(), A()));
32 virtual std::strong_ordering
operator<=>(const B1
&) const = default;
34 bool (B1::*test_b
)(const B1
&) const = &B1::operator==;
37 // OK, B1::operator== is virtual.
38 bool operator==(const B1
&) const override
;
42 std::strong_ordering
operator<=>(const B2
&) const = default;
46 bool operator==(const B2
&) const override
; // expected-error {{only virtual member functions}}
50 std::strong_ordering
operator<=>(const D
&) const;
51 virtual std::strong_ordering
operator<=>(const struct E
&) const = 0;
54 // expected-error@+2 {{only virtual member functions}}
55 // expected-note@+1 {{while declaring the corresponding implicit 'operator==' for this defaulted 'operator<=>'}}
56 std::strong_ordering
operator<=>(const E
&) const override
= default;
60 [[deprecated("oh no")]] std::strong_ordering
operator<=>(const F
&) const = default; // expected-note 4{{deprecated}}
63 void(f
<=> f
); // expected-warning {{oh no}}
64 void(f
< f
); // expected-warning {{oh no}}
65 void(f
== f
); // expected-warning {{oh no}}
66 void(f
!= f
); // expected-warning {{oh no}}
70 // expected-note@+2 {{implicitly declared private here}}
71 // expected-note-re@+1 {{{{^}}declared private here}}
72 std::strong_ordering
operator<=>(const G
&) const = default;
76 void(g
<=> g
); // expected-error {{private}}
77 void(g
== g
); // expected-error {{private}}
81 bool operator==(const H
&) const; // extension-note {{non-constexpr comparison function declared here}}
82 constexpr std::strong_ordering
operator<=>(const H
&) const { return std::strong_ordering::equal
; }
86 H h
; // extension-note {{non-constexpr comparison function would be used to compare member 'h'}}
87 constexpr std::strong_ordering
operator<=>(const I
&) const = default; // extension-warning {{implicit 'operator==' invokes a non-constexpr comparison function is a C++23 extension}}
91 std::strong_ordering
operator<=>(const J
&) const & = default; // expected-note {{candidate function (the implicit 'operator==' for this 'operator<=>)'}}
92 friend std::strong_ordering
operator<=>(const J
&, const J
&) = default; // expected-note {{candidate function (the implicit 'operator==' for this 'operator<=>)'}}
95 void(j
== j
); // expected-error {{ambiguous}}
98 namespace DeleteAfterFirstDecl
{
99 bool operator==(const struct Q
&, const struct Q
&);
102 friend std::strong_ordering
operator<=>(const X
&, const X
&);
103 } x
; // expected-note {{no viable 'operator=='}}
104 // expected-error@+1 {{defaulting the corresponding implicit 'operator==' for this defaulted 'operator<=>' would delete it after its first declaration}}
105 friend std::strong_ordering
operator<=>(const Q
&, const Q
&) = default;
109 // Note, substitution here results in the second parameter of 'operator=='
110 // referring to the first parameter of 'operator==', not to the first parameter
112 // FIXME: Find a case where this matters (attribute enable_if?).
114 friend std::strong_ordering
operator<=>(const K
&k
, decltype(k
)) = default;
116 bool test_k
= K() == K();
118 namespace NoInjectionIfOperatorEqualsDeclared
{
120 void operator==(int); // expected-note 2{{not viable}}
121 std::strong_ordering
operator<=>(const A
&) const = default;
123 bool test_a
= A() == A(); // expected-error {{invalid operands}}
126 friend void operator==(int, struct Q
); // expected-note 2{{not viable}}
127 std::strong_ordering
operator<=>(const B
&) const = default;
129 bool test_b
= B() == B(); // expected-error {{invalid operands}}
132 void operator==(int); // expected-note 2{{not viable}}
133 friend std::strong_ordering
operator<=>(const C
&, const C
&) = default;
135 bool test_c
= C() == C(); // expected-error {{invalid operands}}
139 void operator==(const D
&, int);
142 friend void operator==(const D
&, int);
144 friend std::strong_ordering
operator<=>(const D
&, const D
&) = default;
146 bool test_d
= D() == D();
150 template <typename A
> struct my_struct
{
151 A value
; // extension-note {{non-constexpr comparison function would be used to compare member 'value'}}
153 constexpr friend bool operator==(const my_struct
&, const my_struct
&) noexcept
= default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}}
156 struct non_constexpr_type
{
157 friend bool operator==(non_constexpr_type
, non_constexpr_type
) noexcept
{ // extension-note {{non-constexpr comparison function declared here}}
162 my_struct
<non_constexpr_type
> obj
; // extension-note {{in instantiation of template class 'GH61238::my_struct<GH61238::non_constexpr_type>' requested here}}