1 // This test is for the [class.compare.default]p3 added by P2002R0 2 // Also covers modifications made by P2448R2 3 4 // RUN: %clang_cc1 -std=c++2a -verify=expected,cxx2a %s 5 // RUN: %clang_cc1 -std=c++23 -verify=expected %s 6 7 namespace std { 8 struct strong_ordering { 9 int n; operator intstd::strong_ordering10 constexpr operator int() const { return n; } 11 static const strong_ordering less, equal, greater; 12 }; 13 constexpr strong_ordering strong_ordering::less = {-1}; 14 constexpr strong_ordering strong_ordering::equal = {0}; 15 constexpr strong_ordering strong_ordering::greater = {1}; 16 } 17 18 struct A { 19 friend bool operator==(const A&, const A&) = default; 20 friend bool operator!=(const A&, const A&) = default; 21 22 friend std::strong_ordering operator<=>(const A&, const A&) = default; 23 friend bool operator<(const A&, const A&) = default; 24 friend bool operator<=(const A&, const A&) = default; 25 friend bool operator>(const A&, const A&) = default; 26 friend bool operator>=(const A&, const A&) = default; 27 }; 28 struct TestA { 29 friend constexpr bool operator==(const A&, const A&) noexcept; 30 friend constexpr bool operator!=(const A&, const A&) noexcept; 31 32 friend constexpr std::strong_ordering operator<=>(const A&, const A&) noexcept; 33 friend constexpr bool operator<(const A&, const A&); 34 friend constexpr bool operator<=(const A&, const A&); 35 friend constexpr bool operator>(const A&, const A&); 36 friend constexpr bool operator>=(const A&, const A&); 37 }; 38 39 // Declaration order doesn't matter, even though the secondary operators need 40 // to know whether the primary ones are constexpr. 41 struct ReversedA { 42 friend bool operator>=(const ReversedA&, const ReversedA&) = default; 43 friend bool operator>(const ReversedA&, const ReversedA&) = default; 44 friend bool operator<=(const ReversedA&, const ReversedA&) = default; 45 friend bool operator<(const ReversedA&, const ReversedA&) = default; 46 friend std::strong_ordering operator<=>(const ReversedA&, const ReversedA&) = default; 47 48 friend bool operator!=(const ReversedA&, const ReversedA&) = default; 49 friend bool operator==(const ReversedA&, const ReversedA&) = default; 50 }; 51 struct TestReversedA { 52 friend constexpr bool operator>=(const ReversedA&, const ReversedA&); 53 friend constexpr bool operator>(const ReversedA&, const ReversedA&); 54 friend constexpr bool operator<=(const ReversedA&, const ReversedA&); 55 friend constexpr bool operator<(const ReversedA&, const ReversedA&); 56 friend constexpr std::strong_ordering operator<=>(const ReversedA&, const ReversedA&) noexcept; 57 58 friend constexpr bool operator!=(const ReversedA&, const ReversedA&) noexcept; 59 friend constexpr bool operator==(const ReversedA&, const ReversedA&) noexcept; 60 }; 61 62 struct B { 63 A a; 64 friend bool operator==(const B&, const B&) = default; 65 friend bool operator!=(const B&, const B&) = default; 66 67 friend std::strong_ordering operator<=>(const B&, const B&) = default; 68 friend bool operator<(const B&, const B&) = default; 69 friend bool operator<=(const B&, const B&) = default; 70 friend bool operator>(const B&, const B&) = default; 71 friend bool operator>=(const B&, const B&) = default; 72 }; 73 struct TestB { 74 friend constexpr bool operator==(const B&, const B&) noexcept; 75 friend constexpr bool operator!=(const B&, const B&) noexcept; 76 77 friend constexpr std::strong_ordering operator<=>(const B&, const B&); 78 friend constexpr bool operator<(const B&, const B&); 79 friend constexpr bool operator<=(const B&, const B&); 80 friend constexpr bool operator>(const B&, const B&); 81 friend constexpr bool operator>=(const B&, const B&); 82 }; 83 84 struct C { 85 friend bool operator==(const C&, const C&); // expected-note {{previous}} \ 86 // cxx2a-note 2{{declared here}} 87 friend bool operator!=(const C&, const C&) = default; // expected-note {{previous}} 88 89 friend std::strong_ordering operator<=>(const C&, const C&); // expected-note {{previous}} \ 90 // cxx2a-note 2{{declared here}} 91 friend bool operator<(const C&, const C&) = default; // expected-note {{previous}} 92 friend bool operator<=(const C&, const C&) = default; // expected-note {{previous}} 93 friend bool operator>(const C&, const C&) = default; // expected-note {{previous}} 94 friend bool operator>=(const C&, const C&) = default; // expected-note {{previous}} 95 }; 96 struct TestC { 97 friend constexpr bool operator==(const C&, const C&); // expected-error {{non-constexpr}} 98 friend constexpr bool operator!=(const C&, const C&); // expected-error {{non-constexpr}} 99 100 friend constexpr std::strong_ordering operator<=>(const C&, const C&); // expected-error {{non-constexpr}} 101 friend constexpr bool operator<(const C&, const C&); // expected-error {{non-constexpr}} 102 friend constexpr bool operator<=(const C&, const C&); // expected-error {{non-constexpr}} 103 friend constexpr bool operator>(const C&, const C&); // expected-error {{non-constexpr}} 104 friend constexpr bool operator>=(const C&, const C&); // expected-error {{non-constexpr}} 105 }; 106 107 struct D { 108 A a; 109 C c; 110 A b; 111 friend bool operator==(const D&, const D&) = default; // expected-note {{previous}} 112 friend bool operator!=(const D&, const D&) = default; // expected-note {{previous}} 113 114 friend std::strong_ordering operator<=>(const D&, const D&) = default; // expected-note {{previous}} 115 friend bool operator<(const D&, const D&) = default; // expected-note {{previous}} 116 friend bool operator<=(const D&, const D&) = default; // expected-note {{previous}} 117 friend bool operator>(const D&, const D&) = default; // expected-note {{previous}} 118 friend bool operator>=(const D&, const D&) = default; // expected-note {{previous}} 119 }; 120 struct TestD { 121 friend constexpr bool operator==(const D&, const D&); // expected-error {{non-constexpr}} 122 friend constexpr bool operator!=(const D&, const D&); // expected-error {{non-constexpr}} 123 124 friend constexpr std::strong_ordering operator<=>(const D&, const D&); // expected-error {{non-constexpr}} 125 friend constexpr bool operator<(const D&, const D&); // expected-error {{non-constexpr}} 126 friend constexpr bool operator<=(const D&, const D&); // expected-error {{non-constexpr}} 127 friend constexpr bool operator>(const D&, const D&); // expected-error {{non-constexpr}} 128 friend constexpr bool operator>=(const D&, const D&); // expected-error {{non-constexpr}} 129 }; 130 131 132 struct E { 133 A a; 134 C c; // cxx2a-note 2{{non-constexpr comparison function would be used to compare member 'c'}} 135 A b; 136 friend constexpr bool operator==(const E&, const E&) = default; // cxx2a-error {{cannot be declared constexpr}} 137 friend constexpr bool operator!=(const E&, const E&) = default; 138 139 friend constexpr std::strong_ordering operator<=>(const E&, const E&) = default; // cxx2a-error {{cannot be declared constexpr}} 140 friend constexpr bool operator<(const E&, const E&) = default; 141 friend constexpr bool operator<=(const E&, const E&) = default; 142 friend constexpr bool operator>(const E&, const E&) = default; 143 friend constexpr bool operator>=(const E&, const E&) = default; 144 }; 145 146 struct E2 : A, C { // cxx2a-note 2{{non-constexpr comparison function would be used to compare base class 'C'}} 147 friend constexpr bool operator==(const E2&, const E2&) = default; // cxx2a-error {{cannot be declared constexpr}} 148 friend constexpr bool operator!=(const E2&, const E2&) = default; 149 150 friend constexpr std::strong_ordering operator<=>(const E2&, const E2&) = default; // cxx2a-error {{cannot be declared constexpr}} 151 friend constexpr bool operator<(const E2&, const E2&) = default; 152 friend constexpr bool operator<=(const E2&, const E2&) = default; 153 friend constexpr bool operator>(const E2&, const E2&) = default; 154 friend constexpr bool operator>=(const E2&, const E2&) = default; 155 }; 156 157 struct F { 158 friend bool operator==(const F&, const F&); // cxx2a-note {{declared here}} 159 friend constexpr bool operator!=(const F&, const F&) = default; // cxx2a-error {{cannot be declared constexpr}} 160 161 friend std::strong_ordering operator<=>(const F&, const F&); // cxx2a-note 4{{non-constexpr comparison function declared here}} 162 friend constexpr bool operator<(const F&, const F&) = default; // cxx2a-error {{cannot be declared constexpr}} 163 friend constexpr bool operator<=(const F&, const F&) = default; // cxx2a-error {{cannot be declared constexpr}} 164 friend constexpr bool operator>(const F&, const F&) = default; // cxx2a-error {{cannot be declared constexpr}} 165 friend constexpr bool operator>=(const F&, const F&) = default; // cxx2a-error {{cannot be declared constexpr}} 166 }; 167 168 // No implicit 'constexpr' if it's not the first declaration. 169 // FIXME: This rule creates problems for reordering of declarations; is this 170 // really the right model? 171 struct G; 172 bool operator==(const G&, const G&); // expected-note {{previous declaration}} 173 bool operator!=(const G&, const G&); // expected-note {{previous declaration}} 174 std::strong_ordering operator<=>(const G&, const G&); // expected-note {{previous declaration}} 175 bool operator<(const G&, const G&); // expected-note {{previous declaration}} 176 bool operator<=(const G&, const G&); // expected-note {{previous declaration}} 177 bool operator>(const G&, const G&); // expected-note {{previous declaration}} 178 bool operator>=(const G&, const G&); // expected-note {{previous declaration}} 179 struct G { 180 friend bool operator==(const G&, const G&) = default; // expected-error {{because it was already declared outside}} 181 friend bool operator!=(const G&, const G&) = default; // expected-error {{because it was already declared outside}} 182 183 friend std::strong_ordering operator<=>(const G&, const G&) = default; // expected-error {{because it was already declared outside}} 184 friend bool operator<(const G&, const G&) = default; // expected-error {{because it was already declared outside}} 185 friend bool operator<=(const G&, const G&) = default; // expected-error {{because it was already declared outside}} 186 friend bool operator>(const G&, const G&) = default; // expected-error {{because it was already declared outside}} 187 friend bool operator>=(const G&, const G&) = default; // expected-error {{because it was already declared outside}} 188 }; 189 bool operator==(const G&, const G&); 190 bool operator!=(const G&, const G&); 191 192 std::strong_ordering operator<=>(const G&, const G&); 193 bool operator<(const G&, const G&); 194 bool operator<=(const G&, const G&); 195 bool operator>(const G&, const G&); 196 bool operator>=(const G&, const G&); 197 198 namespace PR44721 { operator ==(T const &,T const &)199 template <typename T> bool operator==(T const &, T const &) { return true; } operator !=(T const &,U const &)200 template <typename T, typename U> bool operator!=(T const &, U const &) { return true; } operator <=>(T const &,T const &)201 template <typename T> int operator<=>(T const &, T const &) { return 0; } 202 203 struct S { 204 friend bool operator==(const S &, const S &) = default; 205 friend bool operator<=>(const S &, const S &) = default; 206 int x; 207 }; 208 } 209