Clang Project

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