862 lines · plain
1// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -emit-llvm -o - -DUSESTRUCT %s | FileCheck %s2 3// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -emit-pch -o %t %s4// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -include-pch %t -emit-llvm -o - -DUSESTRUCT %s | FileCheck %s5 6#ifndef HEADER7#define HEADER8 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#endif88 89#ifdef USESTRUCT90 91StrongSmall getStrongSmall(void);92StrongOuter getStrongOuter(void);93StrongOuter2 getStrongOuter2(void);94void calleeStrongSmall(StrongSmall);95void func(Strong *);96 97@interface C98- (StrongSmall)getStrongSmall;99- (void)m:(StrongSmall)s;100+ (StrongSmall)getStrongSmallClass;101@end102 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 8116// 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 void119 120// CHECK: define linkonce_odr hidden void @__default_constructor_8_S_s16_s24(ptr noundef %[[DST:.*]])121// CHECK: %[[DST_ADDR:.*]] = alloca ptr, align 8122// CHECK: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8123// CHECK: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8124// CHECK: call void @__default_constructor_8_s16(ptr %[[V0]])125// CHECK: %[[V2:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 24126// CHECK: call void @llvm.memset.p0.i64(ptr align 8 %[[V2]], i8 0, i64 8, i1 false)127// CHECK: ret void128 129// CHECK: define linkonce_odr hidden void @__default_constructor_8_s16(ptr noundef %[[DST:.*]])130// CHECK: %[[DST_ADDR:.*]] = alloca ptr, align 8131// CHECK: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8132// CHECK: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8133// CHECK: %[[V2:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 16134// CHECK: call void @llvm.memset.p0.i64(ptr align 8 %[[V2]], i8 0, i64 8, i1 false)135// CHECK: ret void136 137// CHECK: define linkonce_odr hidden void @__destructor_8_S_s16_s24(ptr noundef %[[DST:.*]])138// CHECK: %[[DST_ADDR:.*]] = alloca ptr, align 8139// CHECK: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8140// CHECK: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8141// CHECK: call void @__destructor_8_s16(ptr %[[V0]])142// CHECK: %[[V2:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 24143// CHECK: call void @llvm.objc.storeStrong(ptr %[[V2]], ptr null)144// CHECK: ret void145 146// CHECK: define linkonce_odr hidden void @__destructor_8_s16(ptr noundef %[[DST:.*]])147// CHECK: %[[DST_ADDR:.*]] = alloca ptr, align 8148// CHECK: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8149// CHECK: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8150// CHECK: %[[V2:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 16151// CHECK: call void @llvm.objc.storeStrong(ptr %[[V2]], ptr null)152// CHECK: ret void153 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 8160// CHECK: %[[T:.*]] = alloca %[[STRUCT_STRONGOUTER]], align 8161// CHECK: store ptr %[[S]], ptr %[[S_ADDR]], align 8162// CHECK: %[[V0:.*]] = load ptr, ptr %[[S_ADDR]], align 8163// 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 void166 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 8169// CHECK: %[[SRC_ADDR:.*]] = alloca ptr, align 8170// CHECK: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8171// CHECK: store ptr %[[SRC]], ptr %[[SRC_ADDR]], align 8172// CHECK: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8173// CHECK: %[[V1:.*]] = load ptr, ptr %[[SRC_ADDR]], align 8174// CHECK: call void @__copy_constructor_8_8_t0w16_s16(ptr %[[V0]], ptr %[[V1]])175// CHECK: %[[V3:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 24176// CHECK: %[[V6:.*]] = getelementptr inbounds i8, ptr %[[V1]], i64 24177// CHECK: %[[V8:.*]] = load ptr, ptr %[[V6]], align 8178// CHECK: %[[V9:.*]] = call ptr @llvm.objc.retain(ptr %[[V8]])179// CHECK: store ptr %[[V9]], ptr %[[V3]], align 8180// CHECK: %[[V11:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 32181// CHECK: %[[V14:.*]] = getelementptr inbounds i8, ptr %[[V1]], i64 32182// CHECK: %[[V18:.*]] = load i64, ptr %[[V14]], align 8183// CHECK: store i64 %[[V18]], ptr %[[V11]], align 8184// CHECK: ret void185 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 8188// CHECK: %[[SRC_ADDR:.*]] = alloca ptr, align 8189// CHECK: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8190// CHECK: store ptr %[[SRC]], ptr %[[SRC_ADDR]], align 8191// CHECK: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8192// CHECK: %[[V1:.*]] = load ptr, ptr %[[SRC_ADDR]], align 8193// 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 16195// CHECK: %[[V8:.*]] = getelementptr inbounds i8, ptr %[[V1]], i64 16196// CHECK: %[[V10:.*]] = load ptr, ptr %[[V8]], align 8197// CHECK: %[[V11:.*]] = call ptr @llvm.objc.retain(ptr %[[V10]])198// CHECK: store ptr %[[V11]], ptr %[[V5]], align 8199// CHECK: ret void200 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 8207// CHECK: %[[SRC_ADDR:.*]] = alloca ptr, align 8208// CHECK: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8209// CHECK: store ptr %[[SRC]], ptr %[[SRC_ADDR]], align 8210// CHECK: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8211// CHECK: %[[V1:.*]] = load ptr, ptr %[[SRC_ADDR]], align 8212// CHECK: %[[V3:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 24213// CHECK: %[[V6:.*]] = getelementptr inbounds i8, ptr %[[V1]], i64 24214// CHECK: %[[V8:.*]] = load ptr, ptr %[[V6]], align 8215// 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 7223// 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 7225// 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 8232// CHECK: %[[SRC_ADDR:.*]] = alloca ptr, align 8233// CHECK: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8234// CHECK: store ptr %[[SRC]], ptr %[[SRC_ADDR]], align 8235// CHECK: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8236// CHECK: %[[V1:.*]] = load ptr, ptr %[[SRC_ADDR]], align 8237// CHECK: call void @__move_constructor_8_8_t0w16_s16(ptr %[[V0]], ptr %[[V1]])238// CHECK: %[[V3:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 24239// CHECK: %[[V6:.*]] = getelementptr inbounds i8, ptr %[[V1]], i64 24240// CHECK: %[[V8:.*]] = load ptr, ptr %[[V6]], align 8241// CHECK: store ptr null, ptr %[[V6]], align 8242// CHECK: store ptr %[[V8]], ptr %[[V3]], align 8243 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 8254// CHECK: %[[SRC_ADDR:.*]] = alloca ptr, align 8255// CHECK: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8256// CHECK: store ptr %[[SRC]], ptr %[[SRC_ADDR]], align 8257// CHECK: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8258// CHECK: %[[V1:.*]] = load ptr, ptr %[[SRC_ADDR]], align 8259// CHECK: call void @__move_assignment_8_8_t0w16_s16(ptr %[[V0]], ptr %[[V1]])260// CHECK: %[[V3:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 24261// CHECK: %[[V6:.*]] = getelementptr inbounds i8, ptr %[[V1]], i64 24262// CHECK: %[[V8:.*]] = load ptr, ptr %[[V6]], align 8263// CHECK: store ptr null, ptr %[[V6]], align 8264// CHECK: %[[V9:.*]] = load ptr, ptr %[[V3]], align 8265// CHECK: store ptr %[[V8]], ptr %[[V3]], align 8266// 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 8274// CHECK: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8275// CHECK: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8276// 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 8278// 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 8282// CHECK: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8283// CHECK: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8284// CHECK: call void @llvm.objc.storeStrong(ptr %[[V0]], ptr null)285// CHECK: %[[V2:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 8286// 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 8294// CHECK: %[[SRC_ADDR:.*]] = alloca ptr, align 8295// CHECK: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8296// CHECK: store ptr %[[SRC]], ptr %[[SRC_ADDR]], align 8297// CHECK: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8298// CHECK: %[[V1:.*]] = load ptr, ptr %[[SRC_ADDR]], align 8299// CHECK: %[[V2:.*]] = load ptr, ptr %[[V1]], align 8300// CHECK: %[[V3:.*]] = call ptr @llvm.objc.retain(ptr %[[V2]])301// CHECK: store ptr %[[V3]], ptr %[[V0]], align 8302// CHECK: %[[V5:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 8303// CHECK: %[[V8:.*]] = getelementptr inbounds i8, ptr %[[V1]], i64 8304// 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 8312// CHECK: %[[SRC_ADDR:.*]] = alloca ptr, align 8313// CHECK: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8314// CHECK: store ptr %[[SRC]], ptr %[[SRC_ADDR]], align 8315// CHECK: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8316// CHECK: %[[V1:.*]] = load ptr, ptr %[[SRC_ADDR]], align 8317// CHECK: %[[V2:.*]] = load ptr, ptr %[[V1]], align 8318// CHECK: call void @llvm.objc.storeStrong(ptr %[[V0]], ptr %[[V2]])319// CHECK: %[[V4:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 8320// CHECK: %[[V7:.*]] = getelementptr inbounds i8, ptr %[[V1]], i64 8321// 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 8329// CHECK: %[[SRC_ADDR:.*]] = alloca ptr, align 8330// CHECK: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8331// CHECK: store ptr %[[SRC]], ptr %[[SRC_ADDR]], align 8332// CHECK: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8333// CHECK: %[[V1:.*]] = load ptr, ptr %[[SRC_ADDR]], align 8334// CHECK: %[[V2:.*]] = load ptr, ptr %[[V1]], align 8335// CHECK: store ptr null, ptr %[[V1]], align 8336// CHECK: store ptr %[[V2]], ptr %[[V0]], align 8337// CHECK: %[[V4:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 8338// CHECK: %[[V7:.*]] = getelementptr inbounds i8, ptr %[[V1]], i64 8339// 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 8348// CHECK: %[[SRC_ADDR:.*]] = alloca ptr, align 8349// CHECK: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8350// CHECK: store ptr %[[SRC]], ptr %[[SRC_ADDR]], align 8351// CHECK: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8352// CHECK: %[[V1:.*]] = load ptr, ptr %[[SRC_ADDR]], align 8353// CHECK: %[[V2:.*]] = load ptr, ptr %[[V1]], align 8354// CHECK: store ptr null, ptr %[[V1]], align 8355// CHECK: %[[V3:.*]] = load ptr, ptr %[[V0]], align 8356// CHECK: store ptr %[[V2]], ptr %[[V0]], align 8357// CHECK: call void @llvm.objc.release(ptr %[[V3]])358// CHECK: %[[V5:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 8359// CHECK: %[[V8:.*]] = getelementptr inbounds i8, ptr %[[V1]], i64 8360// 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 8368// CHECK: store [2 x i64] %[[A_COERCE]], ptr %[[A]], align 8369// CHECK: call void @__destructor_8_s8(ptr %[[A]])370// CHECK: ret void371 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 8377// CHECK: %[[TEMP_LVALUE:.*]] = alloca %[[STRUCT_STRONGSMALL]], align 8378// CHECK: store [2 x i64] %[[A_COERCE]], ptr %[[A]], align 8379// 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 8381// CHECK: call void @calleeStrongSmall([2 x i64] %[[V4]])382// CHECK: call void @__destructor_8_s8(ptr %[[A]])383// CHECK: ret void384 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 8391// CHECK: %[[A:.*]] = alloca %[[STRUCT_STRONGSMALL]], align 8392// CHECK: store [2 x i64] %[[A_COERCE]], ptr %[[A]], align 8393// 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 8396// 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 8404// CHECK: %[[CALL:.*]] = call [2 x i64] @getStrongSmall()405// CHECK: store [2 x i64] %[[CALL]], ptr %[[COERCE]], align 8406// CHECK: call void @__destructor_8_s8(ptr %[[COERCE]])407// CHECK: ret void408 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 8415// CHECK: %[[CALL:.*]] = call [2 x i64]{{.*}}@objc_msgSend416// CHECK: store [2 x i64] %[[CALL]], ptr %[[TMP]], align 8417// 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 void427 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 8430// CHECK: %[[SRC_ADDR:.*]] = alloca ptr, align 8431// CHECK: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8432// CHECK: store ptr %[[SRC]], ptr %[[SRC_ADDR]], align 8433// CHECK: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8434// CHECK: %[[V1:.*]] = load ptr, ptr %[[SRC_ADDR]], align 8435// CHECK: %[[V2:.*]] = load ptr, ptr %[[V1]], align 8436// CHECK: %[[V3:.*]] = call ptr @llvm.objc.retainBlock(ptr %[[V2]])437// CHECK: store ptr %[[V3]], ptr %[[V0]], align 8438// CHECK: ret void439 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 8449// CHECK: %[[SRC_ADDR:.*]] = alloca ptr, align 8450// CHECK: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8451// CHECK: store ptr %[[SRC]], ptr %[[SRC_ADDR]], align 8452// CHECK: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8453// CHECK: %[[V1:.*]] = load ptr, ptr %[[SRC_ADDR]], align 8454// CHECK: %[[V2:.*]] = load ptr, ptr %[[V1]], align 8455// CHECK: %[[V3:.*]] = call ptr @llvm.objc.retainBlock(ptr %[[V2]])456// CHECK: %[[V4:.*]] = load ptr, ptr %[[V0]], align 8457// CHECK: store ptr %[[V3]], ptr %[[V0]], align 8458// CHECK: call void @llvm.objc.release(ptr %[[V4]])459// CHECK: ret void460 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 ptr470// CHECK: %[[ADDR_CUR1:.*]] = phi ptr471 472// CHECK: %[[V6:.*]] = load volatile i8, ptr %[[ADDR_CUR1]], align 1473// CHECK: %[[TOBOOL:.*]] = trunc i8 %[[V6]] to i1474// CHECK: %[[FROMBOOL:.*]] = zext i1 %[[TOBOOL]] to i8475// CHECK: store volatile i8 %[[FROMBOOL]], ptr %[[ADDR_CUR]], align 1476 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: call484// CHECK: call void @__destructor_8_sv8(485// CHECK-NOT: call486 487// CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_t0w4_sv8(488// CHECK: %[[V8:.*]] = load volatile ptr, ptr %{{.*}}, align 8489// CHECK: %[[V9:.*]] = call ptr @llvm.objc.retain(ptr %[[V8]])490// CHECK: store volatile ptr %[[V9]], ptr %{{.*}}, align 8491 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 void509 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 void513 514// CHECK: define linkonce_odr hidden void @__destroy_helper_block_8_32n5_8_s16(515// CHECK: call void @__destructor_8_s16(516// CHECK: ret void517 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 4525// CHECK: store i32 %[[N]], ptr %[[N_ADDR]], align 4526// CHECK: %[[V0:.*]] = load i32, ptr %[[N_ADDR]], align 4527// CHECK: %[[V1:.*]] = zext i32 %[[V0]] to i64528// CHECK: %[[VLA:.*]] = alloca %[[STRUCT_STRONG]], i64 %[[V1]], align 8529// CHECK: %[[V4:.*]] = mul nuw i64 24, %[[V1]]530// CHECK: %[[V6:.*]] = getelementptr inbounds i8, ptr %[[VLA]], i64 %[[V4]]531// CHECK: br label532 533// CHECK: %[[DSTADDR_CUR:.*]] = phi ptr [ %[[VLA]], {{.*}} ], [ %[[V7:.*]], {{.*}} ]534// CHECK: %[[DONE:.*]] = icmp eq ptr %[[DSTADDR_CUR]], %[[V6]]535// CHECK: br i1 %[[DONE]], label536 537// CHECK: call void @__default_constructor_8_s16(ptr %[[DSTADDR_CUR]])538// CHECK: %[[V9:.*]] = getelementptr inbounds i8, ptr %[[DSTADDR_CUR]], i64 24539// CHECK: br label540 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]], label545 546// CHECK: %[[ARRAYDESTROY_ELEMENTPAST:.*]] = phi ptr [ %[[V10]], {{.*}} ], [ %[[ARRAYDESTROY_ELEMENT:.*]], {{.*}} ]547// CHECK: %[[ARRAYDESTROY_ELEMENT]] = getelementptr inbounds %[[STRUCT_STRONG]], ptr %[[ARRAYDESTROY_ELEMENTPAST]], i64 -1548// 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]], label551 552// CHECK: ret void553 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 8575// CHECK: %[[SRC_ADDR:.*]] = alloca ptr, align 8576// CHECK: store ptr %[[DST]], ptr %[[DST_ADDR]], align 8577// CHECK: store ptr %[[SRC]], ptr %[[SRC_ADDR]], align 8578// CHECK: %[[V0:.*]] = load ptr, ptr %[[DST_ADDR]], align 8579// CHECK: %[[V1:.*]] = load ptr, ptr %[[SRC_ADDR]], align 8580// CHECK: %[[V4:.*]] = load i64, ptr %[[V1]], align 8581// CHECK: store i64 %[[V4]], ptr %[[V0]], align 8582 583// CHECK: phi ptr584// CHECK: phi ptr585 586// CHECK: phi ptr587// CHECK: phi ptr588 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 8603// CHECK: %[[V8:.*]] = getelementptr inbounds i8, ptr %{{.*}}, i64 8604// CHECK: %[[V12:.*]] = load i16, ptr %[[V8]], align 8605// CHECK: store i16 %[[V12]], ptr %[[V5]], align 8606// CHECK: ret void607 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_tv520w8613// CHECK: %[[V4:.*]] = load i16, ptr %{{.*}}, align 8614// CHECK: store i16 %[[V4]], ptr %{{.*}}, align 8615// CHECK: %[[V21:.*]] = load i32, ptr %{{.*}}, align 8616// CHECK: store i32 %[[V21]], ptr %{{.*}}, align 8617// 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 8620// CHECK: %[[I51:.*]] = getelementptr inbounds nuw %[[STRUCT_BITFIELD1]], ptr %[[V1:.*]], i32 0, i32 8621// CHECK: %[[BF_LOAD:.*]] = load volatile i8, ptr %[[I51]], align 8622// CHECK: %[[BF_SHL:.*]] = shl i8 %[[BF_LOAD]], 5623// CHECK: %[[BF_ASHR:.*]] = ashr i8 %[[BF_SHL]], 6624// CHECK: %[[BF_CAST:.*]] = sext i8 %[[BF_ASHR]] to i32625// CHECK: %[[V56:.*]] = trunc i32 %[[BF_CAST]] to i8626// CHECK: %[[BF_LOAD2:.*]] = load volatile i8, ptr %[[I5]], align 8627// CHECK: %[[BF_VALUE:.*]] = and i8 %[[V56]], 3628// CHECK: %[[BF_SHL3:.*]] = shl i8 %[[BF_VALUE]], 1629// CHECK: %[[BF_CLEAR:.*]] = and i8 %[[BF_LOAD2]], -7630// CHECK: %[[BF_SET:.*]] = or i8 %[[BF_CLEAR]], %[[BF_SHL3]]631// CHECK: store volatile i8 %[[BF_SET]], ptr %[[I5]], align 8632// CHECK: %[[I6:.*]] = getelementptr inbounds nuw %[[STRUCT_BITFIELD1]], ptr %[[V0]], i32 0, i32 9633// CHECK: %[[I64:.*]] = getelementptr inbounds nuw %[[STRUCT_BITFIELD1]], ptr %[[V1]], i32 0, i32 9634// CHECK: %[[V59:.*]] = load volatile i8, ptr %[[I64]], align 1635// CHECK: store volatile i8 %[[V59]], ptr %[[I6]], align 1636 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 ptr646// CHECK: %[[ADDR_CUR1:.*]] = phi ptr647// CHECK: %[[V14:.*]] = load volatile i32, ptr %[[ADDR_CUR1]], align 4648// CHECK: store volatile i32 %[[V14]], ptr %[[ADDR_CUR]], align 4649 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 8656// CHECK: %[[_COMPOUNDLITERAL:.*]] = alloca %[[STRUCT_STRONGSMALL]], align 8657// CHECK: %[[CLEANUP_COND:.*]] = alloca i1, align 1658// CHECK: %[[_COMPOUNDLITERAL1:.*]] = alloca %[[STRUCT_STRONGSMALL]], align 8659// CHECK: %[[CLEANUP_COND4:.*]] = alloca i1, align 1660 661// CHECK: %[[I:.*]] = getelementptr inbounds nuw %[[STRUCT_STRONGSMALL]], ptr %[[_COMPOUNDLITERAL]], i32 0, i32 0662// CHECK: store i32 1, ptr %[[I]], align 8663// CHECK: %[[F1:.*]] = getelementptr inbounds nuw %[[STRUCT_STRONGSMALL]], ptr %[[_COMPOUNDLITERAL]], i32 0, i32 1664// CHECK: store ptr null, ptr %[[F1]], align 8665// CHECK: store i1 true, ptr %[[CLEANUP_COND]], align 1666 667// CHECK: %[[I2:.*]] = getelementptr inbounds nuw %[[STRUCT_STRONGSMALL]], ptr %[[_COMPOUNDLITERAL1]], i32 0, i32 0668// CHECK: store i32 2, ptr %[[I2]], align 8669// CHECK: %[[F13:.*]] = getelementptr inbounds nuw %[[STRUCT_STRONGSMALL]], ptr %[[_COMPOUNDLITERAL1]], i32 0, i32 1670// CHECK: store ptr null, ptr %[[F13]], align 8671// CHECK: store i1 true, ptr %[[CLEANUP_COND4]], align 1672 673// CHECK: %[[COND:.*]] = phi ptr [ %[[_COMPOUNDLITERAL]], %{{.*}} ], [ %[[_COMPOUNDLITERAL1]], %{{.*}} ]674// CHECK: store ptr %[[COND]], ptr %[[P]], align 8675// 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 8690 691// CHECK: %[[I:.*]] = getelementptr inbounds nuw %[[STRUCT_STRONGSMALL]], ptr %[[T]], i32 0, i32 0692// CHECK: store i32 1, ptr %[[I]], align 8693// CHECK: %[[F1:.*]] = getelementptr inbounds nuw %[[STRUCT_STRONGSMALL]], ptr %[[T]], i32 0, i32 1694// CHECK: store ptr null, ptr %[[F1]], align 8695 696// CHECK: %[[I1:.*]] = getelementptr inbounds nuw %[[STRUCT_STRONGSMALL]], ptr %[[T]], i32 0, i32 0697// CHECK: store i32 2, ptr %[[I1]], align 8698// CHECK: %[[F12:.*]] = getelementptr inbounds nuw %[[STRUCT_STRONGSMALL]], ptr %[[T]], i32 0, i32 1699// CHECK: store ptr null, ptr %[[F12]], align 8700 701// CHECK: call void @func(702// CHECK-NOT: call void703// CHECK: call void @__destructor_8_s8(ptr %[[T]])704// CHECK-NOT: call void705 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 8713// CHECK: %[[_COMPOUNDLITERAL:.*]] = alloca %[[STRUCT_STRONGSMALL]], align 8714// CHECK: %[[CLEANUP_COND:.*]] = alloca i1, align 1715// CHECK: %[[_COMPOUNDLITERAL1:.*]] = alloca %[[STRUCT_STRONGSMALL]], align 8716// CHECK: %[[CLEANUP_COND4:.*]] = alloca i1, align 1717// CHECK: %[[V0:.*]] = load ptr, ptr %[[P_ADDR]], align 8718 719// CHECK: %[[I:.*]] = getelementptr inbounds nuw %[[STRUCT_STRONGSMALL]], ptr %[[_COMPOUNDLITERAL]], i32 0, i32 0720// CHECK: store i32 1, ptr %[[I]], align 8721// CHECK: %[[F1:.*]] = getelementptr inbounds nuw %[[STRUCT_STRONGSMALL]], ptr %[[_COMPOUNDLITERAL]], i32 0, i32 1722// CHECK: store ptr null, ptr %[[F1]], align 8723// CHECK: store i1 true, ptr %[[CLEANUP_COND]], align 1724// 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 0727// CHECK: store i32 2, ptr %[[I2]], align 8728// CHECK: %[[F13:.*]] = getelementptr inbounds nuw %[[STRUCT_STRONGSMALL]], ptr %[[_COMPOUNDLITERAL1]], i32 0, i32 1729// CHECK: store ptr null, ptr %[[F13]], align 8730// CHECK: store i1 true, ptr %[[CLEANUP_COND4]], align 1731// 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 8756// 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 8766// 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 8776// 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_sv0802// CHECK: define linkonce_odr hidden void @__copy_assignment_8_8_sv0803void 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 8810 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.autoreleaseReturnValue817 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 @__destructor824 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 8831// 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 @__destructor841 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 8848// CHECK: br i1849 850// CHECK: %[[V8:.*]] = load [2 x i64], ptr %[[AGG_TMP]], align 8851// CHECK: call void @objc_msgSend({{.*}}, [2 x i64] %[[V8]])852// CHECK: br853 854// CHECK: call void @__destructor_8_s8(ptr %[[AGG_TMP]]) #4855// CHECK: br856 857void test_null_reveiver(C *c) {858 [c m:getStrongSmall()];859}860 861#endif /* USESTRUCT */862