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