xref: /llvm-project/clang/test/SemaCXX/constrained-special-member-functions.cpp (revision 0f59bee3d58f5dc7914d58aa520e65f3ba986705)
1 // RUN: %clang_cc1 -verify -std=c++20 %s
2 
3 template <int N>
4 concept C0 = (N == 0);
5 template <int N>
6 concept C1 = (N == 1);
7 template <int N>
8 concept C2 = (N == 2);
9 
10 // Checks are indexed by:
11 // Definition:
12 //  1. Explicitly defaulted definition
13 //  2. Deleted definition
14 //  3. User provided definition
15 // We have a less constrained user provided method that should not disable
16 // the (copyable) triviality of the type.
17 
18 // Note that because Clang does not implement DRs 1496 and 1734, we say some
19 // classes are trivial when the SMFs are deleted.
20 
21 template <int N>
22 struct DefaultConstructorChecker {
23     DefaultConstructorChecker() requires C0<N> = default;
24     DefaultConstructorChecker() requires C1<N> = delete;
25     DefaultConstructorChecker() requires C2<N>;
26     DefaultConstructorChecker();
27 };
28 static_assert(__is_trivially_copyable(DefaultConstructorChecker<0>));
29 static_assert(__is_trivially_copyable(DefaultConstructorChecker<1>));
30 static_assert(__is_trivially_copyable(DefaultConstructorChecker<2>));
31 static_assert(__is_trivially_copyable(DefaultConstructorChecker<3>));
32 static_assert(__is_trivial(DefaultConstructorChecker<0>));
33 // FIXME: DR1496
34 static_assert(__is_trivial(DefaultConstructorChecker<1>));
35 static_assert(!__is_trivial(DefaultConstructorChecker<2>));
36 static_assert(!__is_trivial(DefaultConstructorChecker<3>));
37 
38 template <int N>
39 struct CopyConstructorChecker {
40     CopyConstructorChecker(const CopyConstructorChecker&) requires C0<N> = default;
41     CopyConstructorChecker(const CopyConstructorChecker&) requires C1<N> = delete;
42     CopyConstructorChecker(const CopyConstructorChecker&) requires C2<N>;
43     CopyConstructorChecker(const CopyConstructorChecker&);
44 };
45 
46 static_assert(__is_trivially_copyable(CopyConstructorChecker<0>));
47 // FIXME: DR1734
48 static_assert(__is_trivially_copyable(CopyConstructorChecker<1>));
49 static_assert(!__is_trivially_copyable(CopyConstructorChecker<2>));
50 static_assert(!__is_trivially_copyable(CopyConstructorChecker<3>));
51 static_assert(!__is_trivial(CopyConstructorChecker<0>));
52 static_assert(!__is_trivial(CopyConstructorChecker<1>));
53 static_assert(!__is_trivial(CopyConstructorChecker<2>));
54 static_assert(!__is_trivial(CopyConstructorChecker<3>));
55 
56 template <int N>
57 struct MoveConstructorChecker {
58     MoveConstructorChecker(MoveConstructorChecker&&) requires C0<N> = default;
59     MoveConstructorChecker(MoveConstructorChecker&&) requires C1<N> = delete;
60     MoveConstructorChecker(MoveConstructorChecker&&) requires C2<N>;
61     MoveConstructorChecker(MoveConstructorChecker&&);
62 };
63 
64 static_assert(__is_trivially_copyable(MoveConstructorChecker<0>));
65 // FIXME: DR1734
66 static_assert(__is_trivially_copyable(MoveConstructorChecker<1>));
67 static_assert(!__is_trivially_copyable(MoveConstructorChecker<2>));
68 static_assert(!__is_trivially_copyable(MoveConstructorChecker<3>));
69 static_assert(!__is_trivial(MoveConstructorChecker<0>));
70 static_assert(!__is_trivial(MoveConstructorChecker<1>));
71 static_assert(!__is_trivial(MoveConstructorChecker<2>));
72 static_assert(!__is_trivial(MoveConstructorChecker<3>));
73 
74 template <int N>
75 struct MoveAssignmentChecker {
76     MoveAssignmentChecker& operator=(MoveAssignmentChecker&&) requires C0<N> = default;
77     MoveAssignmentChecker& operator=(MoveAssignmentChecker&&) requires C1<N> = delete;
78     MoveAssignmentChecker& operator=(MoveAssignmentChecker&&) requires C2<N>;
79     MoveAssignmentChecker& operator=(MoveAssignmentChecker&&);
80 };
81 
82 static_assert(__is_trivially_copyable(MoveAssignmentChecker<0>));
83 // FIXME: DR1734.
84 static_assert(__is_trivially_copyable(MoveAssignmentChecker<1>));
85 static_assert(!__is_trivially_copyable(MoveAssignmentChecker<2>));
86 static_assert(!__is_trivially_copyable(MoveAssignmentChecker<3>));
87 static_assert(__is_trivial(MoveAssignmentChecker<0>));
88 // FIXME: DR1734.
89 static_assert(__is_trivial(MoveAssignmentChecker<1>));
90 static_assert(!__is_trivial(MoveAssignmentChecker<2>));
91 static_assert(!__is_trivial(MoveAssignmentChecker<3>));
92 
93 template <int N>
94 struct CopyAssignmentChecker {
95     CopyAssignmentChecker& operator=(const CopyAssignmentChecker&) requires C0<N> = default;
96     CopyAssignmentChecker& operator=(const CopyAssignmentChecker&) requires C1<N> = delete;
97     CopyAssignmentChecker& operator=(const CopyAssignmentChecker&) requires C2<N>;
98     CopyAssignmentChecker& operator=(const CopyAssignmentChecker&);
99 };
100 
101 static_assert(__is_trivially_copyable(CopyAssignmentChecker<0>));
102 // FIXME: DR1734.
103 static_assert(__is_trivially_copyable(CopyAssignmentChecker<1>));
104 static_assert(!__is_trivially_copyable(CopyAssignmentChecker<2>));
105 static_assert(!__is_trivially_copyable(CopyAssignmentChecker<3>));
106 static_assert(__is_trivial(CopyAssignmentChecker<0>));
107 // FIXME: DR1734.
108 static_assert(__is_trivial(CopyAssignmentChecker<1>));
109 static_assert(!__is_trivial(CopyAssignmentChecker<2>));
110 static_assert(!__is_trivial(CopyAssignmentChecker<3>));
111 
112 
113 template <int N>
114 struct KindComparisonChecker1 {
115     KindComparisonChecker1& operator=(const KindComparisonChecker1&) requires C0<N> = default;
116     KindComparisonChecker1& operator=(KindComparisonChecker1&);
117 };
118 
119 template <int N>
120 struct KindComparisonChecker2 {
121     KindComparisonChecker2& operator=(const KindComparisonChecker2&) requires C0<N> = default;
122     const KindComparisonChecker2& operator=(KindComparisonChecker2&) const;
123 };
124 
125 template <int N>
126 struct KindComparisonChecker3 {
127     using Alias = KindComparisonChecker3;
128     Alias& operator=(const Alias&) requires C0<N> = default;
129     KindComparisonChecker3& operator=(const KindComparisonChecker3&);
130 };
131 
132 static_assert(!__is_trivial(KindComparisonChecker1<0>));
133 static_assert(!__is_trivially_copyable(KindComparisonChecker1<0>));
134 
135 static_assert(!__is_trivial(KindComparisonChecker2<0>));
136 static_assert(!__is_trivially_copyable(KindComparisonChecker2<0>));
137 
138 static_assert(__is_trivial(KindComparisonChecker3<0>));
139 static_assert(__is_trivially_copyable(KindComparisonChecker3<0>));
140 
141 template <class T>
142 concept HasA = requires(T t) {
143     { t.a() };
144 };
145 
146 template <class T>
147 concept HasAB = HasA<T> && requires(T t) {
148     { t.b() };
149 };
150 
151 template <class T>
152 concept HasAC = HasA<T> && requires(T t) {
153     { t.c() };
154 };
155 
156 template <class T>
157 concept HasABC = HasAB<T> && HasAC<T> && requires(T t) {
158     { t.c() };
159 };
160 
161 template <class T>
162 struct ComplexConstraints {
163     ComplexConstraints() requires HasABC<T> = default;
164     ComplexConstraints() requires HasAB<T>;
165     ComplexConstraints() requires HasAC<T>;
166     ComplexConstraints() requires HasA<T> = delete;
167     ComplexConstraints();
168 };
169 
170 struct A {
171     void a();
172 };
173 
174 struct AB {
175     void a();
176     void b();
177 };
178 
179 struct ABC {
180     void a();
181     void b();
182     void c();
183 };
184 
185 struct AC {
186     void a();
187     void c();
188 };
189 
190 static_assert(__is_trivial(ComplexConstraints<ABC>), "");
191 static_assert(!__is_trivial(ComplexConstraints<AB>), "");
192 static_assert(!__is_trivial(ComplexConstraints<AC>), "");
193 static_assert(__is_trivial(ComplexConstraints<A>), "");
194 static_assert(!__is_trivial(ComplexConstraints<int>), "");
195 
196 
197 // This is evaluated at the completion of CRTPBase, while `T` is not yet completed.
198 // This is probably correct behavior.
199 template <class T>
200 struct CRTPBase {
201   CRTPBase() requires (sizeof(T) > 0);
202   CRTPBase() = default;
203 };
204 
205 struct Child : CRTPBase<Child> { int x; };
206 static Child c;
207 
208 
209 namespace GH57046 {
210 template<unsigned N>
211 struct Foo {
FooGH57046::Foo212   Foo() requires (N==1) {} // expected-note {{declared here}}
213   Foo() requires (N==2) = default;
214 };
215 
216 template <unsigned N, unsigned M>
217 struct S {
218   Foo<M> data;
SGH57046::S219   S() requires (N==1) {}
220   consteval S() requires (N==2) = default; // expected-note {{non-constexpr constructor 'Foo' cannot be used in a constant expression}}
221 };
222 
func()223 void func() {
224   S<2, 1> s1; // expected-error {{is not a constant expression}} expected-note {{in call to 'S()'}}
225   S<2, 2> s2;
226 }
227 }
228 
229 namespace GH59206 {
230 
231 struct A {
232   A() = default; //eligible, second constructor unsatisfied
233   template<class... Args>
AGH59206::A234   A(Args&&... args) requires (sizeof...(Args) > 0) {}
235 };
236 
237 struct B {
238   B() = default; //ineligible, second constructor more constrained
239   template<class... Args>
BGH59206::B240   B(Args&&... args) requires (sizeof...(Args) == 0) {}
241 };
242 
243 struct C {
244   C() = default; //eligible, but
245   template<class... Args> //also eligible and non-trivial
CGH59206::C246   C(Args&&... args) {}
247 };
248 
249 struct D : B {};
250 
251 static_assert(__is_trivially_copyable(A), "");
252 static_assert(__is_trivially_copyable(B), "");
253 static_assert(__is_trivially_copyable(C), "");
254 static_assert(__is_trivially_copyable(D), "");
255 
256 // FIXME: Update when https://github.com/llvm/llvm-project/issues/59206 is
257 // resolved.
258 static_assert(!__is_trivial(A), "");
259 static_assert(!__is_trivial(B), "");
260 static_assert(!__is_trivial(C), "");
261 static_assert(__is_trivial(D), "");
262 static_assert(__is_trivially_constructible(A), "");
263 static_assert(__is_trivially_constructible(B), "");
264 static_assert(__is_trivially_constructible(C), "");
265 static_assert(__is_trivially_constructible(D), "");
266 
267 }
268 
269 namespace GH60697 {
270 
271 template <class T>
272 struct X {
273     X() requires false = default;
274 };
275 static_assert(!__is_trivial(X<int>));
276 
277 template <class T>
278 struct S {
279     S() requires(__is_trivially_constructible(T)) = default;
280 
SGH60697::S281     S() requires(!__is_trivially_constructible(T) &&
282                   __is_constructible(T)) {}
283 
284     T t;
285 };
286 
287 struct D {
DGH60697::D288     D(int i) : i(i) {}
289     int i;
290 };
291 static_assert(!__is_trivially_constructible(D));
292 static_assert(!__is_constructible(D));
293 static_assert(!__is_trivial(D));
294 
295 static_assert(!__is_trivially_constructible(S<D>));
296 static_assert(!__is_constructible(S<D>));
297 
298 static_assert(__is_trivial(S<int>));
299 static_assert(!__is_trivial(S<D>));
300 
301 }
302 
303 namespace GH62555 {
304 
305 template <bool B>
306 struct ExplicitTemplateArgs {
307     ExplicitTemplateArgs(ExplicitTemplateArgs&&) = default;
ExplicitTemplateArgsGH62555::ExplicitTemplateArgs308     ExplicitTemplateArgs(ExplicitTemplateArgs<false>&&) requires B {};
309 };
310 
311 static_assert(__is_trivially_copyable(ExplicitTemplateArgs<false>));
312 static_assert(__is_trivially_copyable(ExplicitTemplateArgs<true>));
313 
314 }
315