xref: /llvm-project/clang/test/CodeGenCXX/uncopyable-args.cpp (revision 1b9a6e58a8b831193c9e5e733f881aabe0d2d06b)
1 // RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=NEWABI
2 // RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown -fclang-abi-compat=4.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=OLDABI
3 // RUN: %clang_cc1 -std=c++11 -triple x86_64-scei-ps4 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=OLDABI
4 // RUN: %clang_cc1 -std=c++11 -triple x86_64-sie-ps5  -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=NEWABI
5 // RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-msvc -emit-llvm -o - %s -fms-compatibility -fms-compatibility-version=18 | FileCheck %s -check-prefix=WIN64 -check-prefix=WIN64-18
6 // RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-msvc -emit-llvm -o - %s -fms-compatibility -fms-compatibility-version=19 | FileCheck %s -check-prefix=WIN64 -check-prefix=WIN64-19
7 
8 namespace trivial {
9 // Trivial structs should be passed directly.
10 struct A {
11   void *p;
12 };
13 void foo(A);
bar()14 void bar() {
15   foo({});
16 }
17 // CHECK-LABEL: define{{.*}} void @_ZN7trivial3barEv()
18 // CHECK: alloca %"struct.trivial::A"
19 // CHECK: load ptr, ptr
20 // CHECK: call void @_ZN7trivial3fooENS_1AE(ptr %{{.*}})
21 // CHECK-LABEL: declare void @_ZN7trivial3fooENS_1AE(ptr)
22 
23 // WIN64-LABEL: declare dso_local void @"?foo@trivial@@YAXUA@1@@Z"(i64)
24 }
25 
26 namespace default_ctor {
27 struct A {
28   A();
29   void *p;
30 };
31 void foo(A);
bar()32 void bar() {
33   // Core issue 1590.  We can pass this type in registers, even though C++
34   // normally doesn't permit copies when using braced initialization.
35   foo({});
36 }
37 // CHECK-LABEL: define{{.*}} void @_ZN12default_ctor3barEv()
38 // CHECK: alloca %"struct.default_ctor::A"
39 // CHECK: call void @_Z{{.*}}C1Ev(
40 // CHECK: load ptr, ptr
41 // CHECK: call void @_ZN12default_ctor3fooENS_1AE(ptr %{{.*}})
42 // CHECK-LABEL: declare void @_ZN12default_ctor3fooENS_1AE(ptr)
43 
44 // WIN64-LABEL: declare dso_local void @"?foo@default_ctor@@YAXUA@1@@Z"(i64)
45 }
46 
47 namespace move_ctor {
48 // The presence of a move constructor implicitly deletes the trivial copy ctor
49 // and means that we have to pass this struct by address.
50 struct A {
51   A();
52   A(A &&o);
53   void *p;
54 };
55 void foo(A);
bar()56 void bar() {
57   foo({});
58 }
59 // CHECK-LABEL: define{{.*}} void @_ZN9move_ctor3barEv()
60 // CHECK: call void @_Z{{.*}}C1Ev(
61 // CHECK-NOT: call
62 // NEWABI: call void @_ZN9move_ctor3fooENS_1AE(ptr noundef %{{.*}})
63 // OLDABI: call void @_ZN9move_ctor3fooENS_1AE(ptr %{{.*}})
64 // NEWABI-LABEL: declare void @_ZN9move_ctor3fooENS_1AE(ptr noundef)
65 // OLDABI-LABEL: declare void @_ZN9move_ctor3fooENS_1AE(ptr)
66 
67 // WIN64-LABEL: declare dso_local void @"?foo@move_ctor@@YAXUA@1@@Z"(ptr noundef)
68 }
69 
70 namespace all_deleted {
71 struct A {
72   A();
73   A(const A &o) = delete;
74   A(A &&o) = delete;
75   void *p;
76 };
77 void foo(A);
bar()78 void bar() {
79   foo({});
80 }
81 // CHECK-LABEL: define{{.*}} void @_ZN11all_deleted3barEv()
82 // CHECK: call void @_Z{{.*}}C1Ev(
83 // CHECK-NOT: call
84 // NEWABI: call void @_ZN11all_deleted3fooENS_1AE(ptr noundef %{{.*}})
85 // OLDABI: call void @_ZN11all_deleted3fooENS_1AE(ptr %{{.*}})
86 // NEWABI-LABEL: declare void @_ZN11all_deleted3fooENS_1AE(ptr noundef)
87 // OLDABI-LABEL: declare void @_ZN11all_deleted3fooENS_1AE(ptr)
88 
89 // WIN64-LABEL: declare dso_local void @"?foo@all_deleted@@YAXUA@1@@Z"(ptr noundef)
90 }
91 
92 namespace implicitly_deleted {
93 struct A {
94   A();
95   A &operator=(A &&o);
96   void *p;
97 };
98 void foo(A);
bar()99 void bar() {
100   foo({});
101 }
102 // CHECK-LABEL: define{{.*}} void @_ZN18implicitly_deleted3barEv()
103 // CHECK: call void @_Z{{.*}}C1Ev(
104 // CHECK-NOT: call
105 // NEWABI: call void @_ZN18implicitly_deleted3fooENS_1AE(ptr noundef %{{.*}})
106 // OLDABI: call void @_ZN18implicitly_deleted3fooENS_1AE(ptr %{{.*}})
107 // NEWABI-LABEL: declare void @_ZN18implicitly_deleted3fooENS_1AE(ptr noundef)
108 // OLDABI-LABEL: declare void @_ZN18implicitly_deleted3fooENS_1AE(ptr)
109 
110 // In MSVC 2013, the copy ctor is not deleted by a move assignment. In MSVC 2015, it is.
111 // WIN64-18-LABEL: declare dso_local void @"?foo@implicitly_deleted@@YAXUA@1@@Z"(i64
112 // WIN64-19-LABEL: declare dso_local void @"?foo@implicitly_deleted@@YAXUA@1@@Z"(ptr noundef)
113 }
114 
115 namespace one_deleted {
116 struct A {
117   A();
118   A(A &&o) = delete;
119   void *p;
120 };
121 void foo(A);
bar()122 void bar() {
123   foo({});
124 }
125 // CHECK-LABEL: define{{.*}} void @_ZN11one_deleted3barEv()
126 // CHECK: call void @_Z{{.*}}C1Ev(
127 // CHECK-NOT: call
128 // NEWABI: call void @_ZN11one_deleted3fooENS_1AE(ptr noundef %{{.*}})
129 // OLDABI: call void @_ZN11one_deleted3fooENS_1AE(ptr %{{.*}})
130 // NEWABI-LABEL: declare void @_ZN11one_deleted3fooENS_1AE(ptr noundef)
131 // OLDABI-LABEL: declare void @_ZN11one_deleted3fooENS_1AE(ptr)
132 
133 // WIN64-LABEL: declare dso_local void @"?foo@one_deleted@@YAXUA@1@@Z"(ptr noundef)
134 }
135 
136 namespace copy_defaulted {
137 struct A {
138   A();
139   A(const A &o) = default;
140   A(A &&o) = delete;
141   void *p;
142 };
143 void foo(A);
bar()144 void bar() {
145   foo({});
146 }
147 // CHECK-LABEL: define{{.*}} void @_ZN14copy_defaulted3barEv()
148 // CHECK: call void @_Z{{.*}}C1Ev(
149 // CHECK: load ptr, ptr
150 // CHECK: call void @_ZN14copy_defaulted3fooENS_1AE(ptr %{{.*}})
151 // CHECK-LABEL: declare void @_ZN14copy_defaulted3fooENS_1AE(ptr)
152 
153 // WIN64-LABEL: declare dso_local void @"?foo@copy_defaulted@@YAXUA@1@@Z"(i64)
154 }
155 
156 namespace move_defaulted {
157 struct A {
158   A();
159   A(const A &o) = delete;
160   A(A &&o) = default;
161   void *p;
162 };
163 void foo(A);
bar()164 void bar() {
165   foo({});
166 }
167 // CHECK-LABEL: define{{.*}} void @_ZN14move_defaulted3barEv()
168 // CHECK: call void @_Z{{.*}}C1Ev(
169 // CHECK: load ptr, ptr
170 // CHECK: call void @_ZN14move_defaulted3fooENS_1AE(ptr %{{.*}})
171 // CHECK-LABEL: declare void @_ZN14move_defaulted3fooENS_1AE(ptr)
172 
173 // WIN64-LABEL: declare dso_local void @"?foo@move_defaulted@@YAXUA@1@@Z"(ptr noundef)
174 }
175 
176 namespace trivial_defaulted {
177 struct A {
178   A();
179   A(const A &o) = default;
180   void *p;
181 };
182 void foo(A);
bar()183 void bar() {
184   foo({});
185 }
186 // CHECK-LABEL: define{{.*}} void @_ZN17trivial_defaulted3barEv()
187 // CHECK: call void @_Z{{.*}}C1Ev(
188 // CHECK: load ptr, ptr
189 // CHECK: call void @_ZN17trivial_defaulted3fooENS_1AE(ptr %{{.*}})
190 // CHECK-LABEL: declare void @_ZN17trivial_defaulted3fooENS_1AE(ptr)
191 
192 // WIN64-LABEL: declare dso_local void @"?foo@trivial_defaulted@@YAXUA@1@@Z"(i64)
193 }
194 
195 namespace two_copy_ctors {
196 struct A {
197   A();
198   A(const A &) = default;
199   A(const A &, int = 0);
200   void *p;
201 };
202 struct B : A {};
203 
204 void foo(B);
bar()205 void bar() {
206   foo({});
207 }
208 // CHECK-LABEL: define{{.*}} void @_ZN14two_copy_ctors3barEv()
209 // CHECK: call void @_Z{{.*}}C1Ev(
210 // NEWABI: call void @_ZN14two_copy_ctors3fooENS_1BE(ptr noundef %{{.*}})
211 // OLDABI: call void @_ZN14two_copy_ctors3fooENS_1BE(ptr noundef byval
212 // NEWABI-LABEL: declare void @_ZN14two_copy_ctors3fooENS_1BE(ptr noundef)
213 // OLDABI-LABEL: declare void @_ZN14two_copy_ctors3fooENS_1BE(ptr noundef byval
214 
215 // WIN64-LABEL: declare dso_local void @"?foo@two_copy_ctors@@YAXUB@1@@Z"(ptr noundef)
216 }
217 
218 namespace definition_only {
219 struct A {
220   A();
221   A(A &&o);
222   void *p;
223 };
foo(A a)224 void *foo(A a) { return a.p; }
225 // NEWABI-LABEL: define{{.*}} ptr @_ZN15definition_only3fooENS_1AE(ptr
226 // OLDABI-LABEL: define{{.*}} ptr @_ZN15definition_only3fooENS_1AE(ptr
227 // WIN64-LABEL: define dso_local noundef ptr @"?foo@definition_only@@YAPEAXUA@1@@Z"(ptr
228 }
229 
230 namespace deleted_by_member {
231 struct B {
232   B();
233   B(B &&o);
234   void *p;
235 };
236 struct A {
237   A();
238   B b;
239 };
foo(A a)240 void *foo(A a) { return a.b.p; }
241 // NEWABI-LABEL: define{{.*}} ptr @_ZN17deleted_by_member3fooENS_1AE(ptr
242 // OLDABI-LABEL: define{{.*}} ptr @_ZN17deleted_by_member3fooENS_1AE(ptr
243 // WIN64-LABEL: define dso_local noundef ptr @"?foo@deleted_by_member@@YAPEAXUA@1@@Z"(ptr
244 }
245 
246 namespace deleted_by_base {
247 struct B {
248   B();
249   B(B &&o);
250   void *p;
251 };
252 struct A : B {
253   A();
254 };
foo(A a)255 void *foo(A a) { return a.p; }
256 // NEWABI-LABEL: define{{.*}} ptr @_ZN15deleted_by_base3fooENS_1AE(ptr
257 // OLDABI-LABEL: define{{.*}} ptr @_ZN15deleted_by_base3fooENS_1AE(ptr
258 // WIN64-LABEL: define dso_local noundef ptr @"?foo@deleted_by_base@@YAPEAXUA@1@@Z"(ptr
259 }
260 
261 namespace deleted_by_member_copy {
262 struct B {
263   B();
264   B(const B &o) = delete;
265   void *p;
266 };
267 struct A {
268   A();
269   B b;
270 };
foo(A a)271 void *foo(A a) { return a.b.p; }
272 // NEWABI-LABEL: define{{.*}} ptr @_ZN22deleted_by_member_copy3fooENS_1AE(ptr
273 // OLDABI-LABEL: define{{.*}} ptr @_ZN22deleted_by_member_copy3fooENS_1AE(ptr
274 // WIN64-LABEL: define dso_local noundef ptr @"?foo@deleted_by_member_copy@@YAPEAXUA@1@@Z"(ptr
275 }
276 
277 namespace deleted_by_base_copy {
278 struct B {
279   B();
280   B(const B &o) = delete;
281   void *p;
282 };
283 struct A : B {
284   A();
285 };
foo(A a)286 void *foo(A a) { return a.p; }
287 // NEWABI-LABEL: define{{.*}} ptr @_ZN20deleted_by_base_copy3fooENS_1AE(ptr
288 // OLDABI-LABEL: define{{.*}} ptr @_ZN20deleted_by_base_copy3fooENS_1AE(ptr
289 // WIN64-LABEL: define dso_local noundef ptr @"?foo@deleted_by_base_copy@@YAPEAXUA@1@@Z"(ptr
290 }
291 
292 namespace explicit_delete {
293 struct A {
294   A();
295   A(const A &o) = delete;
296   void *p;
297 };
298 // NEWABI-LABEL: define{{.*}} ptr @_ZN15explicit_delete3fooENS_1AE(ptr
299 // OLDABI-LABEL: define{{.*}} ptr @_ZN15explicit_delete3fooENS_1AE(ptr
300 // WIN64-LABEL: define dso_local noundef ptr @"?foo@explicit_delete@@YAPEAXUA@1@@Z"(ptr
foo(A a)301 void *foo(A a) { return a.p; }
302 }
303 
304 namespace implicitly_deleted_copy_ctor {
305 struct A {
306   // No move ctor due to copy assignment.
307   A &operator=(const A&);
308   // Deleted copy ctor due to rvalue ref member.
309   int &&ref;
310 };
311 // NEWABI-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1AE(ptr
312 // OLDABI-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1AE(ptr
313 // WIN64-LABEL: define {{.*}} @"?foo@implicitly_deleted_copy_ctor@@YAAEAHUA@1@@Z"(ptr
foo(A a)314 int &foo(A a) { return a.ref; }
315 
316 struct B {
317   // Passed direct: has non-deleted trivial copy ctor.
318   B &operator=(const B&);
319   int &ref;
320 };
foo(B b)321 int &foo(B b) { return b.ref; }
322 // CHECK-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1BE(ptr
323 // WIN64-LABEL: define {{.*}} @"?foo@implicitly_deleted_copy_ctor@@YAAEAHUB@1@@Z"(i64
324 
325 struct X { X(const X&); };
326 struct Y { Y(const Y&) = default; };
327 
328 union C {
329   C &operator=(const C&);
330   // Passed indirect: copy ctor deleted due to variant member with nontrivial copy ctor.
331   X x;
332   int n;
333 };
foo(C c)334 int foo(C c) { return c.n; }
335 // CHECK-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1CE(ptr
336 // WIN64-LABEL: define {{.*}} @"?foo@implicitly_deleted_copy_ctor@@YAHTC@1@@Z"(ptr
337 
338 struct D {
339   D &operator=(const D&);
340   // Passed indirect: copy ctor deleted due to variant member with nontrivial copy ctor.
341   union {
342     X x;
343     int n;
344   };
345 };
foo(D d)346 int foo(D d) { return d.n; }
347 // CHECK-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1DE(ptr
348 // WIN64-LABEL: define {{.*}} @"?foo@implicitly_deleted_copy_ctor@@YAHUD@1@@Z"(ptr
349 
350 union E {
351   // Passed direct: has non-deleted trivial copy ctor.
352   E &operator=(const E&);
353   Y y;
354   int n;
355 };
foo(E e)356 int foo(E e) { return e.n; }
357 // CHECK-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1EE(i32
358 // WIN64-LABEL: define {{.*}} @"?foo@implicitly_deleted_copy_ctor@@YAHTE@1@@Z"(i32
359 
360 struct F {
361   // Passed direct: has non-deleted trivial copy ctor.
362   F &operator=(const F&);
363   union {
364     Y y;
365     int n;
366   };
367 };
foo(F f)368 int foo(F f) { return f.n; }
369 // CHECK-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1FE(i32
370 // WIN64-LABEL: define {{.*}} @"?foo@implicitly_deleted_copy_ctor@@YAHUF@1@@Z"(i32
371 }
372