1// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -emit-llvm -o - -DUSESTRUCT %s | FileCheck %s 2 3// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -emit-pch -o %t %s 4// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -include-pch %t -emit-llvm -o - -DUSESTRUCT %s | FileCheck %s 5 6#ifndef HEADER 7#define HEADER 8 9typedef void (^BlockTy)(void); 10 11typedef struct { 12 int a[4]; 13} Trivial; 14 15typedef struct { 16 Trivial f0; 17 id f1; 18} Strong; 19 20typedef struct { 21 int i; 22 id f1; 23} StrongSmall; 24 25typedef struct { 26 Strong f0; 27 id f1; 28 double d; 29} StrongOuter; 30 31typedef struct { 32 id f0; 33 Strong f1; 34} StrongOuter2; 35 36typedef struct { 37 int f0; 38 volatile id f1; 39} StrongVolatile; 40 41typedef struct { 42 BlockTy f0; 43} StrongBlock; 44 45typedef struct { 46 int i; 47 id f0[2][2]; 48} IDArray; 49 50typedef struct { 51 double d; 52 Strong f0[2][2]; 53} StructArray; 54 55typedef struct { 56 id f0; 57 int i : 9; 58} Bitfield0; 59 60typedef struct { 61 char c; 62 int i0 : 2; 63 int i1 : 4; 64 id f0; 65 int i2 : 31; 66 int i3 : 1; 67 id f1; 68 int : 0; 69 int a[3]; 70 id f2; 71 double d; 72 int i4 : 1; 73 volatile int i5 : 2; 74 volatile char i6; 75} Bitfield1; 76 77typedef struct { 78 id x; 79 volatile int a[16]; 80} VolatileArray ; 81 82typedef struct { 83 _Bool f0[2]; 84 VolatileArray f1; 85} StructWithBool; 86 87#endif 88 89#ifdef USESTRUCT 90 91StrongSmall getStrongSmall(void); 92StrongOuter getStrongOuter(void); 93StrongOuter2 getStrongOuter2(void); 94void calleeStrongSmall(StrongSmall); 95void func(Strong *); 96 97@interface C 98- (StrongSmall)getStrongSmall; 99- (void)m:(StrongSmall)s; 100+ (StrongSmall)getStrongSmallClass; 101@end 102 103id g0; 104StrongSmall g1, g2; 105 106// CHECK: %[[STRUCT_STRONGSMALL:.*]] = type { i32, ptr } 107// CHECK: %[[STRUCT_STRONGOUTER:.*]] = type { %[[STRUCT_STRONG:.*]], ptr, double } 108// CHECK: %[[STRUCT_STRONG]] = type { %[[STRUCT_TRIVIAL:.*]], ptr } 109// CHECK: %[[STRUCT_TRIVIAL]] = type { [4 x i32] } 110// CHECK: %[[STRUCT_BLOCK_BYREF_T:.*]] = type { ptr, ptr, i32, i32, ptr, ptr, ptr, %[[STRUCT_STRONGOUTER]] } 111// CHECK: %[[STRUCT_STRONGBLOCK:.*]] = type { ptr } 112// CHECK: %[[STRUCT_BITFIELD1:.*]] = type { i8, i8, ptr, i32, ptr, [3 x i32], ptr, double, i8, i8 } 113 114// CHECK: define{{.*}} void @test_constructor_destructor_StrongOuter() 115// CHECK: %[[T:.*]] = alloca %[[STRUCT_STRONGOUTER]], align 8 116// CHECK: call void @__default_constructor_8_S_s16_s24(ptr %[[T]]) 117// CHECK: call void @__destructor_8_S_s16_s24(ptr %[[T]]) 118// CHECK: ret void 119 120// CHECK: define linkonce_odr hidden void @__default_constructor_8_S_s16_s24(ptr noundef %[[DST:.*]]) 121// CHECK: %[[DST_ADDR:.*]] = alloca ptr, align 8 122// CHECK: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8 123// CHECK: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8 124// CHECK: call void @__default_constructor_8_s16(ptr %[[V0]]) 125// CHECK: %[[V2:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 24 126// CHECK: call void @llvm.memset.p0.i64(ptr align 8 %[[V2]], i8 0, i64 8, i1 false) 127// CHECK: ret void 128 129// CHECK: define linkonce_odr hidden void @__default_constructor_8_s16(ptr noundef %[[DST:.*]]) 130// CHECK: %[[DST_ADDR:.*]] = alloca ptr, align 8 131// CHECK: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8 132// CHECK: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8 133// CHECK: %[[V2:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 16 134// CHECK: call void @llvm.memset.p0.i64(ptr align 8 %[[V2]], i8 0, i64 8, i1 false) 135// CHECK: ret void 136 137// CHECK: define linkonce_odr hidden void @__destructor_8_S_s16_s24(ptr noundef %[[DST:.*]]) 138// CHECK: %[[DST_ADDR:.*]] = alloca ptr, align 8 139// CHECK: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8 140// CHECK: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8 141// CHECK: call void @__destructor_8_s16(ptr %[[V0]]) 142// CHECK: %[[V2:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 24 143// CHECK: call void @llvm.objc.storeStrong(ptr %[[V2]], ptr null) 144// CHECK: ret void 145 146// CHECK: define linkonce_odr hidden void @__destructor_8_s16(ptr noundef %[[DST:.*]]) 147// CHECK: %[[DST_ADDR:.*]] = alloca ptr, align 8 148// CHECK: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8 149// CHECK: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8 150// CHECK: %[[V2:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 16 151// CHECK: call void @llvm.objc.storeStrong(ptr %[[V2]], ptr null) 152// CHECK: ret void 153 154void test_constructor_destructor_StrongOuter(void) { 155 StrongOuter t; 156} 157 158// CHECK: define{{.*}} void @test_copy_constructor_StrongOuter(ptr noundef %[[S:.*]]) 159// CHECK: %[[S_ADDR:.*]] = alloca ptr, align 8 160// CHECK: %[[T:.*]] = alloca %[[STRUCT_STRONGOUTER]], align 8 161// CHECK: store ptr %[[S]], ptr %[[S_ADDR]], align 8 162// CHECK: %[[V0:.*]] = load ptr, ptr %[[S_ADDR]], align 8 163// CHECK: call void @__copy_constructor_8_8_S_t0w16_s16_s24_t32w8(ptr %[[T]], ptr %[[V0]]) 164// CHECK: call void @__destructor_8_S_s16_s24(ptr %[[T]]) 165// CHECK: ret void 166 167// CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_S_t0w16_s16_s24_t32w8(ptr noundef %[[DST:.*]], ptr noundef %[[SRC:.*]]) 168// CHECK: %[[DST_ADDR:.*]] = alloca ptr, align 8 169// CHECK: %[[SRC_ADDR:.*]] = alloca ptr, align 8 170// CHECK: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8 171// CHECK: store ptr %[[SRC]], ptr %[[SRC_ADDR]], align 8 172// CHECK: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8 173// CHECK: %[[V1:.*]] = load ptr, ptr %[[SRC_ADDR]], align 8 174// CHECK: call void @__copy_constructor_8_8_t0w16_s16(ptr %[[V0]], ptr %[[V1]]) 175// CHECK: %[[V3:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 24 176// CHECK: %[[V6:.*]] = getelementptr inbounds i8, ptr %[[V1]], i64 24 177// CHECK: %[[V8:.*]] = load ptr, ptr %[[V6]], align 8 178// CHECK: %[[V9:.*]] = call ptr @llvm.objc.retain(ptr %[[V8]]) 179// CHECK: store ptr %[[V9]], ptr %[[V3]], align 8 180// CHECK: %[[V11:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 32 181// CHECK: %[[V14:.*]] = getelementptr inbounds i8, ptr %[[V1]], i64 32 182// CHECK: %[[V18:.*]] = load i64, ptr %[[V14]], align 8 183// CHECK: store i64 %[[V18]], ptr %[[V11]], align 8 184// CHECK: ret void 185 186// CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_t0w16_s16(ptr noundef %[[DST:.*]], ptr noundef %[[SRC:.*]]) 187// CHECK: %[[DST_ADDR:.*]] = alloca ptr, align 8 188// CHECK: %[[SRC_ADDR:.*]] = alloca ptr, align 8 189// CHECK: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8 190// CHECK: store ptr %[[SRC]], ptr %[[SRC_ADDR]], align 8 191// CHECK: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8 192// CHECK: %[[V1:.*]] = load ptr, ptr %[[SRC_ADDR]], align 8 193// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[V0]], ptr align 8 %[[V1]], i64 16, i1 false) 194// CHECK: %[[V5:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 16 195// CHECK: %[[V8:.*]] = getelementptr inbounds i8, ptr %[[V1]], i64 16 196// CHECK: %[[V10:.*]] = load ptr, ptr %[[V8]], align 8 197// CHECK: %[[V11:.*]] = call ptr @llvm.objc.retain(ptr %[[V10]]) 198// CHECK: store ptr %[[V11]], ptr %[[V5]], align 8 199// CHECK: ret void 200 201void test_copy_constructor_StrongOuter(StrongOuter *s) { 202 StrongOuter t = *s; 203} 204 205/// CHECK: define linkonce_odr hidden void @__copy_assignment_8_8_S_t0w16_s16_s24_t32w8(ptr noundef %[[DST:.*]], ptr noundef %[[SRC:.*]]) 206// CHECK: %[[DST_ADDR:.*]] = alloca ptr, align 8 207// CHECK: %[[SRC_ADDR:.*]] = alloca ptr, align 8 208// CHECK: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8 209// CHECK: store ptr %[[SRC]], ptr %[[SRC_ADDR]], align 8 210// CHECK: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8 211// CHECK: %[[V1:.*]] = load ptr, ptr %[[SRC_ADDR]], align 8 212// CHECK: %[[V3:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 24 213// CHECK: %[[V6:.*]] = getelementptr inbounds i8, ptr %[[V1]], i64 24 214// CHECK: %[[V8:.*]] = load ptr, ptr %[[V6]], align 8 215// CHECK: call void @llvm.objc.storeStrong(ptr %[[V3]], ptr %[[V8]]) 216 217void test_copy_assignment_StrongOuter(StrongOuter *d, StrongOuter *s) { 218 *d = *s; 219} 220 221// CHECK: define{{.*}} void @test_move_constructor_StrongOuter() 222// CHECK: %[[T1:.*]] = getelementptr inbounds nuw %[[STRUCT_BLOCK_BYREF_T]], ptr %{{.*}}, i32 0, i32 7 223// CHECK: call void @__default_constructor_8_S_s16_s24(ptr %[[T1]]) 224// CHECK: %[[T2:.*]] = getelementptr inbounds nuw %[[STRUCT_BLOCK_BYREF_T]], ptr %{{.*}}, i32 0, i32 7 225// CHECK: call void @__destructor_8_S_s16_s24(ptr %[[T2]]) 226 227// CHECK: define internal void @__Block_byref_object_copy_(ptr noundef %0, ptr noundef %1) 228// CHECK: call void @__move_constructor_8_8_S_t0w16_s16_s24_t32w8( 229 230// CHECK: define linkonce_odr hidden void @__move_constructor_8_8_S_t0w16_s16_s24_t32w8(ptr noundef %[[DST:.*]], ptr noundef %[[SRC:.*]]) 231// CHECK: %[[DST_ADDR:.*]] = alloca ptr, align 8 232// CHECK: %[[SRC_ADDR:.*]] = alloca ptr, align 8 233// CHECK: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8 234// CHECK: store ptr %[[SRC]], ptr %[[SRC_ADDR]], align 8 235// CHECK: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8 236// CHECK: %[[V1:.*]] = load ptr, ptr %[[SRC_ADDR]], align 8 237// CHECK: call void @__move_constructor_8_8_t0w16_s16(ptr %[[V0]], ptr %[[V1]]) 238// CHECK: %[[V3:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 24 239// CHECK: %[[V6:.*]] = getelementptr inbounds i8, ptr %[[V1]], i64 24 240// CHECK: %[[V8:.*]] = load ptr, ptr %[[V6]], align 8 241// CHECK: store ptr null, ptr %[[V6]], align 8 242// CHECK: store ptr %[[V8]], ptr %[[V3]], align 8 243 244// CHECK: define internal void @__Block_byref_object_dispose_(ptr noundef %0) 245// CHECK: call void @__destructor_8_S_s16_s24( 246 247void test_move_constructor_StrongOuter(void) { 248 __block StrongOuter t; 249 BlockTy b = ^{ (void)t; }; 250} 251 252// CHECK: define linkonce_odr hidden void @__move_assignment_8_8_S_t0w16_s16_s24_t32w8(ptr noundef %[[DST:.*]], ptr noundef %[[SRC:.*]]) 253// CHECK: %[[DST_ADDR:.*]] = alloca ptr, align 8 254// CHECK: %[[SRC_ADDR:.*]] = alloca ptr, align 8 255// CHECK: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8 256// CHECK: store ptr %[[SRC]], ptr %[[SRC_ADDR]], align 8 257// CHECK: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8 258// CHECK: %[[V1:.*]] = load ptr, ptr %[[SRC_ADDR]], align 8 259// CHECK: call void @__move_assignment_8_8_t0w16_s16(ptr %[[V0]], ptr %[[V1]]) 260// CHECK: %[[V3:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 24 261// CHECK: %[[V6:.*]] = getelementptr inbounds i8, ptr %[[V1]], i64 24 262// CHECK: %[[V8:.*]] = load ptr, ptr %[[V6]], align 8 263// CHECK: store ptr null, ptr %[[V6]], align 8 264// CHECK: %[[V9:.*]] = load ptr, ptr %[[V3]], align 8 265// CHECK: store ptr %[[V8]], ptr %[[V3]], align 8 266// CHECK: call void @llvm.objc.release(ptr %[[V9]]) 267 268void test_move_assignment_StrongOuter(StrongOuter *p) { 269 *p = getStrongOuter(); 270} 271 272// CHECK: define linkonce_odr hidden void @__default_constructor_8_s0_S_s24(ptr noundef %[[DST:.*]]) 273// CHECK: %[[DST_ADDR:.*]] = alloca ptr, align 8 274// CHECK: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8 275// CHECK: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8 276// CHECK: call void @llvm.memset.p0.i64(ptr align 8 %[[V0]], i8 0, i64 8, i1 false) 277// CHECK: %[[V3:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 8 278// CHECK: call void @__default_constructor_8_s16(ptr %[[V3]]) 279 280// CHECK: define linkonce_odr hidden void @__destructor_8_s0_S_s24(ptr noundef %[[DST:.*]]) 281// CHECK: %[[DST_ADDR:.*]] = alloca ptr, align 8 282// CHECK: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8 283// CHECK: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8 284// CHECK: call void @llvm.objc.storeStrong(ptr %[[V0]], ptr null) 285// CHECK: %[[V2:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 8 286// CHECK: call void @__destructor_8_s16(ptr %[[V2]]) 287 288void test_constructor_destructor_StrongOuter2(void) { 289 StrongOuter2 t; 290} 291 292// CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_s0_S_t8w16_s24(ptr noundef %[[DST:.*]], ptr noundef %[[SRC:.*]]) 293// CHECK: %[[DST_ADDR:.*]] = alloca ptr, align 8 294// CHECK: %[[SRC_ADDR:.*]] = alloca ptr, align 8 295// CHECK: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8 296// CHECK: store ptr %[[SRC]], ptr %[[SRC_ADDR]], align 8 297// CHECK: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8 298// CHECK: %[[V1:.*]] = load ptr, ptr %[[SRC_ADDR]], align 8 299// CHECK: %[[V2:.*]] = load ptr, ptr %[[V1]], align 8 300// CHECK: %[[V3:.*]] = call ptr @llvm.objc.retain(ptr %[[V2]]) 301// CHECK: store ptr %[[V3]], ptr %[[V0]], align 8 302// CHECK: %[[V5:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 8 303// CHECK: %[[V8:.*]] = getelementptr inbounds i8, ptr %[[V1]], i64 8 304// CHECK: call void @__copy_constructor_8_8_t0w16_s16(ptr %[[V5]], ptr %[[V8]]) 305 306void test_copy_constructor_StrongOuter2(StrongOuter2 *s) { 307 StrongOuter2 t = *s; 308} 309 310// CHECK: define linkonce_odr hidden void @__copy_assignment_8_8_s0_S_t8w16_s24(ptr noundef %[[DST:.*]], ptr noundef %[[SRC:.*]]) 311// CHECK: %[[DST_ADDR:.*]] = alloca ptr, align 8 312// CHECK: %[[SRC_ADDR:.*]] = alloca ptr, align 8 313// CHECK: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8 314// CHECK: store ptr %[[SRC]], ptr %[[SRC_ADDR]], align 8 315// CHECK: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8 316// CHECK: %[[V1:.*]] = load ptr, ptr %[[SRC_ADDR]], align 8 317// CHECK: %[[V2:.*]] = load ptr, ptr %[[V1]], align 8 318// CHECK: call void @llvm.objc.storeStrong(ptr %[[V0]], ptr %[[V2]]) 319// CHECK: %[[V4:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 8 320// CHECK: %[[V7:.*]] = getelementptr inbounds i8, ptr %[[V1]], i64 8 321// CHECK: call void @__copy_assignment_8_8_t0w16_s16(ptr %[[V4]], ptr %[[V7]]) 322 323void test_copy_assignment_StrongOuter2(StrongOuter2 *d, StrongOuter2 *s) { 324 *d = *s; 325} 326 327// CHECK: define linkonce_odr hidden void @__move_constructor_8_8_s0_S_t8w16_s24(ptr noundef %[[DST:.*]], ptr noundef %[[SRC:.*]]) 328// CHECK: %[[DST_ADDR:.*]] = alloca ptr, align 8 329// CHECK: %[[SRC_ADDR:.*]] = alloca ptr, align 8 330// CHECK: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8 331// CHECK: store ptr %[[SRC]], ptr %[[SRC_ADDR]], align 8 332// CHECK: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8 333// CHECK: %[[V1:.*]] = load ptr, ptr %[[SRC_ADDR]], align 8 334// CHECK: %[[V2:.*]] = load ptr, ptr %[[V1]], align 8 335// CHECK: store ptr null, ptr %[[V1]], align 8 336// CHECK: store ptr %[[V2]], ptr %[[V0]], align 8 337// CHECK: %[[V4:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 8 338// CHECK: %[[V7:.*]] = getelementptr inbounds i8, ptr %[[V1]], i64 8 339// CHECK: call void @__move_constructor_8_8_t0w16_s16(ptr %[[V4]], ptr %[[V7]]) 340 341void test_move_constructor_StrongOuter2(void) { 342 __block StrongOuter2 t; 343 BlockTy b = ^{ (void)t; }; 344} 345 346// CHECK: define linkonce_odr hidden void @__move_assignment_8_8_s0_S_t8w16_s24(ptr noundef %[[DST:.*]], ptr noundef %[[SRC:.*]]) 347// CHECK: %[[DST_ADDR:.*]] = alloca ptr, align 8 348// CHECK: %[[SRC_ADDR:.*]] = alloca ptr, align 8 349// CHECK: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8 350// CHECK: store ptr %[[SRC]], ptr %[[SRC_ADDR]], align 8 351// CHECK: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8 352// CHECK: %[[V1:.*]] = load ptr, ptr %[[SRC_ADDR]], align 8 353// CHECK: %[[V2:.*]] = load ptr, ptr %[[V1]], align 8 354// CHECK: store ptr null, ptr %[[V1]], align 8 355// CHECK: %[[V3:.*]] = load ptr, ptr %[[V0]], align 8 356// CHECK: store ptr %[[V2]], ptr %[[V0]], align 8 357// CHECK: call void @llvm.objc.release(ptr %[[V3]]) 358// CHECK: %[[V5:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 8 359// CHECK: %[[V8:.*]] = getelementptr inbounds i8, ptr %[[V1]], i64 8 360// CHECK: call void @__move_assignment_8_8_t0w16_s16(ptr %[[V5]], ptr %[[V8]]) 361 362void test_move_assignment_StrongOuter2(StrongOuter2 *p) { 363 *p = getStrongOuter2(); 364} 365 366// CHECK: define{{.*}} void @test_parameter_StrongSmall([2 x i64] %[[A_COERCE:.*]]) 367// CHECK: %[[A:.*]] = alloca %[[STRUCT_STRONGSMALL]], align 8 368// CHECK: store [2 x i64] %[[A_COERCE]], ptr %[[A]], align 8 369// CHECK: call void @__destructor_8_s8(ptr %[[A]]) 370// CHECK: ret void 371 372void test_parameter_StrongSmall(StrongSmall a) { 373} 374 375// CHECK: define{{.*}} void @test_argument_StrongSmall([2 x i64] %[[A_COERCE:.*]]) 376// CHECK: %[[A:.*]] = alloca %[[STRUCT_STRONGSMALL]], align 8 377// CHECK: %[[TEMP_LVALUE:.*]] = alloca %[[STRUCT_STRONGSMALL]], align 8 378// CHECK: store [2 x i64] %[[A_COERCE]], ptr %[[A]], align 8 379// CHECK: call void @__copy_constructor_8_8_t0w4_s8(ptr %[[TEMP_LVALUE]], ptr %[[A]]) 380// CHECK: %[[V4:.*]] = load [2 x i64], ptr %[[TEMP_LVALUE]], align 8 381// CHECK: call void @calleeStrongSmall([2 x i64] %[[V4]]) 382// CHECK: call void @__destructor_8_s8(ptr %[[A]]) 383// CHECK: ret void 384 385void test_argument_StrongSmall(StrongSmall a) { 386 calleeStrongSmall(a); 387} 388 389// CHECK: define{{.*}} [2 x i64] @test_return_StrongSmall([2 x i64] %[[A_COERCE:.*]]) 390// CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_STRONGSMALL]], align 8 391// CHECK: %[[A:.*]] = alloca %[[STRUCT_STRONGSMALL]], align 8 392// CHECK: store [2 x i64] %[[A_COERCE]], ptr %[[A]], align 8 393// CHECK: call void @__copy_constructor_8_8_t0w4_s8(ptr %[[RETVAL]], ptr %[[A]]) 394// CHECK: call void @__destructor_8_s8(ptr %[[A]]) 395// CHECK: %[[V5:.*]] = load [2 x i64], ptr %[[RETVAL]], align 8 396// CHECK: ret [2 x i64] %[[V5]] 397 398StrongSmall test_return_StrongSmall(StrongSmall a) { 399 return a; 400} 401 402// CHECK: define{{.*}} void @test_destructor_ignored_result() 403// CHECK: %[[COERCE:.*]] = alloca %[[STRUCT_STRONGSMALL]], align 8 404// CHECK: %[[CALL:.*]] = call [2 x i64] @getStrongSmall() 405// CHECK: store [2 x i64] %[[CALL]], ptr %[[COERCE]], align 8 406// CHECK: call void @__destructor_8_s8(ptr %[[COERCE]]) 407// CHECK: ret void 408 409void test_destructor_ignored_result(void) { 410 getStrongSmall(); 411} 412 413// CHECK: define{{.*}} void @test_destructor_ignored_result2(ptr noundef %[[C:.*]]) 414// CHECK: %[[TMP:.*]] = alloca %[[STRUCT_STRONGSMALL]], align 8 415// CHECK: %[[CALL:.*]] = call [2 x i64]{{.*}}@objc_msgSend 416// CHECK: store [2 x i64] %[[CALL]], ptr %[[TMP]], align 8 417// CHECK: call void @__destructor_8_s8(ptr %[[TMP]]) 418 419void test_destructor_ignored_result2(C *c) { 420 [c getStrongSmall]; 421} 422 423// CHECK: define{{.*}} void @test_copy_constructor_StrongBlock( 424// CHECK: call void @__copy_constructor_8_8_sb0( 425// CHECK: call void @__destructor_8_sb0( 426// CHECK: ret void 427 428// CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_sb0(ptr noundef %[[DST:.*]], ptr noundef %[[SRC:.*]]) 429// CHECK: %[[DST_ADDR:.*]] = alloca ptr, align 8 430// CHECK: %[[SRC_ADDR:.*]] = alloca ptr, align 8 431// CHECK: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8 432// CHECK: store ptr %[[SRC]], ptr %[[SRC_ADDR]], align 8 433// CHECK: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8 434// CHECK: %[[V1:.*]] = load ptr, ptr %[[SRC_ADDR]], align 8 435// CHECK: %[[V2:.*]] = load ptr, ptr %[[V1]], align 8 436// CHECK: %[[V3:.*]] = call ptr @llvm.objc.retainBlock(ptr %[[V2]]) 437// CHECK: store ptr %[[V3]], ptr %[[V0]], align 8 438// CHECK: ret void 439 440void test_copy_constructor_StrongBlock(StrongBlock *s) { 441 StrongBlock t = *s; 442} 443 444// CHECK: define{{.*}} void @test_copy_assignment_StrongBlock(ptr noundef %[[D:.*]], ptr noundef %[[S:.*]]) 445// CHECK: call void @__copy_assignment_8_8_sb0( 446 447// CHECK: define linkonce_odr hidden void @__copy_assignment_8_8_sb0(ptr noundef %[[DST:.*]], ptr noundef %[[SRC:.*]]) 448// CHECK: %[[DST_ADDR:.*]] = alloca ptr, align 8 449// CHECK: %[[SRC_ADDR:.*]] = alloca ptr, align 8 450// CHECK: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8 451// CHECK: store ptr %[[SRC]], ptr %[[SRC_ADDR]], align 8 452// CHECK: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8 453// CHECK: %[[V1:.*]] = load ptr, ptr %[[SRC_ADDR]], align 8 454// CHECK: %[[V2:.*]] = load ptr, ptr %[[V1]], align 8 455// CHECK: %[[V3:.*]] = call ptr @llvm.objc.retainBlock(ptr %[[V2]]) 456// CHECK: %[[V4:.*]] = load ptr, ptr %[[V0]], align 8 457// CHECK: store ptr %[[V3]], ptr %[[V0]], align 8 458// CHECK: call void @llvm.objc.release(ptr %[[V4]]) 459// CHECK: ret void 460 461void test_copy_assignment_StrongBlock(StrongBlock *d, StrongBlock *s) { 462 *d = *s; 463} 464 465// CHECK-LABEL: define{{.*}} void @test_copy_assignment_StructWithBool( 466// CHECK: call void @__copy_assignment_8_8_AB0s1n2_tv0w8_AE_S_sv8_AB16s4n16_tv128w32_AE( 467 468// CHECK-LABEL: define linkonce_odr hidden void @__copy_assignment_8_8_AB0s1n2_tv0w8_AE_S_sv8_AB16s4n16_tv128w32_AE( 469// CHECK: %[[ADDR_CUR:.*]] = phi ptr 470// CHECK: %[[ADDR_CUR1:.*]] = phi ptr 471 472// CHECK: %[[V6:.*]] = load volatile i8, ptr %[[ADDR_CUR1]], align 1 473// CHECK: %[[TOBOOL:.*]] = trunc i8 %[[V6]] to i1 474// CHECK: %[[FROMBOOL:.*]] = zext i1 %[[TOBOOL]] to i8 475// CHECK: store volatile i8 %[[FROMBOOL]], ptr %[[ADDR_CUR]], align 1 476 477void test_copy_assignment_StructWithBool(StructWithBool *d, StructWithBool *s) { 478 *d = *s; 479} 480 481// CHECK: define{{.*}} void @test_copy_constructor_StrongVolatile0( 482// CHECK: call void @__copy_constructor_8_8_t0w4_sv8( 483// CHECK-NOT: call 484// CHECK: call void @__destructor_8_sv8( 485// CHECK-NOT: call 486 487// CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_t0w4_sv8( 488// CHECK: %[[V8:.*]] = load volatile ptr, ptr %{{.*}}, align 8 489// CHECK: %[[V9:.*]] = call ptr @llvm.objc.retain(ptr %[[V8]]) 490// CHECK: store volatile ptr %[[V9]], ptr %{{.*}}, align 8 491 492void test_copy_constructor_StrongVolatile0(StrongVolatile *s) { 493 StrongVolatile t = *s; 494} 495 496// CHECK: define{{.*}} void @test_copy_constructor_StrongVolatile1( 497// CHECK: call void @__copy_constructor_8_8_tv0w128_sv16( 498 499void test_copy_constructor_StrongVolatile1(Strong *s) { 500 volatile Strong t = *s; 501} 502 503// CHECK: define{{.*}} void @test_block_capture_Strong() 504// CHECK: call void @__default_constructor_8_s16( 505// CHECK: call void @__copy_constructor_8_8_t0w16_s16( 506// CHECK: call void @__destructor_8_s16( 507// CHECK: call void @__destructor_8_s16( 508// CHECK: ret void 509 510// CHECK: define linkonce_odr hidden void @__copy_helper_block_8_32n13_8_8_t0w16_s16(ptr noundef %0, ptr noundef %1) 511// CHECK: call void @__copy_constructor_8_8_t0w16_s16( 512// CHECK: ret void 513 514// CHECK: define linkonce_odr hidden void @__destroy_helper_block_8_32n5_8_s16( 515// CHECK: call void @__destructor_8_s16( 516// CHECK: ret void 517 518void test_block_capture_Strong(void) { 519 Strong t; 520 BlockTy b = ^(void){ (void)t; }; 521} 522 523// CHECK: define{{.*}} void @test_variable_length_array(i32 noundef %[[N:.*]]) 524// CHECK: %[[N_ADDR:.*]] = alloca i32, align 4 525// CHECK: store i32 %[[N]], ptr %[[N_ADDR]], align 4 526// CHECK: %[[V0:.*]] = load i32, ptr %[[N_ADDR]], align 4 527// CHECK: %[[V1:.*]] = zext i32 %[[V0]] to i64 528// CHECK: %[[VLA:.*]] = alloca %[[STRUCT_STRONG]], i64 %[[V1]], align 8 529// CHECK: %[[V4:.*]] = mul nuw i64 24, %[[V1]] 530// CHECK: %[[V6:.*]] = getelementptr inbounds i8, ptr %[[VLA]], i64 %[[V4]] 531// CHECK: br label 532 533// CHECK: %[[DSTADDR_CUR:.*]] = phi ptr [ %[[VLA]], {{.*}} ], [ %[[V7:.*]], {{.*}} ] 534// CHECK: %[[DONE:.*]] = icmp eq ptr %[[DSTADDR_CUR]], %[[V6]] 535// CHECK: br i1 %[[DONE]], label 536 537// CHECK: call void @__default_constructor_8_s16(ptr %[[DSTADDR_CUR]]) 538// CHECK: %[[V9:.*]] = getelementptr inbounds i8, ptr %[[DSTADDR_CUR]], i64 24 539// CHECK: br label 540 541// CHECK: call void @func(ptr noundef %[[VLA]]) 542// CHECK: %[[V10:.*]] = getelementptr inbounds %[[STRUCT_STRONG]], ptr %[[VLA]], i64 %[[V1]] 543// CHECK: %[[ARRAYDESTROY_ISEMPTY:.*]] = icmp eq ptr %[[VLA]], %[[V10]] 544// CHECK: br i1 %[[ARRAYDESTROY_ISEMPTY]], label 545 546// CHECK: %[[ARRAYDESTROY_ELEMENTPAST:.*]] = phi ptr [ %[[V10]], {{.*}} ], [ %[[ARRAYDESTROY_ELEMENT:.*]], {{.*}} ] 547// CHECK: %[[ARRAYDESTROY_ELEMENT]] = getelementptr inbounds %[[STRUCT_STRONG]], ptr %[[ARRAYDESTROY_ELEMENTPAST]], i64 -1 548// CHECK: call void @__destructor_8_s16(ptr %[[ARRAYDESTROY_ELEMENT]]) 549// CHECK: %[[ARRAYDESTROY_DONE:.*]] = icmp eq ptr %[[ARRAYDESTROY_ELEMENT]], %[[VLA]] 550// CHECK: br i1 %[[ARRAYDESTROY_DONE]], label 551 552// CHECK: ret void 553 554void test_variable_length_array(int n) { 555 Strong a[n]; 556 func(a); 557} 558 559// CHECK: define linkonce_odr hidden void @__default_constructor_8_AB8s8n4_s8_AE( 560// CHECK: call void @llvm.memset.p0.i64(ptr align 8 %{{.*}}, i8 0, i64 32, i1 false) 561void test_constructor_destructor_IDArray(void) { 562 IDArray t; 563} 564 565// CHECK: define linkonce_odr hidden void @__default_constructor_8_AB8s24n4_S_s24_AE( 566void test_constructor_destructor_StructArray(void) { 567 StructArray t; 568} 569 570// Test that StructArray's field 'd' is copied before entering the loop. 571 572// CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_t0w8_AB8s24n4_S_t8w16_s24_AE(ptr noundef %[[DST:.*]], ptr noundef %[[SRC:.*]]) 573// CHECK: entry: 574// CHECK: %[[DST_ADDR:.*]] = alloca ptr, align 8 575// CHECK: %[[SRC_ADDR:.*]] = alloca ptr, align 8 576// CHECK: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8 577// CHECK: store ptr %[[SRC]], ptr %[[SRC_ADDR]], align 8 578// CHECK: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8 579// CHECK: %[[V1:.*]] = load ptr, ptr %[[SRC_ADDR]], align 8 580// CHECK: %[[V4:.*]] = load i64, ptr %[[V1]], align 8 581// CHECK: store i64 %[[V4]], ptr %[[V0]], align 8 582 583// CHECK: phi ptr 584// CHECK: phi ptr 585 586// CHECK: phi ptr 587// CHECK: phi ptr 588 589// CHECK-NOT: load i64, ptr % 590// CHECK-NOT: store i64 % 591// CHECK: call void @__copy_constructor_8_8_t0w16_s16( 592 593void test_copy_constructor_StructArray(StructArray a) { 594 StructArray t = a; 595} 596 597// Check that IRGen copies the 9-bit bitfield emitting i16 load and store. 598 599// CHECK: define{{.*}} void @test_copy_constructor_Bitfield0( 600 601// CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_s0_t8w2( 602// CHECK: %[[V5:.*]] = getelementptr inbounds i8, ptr %{{.*}}, i64 8 603// CHECK: %[[V8:.*]] = getelementptr inbounds i8, ptr %{{.*}}, i64 8 604// CHECK: %[[V12:.*]] = load i16, ptr %[[V8]], align 8 605// CHECK: store i16 %[[V12]], ptr %[[V5]], align 8 606// CHECK: ret void 607 608void test_copy_constructor_Bitfield0(Bitfield0 *a) { 609 Bitfield0 t = *a; 610} 611 612// CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_t0w2_s8_t16w4_s24_t32w12_s48_t56w9_tv513w2_tv520w8 613// CHECK: %[[V4:.*]] = load i16, ptr %{{.*}}, align 8 614// CHECK: store i16 %[[V4]], ptr %{{.*}}, align 8 615// CHECK: %[[V21:.*]] = load i32, ptr %{{.*}}, align 8 616// CHECK: store i32 %[[V21]], ptr %{{.*}}, align 8 617// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %{{.*}}, ptr align 8 %{{.*}}, i64 12, i1 false) 618// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %{{.*}}, ptr align 8 %{{.*}}, i64 9, i1 false) 619// CHECK: %[[I5:.*]] = getelementptr inbounds nuw %[[STRUCT_BITFIELD1]], ptr %[[V0:.*]], i32 0, i32 8 620// CHECK: %[[I51:.*]] = getelementptr inbounds nuw %[[STRUCT_BITFIELD1]], ptr %[[V1:.*]], i32 0, i32 8 621// CHECK: %[[BF_LOAD:.*]] = load volatile i8, ptr %[[I51]], align 8 622// CHECK: %[[BF_SHL:.*]] = shl i8 %[[BF_LOAD]], 5 623// CHECK: %[[BF_ASHR:.*]] = ashr i8 %[[BF_SHL]], 6 624// CHECK: %[[BF_CAST:.*]] = sext i8 %[[BF_ASHR]] to i32 625// CHECK: %[[V56:.*]] = trunc i32 %[[BF_CAST]] to i8 626// CHECK: %[[BF_LOAD2:.*]] = load volatile i8, ptr %[[I5]], align 8 627// CHECK: %[[BF_VALUE:.*]] = and i8 %[[V56]], 3 628// CHECK: %[[BF_SHL3:.*]] = shl i8 %[[BF_VALUE]], 1 629// CHECK: %[[BF_CLEAR:.*]] = and i8 %[[BF_LOAD2]], -7 630// CHECK: %[[BF_SET:.*]] = or i8 %[[BF_CLEAR]], %[[BF_SHL3]] 631// CHECK: store volatile i8 %[[BF_SET]], ptr %[[I5]], align 8 632// CHECK: %[[I6:.*]] = getelementptr inbounds nuw %[[STRUCT_BITFIELD1]], ptr %[[V0]], i32 0, i32 9 633// CHECK: %[[I64:.*]] = getelementptr inbounds nuw %[[STRUCT_BITFIELD1]], ptr %[[V1]], i32 0, i32 9 634// CHECK: %[[V59:.*]] = load volatile i8, ptr %[[I64]], align 1 635// CHECK: store volatile i8 %[[V59]], ptr %[[I6]], align 1 636 637void test_copy_constructor_Bitfield1(Bitfield1 *a) { 638 Bitfield1 t = *a; 639} 640 641// CHECK: define{{.*}} void @test_copy_constructor_VolatileArray( 642// CHECK: call void @__copy_constructor_8_8_s0_AB8s4n16_tv64w32_AE( 643 644// CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_s0_AB8s4n16_tv64w32_AE( 645// CHECK: %[[ADDR_CUR:.*]] = phi ptr 646// CHECK: %[[ADDR_CUR1:.*]] = phi ptr 647// CHECK: %[[V14:.*]] = load volatile i32, ptr %[[ADDR_CUR1]], align 4 648// CHECK: store volatile i32 %[[V14]], ptr %[[ADDR_CUR]], align 4 649 650void test_copy_constructor_VolatileArray(VolatileArray *a) { 651 VolatileArray t = *a; 652} 653 654// CHECK: define{{.*}} void @test_compound_literal0( 655// CHECK: %[[P:.*]] = alloca ptr, align 8 656// CHECK: %[[_COMPOUNDLITERAL:.*]] = alloca %[[STRUCT_STRONGSMALL]], align 8 657// CHECK: %[[CLEANUP_COND:.*]] = alloca i1, align 1 658// CHECK: %[[_COMPOUNDLITERAL1:.*]] = alloca %[[STRUCT_STRONGSMALL]], align 8 659// CHECK: %[[CLEANUP_COND4:.*]] = alloca i1, align 1 660 661// CHECK: %[[I:.*]] = getelementptr inbounds nuw %[[STRUCT_STRONGSMALL]], ptr %[[_COMPOUNDLITERAL]], i32 0, i32 0 662// CHECK: store i32 1, ptr %[[I]], align 8 663// CHECK: %[[F1:.*]] = getelementptr inbounds nuw %[[STRUCT_STRONGSMALL]], ptr %[[_COMPOUNDLITERAL]], i32 0, i32 1 664// CHECK: store ptr null, ptr %[[F1]], align 8 665// CHECK: store i1 true, ptr %[[CLEANUP_COND]], align 1 666 667// CHECK: %[[I2:.*]] = getelementptr inbounds nuw %[[STRUCT_STRONGSMALL]], ptr %[[_COMPOUNDLITERAL1]], i32 0, i32 0 668// CHECK: store i32 2, ptr %[[I2]], align 8 669// CHECK: %[[F13:.*]] = getelementptr inbounds nuw %[[STRUCT_STRONGSMALL]], ptr %[[_COMPOUNDLITERAL1]], i32 0, i32 1 670// CHECK: store ptr null, ptr %[[F13]], align 8 671// CHECK: store i1 true, ptr %[[CLEANUP_COND4]], align 1 672 673// CHECK: %[[COND:.*]] = phi ptr [ %[[_COMPOUNDLITERAL]], %{{.*}} ], [ %[[_COMPOUNDLITERAL1]], %{{.*}} ] 674// CHECK: store ptr %[[COND]], ptr %[[P]], align 8 675// CHECK: call void @func( 676 677// CHECK: call void @__destructor_8_s8(ptr %[[_COMPOUNDLITERAL1]]) 678 679// CHECK: call void @__destructor_8_s8(ptr %[[_COMPOUNDLITERAL]]) 680 681void test_compound_literal0(int c) { 682 StrongSmall *p = c ? &(StrongSmall){ 1, 0 } : &(StrongSmall){ 2, 0 }; 683 func(0); 684} 685 686// Check that there is only one destructor call, which destructs 't'. 687 688// CHECK: define{{.*}} void @test_compound_literal1( 689// CHECK: %[[T:.*]] = alloca %[[STRUCT_STRONGSMALL]], align 8 690 691// CHECK: %[[I:.*]] = getelementptr inbounds nuw %[[STRUCT_STRONGSMALL]], ptr %[[T]], i32 0, i32 0 692// CHECK: store i32 1, ptr %[[I]], align 8 693// CHECK: %[[F1:.*]] = getelementptr inbounds nuw %[[STRUCT_STRONGSMALL]], ptr %[[T]], i32 0, i32 1 694// CHECK: store ptr null, ptr %[[F1]], align 8 695 696// CHECK: %[[I1:.*]] = getelementptr inbounds nuw %[[STRUCT_STRONGSMALL]], ptr %[[T]], i32 0, i32 0 697// CHECK: store i32 2, ptr %[[I1]], align 8 698// CHECK: %[[F12:.*]] = getelementptr inbounds nuw %[[STRUCT_STRONGSMALL]], ptr %[[T]], i32 0, i32 1 699// CHECK: store ptr null, ptr %[[F12]], align 8 700 701// CHECK: call void @func( 702// CHECK-NOT: call void 703// CHECK: call void @__destructor_8_s8(ptr %[[T]]) 704// CHECK-NOT: call void 705 706void test_compound_literal1(int c) { 707 StrongSmall t = c ? (StrongSmall){ 1, 0 } : (StrongSmall){ 2, 0 }; 708 func(0); 709} 710 711// CHECK: define{{.*}} void @test_compound_literal2( 712// CHECK: %[[P_ADDR:.*]] = alloca ptr, align 8 713// CHECK: %[[_COMPOUNDLITERAL:.*]] = alloca %[[STRUCT_STRONGSMALL]], align 8 714// CHECK: %[[CLEANUP_COND:.*]] = alloca i1, align 1 715// CHECK: %[[_COMPOUNDLITERAL1:.*]] = alloca %[[STRUCT_STRONGSMALL]], align 8 716// CHECK: %[[CLEANUP_COND4:.*]] = alloca i1, align 1 717// CHECK: %[[V0:.*]] = load ptr, ptr %[[P_ADDR]], align 8 718 719// CHECK: %[[I:.*]] = getelementptr inbounds nuw %[[STRUCT_STRONGSMALL]], ptr %[[_COMPOUNDLITERAL]], i32 0, i32 0 720// CHECK: store i32 1, ptr %[[I]], align 8 721// CHECK: %[[F1:.*]] = getelementptr inbounds nuw %[[STRUCT_STRONGSMALL]], ptr %[[_COMPOUNDLITERAL]], i32 0, i32 1 722// CHECK: store ptr null, ptr %[[F1]], align 8 723// CHECK: store i1 true, ptr %[[CLEANUP_COND]], align 1 724// CHECK: call void @__copy_assignment_8_8_t0w4_s8(ptr %[[V0]], ptr %[[_COMPOUNDLITERAL]]) 725 726// CHECK: %[[I2:.*]] = getelementptr inbounds nuw %[[STRUCT_STRONGSMALL]], ptr %[[_COMPOUNDLITERAL1]], i32 0, i32 0 727// CHECK: store i32 2, ptr %[[I2]], align 8 728// CHECK: %[[F13:.*]] = getelementptr inbounds nuw %[[STRUCT_STRONGSMALL]], ptr %[[_COMPOUNDLITERAL1]], i32 0, i32 1 729// CHECK: store ptr null, ptr %[[F13]], align 8 730// CHECK: store i1 true, ptr %[[CLEANUP_COND4]], align 1 731// CHECK: call void @__copy_assignment_8_8_t0w4_s8(ptr %[[V0]], ptr %[[_COMPOUNDLITERAL1]]) 732 733// CHECK: call void @func( 734 735// CHECK: call void @__destructor_8_s8(ptr %[[_COMPOUNDLITERAL1]]) 736 737// CHECK: call void @__destructor_8_s8(ptr %[[_COMPOUNDLITERAL]]) 738 739void test_compound_literal2(int c, StrongSmall *p) { 740 *p = c ? (StrongSmall){ 1, 0 } : (StrongSmall){ 2, 0 }; 741 func(0); 742} 743 744// CHECK: define{{.*}} void @test_member_access( 745// CHECK: %[[TMP:.*]] = alloca %[[STRUCT_STRONGSMALL]], 746// CHECK: call void @__destructor_8_s8(ptr %[[TMP]]) 747// CHECK: call void @func( 748 749void test_member_access(void) { 750 g0 = getStrongSmall().f1; 751 func(0); 752} 753 754// CHECK: define{{.*}} void @test_member_access2(ptr noundef %[[C:.*]]) 755// CHECK: %[[COERCE:.*]] = alloca %[[STRUCT_STRONGSMALL]], align 8 756// CHECK: call void @__destructor_8_s8(ptr %[[COERCE]]) 757// CHECK: call void @func( 758 759void test_member_access2(C *c) { 760 g0 = [c getStrongSmall].f1; 761 func(0); 762} 763 764// CHECK: define{{.*}} void @test_member_access3( 765// CHECK: %[[COERCE:.*]] = alloca %[[STRUCT_STRONGSMALL]], align 8 766// CHECK: call void @__destructor_8_s8(ptr %[[COERCE]]) 767// CHECK: call void @func( 768 769void test_member_access3(void) { 770 g0 = [C getStrongSmallClass].f1; 771 func(0); 772} 773 774// CHECK: define{{.*}} void @test_member_access4() 775// CHECK: %[[COERCE:.*]] = alloca %[[STRUCT_STRONGSMALL]], align 8 776// CHECK: call void @__destructor_8_s8(ptr %[[COERCE]]) 777// CHECK: call void @func( 778 779void test_member_access4(void) { 780 g0 = ^{ StrongSmall s; return s; }().f1; 781 func(0); 782} 783 784// CHECK: define{{.*}} void @test_volatile_variable_reference( 785// CHECK: %[[AGG_TMP_ENSURED:.*]] = alloca %[[STRUCT_STRONGSMALL]], 786// CHECK: call void @__copy_constructor_8_8_tv0w32_sv8(ptr %[[AGG_TMP_ENSURED]], ptr %{{.*}}) 787// CHECK: call void @__destructor_8_s8(ptr %[[AGG_TMP_ENSURED]]) 788// CHECK: call void @func( 789 790void test_volatile_variable_reference(volatile StrongSmall *a) { 791 (void)*a; 792 func(0); 793} 794 795struct ZeroBitfield { 796 int : 0; 797 id strong; 798}; 799 800 801// CHECK: define linkonce_odr hidden void @__default_constructor_8_sv0 802// CHECK: define linkonce_odr hidden void @__copy_assignment_8_8_sv0 803void test_zero_bitfield(void) { 804 struct ZeroBitfield volatile a, b; 805 a = b; 806} 807 808// CHECK-LABEL: define{{.*}} ptr @test_conditional0( 809// CHECK: %[[TMP:.*]] = alloca %[[STRUCT_STRONGSMALL]], align 8 810 811// CHECK: call void @__copy_constructor_8_8_t0w4_s8(ptr %[[TMP]], ptr @g2) 812 813// CHECK: call void @__copy_constructor_8_8_t0w4_s8(ptr %[[TMP]], ptr @g1) 814 815// CHECK: call void @__destructor_8_s8(ptr %[[TMP]]) 816// CHECK: @llvm.objc.autoreleaseReturnValue 817 818id test_conditional0(int c) { 819 return (c ? g2 : g1).f1; 820} 821 822// CHECK-LABEL: define{{.*}} void @test_conditional1( 823// CHECK-NOT: call void @__destructor 824 825void test_conditional1(int c) { 826 calleeStrongSmall(c ? g2 : g1); 827} 828 829// CHECK-LABEL: define{{.*}} ptr @test_assignment0( 830// CHECK: %[[TMP:.*]] = alloca %[[STRUCT_STRONGSMALL]], align 8 831// CHECK: call void @__copy_assignment_8_8_t0w4_s8(ptr @g2, ptr @g1) 832// CHECK: call void @__copy_constructor_8_8_t0w4_s8(ptr %[[TMP]], ptr @g2) 833// CHECK: call void @__destructor_8_s8(ptr %[[TMP]]) 834 835id test_assignment0(void) { 836 return (g2 = g1).f1; 837} 838 839// CHECK-LABEL: define{{.*}} void @test_assignment1( 840// CHECK-NOT: call void @__destructor 841 842void test_assignment1(void) { 843 calleeStrongSmall(g2 = g1); 844} 845 846// CHECK-LABEL: define{{.*}} void @test_null_reveiver( 847// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_STRONGSMALL]], align 8 848// CHECK: br i1 849 850// CHECK: %[[V8:.*]] = load [2 x i64], ptr %[[AGG_TMP]], align 8 851// CHECK: call void @objc_msgSend({{.*}}, [2 x i64] %[[V8]]) 852// CHECK: br 853 854// CHECK: call void @__destructor_8_s8(ptr %[[AGG_TMP]]) #4 855// CHECK: br 856 857void test_null_reveiver(C *c) { 858 [c m:getStrongSmall()]; 859} 860 861#endif /* USESTRUCT */ 862