183 lines · cpp
1// RUN: %clang_cc1 -std=c++2a -verify=expected,cxx2a %s2// RUN: %clang_cc1 -std=c++23 -verify=expected %s3 4// This test is for [class.compare.default]p3 as modified and renumbered to p45// by P2002R0.6// Also covers modifications made by P2448R27 8namespace std {9 struct strong_ordering {10 int n;11 constexpr operator int() const { return n; }12 static const strong_ordering less, equal, greater;13 };14 constexpr strong_ordering strong_ordering::less = {-1};15 constexpr strong_ordering strong_ordering::equal = {0};16 constexpr strong_ordering strong_ordering::greater = {1};17}18 19namespace N {20 struct A {21 friend constexpr std::strong_ordering operator<=>(const A&, const A&) = default; // expected-note 2{{declared here}}22 };23 24 constexpr std::strong_ordering (*test_a_threeway_not_found)(const A&, const A&) = &operator<=>; // expected-error {{undeclared}}25 26 constexpr std::strong_ordering operator<=>(const A&, const A&) noexcept;27 constexpr std::strong_ordering (*test_a_threeway)(const A&, const A&) = &operator<=>;28 static_assert(!(*test_a_threeway)(A(), A())); // expected-error {{static assertion expression is not an integral constant expression}}29 // expected-note@-1 {{undefined function 'operator<=>' cannot be used in a constant expression}}30 31 constexpr bool (*test_a_equal_not_found)(const A&, const A&) = &operator==; // expected-error {{undeclared}}32 33 constexpr bool operator==(const A&, const A&) noexcept;34 constexpr bool (*test_a_equal)(const A&, const A&) noexcept = &operator==;35 static_assert((*test_a_equal)(A(), A())); // expected-error {{static assertion expression is not an integral constant expression}}36 // expected-note@-1 {{undefined function 'operator==' cannot be used in a constant expression}}37}38 39struct B1 {40 virtual std::strong_ordering operator<=>(const B1&) const = default;41};42bool (B1::*test_b)(const B1&) const = &B1::operator==;43 44struct C1 : B1 {45 // OK, B1::operator== is virtual.46 bool operator==(const B1&) const override;47};48 49struct B2 {50 std::strong_ordering operator<=>(const B2&) const = default;51};52 53struct C2 : B2 {54 bool operator==(const B2&) const override; // expected-error {{only virtual member functions}}55};56 57struct D {58 std::strong_ordering operator<=>(const D&) const;59 virtual std::strong_ordering operator<=>(const struct E&) const = 0;60};61struct E : D {62 // expected-error@+2 {{only virtual member functions}}63 // expected-note@+1 {{while declaring the corresponding implicit 'operator==' for this defaulted 'operator<=>'}}64 std::strong_ordering operator<=>(const E&) const override = default;65};66 67struct F {68 [[deprecated("oh no")]] std::strong_ordering operator<=>(const F&) const = default; // expected-note 4{{deprecated}}69};70void use_f(F f) {71 void(f <=> f); // expected-warning {{oh no}}72 void(f < f); // expected-warning {{oh no}}73 void(f == f); // expected-warning {{oh no}}74 void(f != f); // expected-warning {{oh no}}75}76 77class G {78 // expected-note@+2 {{implicitly declared private here}}79 // expected-note-re@+1 {{{{^}}declared private here}}80 std::strong_ordering operator<=>(const G&) const = default;81public:82};83void use_g(G g) {84 void(g <=> g); // expected-error {{private}}85 void(g == g); // expected-error {{private}}86}87 88struct H {89 bool operator==(const H&) const; // cxx2a-note {{non-constexpr comparison function declared here}}90 constexpr std::strong_ordering operator<=>(const H&) const { return std::strong_ordering::equal; }91};92 93struct I {94 H h; // cxx2a-note {{non-constexpr comparison function would be used to compare member 'h'}}95 constexpr std::strong_ordering operator<=>(const I&) const = default; // cxx2a-error {{cannot be declared constexpr}}96};97 98struct J {99 std::strong_ordering operator<=>(const J&) const & = default; // expected-note {{candidate function (the implicit 'operator==' for this 'operator<=>)'}}100 friend std::strong_ordering operator<=>(const J&, const J&) = default; // expected-note {{candidate function (the implicit 'operator==' for this 'operator<=>)'}}101};102void use_j(J j) {103 void(j == j); // expected-error {{ambiguous}}104}105 106namespace DeleteAfterFirstDecl {107 bool operator==(const struct Q&, const struct Q&);108 struct Q {109 struct X {110 friend std::strong_ordering operator<=>(const X&, const X&);111 } x; // expected-note {{no viable 'operator=='}}112 // expected-error@+1 {{defaulting the corresponding implicit 'operator==' for this defaulted 'operator<=>' would delete it after its first declaration}}113 friend std::strong_ordering operator<=>(const Q&, const Q&) = default;114 };115}116 117// Note, substitution here results in the second parameter of 'operator=='118// referring to the first parameter of 'operator==', not to the first parameter119// of 'operator<=>'.120// FIXME: Find a case where this matters (attribute enable_if?).121struct K {122 friend std::strong_ordering operator<=>(const K &k, decltype(k)) = default;123};124bool test_k = K() == K();125 126namespace NoInjectionIfOperatorEqualsDeclared {127 struct A {128 void operator==(int); // expected-note 2{{not viable}}129 std::strong_ordering operator<=>(const A&) const = default;130 };131 bool test_a = A() == A(); // expected-error {{invalid operands}}132 133 struct B {134 friend void operator==(int, struct Q); // expected-note 2{{not viable}}135 std::strong_ordering operator<=>(const B&) const = default;136 };137 bool test_b = B() == B(); // expected-error {{invalid operands}}138 139 struct C {140 void operator==(int); // expected-note 2{{not viable}}141 friend std::strong_ordering operator<=>(const C&, const C&) = default;142 };143 bool test_c = C() == C(); // expected-error {{invalid operands}}144 145 struct D {146 void f() {147 void operator==(const D&, int);148 }149 struct X {150 friend void operator==(const D&, int);151 };152 friend std::strong_ordering operator<=>(const D&, const D&) = default;153 };154 bool test_d = D() == D();155}156 157namespace GH61238 {158template <typename A> struct my_struct {159 A value; // cxx2a-note {{non-constexpr comparison function would be used to compare member 'value'}}160 161 constexpr friend bool operator==(const my_struct &, const my_struct &) noexcept = default; // cxx2a-error {{cannot be declared constexpr}}162};163 164struct non_constexpr_type {165 friend bool operator==(non_constexpr_type, non_constexpr_type) noexcept { // cxx2a-note {{non-constexpr comparison function declared here}}166 return false;167 }168};169 170my_struct<non_constexpr_type> obj; // cxx2a-note {{in instantiation of template class 'GH61238::my_struct<GH61238::non_constexpr_type>' requested here}}171}172 173namespace Constrained {174 template<typename T>175 struct A {176 std::strong_ordering operator<=>(const A&) const requires true = default;177 };178 179 bool f(A<int> a) {180 return a != A<int>();181 }182}183