1 // RUN: %clang_cc1 -std=c++20 %s -emit-llvm -triple x86_64-unknown-linux-gnu -o - | FileCheck %s 2 3 template <typename T> 4 struct IsChar { 5 constexpr operator bool() const { return false; } 6 }; 7 8 template<> 9 struct IsChar<char> { 10 constexpr operator bool() const { return true; } 11 }; 12 13 template <typename T> 14 concept SameAsChar = (bool)IsInt<T>(); 15 16 // CHECK-DAG: [[STRUCT_A:%.*]] = type { i8, double } 17 struct A { 18 char i; 19 double j; 20 21 template <SameAsChar T> 22 operator T() const { return i; }; 23 }; 24 25 // CHECK-DAG: [[STRUCT_B:%.*]] = type { [[STRUCT_A]], i32 } 26 struct B { 27 A a; 28 int b; 29 }; 30 31 // CHECK-DAG: [[STRUCT_C:%.*]] = type <{ [[STRUCT_B]], [[STRUCT_A]], i32, [4 x i8] }> 32 struct C : public B, public A { 33 int c; 34 }; 35 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; 42 }; 43 44 // CHECK-DAG: [[STRUCT_E:%.*]] = type { i32, ptr } 45 struct E { 46 int a; 47 const char* fn = __builtin_FUNCTION(); 48 ~E() {}; 49 }; 50 51 struct F { 52 F (int i = 1); 53 F (const F &f) = delete; 54 F (F &&f) = default; 55 }; 56 57 // CHECK-DAG: [[STRUCT_G:%.*]] = type <{ i32, [4 x i8] }> 58 struct G { 59 int a; 60 F f; 61 }; 62 63 // CHECK-DAG: [[UNION_U:%.*]] = type { [[STRUCT_A]] } 64 // CHECK-DAG: [[STR:@.*]] = private unnamed_addr constant [6 x i8] {{.*}}foo18{{.*}}, align 1 65 union U { 66 unsigned : 1; 67 A a; 68 char b; 69 }; 70 71 72 namespace gh61145 { 73 // CHECK-DAG: [[STRUCT_VEC:%.*]] = type { i8 } 74 struct Vec { 75 Vec(); 76 Vec(Vec&&); 77 ~Vec(); 78 }; 79 80 // CHECK-DAG: [[STRUCT_S1:%.*]] = type { i8 } 81 struct S1 { 82 Vec v; 83 }; 84 85 // CHECK-DAG: [[STRUCT_S2:%.*]] = type { i8, i8 } 86 struct S2 { 87 Vec v; 88 char c; 89 }; 90 } 91 92 namespace gh62266 { 93 // CHECK-DAG: [[STRUCT_H:%.*H.*]] = type { i32, i32 } 94 template <int J> 95 struct H { 96 int i; 97 int j = J; 98 }; 99 } 100 101 namespace gh61567 { 102 // CHECK-DAG: [[STRUCT_I:%.*I.*]] = type { i32, ptr } 103 struct I { 104 int a; 105 int&& r = 2; 106 }; 107 } 108 109 // CHECK-DAG: [[A1:@.*a1.*]] = internal constant [[STRUCT_A]] { i8 3, double 2.000000e+00 }, align 8 110 constexpr A a1(3.1, 2.0); 111 // CHECK-DAG: [[A2:@.*a2.*]] = internal constant [[STRUCT_A]] { i8 99, double 0.000000e+00 }, align 8 112 constexpr auto a2 = static_cast<A>('c'); 113 // CHECK-DAG: [[B1:@.*b1.*]] = internal constant [[STRUCT_B]] { [[STRUCT_A]] { i8 99, double 0.000000e+00 }, i32 0 }, align 8 114 constexpr B b1(A('c')); 115 // 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 116 constexpr C c1(b1, a1); 117 // CHECK-DAG: [[U1:@.*u1.*]] = internal constant [[UNION_U]] { [[STRUCT_A]] { i8 1, double 1.000000e+00 } }, align 8 118 constexpr U u1(A(1, 1)); 119 // 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 120 constexpr D d1(A(2, 2)); 121 // CHECK-DAG: [[ARR1:@.*arr1.*]] = internal constant [3 x i32] [i32 1, i32 2, i32 0], align 4 122 constexpr int arr1[3](1, 2); 123 // CHECK-DAG: [[ARR4:@.*arr4.*]] = internal constant [1 x i32] [i32 1], align 4 124 constexpr int arr4[](1); 125 // CHECK-DAG: [[ARR5:@.*arr5.*]] = internal constant [2 x i32] [i32 2, i32 0], align 4 126 constexpr int arr5[2](2); 127 128 // CHECK: define dso_local { i8, double } @{{.*foo1.*}} 129 // CHECK-NEXT: entry: 130 // CHECK-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_A]], align 8 131 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[RETVAL]], ptr align 8 [[A1]], i64 16, i1 false) 132 // CHECK-NEXT: [[TMP_0:%.*]] = load { i8, double }, ptr [[RETVAL]], align 8 133 // CHECK-NEXT: ret { i8, double } [[TMP_0]] 134 A foo1() { 135 return a1; 136 } 137 138 // CHECK: define dso_local void @{{.*foo2.*}}(ptr dead_on_unwind noalias writable sret([[STRUCT_B]]) align 8 [[AGG_RESULT:%.*]]) 139 // CHECK-NEXT: entry: 140 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_RESULT]], ptr align 8 [[B1]], i64 24, i1 false) 141 // CHECK-NEXT: ret void 142 B foo2() { 143 return b1; 144 } 145 146 // CHECK: define dso_local void @{{.*foo3.*}}(ptr dead_on_unwind noalias writable sret([[STRUCT_C]]) align 8 [[AGG_RESULT:%.*]]) 147 // CHECK-NEXT: entry: 148 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_RESULT]], ptr align 8 [[C1]], i64 48, i1 false) 149 // CHECK-NEXT: ret void 150 C foo3() { 151 return c1; 152 } 153 154 // CHECK: define dso_local void @{{.*foo4.*}} 155 // CHECK-NEXT: entry: 156 // CHECK-NEXT: [[C2:%.*]] = alloca [[STRUCT_C:%.*]], align 8 157 // CHECK-NEXT: [[REF_TMP:%.*]] = alloca [[STRUCT_B:%.*]], align 8 158 // CHECK-NEXT: [[REF_TMP_1:%.*]] = alloca [[STRUCT_A:%.*]], align 8 159 // CHECK-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_B]], ptr [[REF_TMP]], i32 0, i32 0 160 // CHECK-NEXT: [[I:%.*]] = getelementptr inbounds nuw [[STRUCT_A]], ptr [[A]], i32 0, i32 0 161 // CHECK-NEXT: store i8 1, ptr [[I]], align 8 162 // CHECK-NEXT: [[J:%.*]] = getelementptr inbounds nuw [[STRUCT_A]], ptr [[A]], i32 0, i32 1 163 // CHECK-NEXT: store double 1.000000e+00, ptr [[J]], align 8 164 // CHECK-NEXT: [[B:%.*]] = getelementptr inbounds nuw [[STRUCT_B]], ptr [[REF_TMP]], i32 0, i32 1 165 // CHECK-NEXT: store i32 1, ptr [[B]], align 8 166 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[C2]], ptr align 8 [[REF_TMP]], i64 24, i1 false) 167 // CHECK-NEXT: [[TMP_0:%.*]] = getelementptr inbounds i8, ptr [[C2]], i64 24 168 // CHECK-NEXT: [[I2:%.*]] = getelementptr inbounds nuw [[STRUCT_A]], ptr [[REF_TMP_1]], i32 0, i32 0 169 // CHECK-NEXT: store i8 97, ptr [[I2]], align 8 170 // CHECK-NEXT: [[J3:%.*]] = getelementptr inbounds nuw [[STRUCT_A]], ptr [[REF_TMP_1]], i32 0, i32 1 171 // CHECK-NEXT: store double 0.000000e+00, ptr [[J3]], align 8 172 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[TMP_0]], ptr align 8 [[REF_TMP_1]], i64 16, i1 false) 173 // CHECK-NEXT: [[C:%.*]] = getelementptr inbounds nuw %struct.C, ptr %c2, i32 0, i32 2 174 // CHECK-NEXT: store i32 2, ptr %c, align 8 175 // CHECK-NEXT: ret void 176 void foo4() { 177 C c2(B(A(1, 1), 1), A('a'), 2); 178 } 179 180 // CHECK: define dso_local { i64, double } @{{.*foo5.*}} 181 // CHECK-NEXT: entry: 182 // CHECK-NEXT [[RETVAL:%.*]] = alloca [[UNION_U]], align 8 183 // CHECK-NEXT call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[RETVAL]], ptr align 8 [[U1]], i64 16, i1 false) 184 // CHECK-NEXT [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[UNION_U]], ptr %retval, i32 0, i32 0 185 // CHECK-NEXT [[TMP_0:%.*]] = load { i64, double }, ptr [[COERCE_DIVE]], align 8 186 // CHECK-NEXT ret { i64, double } [[TMP_0]] 187 U foo5() { 188 return u1; 189 } 190 191 192 // CHECK: define dso_local { i64, double } @{{.*foo6.*}}(i8 [[A_COERCE_0:%.*]], double [[A_COERCE_1:%.*]]) 193 // CHECK-NEXT: entry: 194 // CHECK-NEXT: [[RETVAL:%.*]] = alloca [[UNION_U]], align 8 195 // CHECK-NEXT: [[A:%.*]] = alloca [[STRUCT_A]], align 8 196 // CHECK-NEXT: [[TMP_0:%.*]] = getelementptr inbounds nuw { i8, double }, ptr [[A]], i32 0, i32 0 197 // CHECK-NEXT: store i8 [[A_COERCE_0]], ptr [[TMP_0]], align 8 198 // CHECK-NEXT: [[TMP_1:%.*]] = getelementptr inbounds nuw { i8, double }, ptr [[A]], i32 0, i32 1 199 // CHECK-NEXT: store double [[A_COERCE_1]], ptr [[TMP_1]], align 8 200 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[RETVAL]], ptr align 8 [[A]], i64 16, i1 false) 201 // CHECK-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[UNION_U]], ptr [[RETVAL]], i32 0, i32 0 202 // CHECK-NEXT: [[TMP_2:%.*]] = load { i64, double }, ptr [[COERCE_DIVE:%.*]], align 8 203 // CHECK-NEXT: ret { i64, double } [[TMP_2]] 204 U foo6(A a) { 205 return U(a); 206 } 207 208 // CHECK: define dso_local void @{{.*foo7.*}} 209 // CHECK-NEXT: entry: 210 // CHECK-NEXT: [[D:%.*]] = alloca [[STRUCT_D:%.*]], align 8 211 // CHECK-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_D]], ptr [[D]], i32 0, i32 0 212 // CHECK-NEXT: [[I]] = getelementptr inbounds nuw [[STRUCT_A:%.*]], ptr [[A]], i32 0, i32 0 213 // CHECK-NEXT: store i8 1, ptr [[I]], align 8 214 // CHECK-NEXT: [[J:%.*]] = getelementptr inbounds nuw [[STRUCT_A]], ptr [[A]], i32 0, i32 1 215 // CHECK-NEXT: store double 1.000000e+00, ptr [[J]], align 8 216 // CHECK-NEXT: [[B:%.*]] = getelementptr inbounds nuw [[STRUCT_D]], ptr [[D]], i32 0, i32 1 217 // CHECK-NEXT: [[I1:%.*]] = getelementptr inbounds nuw [[STRUCT_A]], ptr [[B]], i32 0, i32 0 218 // CHECK-NEXT: store i8 11, ptr [[I1]], align 8 219 // CHECK-NEXT: [[J2:%.*]] = getelementptr inbounds nuw [[STRUCT_A]], ptr [[B]], i32 0, i32 1 220 // CHECK-NEXT: store double 1.100000e+01, ptr [[J2]], align 8 221 // CHECK-NEXT: [[C:%.*]] = getelementptr inbounds nuw [[STRUCT_D]], ptr [[D]], i32 0, i32 3 222 // CHECK-NEXT: [[I3:%.*]] = getelementptr inbounds nuw [[STRUCT_A]], ptr [[C]], i32 0, i32 0 223 // CHECK-NEXT: store i8 111, ptr [[I3]], align 8 224 // CHECK-NEXT: [[J4:%.*]] = getelementptr inbounds nuw [[STRUCT_A]], ptr [[C]], i32 0, i32 1 225 // CHECK-NEXT: store double 1.110000e+02, ptr [[J4]], align 8 226 // CHECK-NEXT: ret void 227 void foo7() { 228 D d(A(1, 1), A(11, 11), A(111, 111)); 229 } 230 231 // CHECK: dso_local void @{{.*foo8.*}}(ptr dead_on_unwind noalias writable sret([[STRUCT_D]]) align 8 [[AGG_RESULT:%.*]]) 232 // CHECK-NEXT: entry: 233 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_RESULT]], ptr align 8 [[D1]], i64 56, i1 false) 234 // CHECK-NEXT: ret void 235 D foo8() { 236 return d1; 237 } 238 239 // CHECK: define dso_local void @{{.*foo9.*}} 240 // CHECK-NEXT: entry: 241 // CHECK-NEXT: [[D:%.*]] = alloca [[STRUCT_D:%.*]], align 8 242 // CHECK-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_D]], ptr [[D]], i32 0, i32 0 243 // CHECK-NEXT: [[I]] = getelementptr inbounds nuw [[STRUCT_A:%.*]], ptr [[A]], i32 0, i32 0 244 // CHECK-NEXT: store i8 1, ptr [[I]], align 8 245 // CHECK-NEXT: [[J:%.*]] = getelementptr inbounds nuw [[STRUCT_A]], ptr [[A]], i32 0, i32 1 246 // CHECK-NEXT: store double 1.000000e+00, ptr [[J]], align 8 247 // CHECK-NEXT: [[B:%.*]] = getelementptr inbounds nuw [[STRUCT_D]], ptr [[D]], i32 0, i32 1 248 // CHECK-NEXT: [[I1:%.*]] = getelementptr inbounds nuw [[STRUCT_A]], ptr [[B]], i32 0, i32 0 249 // CHECK-NEXT: store i8 2, ptr [[I1]], align 8 250 // CHECK-NEXT: [[J2:%.*]] = getelementptr inbounds nuw [[STRUCT_A]], ptr [[B]], i32 0, i32 1 251 // CHECK-NEXT: store double 2.000000e+00, ptr [[J2]], align 8 252 // CHECK-NEXT: [[C:%.*]] = getelementptr inbounds nuw [[STRUCT_D]], ptr [[D]], i32 0, i32 3 253 // CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[C]], i8 0, i64 16, i1 false) 254 // CHECK-NEXT: ret void 255 void foo9() { 256 D d(A(1, 1)); 257 } 258 259 // CHECK: define dso_local noundef ptr @{{.*foo10.*}}() 260 // CHECK-NEXT: entry: 261 // CHECK-NEXT: ret ptr [[ARR1]] 262 const int* foo10() { 263 return arr1; 264 } 265 266 // CHECK: define dso_local void @{{.*foo11.*}} 267 // CHECK-NEXT: entry: 268 // CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 269 // CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4 270 // CHECK-NEXT: [[ARR_2:%.*]] = alloca [4 x i32], align 16 271 // CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4 272 // CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4 273 // CHECK-NEXT: [[TMP_0:%.*]] = load i32, ptr [[A_ADDR]], align 4 274 // CHECK-NEXT: store i32 [[TMP_0]], ptr [[ARR_2]], align 4 275 // CHECK-NEXT: [[ARRINIT_ELEM:%.*]] = getelementptr inbounds i32, ptr [[ARR_2]], i64 1 276 // CHECK-NEXT: [[TMP_1:%.*]] = load i32, ptr [[B_ADDR]], align 4 277 // CHECK-NEXT: store i32 [[TMP_1]], ptr [[ARRINIT_ELEM]], align 4 278 // CHECK-NEXT: [[ARRINIT_START:%.*]] = getelementptr inbounds i32, ptr [[ARR_2]], i64 2 279 // CHECK-NEXT: [[ARRINIT_END:%.*]] = getelementptr inbounds i32, ptr [[ARR_2]], i64 4 280 // CHECK-NEXT: br label [[ARRINIT_BODY:%.*]] 281 // CHECK: [[ARRINIT_CUR:%.*]] = phi ptr [ [[ARRINIT_START]], %entry ], [ [[ARRINIT_NEXT:%.*]], [[ARRINIT_BODY]] ] 282 // CHECK-NEXT: store i32 0, ptr [[ARRINIT_CUR]], align 4 283 // CHECK-NEXT: [[ARRINIT_NEXT]] = getelementptr inbounds i32, ptr [[ARRINIT_CUR]], i64 1 284 // CHECK-NEXT: [[ARRINIT_DONE:%.*]] = icmp eq ptr [[ARRINIT_NEXT]], [[ARRINIT_END:%.*]] 285 // CHECK-NEXT: br i1 [[ARRINIT_DONE]], label [[ARRINIT_END1:%.*]], label [[ARRINIT_BODY]] 286 // CHECK: ret void 287 void foo11(int a, int b) { 288 int arr2[4](a, b); 289 } 290 291 // CHECK: define dso_local void @{{.*foo12.*}} 292 // CHECK-NEXT: entry: 293 // CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 294 // CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4 295 // CHECK-NEXT: [[ARR_3:%.*]] = alloca [2 x i32], align 4 296 // CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4 297 // CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4 298 // CHECK-NEXT: [[TMP_0:%.*]] = load i32, ptr [[A_ADDR]], align 4 299 // CHECK-NEXT: store i32 [[TMP_0]], ptr [[ARR_3]], align 4 300 // CHECK-NEXT: [[ARRINIT_ELEMENT:%.*]] = getelementptr inbounds i32, ptr [[ARR_3]], i64 1 301 // CHECK-NEXT: [[TMP_1:%.*]] = load i32, ptr [[B_ADDR]], align 4 302 // CHECK-NEXT: store i32 [[TMP_1]], ptr [[ARRINIT_ELEMENT]], align 4 303 // CHECK-NEXT: ret void 304 void foo12(int a, int b) { 305 int arr3[](a, b); 306 } 307 308 // CHECK: define dso_local { i8, double } @{{.*foo13.*}} 309 // CHECK-NEXT: entry: 310 // CHECK-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_A]], align 8 311 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[RETVAL]], ptr align 8 [[A2]], i64 16, i1 false) 312 // CHECK-NEXT: [[TMP_0:%.*]] = load { i8, double }, ptr [[RETVAL]], align 8 313 // CHECK-NEXT: ret { i8, double } [[TMP_0]] 314 A foo13() { 315 return a2; 316 } 317 318 // CHECK: define dso_local noundef ptr @{{.*foo14.*}}() 319 // CHECK-NEXT: entry: 320 // CHECK-NEXT: ret ptr [[ARR4]] 321 const int* foo14() { 322 return arr4; 323 } 324 325 // CHECK: define dso_local noundef ptr @{{.*foo15.*}}() 326 // CHECK-NEXT: entry: 327 // CHECK-NEXT: ret ptr [[ARR5]] 328 const int* foo15() { 329 return arr5; 330 } 331 332 // CHECK: define dso_local void @{{.*foo16.*}} 333 // CHECK-NEXT: entry: 334 // CHECK-NEXT: [[ARR_6:%.*arr6.*]] = alloca ptr, align 8 335 // CHECK-NEXT: [[REF_TMP:%.*]] = alloca [1 x i32], align 4 336 // CHECK-NEXT: store i32 3, ptr [[REF_TMP]], align 4 337 // CHECK-NEXT: store ptr [[REF_TMP]], ptr [[ARR_6]], align 8 338 // CHECK-NEXT: ret void 339 void foo16() { 340 int (&&arr6)[] = static_cast<int[]>(3); 341 } 342 343 // CHECK: define dso_local void @{{.*foo17.*}} 344 // CHECK-NEXT: entry: 345 // CHECK-NEXT: [[ARR_7:%.*arr7.*]] = alloca ptr, align 8 346 // CHECK-NEXT: [[REF_TMP:%.*]] = alloca [2 x i32], align 4 347 // CHECK-NEXT: store i32 4, ptr [[REF_TMP]], align 4 348 // CHECK-NEXT: [[ARRINIT_START:%.*]] = getelementptr inbounds i32, ptr [[REF_TMP]], i64 1 349 // CHECK-NEXT: [[ARRINIT_END:%.*]] = getelementptr inbounds i32, ptr [[REF_TMP]], i64 2 350 // CHECK-NEXT: br label [[ARRINIT_BODY]] 351 // CHECK: [[ARRINIT_CUR:%.*]] = phi ptr [ [[ARRINIT_START]], %entry ], [ [[ARRINIT_NEXT:%.*]], [[ARRINIT_BODY]] ] 352 // CHECK-NEXT: store i32 0, ptr [[ARRINIT_CUR]], align 4 353 // CHECK-NEXT: [[ARRINIT_NEXT]] = getelementptr inbounds i32, ptr [[ARRINIT_CUR]], i64 1 354 // CHECK-NEXT: [[ARRINIT_DONE:%.*]] = icmp eq ptr [[ARRINIT_NEXT]], [[ARRINIT_END:%.*]] 355 // CHECK-NEXT: br i1 [[ARRINIT_DONE]], label [[ARRINIT_END1:%.*]], label [[ARRINIT_BODY]] 356 // CHECK: store ptr [[REF_TMP]], ptr [[ARR_7]], align 8 357 // CHECK: ret void 358 void foo17() { 359 int (&&arr7)[2] = static_cast<int[2]>(4); 360 } 361 362 // CHECK: define dso_local void @{{.*foo18.*}} 363 // CHECK-NEXT: entry: 364 // CHECK-NEXT: [[E:%.*e.*]] = alloca [[STRUCT_E]], align 8 365 // CHECK-NEXT: [[A:%.*a.*]] = getelementptr inbounds nuw [[STRUCT_E]], ptr [[E]], i32 0, i32 0 366 // CHECK-NEXT: store i32 1, ptr [[A]], align 8 367 // CHECK-NEXT: [[FN:%.*fn.*]] = getelementptr inbounds nuw [[STRUCT_E]], ptr [[E]], i32 0, i32 1 368 // CHECK-NEXT: store ptr [[STR]], ptr [[FN]], align 8 369 // CHECK: ret void 370 void foo18() { 371 E e(1); 372 } 373 374 // CHECK: define dso_local void @{{.*foo19.*}} 375 // CHECK-NEXT: entry: 376 // CHECK-NEXT: [[G:%.*g.*]] = alloca [[STRUCT_G]], align 4 377 // CHECK-NEXT: [[A:%.*a.*]] = getelementptr inbounds nuw [[STRUCT_G]], ptr [[G]], i32 0, i32 0 378 // CHECK-NEXT: store i32 2, ptr [[A]], align 4 379 // CHECK-NEXT: [[F:%.*]] = getelementptr inbounds i8, ptr [[G]], i64 4 380 // CHECk-NEXT: call void @{{.*F.*}}(ptr noundef nonnull align 1 dereferenceable(1)) [[F]], ie32 noundef 1) 381 // CHECK: ret void 382 void foo19() { 383 G g(2); 384 } 385 386 namespace gh61145 { 387 // a.k.a. void make1<0>() 388 // CHECK: define {{.*}} void @_ZN7gh611455make1ILi0EEEvv 389 // CHECK-NEXT: entry: 390 // CHECK-NEXT: [[V:%.*v.*]] = alloca [[STRUCT_VEC]], align 1 391 // CHECK-NEXT: [[AGG_TMP_ENSURED:%.*agg.tmp.ensured.*]] = alloca [[STRUCT_S1]], align 1 392 // a.k.a. Vec::Vec() 393 // CHECK-NEXT: call void @_ZN7gh611453VecC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[V]]) 394 // a.k.a. Vec::Vec(Vec&&) 395 // CHECK-NEXT: call void @_ZN7gh611453VecC1EOS0_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_TMP_ENSURED]], ptr noundef nonnull align 1 dereferenceable(1) [[V]]) 396 // a.k.a. S1::~S1() 397 // CHECK-NEXT: call void @_ZN7gh611452S1D1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_TMP_ENSURED]]) 398 // a.k.a.Vec::~Vec() 399 // CHECK-NEXT: call void @_ZN7gh611453VecD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[V]]) 400 // CHECK-NEXT: ret void 401 template <int I> 402 void make1() { 403 Vec v; 404 S1((Vec&&) v); 405 } 406 407 // a.k.a. void make1<0>() 408 // CHECK: define {{.*}} void @_ZN7gh611455make2ILi0EEEvv 409 // CHECK-NEXT: entry: 410 // CHECK-NEXT: [[V:%.*v.*]] = alloca [[STRUCT_VEC]], align 1 411 // CHECK-NEXT: [[AGG_TMP_ENSURED:%.*agg.tmp.ensured.*]] = alloca [[STRUCT_S2]], align 1 412 // a.k.a. Vec::Vec() 413 // CHECK-NEXT: call void @_ZN7gh611453VecC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[V]]) 414 // a.k.a. Vec::Vec(Vec&&) 415 // CHECK-NEXT: call void @_ZN7gh611453VecC1EOS0_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_TMP_ENSURED]], ptr noundef nonnull align 1 dereferenceable(1) [[V]]) 416 // CHECK-NEXT: [[C:%.*c.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 417 // CHECK-NEXT: store i8 0, ptr [[C]], align 1 418 // a.k.a. S2::~S2() 419 // CHECK-NEXT: call void @_ZN7gh611452S2D1Ev(ptr noundef nonnull align 1 dereferenceable(2) [[AGG_TMP_ENSURED]]) 420 // a.k.a. Vec::~Vec() 421 // CHECK-NEXT: call void @_ZN7gh611453VecD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[V]]) 422 // CHECK-NEXT: ret void 423 template <int I> 424 void make2() { 425 Vec v; 426 S2((Vec&&) v, 0); 427 } 428 429 void foo() { 430 make1<0>(); 431 make2<0>(); 432 } 433 } 434 435 namespace gh62266 { 436 // CHECK: define {{.*}} void {{.*foo20.*}} 437 // CHECK-NEXT: entry: 438 // CHECK-NEXT: [[H:%.*h.*]] = alloca [[STRUCT_H]], align 4 439 // CHECK-NEXT: [[I:%.*i.*]] = getelementptr inbounds nuw [[STRUCT_H]], ptr [[H]], i32 0, i32 0 440 // CHECK-NEXT: store i32 1, ptr [[I]], align 4 441 // CHECK-NEXT: [[J:%.*j.*]] = getelementptr inbounds nuw [[STRUCT_H]], ptr [[H]], i32 0, i32 1 442 // CHECK-NEXT: store i32 2, ptr [[J]], align 4 443 // CHECK-NEXT: ret void 444 void foo20() { 445 H<2> h(1); 446 } 447 } 448 449 namespace gh61567 { 450 int foo20(); 451 452 // CHECK: define {{.*}} void @{{.*foo21.*}} { 453 // CHECK-NEXT: entry 454 // CHECK-NEXT: [[AGG_TMP_ENSURED:%.*]] = alloca [[STRUCT_I]], align 8 455 // CHECK-NEXT: [[REF_TMP:%.*]] = alloca i32, align 4 456 // CHECK-NEXT: [[A:%.*a.*]] = getelementptr inbounds nuw [[STRUCT_I]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 0 457 // CHECK-NEXT: store i32 0, ptr [[A]], align 8 458 // CHECK-NEXT: [[R:%.*r.*]] = getelementptr inbounds nuw [[STRUCT_I]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 1 459 // CHECK-NEXT: store i32 1, ptr [[REF_TMP]], align 4 460 // CHECK-NEXT: store ptr [[REF_TMP]], ptr [[R]], align 8 461 // CHECK-NEXT: ret void 462 void foo21() { 463 I(0, 1); 464 } 465 466 // CHECK: define {{.*}} void @{{.*foo22.*}} { 467 // CHECK-NEXT: entry 468 // CHECK-NEXT: [[AGG_TMP_ENSURED:%.*]] = alloca [[STRUCT_I]], align 8 469 // CHECK-NEXT: [[REF_TMP:%.*]] = alloca i32, align 4 470 // CHECK-NEXT: [[A:%.*a.*]] = getelementptr inbounds nuw [[STRUCT_I]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 0 471 // CHECK-NEXT: store i32 0, ptr [[A]], align 8 472 // CHECK-NEXT: [[R:%.*r.*]] = getelementptr inbounds nuw [[STRUCT_I]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 1 473 // CHECK-NEXT: [[CALL:%.*call*]] = call noundef i32 @{{.*foo20.*}} 474 // CHECK-NEXT: store i32 [[CALL]], ptr [[REF_TMP]], align 4 475 // CHECK-NEXT: store ptr [[REF_TMP]], ptr [[R]], align 8 476 // CHECK-NEXT: ret void 477 void foo22() { 478 I(0, foo20()); 479 } 480 481 // CHECK: define {{.*}} void @{{.*foo23.*}}(i32 noundef [[I:%.*i.*]]) 482 // CHECK-NEXT: entry 483 // CHECK-NEXT: [[I_ADDR:%.*i.*]] = alloca i32, align 4 484 // CHECK-NEXT: [[AGG_TMP_ENSURED:%.*]] = alloca [[STRUCT_I]], align 8 485 // CHECK-NEXT: store i32 [[I]], ptr [[I_ADDR]], align 4 486 // CHECK-NEXT: [[A:%.*a.*]] = getelementptr inbounds nuw [[STRUCT_I]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 0 487 // CHECK-NEXT: store i32 0, ptr [[A]], align 8 488 // CHECK-NEXT: [[R:%.*r.*]] = getelementptr inbounds nuw [[STRUCT_I]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 1 489 // CHECK-NEXT: store ptr [[I_ADDR]], ptr [[R]], align 8 490 // CHECK-NEXT: ret void 491 void foo23(int i) { 492 I(0, static_cast<int&&>(i)); 493 } 494 495 // CHECK: define {{.*}} void @{{.*foo24.*}} { 496 // CHECK-NEXT: entry 497 // CHECK-NEXT: [[AGG_TMP_ENSURED:%.*]] = alloca [[STRUCT_I]], align 8 498 // CHECK-NEXT: [[REF_TMP:%.*]] = alloca i32, align 4 499 // CHECK-NEXT: [[A:%.*a.*]] = getelementptr inbounds nuw [[STRUCT_I]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 0 500 // CHECK-NEXT: store i32 0, ptr [[A]], align 8 501 // CHECK-NEXT: [[R:%.*r.*]] = getelementptr inbounds nuw [[STRUCT_I]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 1 502 // CHECK-NEXT: store i32 2, ptr [[REF_TMP]], align 4 503 // CHECK-NEXT: store ptr [[REF_TMP]], ptr [[R]], align 8 504 // CHECK-NEXT: ret void 505 void foo24() { 506 I(0); 507 } 508 } 509 510 namespace gh68198 { 511 // CHECK: define {{.*}} void @{{.*foo25.*}} { 512 // CHECK-NEXT: entry 513 // CHECK-NEXT: [[ARR_8:%.*arr8.*]] = alloca ptr, align 8 514 // CHECK-NEXT: [[CALL_PTR:%.*]] = call noalias noundef nonnull ptr @_Znam(i64 noundef 8) 515 // CHECK-NEXT: store i32 1, ptr [[CALL_PTR]], align 4 516 // CHECK-NEXT: [[ARRAY_EXP_NEXT:%.*]] = getelementptr inbounds i32, ptr [[CALL_PTR]], i64 1 517 // CHECK-NEXT: store i32 2, ptr [[ARRAY_EXP_NEXT]], align 4 518 // CHECK-NEXT: [[ARRAY_EXP_NEXT1:%.*]] = getelementptr inbounds i32, ptr [[ARRAY_EXP_NEXT]], i64 1 519 // CHECK-NEXT: store ptr [[CALL_PTR]], ptr %arr8, align 8 520 // CHECK-NEXT: ret void 521 void foo25() { 522 int* arr8 = new int[](1, 2); 523 } 524 525 // CHECK: define {{.*}} void @{{.*foo26.*}} { 526 // CHECK-NEXT: entry 527 // CHECK-NEXT: [[ARR_10:%.*arr9.*]] = alloca ptr, align 8 528 // CHECK-NEXT: [[CALL_PTR]] = call noalias noundef nonnull ptr @_Znam(i64 noundef 16) 529 // CHECK-NEXT: store i32 1, ptr [[CALL]], align 4 530 // CHECK-NEXT: [[ARRAYINIT_ELEMENT:%.*]] = getelementptr inbounds i32, ptr [[CALL]], i64 1 531 // CHECK-NEXT: store i32 2, ptr [[ARRAYINIT_ELEMENT]], align 4 532 // CHECK-NEXT: [[ARRAY_EXP_NEXT:%.*]] = getelementptr inbounds [2 x i32], ptr %call, i64 1 533 // CHECK-NEXT: store i32 3, ptr [[ARRAY_EXP_NEXT]], align 4 534 // CHECK-NEXT: [[ARRAYINIT_ELEMENT2:%.*]] = getelementptr inbounds i32, ptr [[ARRAY_EXP_NEXT]], i64 1 535 // CHECK-NEXT: store i32 4, ptr [[ARRAYINIT_ELEMENT2]], align 4 536 // CHECK-NEXT: [[ARRAY_EXP_NEXT3:%.*]] = getelementptr inbounds [2 x i32], ptr [[ARRAY_EXP_NEXT]], i64 1 537 // CHECK-NEXT: store ptr [[CALL_PTR]], ptr [[ARR_10]], align 8 538 // CHECK-NEXT: ret void 539 void foo26() { 540 void* arr9 = new int[][2]({1, 2}, {3, 4}); 541 } 542 543 // CHECK: define {{.*}} void @{{.*foo27.*}} { 544 // CHECK-NEXT: entry 545 // CHECK-NEXT: [[ARR_10:%.*arr10.*]] = alloca ptr, align 8 546 // CHECK-NEXT: [[CALL_PTR]] = call noalias noundef nonnull ptr @_Znam(i64 noundef 32) 547 // CHECK-NEXT: store i32 5, ptr [[CALL]], align 4 548 // CHECK-NEXT: [[ARRAYINIT_ELEMENT:%.*]] = getelementptr inbounds i32, ptr [[CALL]], i64 1 549 // CHECK-NEXT: store i32 6, ptr [[ARRAYINIT_ELEMENT]], align 4 550 // CHECK-NEXT: [[ARRAY_EXP_NEXT:%.*]] = getelementptr inbounds [2 x i32], ptr %call, i64 1 551 // CHECK-NEXT: store i32 7, ptr [[ARRAY_EXP_NEXT]], align 4 552 // CHECK-NEXT: [[ARRAYINIT_ELEMENT2:%.*]] = getelementptr inbounds i32, ptr [[ARRAY_EXP_NEXT]], i64 1 553 // CHECK-NEXT: store i32 8, ptr [[ARRAYINIT_ELEMENT2]], align 4 554 // CHECK-NEXT: [[ARRAY_EXP_NEXT3:%.*]] = getelementptr inbounds [2 x i32], ptr [[ARRAY_EXP_NEXT]], i64 1 555 // CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[ARRAY_EXP_NEXT3]], i8 0, i64 16, i1 false) 556 // CHECK-NEXT: store ptr [[CALL_PTR]], ptr [[ARR_10]], align 8 557 // CHECK-NEXT: ret void 558 void foo27() { 559 void* arr10 = new int[4][2]({5, 6}, {7, 8}); 560 } 561 } 562