1 // RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-linux | FileCheck -check-prefix LINUX %s
2 // RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WIN32 %s
3 // RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WIN64 %s
4 
5 struct Empty {};
6 
7 struct EmptyWithCtor {
8   EmptyWithCtor() {}
9 };
10 
11 struct Small {
12   int x;
13 };
14 
15 // This is a C++11 trivial and standard-layout struct but not a C++03 POD.
16 struct SmallCpp11NotCpp03Pod : Empty {
17   int x;
18 };
19 
20 struct SmallWithCtor {
21   SmallWithCtor() {}
22   int x;
23 };
24 
25 struct Multibyte {
26   char a, b, c, d;
27 };
28 
29 struct Packed {
30   short a;
31   int b;
32   short c;
33 };
34 
35 struct SmallWithDtor {
36   SmallWithDtor();
37   ~SmallWithDtor();
38   int x;
39 };
40 
41 struct SmallWithVftable {
42   int x;
43   virtual void foo();
44 };
45 
46 struct Medium {
47   int x, y;
48 };
49 
50 struct MediumWithCopyCtor {
51   MediumWithCopyCtor();
52   MediumWithCopyCtor(const struct MediumWithCopyCtor &);
53   int x, y;
54 };
55 
56 struct Big {
57   int a, b, c, d, e, f;
58 };
59 
60 struct BigWithDtor {
61   BigWithDtor();
62   ~BigWithDtor();
63   int a, b, c, d, e, f;
64 };
65 
66 // WIN32: declare void @"{{.*take_bools_and_chars.*}}"
67 // WIN32:       (<{ i8, [3 x i8], i8, [3 x i8], %struct.SmallWithDtor,
68 // WIN32:           i8, [3 x i8], i8, [3 x i8], i32, i8, [3 x i8] }>* inalloca)
69 void take_bools_and_chars(char a, char b, SmallWithDtor c, char d, bool e, int f, bool g);
70 void call_bools_and_chars() {
71   take_bools_and_chars('A', 'B', SmallWithDtor(), 'D', true, 13, false);
72 }
73 
74 // Returning structs that fit into a register.
75 Small small_return() { return Small(); }
76 // LINUX-LABEL: define void @_Z12small_returnv(%struct.Small* noalias sret %agg.result)
77 // WIN32: define i32 @"\01?small_return@@YA?AUSmall@@XZ"()
78 // WIN64: define i32 @"\01?small_return@@YA?AUSmall@@XZ"()
79 
80 Medium medium_return() { return Medium(); }
81 // LINUX-LABEL: define void @_Z13medium_returnv(%struct.Medium* noalias sret %agg.result)
82 // WIN32: define i64 @"\01?medium_return@@YA?AUMedium@@XZ"()
83 // WIN64: define i64 @"\01?medium_return@@YA?AUMedium@@XZ"()
84 
85 // Returning structs that fit into a register but are not POD.
86 SmallCpp11NotCpp03Pod small_non_pod_return() { return SmallCpp11NotCpp03Pod(); }
87 // LINUX-LABEL: define void @_Z20small_non_pod_returnv(%struct.SmallCpp11NotCpp03Pod* noalias sret %agg.result)
88 // WIN32: define void @"\01?small_non_pod_return@@YA?AUSmallCpp11NotCpp03Pod@@XZ"(%struct.SmallCpp11NotCpp03Pod* noalias sret %agg.result)
89 // WIN64: define void @"\01?small_non_pod_return@@YA?AUSmallCpp11NotCpp03Pod@@XZ"(%struct.SmallCpp11NotCpp03Pod* noalias sret %agg.result)
90 
91 SmallWithCtor small_with_ctor_return() { return SmallWithCtor(); }
92 // LINUX-LABEL: define void @_Z22small_with_ctor_returnv(%struct.SmallWithCtor* noalias sret %agg.result)
93 // WIN32: define void @"\01?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(%struct.SmallWithCtor* noalias sret %agg.result)
94 // WIN64: define void @"\01?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(%struct.SmallWithCtor* noalias sret %agg.result)
95 
96 SmallWithVftable small_with_vftable_return() { return SmallWithVftable(); }
97 // LINUX-LABEL: define void @_Z25small_with_vftable_returnv(%struct.SmallWithVftable* noalias sret %agg.result)
98 // WIN32: define void @"\01?small_with_vftable_return@@YA?AUSmallWithVftable@@XZ"(%struct.SmallWithVftable* noalias sret %agg.result)
99 // WIN64: define void @"\01?small_with_vftable_return@@YA?AUSmallWithVftable@@XZ"(%struct.SmallWithVftable* noalias sret %agg.result)
100 
101 MediumWithCopyCtor medium_with_copy_ctor_return() { return MediumWithCopyCtor(); }
102 // LINUX-LABEL: define void @_Z28medium_with_copy_ctor_returnv(%struct.MediumWithCopyCtor* noalias sret %agg.result)
103 // WIN32: define void @"\01?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(%struct.MediumWithCopyCtor* noalias sret %agg.result)
104 // WIN64: define void @"\01?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(%struct.MediumWithCopyCtor* noalias sret %agg.result)
105 
106 // Returning a large struct that doesn't fit into a register.
107 Big big_return() { return Big(); }
108 // LINUX-LABEL: define void @_Z10big_returnv(%struct.Big* noalias sret %agg.result)
109 // WIN32: define void @"\01?big_return@@YA?AUBig@@XZ"(%struct.Big* noalias sret %agg.result)
110 // WIN64: define void @"\01?big_return@@YA?AUBig@@XZ"(%struct.Big* noalias sret %agg.result)
111 
112 
113 void small_arg(Small s) {}
114 // LINUX-LABEL: define void @_Z9small_arg5Small(i32 %s.0)
115 // WIN32: define void @"\01?small_arg@@YAXUSmall@@@Z"(i32 %s.0)
116 // WIN64: define void @"\01?small_arg@@YAXUSmall@@@Z"(i32 %s.coerce)
117 
118 void medium_arg(Medium s) {}
119 // LINUX-LABEL: define void @_Z10medium_arg6Medium(i32 %s.0, i32 %s.1)
120 // WIN32: define void @"\01?medium_arg@@YAXUMedium@@@Z"(i32 %s.0, i32 %s.1)
121 // WIN64: define void @"\01?medium_arg@@YAXUMedium@@@Z"(i64 %s.coerce)
122 
123 void small_arg_with_ctor(SmallWithCtor s) {}
124 // LINUX-LABEL: define void @_Z19small_arg_with_ctor13SmallWithCtor(%struct.SmallWithCtor* byval align 4 %s)
125 // WIN32: define void @"\01?small_arg_with_ctor@@YAXUSmallWithCtor@@@Z"(i32 %s.0)
126 // WIN64: define void @"\01?small_arg_with_ctor@@YAXUSmallWithCtor@@@Z"(i32 %s.coerce)
127 
128 // FIXME: We could coerce to a series of i32s here if we wanted to.
129 void multibyte_arg(Multibyte s) {}
130 // LINUX-LABEL: define void @_Z13multibyte_arg9Multibyte(%struct.Multibyte* byval align 4 %s)
131 // WIN32: define void @"\01?multibyte_arg@@YAXUMultibyte@@@Z"(%struct.Multibyte* byval align 4 %s)
132 // WIN64: define void @"\01?multibyte_arg@@YAXUMultibyte@@@Z"(i32 %s.coerce)
133 
134 void packed_arg(Packed s) {}
135 // LINUX-LABEL: define void @_Z10packed_arg6Packed(%struct.Packed* byval align 4 %s)
136 // WIN32: define void @"\01?packed_arg@@YAXUPacked@@@Z"(%struct.Packed* byval align 4 %s)
137 // WIN64: define void @"\01?packed_arg@@YAXUPacked@@@Z"(%struct.Packed* %s)
138 
139 // Test that dtors are invoked in the callee.
140 void small_arg_with_dtor(SmallWithDtor s) {}
141 // WIN32: define void @"\01?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(<{ %struct.SmallWithDtor }>* inalloca) {{.*}} {
142 // WIN32:   call x86_thiscallcc void @"\01??1SmallWithDtor@@QAE@XZ"
143 // WIN32: }
144 // WIN64: define void @"\01?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i32 %s.coerce) {{.*}} {
145 // WIN64:   call void @"\01??1SmallWithDtor@@QEAA@XZ"
146 // WIN64: }
147 
148 void call_small_arg_with_dtor() {
149   small_arg_with_dtor(SmallWithDtor());
150 }
151 // The temporary is copied, so it's destroyed in the caller as well as the
152 // callee.
153 // WIN64-LABEL: define void @"\01?call_small_arg_with_dtor@@YAXXZ"()
154 // WIN64:   call %struct.SmallWithDtor* @"\01??0SmallWithDtor@@QEAA@XZ"
155 // WIN64:   call void @"\01?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i32 %{{.*}})
156 // WIN64:   call void @"\01??1SmallWithDtor@@QEAA@XZ"
157 // WIN64:   ret void
158 
159 // Test that references aren't destroyed in the callee.
160 void ref_small_arg_with_dtor(const SmallWithDtor &s) { }
161 // WIN32: define void @"\01?ref_small_arg_with_dtor@@YAXABUSmallWithDtor@@@Z"(%struct.SmallWithDtor* dereferenceable({{[0-9]+}}) %s) {{.*}} {
162 // WIN32-NOT:   call x86_thiscallcc void @"\01??1SmallWithDtor@@QAE@XZ"
163 // WIN32: }
164 // WIN64-LABEL: define void @"\01?ref_small_arg_with_dtor@@YAXAEBUSmallWithDtor@@@Z"(%struct.SmallWithDtor* dereferenceable({{[0-9]+}}) %s)
165 
166 void big_arg_with_dtor(BigWithDtor s) {}
167 // WIN64-LABEL: define void @"\01?big_arg_with_dtor@@YAXUBigWithDtor@@@Z"(%struct.BigWithDtor* %s)
168 // WIN64:   call void @"\01??1BigWithDtor@@QEAA@XZ"
169 // WIN64: }
170 
171 void call_big_arg_with_dtor() {
172   big_arg_with_dtor(BigWithDtor());
173 }
174 // We can elide the copy of the temporary in the caller, because this object is
175 // larger than 8 bytes and is passed indirectly.
176 // WIN64-LABEL: define void @"\01?call_big_arg_with_dtor@@YAXXZ"()
177 // WIN64:   call %struct.BigWithDtor* @"\01??0BigWithDtor@@QEAA@XZ"
178 // WIN64:   call void @"\01?big_arg_with_dtor@@YAXUBigWithDtor@@@Z"(%struct.BigWithDtor* %{{.*}})
179 // WIN64-NOT: call void @"\01??1BigWithDtor@@QEAA@XZ"
180 // WIN64:   ret void
181 
182 // Test that temporaries passed by reference are destroyed in the caller.
183 void temporary_ref_with_dtor() {
184   ref_small_arg_with_dtor(SmallWithDtor());
185 }
186 // WIN32: define void @"\01?temporary_ref_with_dtor@@YAXXZ"() {{.*}} {
187 // WIN32:   call x86_thiscallcc %struct.SmallWithDtor* @"\01??0SmallWithDtor@@QAE@XZ"
188 // WIN32:   call void @"\01?ref_small_arg_with_dtor@@YAXABUSmallWithDtor@@@Z"
189 // WIN32:   call x86_thiscallcc void @"\01??1SmallWithDtor@@QAE@XZ"
190 // WIN32: }
191 
192 void takes_two_by_val_with_dtor(SmallWithDtor a, SmallWithDtor b);
193 void eh_cleanup_arg_with_dtor() {
194   takes_two_by_val_with_dtor(SmallWithDtor(), SmallWithDtor());
195 }
196 //   When exceptions are off, we don't have any cleanups.  See
197 //   microsoft-abi-exceptions.cpp for these cleanups.
198 // WIN32: define void @"\01?eh_cleanup_arg_with_dtor@@YAXXZ"() {{.*}} {
199 // WIN32:   call x86_thiscallcc %struct.SmallWithDtor* @"\01??0SmallWithDtor@@QAE@XZ"
200 // WIN32:   call x86_thiscallcc %struct.SmallWithDtor* @"\01??0SmallWithDtor@@QAE@XZ"
201 // WIN32:   call void @"\01?takes_two_by_val_with_dtor@@YAXUSmallWithDtor@@0@Z"
202 // WIN32-NOT: call x86_thiscallcc void @"\01??1SmallWithDtor@@QAE@XZ"
203 // WIN32: }
204 
205 void small_arg_with_vftable(SmallWithVftable s) {}
206 // LINUX-LABEL: define void @_Z22small_arg_with_vftable16SmallWithVftable(%struct.SmallWithVftable* %s)
207 // WIN32: define void @"\01?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(<{ %struct.SmallWithVftable }>* inalloca)
208 // WIN64: define void @"\01?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(%struct.SmallWithVftable* %s)
209 
210 void medium_arg_with_copy_ctor(MediumWithCopyCtor s) {}
211 // LINUX-LABEL: define void @_Z25medium_arg_with_copy_ctor18MediumWithCopyCtor(%struct.MediumWithCopyCtor* %s)
212 // WIN32: define void @"\01?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(<{ %struct.MediumWithCopyCtor }>* inalloca)
213 // WIN64: define void @"\01?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(%struct.MediumWithCopyCtor* %s)
214 
215 void big_arg(Big s) {}
216 // LINUX-LABEL: define void @_Z7big_arg3Big(%struct.Big* byval align 4 %s)
217 // WIN32: define void @"\01?big_arg@@YAXUBig@@@Z"(%struct.Big* byval align 4 %s)
218 // WIN64: define void @"\01?big_arg@@YAXUBig@@@Z"(%struct.Big* %s)
219 
220 // PR27607: We would attempt to load i32 value out of the reference instead of
221 // just loading the pointer from the struct during argument expansion.
222 struct RefField {
223   RefField(int &x);
224   int &x;
225 };
226 void takes_ref_field(RefField s) {}
227 // LINUX-LABEL: define void @_Z15takes_ref_field8RefField(%struct.RefField* byval align 4 %s)
228 // WIN32: define void @"\01?takes_ref_field@@YAXURefField@@@Z"(i32* %s.0)
229 // WIN64: define void @"\01?takes_ref_field@@YAXURefField@@@Z"(i64 %s.coerce)
230 
231 void pass_ref_field() {
232   int x;
233   takes_ref_field(RefField(x));
234 }
235 // LINUX-LABEL: define void @_Z14pass_ref_fieldv()
236 // LINUX: call void @_Z15takes_ref_field8RefField(%struct.RefField* byval align 4 %{{.*}})
237 // WIN32-LABEL: define void @"\01?pass_ref_field@@YAXXZ"()
238 // WIN32: call void @"\01?takes_ref_field@@YAXURefField@@@Z"(i32* %{{.*}})
239 // WIN64-LABEL: define void @"\01?pass_ref_field@@YAXXZ"()
240 // WIN64: call void @"\01?takes_ref_field@@YAXURefField@@@Z"(i64 %{{.*}})
241 
242 class Class {
243  public:
244   Small thiscall_method_small() { return Small(); }
245   // LINUX: define {{.*}} void @_ZN5Class21thiscall_method_smallEv(%struct.Small* noalias sret %agg.result, %class.Class* %this)
246   // WIN32: define {{.*}} x86_thiscallcc void @"\01?thiscall_method_small@Class@@QAE?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret %agg.result)
247   // WIN64: define linkonce_odr void @"\01?thiscall_method_small@Class@@QEAA?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret %agg.result)
248 
249   SmallWithCtor thiscall_method_small_with_ctor() { return SmallWithCtor(); }
250   // LINUX: define {{.*}} void @_ZN5Class31thiscall_method_small_with_ctorEv(%struct.SmallWithCtor* noalias sret %agg.result, %class.Class* %this)
251   // WIN32: define {{.*}} x86_thiscallcc void @"\01?thiscall_method_small_with_ctor@Class@@QAE?AUSmallWithCtor@@XZ"(%class.Class* %this, %struct.SmallWithCtor* noalias sret %agg.result)
252   // WIN64: define linkonce_odr void @"\01?thiscall_method_small_with_ctor@Class@@QEAA?AUSmallWithCtor@@XZ"(%class.Class* %this, %struct.SmallWithCtor* noalias sret %agg.result)
253 
254   Small __cdecl cdecl_method_small() { return Small(); }
255   // LINUX: define {{.*}} void @_ZN5Class18cdecl_method_smallEv(%struct.Small* noalias sret %agg.result, %class.Class* %this)
256   // WIN32: define {{.*}} void @"\01?cdecl_method_small@Class@@QAA?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret %agg.result)
257   // WIN64: define linkonce_odr void @"\01?cdecl_method_small@Class@@QEAA?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret %agg.result)
258 
259   Big __cdecl cdecl_method_big() { return Big(); }
260   // LINUX: define {{.*}} void @_ZN5Class16cdecl_method_bigEv(%struct.Big* noalias sret %agg.result, %class.Class* %this)
261   // WIN32: define {{.*}} void @"\01?cdecl_method_big@Class@@QAA?AUBig@@XZ"(%class.Class* %this, %struct.Big* noalias sret %agg.result)
262   // WIN64: define linkonce_odr void @"\01?cdecl_method_big@Class@@QEAA?AUBig@@XZ"(%class.Class* %this, %struct.Big* noalias sret %agg.result)
263 
264   void thiscall_method_arg(Empty s) {}
265   // LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE5Empty(%class.Class* %this)
266   // WIN32: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUEmpty@@@Z"(%class.Class* %this, %struct.Empty* byval align 4 %s)
267   // WIN64: define linkonce_odr void @"\01?thiscall_method_arg@Class@@QEAAXUEmpty@@@Z"(%class.Class* %this, i8 %s.coerce)
268 
269   void thiscall_method_arg(EmptyWithCtor s) {}
270   // LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE13EmptyWithCtor(%class.Class* %this)
271   // WIN32: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUEmptyWithCtor@@@Z"(%class.Class* %this, %struct.EmptyWithCtor* byval align 4 %s)
272   // WIN64: define linkonce_odr void @"\01?thiscall_method_arg@Class@@QEAAXUEmptyWithCtor@@@Z"(%class.Class* %this, i8 %s.coerce)
273 
274   void thiscall_method_arg(Small s) {}
275   // LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE5Small(%class.Class* %this, i32 %s.0)
276   // WIN32: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUSmall@@@Z"(%class.Class* %this, i32 %s.0)
277   // WIN64: define linkonce_odr void @"\01?thiscall_method_arg@Class@@QEAAXUSmall@@@Z"(%class.Class* %this, i32 %s.coerce)
278 
279   void thiscall_method_arg(SmallWithCtor s) {}
280   // LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE13SmallWithCtor(%class.Class* %this, %struct.SmallWithCtor* byval align 4 %s)
281   // WIN32: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUSmallWithCtor@@@Z"(%class.Class* %this, i32 %s.0)
282   // WIN64: define linkonce_odr void @"\01?thiscall_method_arg@Class@@QEAAXUSmallWithCtor@@@Z"(%class.Class* %this, i32 %s.coerce)
283 
284   void thiscall_method_arg(Big s) {}
285   // LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE3Big(%class.Class* %this, %struct.Big* byval align 4 %s)
286   // WIN32: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUBig@@@Z"(%class.Class* %this, %struct.Big* byval align 4 %s)
287   // WIN64: define linkonce_odr void @"\01?thiscall_method_arg@Class@@QEAAXUBig@@@Z"(%class.Class* %this, %struct.Big* %s)
288 };
289 
290 void use_class() {
291   Class c;
292   c.thiscall_method_small();
293   c.thiscall_method_small_with_ctor();
294 
295   c.cdecl_method_small();
296   c.cdecl_method_big();
297 
298   c.thiscall_method_arg(Empty());
299   c.thiscall_method_arg(EmptyWithCtor());
300   c.thiscall_method_arg(Small());
301   c.thiscall_method_arg(SmallWithCtor());
302   c.thiscall_method_arg(Big());
303 }
304 
305 struct X {
306   X();
307   ~X();
308 };
309 void g(X) {
310 }
311 // WIN32: define void @"\01?g@@YAXUX@@@Z"(<{ %struct.X, [3 x i8] }>* inalloca) {{.*}} {
312 // WIN32:   call x86_thiscallcc void @"\01??1X@@QAE@XZ"(%struct.X* {{.*}})
313 // WIN32: }
314 void f() {
315   g(X());
316 }
317 // WIN32: define void @"\01?f@@YAXXZ"() {{.*}} {
318 // WIN32-NOT: call {{.*}} @"\01??1X@@QAE@XZ"
319 // WIN32: }
320 
321 
322 namespace test2 {
323 // We used to crash on this due to the mixture of POD byval and non-trivial
324 // byval.
325 
326 struct NonTrivial {
327   NonTrivial();
328   NonTrivial(const NonTrivial &o);
329   ~NonTrivial();
330   int a;
331 };
332 struct POD { int b; };
333 
334 int foo(NonTrivial a, POD b);
335 void bar() {
336   POD b;
337   b.b = 13;
338   int c = foo(NonTrivial(), b);
339 }
340 // WIN32-LABEL: define void @"\01?bar@test2@@YAXXZ"() {{.*}} {
341 // WIN32:   %[[argmem:[^ ]*]] = alloca inalloca [[argmem_ty:<{ %"struct.test2::NonTrivial", %"struct.test2::POD" }>]]
342 // WIN32:   getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 1
343 // WIN32:   call void @llvm.memcpy
344 // WIN32:   getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 0
345 // WIN32:   call x86_thiscallcc %"struct.test2::NonTrivial"* @"\01??0NonTrivial@test2@@QAE@XZ"
346 // WIN32:   call i32 @"\01?foo@test2@@YAHUNonTrivial@1@UPOD@1@@Z"([[argmem_ty]]* inalloca %argmem)
347 // WIN32:   ret void
348 // WIN32: }
349 
350 }
351 
352 namespace test3 {
353 
354 // Check that we padded the inalloca struct to a multiple of 4.
355 struct NonTrivial {
356   NonTrivial();
357   NonTrivial(const NonTrivial &o);
358   ~NonTrivial();
359   int a;
360 };
361 void foo(NonTrivial a, bool b) { }
362 // WIN32-LABEL: define void @"\01?foo@test3@@YAXUNonTrivial@1@_N@Z"(<{ %"struct.test3::NonTrivial", i8, [3 x i8] }>* inalloca)
363 
364 }
365 
366 // We would crash here because the later definition of ForwardDeclare1 results
367 // in a different IR type for the value we want to store.  However, the alloca's
368 // type will use the argument type selected by fn1.
369 struct ForwardDeclare1;
370 
371 typedef void (*FnPtr1)(ForwardDeclare1);
372 void fn1(FnPtr1 a, SmallWithDtor b) { }
373 
374 struct ForwardDeclare1 {};
375 
376 void fn2(FnPtr1 a, SmallWithDtor b) { fn1(a, b); };
377 // WIN32-LABEL: define void @"\01?fn2@@YAXP6AXUForwardDeclare1@@@ZUSmallWithDtor@@@Z"
378 // WIN32:   %[[a:[^ ]*]] = getelementptr inbounds [[argmem_ty:<{ {}\*, %struct.SmallWithDtor }>]], [[argmem_ty:<{ {}\*, %struct.SmallWithDtor }>]]* %{{.*}}, i32 0, i32 0
379 // WIN32:   %[[a1:[^ ]*]] = bitcast {}** %[[a]] to void [[dst_ty:\(%struct.ForwardDeclare1\*\)\*]]*
380 // WIN32:   %[[argmem:[^ ]*]] = alloca inalloca [[argmem_ty]]
381 // WIN32:   %[[gep1:[^ ]*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 1
382 // WIN32:   %[[bc1:[^ ]*]] = bitcast %struct.SmallWithDtor* %[[gep1]] to i8*
383 // WIN32:   call void @llvm.memcpy.p0i8.p0i8.i32(i8* %[[bc1]], i8* {{.*}}, i32 4, i32 4, i1 false)
384 // WIN32:   %[[a2:[^ ]*]] = load void [[dst_ty]], void [[dst_ty]]* %[[a1]], align 4
385 // WIN32:   %[[gep2:[^ ]*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 0
386 // WIN32:   %[[addr:[^ ]*]] = bitcast {}** %[[gep2]] to void [[dst_ty]]*
387 // WIN32:   store void [[dst_ty]] %[[a2]], void [[dst_ty]]* %[[addr]], align 4
388 // WIN32:   call void @"\01?fn1@@YAXP6AXUForwardDeclare1@@@ZUSmallWithDtor@@@Z"([[argmem_ty]]* inalloca %[[argmem]])
389