Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / clang / test / CodeGen / paren-list-agg-init.cpp
blob0e68beb5c37066bc0fe0528c001d4785d675d76a
1 // RUN: %clang_cc1 -std=c++20 %s -emit-llvm -triple x86_64-unknown-linux-gnu -o - | FileCheck %s
3 template <typename T>
4 struct IsChar {
5 constexpr operator bool() const { return false; }
6 };
8 template<>
9 struct IsChar<char> {
10 constexpr operator bool() const { return true; }
13 template <typename T>
14 concept SameAsChar = (bool)IsInt<T>();
16 // CHECK-DAG: [[STRUCT_A:%.*]] = type { i8, double }
17 struct A {
18 char i;
19 double j;
21 template <SameAsChar T>
22 operator T() const { return i; };
25 // CHECK-DAG: [[STRUCT_B:%.*]] = type { [[STRUCT_A]], i32 }
26 struct B {
27 A a;
28 int b;
31 // CHECK-DAG: [[STRUCT_C:%.*]] = type <{ [[STRUCT_B]], [[STRUCT_A]], i32, [4 x i8] }>
32 struct C : public B, public A {
33 int c;
36 // CHECK-DAG: [[STRUCT_D:%.*]] = type { [[STRUCT_A]], [[STRUCT_A]], i8, [[STRUCT_A]] }
37 struct D {
38 A a;
39 A b = A{2, 2.0};
40 unsigned : 2;
41 A c;
44 // CHECK-DAG: [[STRUCT_E:%.*]] = type { i32, ptr }
45 struct E {
46 int a;
47 const char* fn = __builtin_FUNCTION();
48 ~E() {};
51 // CHECK-DAG: [[STRUCT_F:%.*]] = type { i8 }
52 struct F {
53 F (int i = 1);
54 F (const F &f) = delete;
55 F (F &&f) = default;
58 // CHECK-DAG: [[STRUCT_G:%.*]] = type <{ i32, [[STRUCT_F]], [3 x i8] }>
59 struct G {
60 int a;
61 F f;
64 // CHECK-DAG: [[UNION_U:%.*]] = type { [[STRUCT_A]] }
65 // CHECK-DAG: [[STR:@.*]] = private unnamed_addr constant [6 x i8] {{.*}}foo18{{.*}}, align 1
66 union U {
67 unsigned : 1;
68 A a;
69 char b;
73 namespace gh61145 {
74 // CHECK-DAG: [[STRUCT_VEC:%.*]] = type { i8 }
75 struct Vec {
76 Vec();
77 Vec(Vec&&);
78 ~Vec();
81 // CHECK-DAG: [[STRUCT_S1:%.*]] = type { [[STRUCT_VEC]] }
82 struct S1 {
83 Vec v;
86 // CHECK-DAG: [[STRUCT_S2:%.*]] = type { [[STRUCT_VEC]], i8 }
87 struct S2 {
88 Vec v;
89 char c;
93 namespace gh62266 {
94 // CHECK-DAG: [[STRUCT_H:%.*H.*]] = type { i32, i32 }
95 template <int J>
96 struct H {
97 int i;
98 int j = J;
102 namespace gh61567 {
103 // CHECK-DAG: [[STRUCT_I:%.*I.*]] = type { i32, ptr }
104 struct I {
105 int a;
106 int&& r = 2;
110 // CHECK-DAG: [[A1:@.*a1.*]] = internal constant [[STRUCT_A]] { i8 3, double 2.000000e+00 }, align 8
111 constexpr A a1(3.1, 2.0);
112 // CHECK-DAG: [[A2:@.*a2.*]] = internal constant [[STRUCT_A]] { i8 99, double 0.000000e+00 }, align 8
113 constexpr auto a2 = static_cast<A>('c');
114 // CHECK-DAG: [[B1:@.*b1.*]] = internal constant [[STRUCT_B]] { [[STRUCT_A]] { i8 99, double 0.000000e+00 }, i32 0 }, align 8
115 constexpr B b1(A('c'));
116 // CHECK-DAG: [[C1:@.*c1.*]] = internal constant { [[STRUCT_A]], i32, [4 x i8], i8, double, i32 } { [[STRUCT_A]] { i8 99, double 0.000000e+00 }, i32 0, [4 x i8] undef, i8 3, double 2.000000e+00, i32 0 }, align
117 constexpr C c1(b1, a1);
118 // CHECK-DAG: [[U1:@.*u1.*]] = internal constant [[UNION_U]] { [[STRUCT_A]] { i8 1, double 1.000000e+00 } }, align 8
119 constexpr U u1(A(1, 1));
120 // CHECK-DAG: [[D1:@.*d1.*]] = internal constant { [[STRUCT_A]], [[STRUCT_A]], [8 x i8], [[STRUCT_A]] } { [[STRUCT_A]] { i8 2, double 2.000000e+00 }, [[STRUCT_A]] { i8 2, double 2.000000e+00 }, [8 x i8] undef, [[STRUCT_A]] zeroinitializer }, align 8
121 constexpr D d1(A(2, 2));
122 // CHECK-DAG: [[ARR1:@.*arr1.*]] = internal constant [3 x i32] [i32 1, i32 2, i32 0], align 4
123 constexpr int arr1[3](1, 2);
124 // CHECK-DAG: [[ARR4:@.*arr4.*]] = internal constant [1 x i32] [i32 1], align 4
125 constexpr int arr4[](1);
126 // CHECK-DAG: [[ARR5:@.*arr5.*]] = internal constant [2 x i32] [i32 2, i32 0], align 4
127 constexpr int arr5[2](2);
129 // CHECK: define dso_local { i8, double } @{{.*foo1.*}}
130 // CHECK-NEXT: entry:
131 // CHECK-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_A]], align 8
132 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[RETVAL]], ptr align 8 [[A1]], i64 16, i1 false)
133 // CHECK-NEXT: [[TMP_0:%.*]] = load { i8, double }, ptr [[RETVAL]], align 8
134 // CHECK-NEXT: ret { i8, double } [[TMP_0]]
135 A foo1() {
136 return a1;
139 // CHECK: define dso_local void @{{.*foo2.*}}(ptr noalias sret([[STRUCT_B]]) align 8 [[AGG_RESULT:%.*]])
140 // CHECK-NEXT: entry:
141 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_RESULT]], ptr align 8 [[B1]], i64 24, i1 false)
142 // CHECK-NEXT: ret void
143 B foo2() {
144 return b1;
147 // CHECK: define dso_local void @{{.*foo3.*}}(ptr noalias sret([[STRUCT_C]]) align 8 [[AGG_RESULT:%.*]])
148 // CHECK-NEXT: entry:
149 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_RESULT]], ptr align 8 [[C1]], i64 48, i1 false)
150 // CHECK-NEXT: ret void
151 C foo3() {
152 return c1;
155 // CHECK: define dso_local void @{{.*foo4.*}}
156 // CHECK-NEXT: entry:
157 // CHECK-NEXT: [[C2:%.*]] = alloca [[STRUCT_C:%.*]], align 8
158 // CHECK-NEXT: [[REF_TMP:%.*]] = alloca [[STRUCT_B:%.*]], align 8
159 // CHECK-NEXT: [[REF_TMP_1:%.*]] = alloca [[STRUCT_A:%.*]], align 8
160 // CHECK-NEXT: [[A:%.*]] = getelementptr inbounds [[STRUCT_B]], ptr [[REF_TMP]], i32 0, i32 0
161 // CHECK-NEXT: [[I:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[A]], i32 0, i32 0
162 // CHECK-NEXT: store i8 1, ptr [[I]], align 8
163 // CHECK-NEXT: [[J:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[A]], i32 0, i32 1
164 // CHECK-NEXT: store double 1.000000e+00, ptr [[J]], align 8
165 // CHECK-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_B]], ptr [[REF_TMP]], i32 0, i32 1
166 // CHECK-NEXT: store i32 1, ptr [[B]], align 8
167 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[C2]], ptr align 8 [[REF_TMP]], i64 24, i1 false)
168 // CHECK-NEXT: [[TMP_0:%.*]] = getelementptr inbounds i8, ptr [[C2]], i64 24
169 // CHECK-NEXT: [[I2:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[REF_TMP_1]], i32 0, i32 0
170 // CHECK-NEXT: store i8 97, ptr [[I2]], align 8
171 // CHECK-NEXT: [[J3:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[REF_TMP_1]], i32 0, i32 1
172 // CHECK-NEXT: store double 0.000000e+00, ptr [[J3]], align 8
173 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[TMP_0]], ptr align 8 [[REF_TMP_1]], i64 16, i1 false)
174 // CHECK-NEXT: [[C:%.*]] = getelementptr inbounds %struct.C, ptr %c2, i32 0, i32 2
175 // CHECK-NEXT: store i32 2, ptr %c, align 8
176 // CHECK-NEXT: ret void
177 void foo4() {
178 C c2(B(A(1, 1), 1), A('a'), 2);
181 // CHECK: define dso_local { i64, double } @{{.*foo5.*}}
182 // CHECK-NEXT: entry:
183 // CHECK-NEXT [[RETVAL:%.*]] = alloca [[UNION_U]], align 8
184 // CHECK-NEXT call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[RETVAL]], ptr align 8 [[U1]], i64 16, i1 false)
185 // CHECK-NEXT [[COERCE_DIVE:%.*]] = getelementptr inbounds [[UNION_U]], ptr %retval, i32 0, i32 0
186 // CHECK-NEXT [[TMP_0:%.*]] = load { i64, double }, ptr [[COERCE_DIVE]], align 8
187 // CHECK-NEXT ret { i64, double } [[TMP_0]]
188 U foo5() {
189 return u1;
193 // CHECK: define dso_local { i64, double } @{{.*foo6.*}}(i8 [[A_COERCE_0:%.*]], double [[A_COERCE_1:%.*]])
194 // CHECK-NEXT: entry:
195 // CHECK-NEXT: [[RETVAL:%.*]] = alloca [[UNION_U]], align 8
196 // CHECK-NEXT: [[A:%.*]] = alloca [[STRUCT_A]], align 8
197 // CHECK-NEXT: [[TMP_0:%.*]] = getelementptr inbounds { i8, double }, ptr [[A]], i32 0, i32 0
198 // CHECK-NEXT: store i8 [[A_COERCE_0]], ptr [[TMP_0]], align 8
199 // CHECK-NEXT: [[TMP_1:%.*]] = getelementptr inbounds { i8, double }, ptr [[A]], i32 0, i32 1
200 // CHECK-NEXT: store double [[A_COERCE_1]], ptr [[TMP_1]], align 8
201 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[RETVAL]], ptr align 8 [[A]], i64 16, i1 false)
202 // CHECK-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds [[UNION_U]], ptr [[RETVAL]], i32 0, i32 0
203 // CHECK-NEXT: [[TMP_2:%.*]] = load { i64, double }, ptr [[COERCE_DIVE:%.*]], align 8
204 // CHECK-NEXT: ret { i64, double } [[TMP_2]]
205 U foo6(A a) {
206 return U(a);
209 // CHECK: define dso_local void @{{.*foo7.*}}
210 // CHECK-NEXT: entry:
211 // CHECK-NEXT: [[D:%.*]] = alloca [[STRUCT_D:%.*]], align 8
212 // CHECK-NEXT: [[A:%.*]] = getelementptr inbounds [[STRUCT_D]], ptr [[D]], i32 0, i32 0
213 // CHECK-NEXT: [[I]] = getelementptr inbounds [[STRUCT_A:%.*]], ptr [[A]], i32 0, i32 0
214 // CHECK-NEXT: store i8 1, ptr [[I]], align 8
215 // CHECK-NEXT: [[J:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[A]], i32 0, i32 1
216 // CHECK-NEXT: store double 1.000000e+00, ptr [[J]], align 8
217 // CHECK-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_D]], ptr [[D]], i32 0, i32 1
218 // CHECK-NEXT: [[I1:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[B]], i32 0, i32 0
219 // CHECK-NEXT: store i8 11, ptr [[I1]], align 8
220 // CHECK-NEXT: [[J2:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[B]], i32 0, i32 1
221 // CHECK-NEXT: store double 1.100000e+01, ptr [[J2]], align 8
222 // CHECK-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_D]], ptr [[D]], i32 0, i32 3
223 // CHECK-NEXT: [[I3:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[C]], i32 0, i32 0
224 // CHECK-NEXT: store i8 111, ptr [[I3]], align 8
225 // CHECK-NEXT: [[J4:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[C]], i32 0, i32 1
226 // CHECK-NEXT: store double 1.110000e+02, ptr [[J4]], align 8
227 // CHECK-NEXT: ret void
228 void foo7() {
229 D d(A(1, 1), A(11, 11), A(111, 111));
232 // CHECK: dso_local void @{{.*foo8.*}}(ptr noalias sret([[STRUCT_D]]) align 8 [[AGG_RESULT:%.*]])
233 // CHECK-NEXT: entry:
234 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_RESULT]], ptr align 8 [[D1]], i64 56, i1 false)
235 // CHECK-NEXT: ret void
236 D foo8() {
237 return d1;
240 // CHECK: define dso_local void @{{.*foo9.*}}
241 // CHECK-NEXT: entry:
242 // CHECK-NEXT: [[D:%.*]] = alloca [[STRUCT_D:%.*]], align 8
243 // CHECK-NEXT: [[A:%.*]] = getelementptr inbounds [[STRUCT_D]], ptr [[D]], i32 0, i32 0
244 // CHECK-NEXT: [[I]] = getelementptr inbounds [[STRUCT_A:%.*]], ptr [[A]], i32 0, i32 0
245 // CHECK-NEXT: store i8 1, ptr [[I]], align 8
246 // CHECK-NEXT: [[J:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[A]], i32 0, i32 1
247 // CHECK-NEXT: store double 1.000000e+00, ptr [[J]], align 8
248 // CHECK-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_D]], ptr [[D]], i32 0, i32 1
249 // CHECK-NEXT: [[I1:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[B]], i32 0, i32 0
250 // CHECK-NEXT: store i8 2, ptr [[I1]], align 8
251 // CHECK-NEXT: [[J2:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[B]], i32 0, i32 1
252 // CHECK-NEXT: store double 2.000000e+00, ptr [[J2]], align 8
253 // CHECK-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_D]], ptr [[D]], i32 0, i32 3
254 // CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[C]], i8 0, i64 16, i1 false)
255 // CHECK-NEXT: ret void
256 void foo9() {
257 D d(A(1, 1));
260 // CHECK: define dso_local noundef ptr @{{.*foo10.*}}()
261 // CHECK-NEXT: entry:
262 // CHECK-NEXT: ret ptr [[ARR1]]
263 const int* foo10() {
264 return arr1;
267 // CHECK: define dso_local void @{{.*foo11.*}}
268 // CHECK-NEXT: entry:
269 // CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
270 // CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
271 // CHECK-NEXT: [[ARR_2:%.*]] = alloca [4 x i32], align 16
272 // CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
273 // CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
274 // CHECK-NEXT: [[ARRINIT_BEGIN:%.*]] = getelementptr inbounds [4 x i32], ptr [[ARR_2]], i64 0, i64 0
275 // CHECK-NEXT: [[TMP_0:%.*]] = load i32, ptr [[A_ADDR]], align 4
276 // CHECK-NEXT: store i32 [[TMP_0]], ptr [[ARRINIT_BEGIN]], align 4
277 // CHECK-NEXT: [[ARRINIT_ELEM:%.*]] = getelementptr inbounds i32, ptr [[ARRINIT_BEGIN]], i64 1
278 // CHECK-NEXT: [[TMP_1:%.*]] = load i32, ptr [[B_ADDR]], align 4
279 // CHECK-NEXT: store i32 [[TMP_1]], ptr [[ARRINIT_ELEM]], align 4
280 // CHECK-NEXT: [[ARRINIT_START:%.*]] = getelementptr inbounds i32, ptr [[ARRINIT_ELEM]], i64 1
281 // CHECK-NEXT: [[ARRINIT_END:%.*]] = getelementptr inbounds i32, ptr [[ARRINIT_BEGIN]], i64 4
282 // CHECK-NEXT: br label [[ARRINIT_BODY:%.*]]
283 // CHECK: [[ARRINIT_CUR:%.*]] = phi ptr [ [[ARRINIT_START]], %entry ], [ [[ARRINIT_NEXT:%.*]], [[ARRINIT_BODY]] ]
284 // CHECK-NEXT: store i32 0, ptr [[ARRINIT_CUR]], align 4
285 // CHECK-NEXT: [[ARRINIT_NEXT]] = getelementptr inbounds i32, ptr [[ARRINIT_CUR]], i64 1
286 // CHECK-NEXT: [[ARRINIT_DONE:%.*]] = icmp eq ptr [[ARRINIT_NEXT]], [[ARRINIT_END:%.*]]
287 // CHECK-NEXT: br i1 [[ARRINIT_DONE]], label [[ARRINIT_END1:%.*]], label [[ARRINIT_BODY]]
288 // CHECK: ret void
289 void foo11(int a, int b) {
290 int arr2[4](a, b);
293 // CHECK: define dso_local void @{{.*foo12.*}}
294 // CHECK-NEXT: entry:
295 // CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
296 // CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
297 // CHECK-NEXT: [[ARR_3:%.*]] = alloca [2 x i32], align 4
298 // CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
299 // CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
300 // CHECK-NEXT: [[ARRINIT_BEGIN:%.*]] = getelementptr inbounds [2 x i32], ptr [[ARR_3]], i64 0, i64 0
301 // CHECK-NEXT: [[TMP_0:%.*]] = load i32, ptr [[A_ADDR]], align 4
302 // CHECK-NEXT: store i32 [[TMP_0]], ptr [[ARRINIT_BEGIN]], align 4
303 // CHECK-NEXT: [[ARRINIT_ELEMENT:%.*]] = getelementptr inbounds i32, ptr [[ARRINIT_BEGIN]], i64 1
304 // CHECK-NEXT: [[TMP_1:%.*]] = load i32, ptr [[B_ADDR]], align 4
305 // CHECK-NEXT: store i32 [[TMP_1]], ptr [[ARRINIT_ELEMENT]], align 4
306 // CHECK-NEXT: ret void
307 void foo12(int a, int b) {
308 int arr3[](a, b);
311 // CHECK: define dso_local { i8, double } @{{.*foo13.*}}
312 // CHECK-NEXT: entry:
313 // CHECK-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_A]], align 8
314 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[RETVAL]], ptr align 8 [[A2]], i64 16, i1 false)
315 // CHECK-NEXT: [[TMP_0:%.*]] = load { i8, double }, ptr [[RETVAL]], align 8
316 // CHECK-NEXT: ret { i8, double } [[TMP_0]]
317 A foo13() {
318 return a2;
321 // CHECK: define dso_local noundef ptr @{{.*foo14.*}}()
322 // CHECK-NEXT: entry:
323 // CHECK-NEXT: ret ptr [[ARR4]]
324 const int* foo14() {
325 return arr4;
328 // CHECK: define dso_local noundef ptr @{{.*foo15.*}}()
329 // CHECK-NEXT: entry:
330 // CHECK-NEXT: ret ptr [[ARR5]]
331 const int* foo15() {
332 return arr5;
335 // CHECK: define dso_local void @{{.*foo16.*}}
336 // CHECK-NEXT: entry:
337 // CHECK-NEXT: [[ARR_6:%.*arr6.*]] = alloca ptr, align 8
338 // CHECK-NEXT: [[REF_TMP:%.*]] = alloca [1 x i32], align 4
339 // CHECK-NEXT: [[ARRINIT_BEGIN:%.*]] = getelementptr inbounds [1 x i32], ptr [[REF_TMP]], i64 0, i64 0
340 // CHECK-NEXT: store i32 3, ptr [[ARRINIT_BEGIN]], align 4
341 // CHECK-NEXT: store ptr [[REF_TMP]], ptr [[ARR_6]], align 8
342 // CHECK-NEXT: ret void
343 void foo16() {
344 int (&&arr6)[] = static_cast<int[]>(3);
347 // CHECK: define dso_local void @{{.*foo17.*}}
348 // CHECK-NEXT: entry:
349 // CHECK-NEXT: [[ARR_7:%.*arr7.*]] = alloca ptr, align 8
350 // CHECK-NEXT: [[REF_TMP:%.*]] = alloca [2 x i32], align 4
351 // CHECK-NEXT: [[ARRINIT_BEGIN:%.*]] = getelementptr inbounds [2 x i32], ptr [[REF_TMP]], i64 0, i64 0
352 // CHECK-NEXT: store i32 4, ptr [[ARRINIT_BEGIN]], align 4
353 // CHECK-NEXT: [[ARRINIT_START:%.*]] = getelementptr inbounds i32, ptr [[ARRINIT_BEGIN]], i64 1
354 // CHECK-NEXT: [[ARRINIT_END:%.*]] = getelementptr inbounds i32, ptr [[ARRINIT_BEGIN]], i64 2
355 // CHECK-NEXT: br label [[ARRINIT_BODY]]
356 // CHECK: [[ARRINIT_CUR:%.*]] = phi ptr [ [[ARRINIT_START]], %entry ], [ [[ARRINIT_NEXT:%.*]], [[ARRINIT_BODY]] ]
357 // CHECK-NEXT: store i32 0, ptr [[ARRINIT_CUR]], align 4
358 // CHECK-NEXT: [[ARRINIT_NEXT]] = getelementptr inbounds i32, ptr [[ARRINIT_CUR]], i64 1
359 // CHECK-NEXT: [[ARRINIT_DONE:%.*]] = icmp eq ptr [[ARRINIT_NEXT]], [[ARRINIT_END:%.*]]
360 // CHECK-NEXT: br i1 [[ARRINIT_DONE]], label [[ARRINIT_END1:%.*]], label [[ARRINIT_BODY]]
361 // CHECK: store ptr [[REF_TMP]], ptr [[ARR_7]], align 8
362 // CHECK: ret void
363 void foo17() {
364 int (&&arr7)[2] = static_cast<int[2]>(4);
367 // CHECK: define dso_local void @{{.*foo18.*}}
368 // CHECK-NEXT: entry:
369 // CHECK-NEXT: [[E:%.*e.*]] = alloca [[STRUCT_E]], align 8
370 // CHECK-NEXT: [[A:%.*a.*]] = getelementptr inbounds [[STRUCT_E]], ptr [[E]], i32 0, i32 0
371 // CHECK-NEXT: store i32 1, ptr [[A]], align 8
372 // CHECK-NEXT: [[FN:%.*fn.*]] = getelementptr inbounds [[STRUCT_E]], ptr [[E]], i32 0, i32 1
373 // CHECK-NEXT: store ptr [[STR]], ptr [[FN]], align 8
374 // CHECK: ret void
375 void foo18() {
376 E e(1);
379 // CHECK: define dso_local void @{{.*foo19.*}}
380 // CHECK-NEXT: entry:
381 // CHECK-NEXT: [[G:%.*g.*]] = alloca [[STRUCT_G]], align 4
382 // CHECK-NEXT: [[A:%.*a.*]] = getelementptr inbounds [[STRUCT_G]], ptr [[G]], i32 0, i32 0
383 // CHECK-NEXT: store i32 2, ptr [[A]], align 4
384 // CHECK-NEXT: [[F:%.*f.*]] = getelementptr inbounds [[STRUCT_G]], ptr [[G]], i32 0, i32 1
385 // CHECk-NEXT: call void @{{.*F.*}}(ptr noundef nonnull align 1 dereferenceable(1)) [[F]], ie32 noundef 1)
386 // CHECK: ret void
387 void foo19() {
388 G g(2);
391 namespace gh61145 {
392 // a.k.a. void make1<0>()
393 // CHECK: define {{.*}} void @_ZN7gh611455make1ILi0EEEvv
394 // CHECK-NEXT: entry:
395 // CHECK-NEXT: [[V:%.*v.*]] = alloca [[STRUCT_VEC]], align 1
396 // CHECK-NEXT: [[AGG_TMP_ENSURED:%.*agg.tmp.ensured.*]] = alloca [[STRUCT_S1]], align 1
397 // a.k.a. Vec::Vec()
398 // CHECK-NEXT: call void @_ZN7gh611453VecC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[V]])
399 // CHECK-NEXT: [[V1:%.*v1.*]] = getelementptr inbounds [[STRUCT_S1]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 0
400 // a.k.a. Vec::Vec(Vec&&)
401 // CHECK-NEXT: call void @_ZN7gh611453VecC1EOS0_(ptr noundef nonnull align 1 dereferenceable(1) [[V1]], ptr noundef nonnull align 1 dereferenceable(1) [[V]])
402 // a.k.a. S1::~S1()
403 // CHECK-NEXT: call void @_ZN7gh611452S1D1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_TMP_ENSURED]])
404 // a.k.a.Vec::~Vec()
405 // CHECK-NEXT: call void @_ZN7gh611453VecD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[V]])
406 // CHECK-NEXT: ret void
407 template <int I>
408 void make1() {
409 Vec v;
410 S1((Vec&&) v);
413 // a.k.a. void make1<0>()
414 // CHECK: define {{.*}} void @_ZN7gh611455make2ILi0EEEvv
415 // CHECK-NEXT: entry:
416 // CHECK-NEXT: [[V:%.*v.*]] = alloca [[STRUCT_VEC]], align 1
417 // CHECK-NEXT: [[AGG_TMP_ENSURED:%.*agg.tmp.ensured.*]] = alloca [[STRUCT_S2]], align 1
418 // a.k.a. Vec::Vec()
419 // CHECK-NEXT: call void @_ZN7gh611453VecC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[V]])
420 // CHECK-NEXT: [[V1:%.*v1.*]] = getelementptr inbounds [[STRUCT_S2]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 0
421 // a.k.a. Vec::Vec(Vec&&)
422 // CHECK-NEXT: call void @_ZN7gh611453VecC1EOS0_(ptr noundef nonnull align 1 dereferenceable(1) [[V1]], ptr noundef nonnull align 1 dereferenceable(1) [[V]])
423 // CHECK-NEXT: [[C:%.*c.*]] = getelementptr inbounds [[STRUCT_S2]], ptr [[AGG_TMP_ENSURED]], i32 0, i32
424 // CHECK-NEXT: store i8 0, ptr [[C]], align 1
425 // a.k.a. S2::~S2()
426 // CHECK-NEXT: call void @_ZN7gh611452S2D1Ev(ptr noundef nonnull align 1 dereferenceable(2) [[AGG_TMP_ENSURED]])
427 // a.k.a. Vec::~Vec()
428 // CHECK-NEXT: call void @_ZN7gh611453VecD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[V]])
429 // CHECK-NEXT: ret void
430 template <int I>
431 void make2() {
432 Vec v;
433 S2((Vec&&) v, 0);
436 void foo() {
437 make1<0>();
438 make2<0>();
442 namespace gh62266 {
443 // CHECK: define {{.*}} void {{.*foo20.*}}
444 // CHECK-NEXT: entry:
445 // CHECK-NEXT: [[H:%.*h.*]] = alloca [[STRUCT_H]], align 4
446 // CHECK-NEXT: [[I:%.*i.*]] = getelementptr inbounds [[STRUCT_H]], ptr [[H]], i32 0, i32 0
447 // CHECK-NEXT: store i32 1, ptr [[I]], align 4
448 // CHECK-NEXT: [[J:%.*j.*]] = getelementptr inbounds [[STRUCT_H]], ptr [[H]], i32 0, i32 1
449 // CHECK-NEXT: store i32 2, ptr [[J]], align 4
450 // CHECK-NEXT: ret void
451 void foo20() {
452 H<2> h(1);
456 namespace gh61567 {
457 int foo20();
459 // CHECK: define {{.*}} void @{{.*foo21.*}} {
460 // CHECK-NEXT: entry
461 // CHECK-NEXT: [[AGG_TMP_ENSURED:%.*]] = alloca [[STRUCT_I]], align 8
462 // CHECK-NEXT: [[REF_TMP:%.*]] = alloca i32, align 4
463 // CHECK-NEXT: [[A:%.*a.*]] = getelementptr inbounds [[STRUCT_I]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 0
464 // CHECK-NEXT: store i32 0, ptr [[A]], align 8
465 // CHECK-NEXT: [[R:%.*r.*]] = getelementptr inbounds [[STRUCT_I]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 1
466 // CHECK-NEXT: store i32 1, ptr [[REF_TMP]], align 4
467 // CHECK-NEXT: store ptr [[REF_TMP]], ptr [[R]], align 8
468 // CHECK-NEXT: ret void
469 void foo21() {
470 I(0, 1);
473 // CHECK: define {{.*}} void @{{.*foo22.*}} {
474 // CHECK-NEXT: entry
475 // CHECK-NEXT: [[AGG_TMP_ENSURED:%.*]] = alloca [[STRUCT_I]], align 8
476 // CHECK-NEXT: [[REF_TMP:%.*]] = alloca i32, align 4
477 // CHECK-NEXT: [[A:%.*a.*]] = getelementptr inbounds [[STRUCT_I]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 0
478 // CHECK-NEXT: store i32 0, ptr [[A]], align 8
479 // CHECK-NEXT: [[R:%.*r.*]] = getelementptr inbounds [[STRUCT_I]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 1
480 // CHECK-NEXT: [[CALL:%.*call*]] = call noundef i32 @{{.*foo20.*}}
481 // CHECK-NEXT: store i32 [[CALL]], ptr [[REF_TMP]], align 4
482 // CHECK-NEXT: store ptr [[REF_TMP]], ptr [[R]], align 8
483 // CHECK-NEXT: ret void
484 void foo22() {
485 I(0, foo20());
488 // CHECK: define {{.*}} void @{{.*foo23.*}}(i32 noundef [[I:%.*i.*]])
489 // CHECK-NEXT: entry
490 // CHECK-NEXT: [[I_ADDR:%.*i.*]] = alloca i32, align 4
491 // CHECK-NEXT: [[AGG_TMP_ENSURED:%.*]] = alloca [[STRUCT_I]], align 8
492 // CHECK-NEXT: store i32 [[I]], ptr [[I_ADDR]], align 4
493 // CHECK-NEXT: [[A:%.*a.*]] = getelementptr inbounds [[STRUCT_I]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 0
494 // CHECK-NEXT: store i32 0, ptr [[A]], align 8
495 // CHECK-NEXT: [[R:%.*r.*]] = getelementptr inbounds [[STRUCT_I]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 1
496 // CHECK-NEXT: store ptr [[I_ADDR]], ptr [[R]], align 8
497 // CHECK-NEXT: ret void
498 void foo23(int i) {
499 I(0, static_cast<int&&>(i));
502 // CHECK: define {{.*}} void @{{.*foo24.*}} {
503 // CHECK-NEXT: entry
504 // CHECK-NEXT: [[AGG_TMP_ENSURED:%.*]] = alloca [[STRUCT_I]], align 8
505 // CHECK-NEXT: [[REF_TMP:%.*]] = alloca i32, align 4
506 // CHECK-NEXT: [[A:%.*a.*]] = getelementptr inbounds [[STRUCT_I]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 0
507 // CHECK-NEXT: store i32 0, ptr [[A]], align 8
508 // CHECK-NEXT: [[R:%.*r.*]] = getelementptr inbounds [[STRUCT_I]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 1
509 // CHECK-NEXT: store i32 2, ptr [[REF_TMP]], align 4
510 // CHECK-NEXT: store ptr [[REF_TMP]], ptr [[R]], align 8
511 // CHECK-NEXT: ret void
512 void foo24() {
513 I(0);