brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.7 KiB · ac761ba Raw
260 lines · plain
1// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-passes -o - %s | FileCheck %s2 3#define PRECISE_LIFETIME __attribute__((objc_precise_lifetime))4 5id test0_helper(void) __attribute__((ns_returns_retained));6void test0(void) {7  PRECISE_LIFETIME id x = test0_helper();8  x = 0;9  // CHECK:      [[X:%.*]] = alloca ptr10  // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[X]])11  // CHECK-NEXT: [[CALL:%.*]] = call ptr @test0_helper()12  // CHECK-NEXT: store ptr [[CALL]], ptr [[X]]13 14  // CHECK-NEXT: [[T1:%.*]] = load ptr, ptr [[X]]15  // CHECK-NEXT: store ptr null, ptr [[X]]16  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]]) [[NUW:#[0-9]+]]17  // CHECK-NOT:  clang.imprecise_release18 19  // CHECK-NEXT: [[T1:%.*]] = load ptr, ptr [[X]]20  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T1]]) [[NUW:#[0-9]+]]21  // CHECK-NOT:  clang.imprecise_release22 23  // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[X]])24  // CHECK-NEXT: ret void25}26 27// precise lifetime should suppress extension28// should work for calls via property syntax, too29@interface Test130- (char*) interior __attribute__((objc_returns_inner_pointer));31// Should we allow this on properties? Yes!32@property (nonatomic, readonly) char * PropertyReturnsInnerPointer __attribute__((objc_returns_inner_pointer));33@end34extern Test1 *test1_helper(void);35 36// CHECK-LABEL: define{{.*}} void @test1a_message()37void test1a_message(void) {38  // CHECK:      [[PTR:%.*]] = alloca ptr, align 839  // CHECK:      [[C:%.*]] = alloca ptr, align 840  // CHECK:      call void @llvm.lifetime.start.p0(ptr [[PTR]])41  // CHECK:      [[T0:%.*]] = call ptr @test1_helper() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]42  // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])43  // CHECK-NEXT: store ptr [[T0]]44  // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[C]])45  // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr46  // CHECK-NEXT: [[T2:%.*]] = call ptr @llvm.objc.retainAutorelease(ptr [[T0]])47  // CHECK-NEXT: [[T4:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES_48  // CHECK-NEXT: [[T6:%.*]] = call ptr49  // CHECK-NEXT: store ptr [[T6]], ptr50  // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[C]])51  // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr52  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) [[NUW]], !clang.imprecise_release53  // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[PTR]])54  // CHECK-NEXT: ret void55  Test1 *ptr = test1_helper();56  char *c = [(ptr) interior];57}58 59 60// CHECK-LABEL: define{{.*}} void @test1a_property()61void test1a_property(void) {62  // CHECK:      [[PTR:%.*]] = alloca ptr, align 863  // CHECK:      [[C:%.*]] = alloca ptr, align 864  // CHECK:      call void @llvm.lifetime.start.p0(ptr [[PTR]])65  // CHECK:      [[T0:%.*]] = call ptr @test1_helper() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]66  // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])67  // CHECK-NEXT: store ptr [[T0]]68  // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[C]])69  // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr70  // CHECK-NEXT: [[T2:%.*]] = call ptr @llvm.objc.retainAutorelease(ptr [[T0]])71  // CHECK-NEXT: [[T4:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES_72  // CHECK-NEXT: [[T6:%.*]] = call ptr73  // CHECK-NEXT: store ptr [[T6]], ptr74  // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[C]])75  // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr76  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) [[NUW]], !clang.imprecise_release77  // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[PTR]])78  // CHECK-NEXT: ret void79  Test1 *ptr = test1_helper();80  char *c = ptr.interior;81}82 83 84// CHECK-LABEL: define{{.*}} void @test1b_message()85void test1b_message(void) {86  // CHECK:      [[PTR:%.*]] = alloca ptr, align 887  // CHECK:      [[C:%.*]] = alloca ptr, align 888  // CHECK:      call void @llvm.lifetime.start.p0(ptr [[PTR]])89  // CHECK:      [[T0:%.*]] = call ptr @test1_helper() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]90  // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])91  // CHECK-NEXT: store ptr [[T0]]92  // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[C]])93  // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr94  // CHECK-NEXT: [[T1:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES_95  // CHECK-NEXT: [[T3:%.*]] = call ptr96  // CHECK-NEXT: store ptr [[T3]], ptr97  // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[C]])98  // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr99  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) [[NUW]]100  // CHECK-NOT:  clang.imprecise_release101  // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[PTR]])102  // CHECK-NEXT: ret void103  PRECISE_LIFETIME Test1 *ptr = test1_helper();104  char *c = [ptr interior];105}106 107// CHECK-LABEL: define{{.*}} void @test1b_property()108void test1b_property(void) {109  // CHECK:      [[PTR:%.*]] = alloca ptr, align 8110  // CHECK:      [[C:%.*]] = alloca ptr, align 8111  // CHECK:      call void @llvm.lifetime.start.p0(ptr [[PTR]])112  // CHECK:      [[T0:%.*]] = call ptr @test1_helper() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]113  // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])114  // CHECK-NEXT: store ptr [[T0]]115  // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[C]])116  // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr117  // CHECK-NEXT: [[T1:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES_118  // CHECK-NEXT: [[T3:%.*]] = call ptr119  // CHECK-NEXT: store ptr [[T3]], ptr120  // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[C]])121  // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr122  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) [[NUW]]123  // CHECK-NOT:  clang.imprecise_release124  // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[PTR]])125  // CHECK-NEXT: ret void126  PRECISE_LIFETIME Test1 *ptr = test1_helper();127  char *c = ptr.interior;128}129 130// CHECK-LABEL: define{{.*}} void @test1c_message()131void test1c_message(void) {132  // CHECK:      [[PTR:%.*]] = alloca ptr, align 8133  // CHECK:      [[PC:%.*]] = alloca ptr, align 8134  // CHECK:      call void @llvm.lifetime.start.p0(ptr [[PTR]])135  // CHECK:      [[T0:%.*]] = call ptr @test1_helper() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]136  // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])137  // CHECK-NEXT: store ptr [[T0]]138  // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[PC]])139  // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr140  // CHECK-NEXT: [[T2:%.*]] = call ptr @llvm.objc.retainAutorelease(ptr [[T0]])141  // CHECK-NEXT: [[T4:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES_142  // CHECK-NEXT: [[T6:%.*]] = call ptr143  // CHECK-NEXT: store ptr [[T6]], ptr144  // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[PC]])145  // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr146  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) [[NUW]], !clang.imprecise_release147  // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[PTR]])148  // CHECK-NEXT: ret void149  Test1 *ptr = test1_helper();150  char *pc = [ptr PropertyReturnsInnerPointer];151}152 153// CHECK-LABEL: define{{.*}} void @test1c_property()154void test1c_property(void) {155  // CHECK:      [[PTR:%.*]] = alloca ptr, align 8156  // CHECK:      [[PC:%.*]] = alloca ptr, align 8157  // CHECK:      call void @llvm.lifetime.start.p0(ptr [[PTR]])158  // CHECK:      [[T0:%.*]] = call ptr @test1_helper() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]159  // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])160  // CHECK-NEXT: store ptr [[T0]]161  // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[PC]])162  // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr163  // CHECK-NEXT: [[T2:%.*]] = call ptr @llvm.objc.retainAutorelease(ptr [[T0]])164  // CHECK-NEXT: [[T4:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES_165  // CHECK-NEXT: [[T6:%.*]] = call ptr166  // CHECK-NEXT: store ptr [[T6]], ptr167  // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[PC]])168  // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr169  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) [[NUW]], !clang.imprecise_release170  // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[PTR]])171  // CHECK-NEXT: ret void172  Test1 *ptr = test1_helper();173  char *pc = ptr.PropertyReturnsInnerPointer;174}175 176// CHECK-LABEL: define{{.*}} void @test1d_message()177void test1d_message(void) {178  // CHECK:      [[PTR:%.*]] = alloca ptr, align 8179  // CHECK:      [[PC:%.*]] = alloca ptr, align 8180  // CHECK:      call void @llvm.lifetime.start.p0(ptr [[PTR]])181  // CHECK:      [[T0:%.*]] = call ptr @test1_helper() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]182  // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])183  // CHECK-NEXT: store ptr [[T0]]184  // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[PC]])185  // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr186  // CHECK-NEXT: [[SEL:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES_187  // CHECK-NEXT: [[CALL1:%.*]] = call ptr @objc_msgSend(ptr noundef [[T0]], ptr noundef [[SEL]])188  // CHECK-NEXT: store ptr [[CALL1]], ptr189  // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[PC]])190  // CHECK-NEXT: [[NINE:%.*]] = load ptr, ptr191  // CHECK-NEXT: call void @llvm.objc.release(ptr [[NINE]])192  // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[PTR]])193  // CHECK-NEXT: ret void194  PRECISE_LIFETIME Test1 *ptr = test1_helper();195  char *pc = [ptr PropertyReturnsInnerPointer];196}197 198// CHECK-LABEL: define{{.*}} void @test1d_property()199void test1d_property(void) {200  // CHECK:      [[PTR:%.*]] = alloca ptr, align 8201  // CHECK:      [[PC:%.*]] = alloca ptr, align 8202  // CHECK:      call void @llvm.lifetime.start.p0(ptr [[PTR]])203  // CHECK:      [[T0:%.*]] = call ptr @test1_helper() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]204  // CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])205  // CHECK-NEXT: store ptr [[T0]]206  // CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[PC]])207  // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr208  // CHECK-NEXT: [[SEL:%.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES_209  // CHECK-NEXT: [[CALL1:%.*]] = call ptr @objc_msgSend(ptr noundef [[T0]], ptr noundef [[SEL]])210  // CHECK-NEXT: store ptr [[CALL1]], ptr211  // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[PC]])212  // CHECK-NEXT: [[NINE:%.*]] = load ptr, ptr213  // CHECK-NEXT: call void @llvm.objc.release(ptr [[NINE]])214  // CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[PTR]])215  // CHECK-NEXT: ret void216  PRECISE_LIFETIME Test1 *ptr = test1_helper();217  char *pc = ptr.PropertyReturnsInnerPointer;218}219 220@interface Test2 {221@public222  id ivar;223}224@end225// CHECK-LABEL:      define{{.*}} void @test2(226void test2(Test2 *x) {227  x->ivar = 0;228  // CHECK:      [[X:%.*]] = alloca ptr229  // CHECK-NEXT: [[T1:%.*]] = call ptr @llvm.objc.retain(ptr {{%.*}}) [[NUW]]230  // CHECK-NEXT: store ptr [[T1]], ptr [[X]],231 232  // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[X]],233  // CHECK-NEXT: [[OFFSET:%.*]] = load i64, ptr @"OBJC_IVAR_$_Test2.ivar"234  // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds i8, ptr [[T0]], i64 [[OFFSET]]235  // CHECK-NEXT: [[T4:%.*]] = load ptr, ptr [[T2]],236  // CHECK-NEXT: store ptr null, ptr [[T2]],237  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T4]]) [[NUW]]238  // CHECK-NOT:  imprecise239 240  // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[X]]241  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) [[NUW]], !clang.imprecise_release242 243  // CHECK-NEXT: ret void244}245 246// CHECK-LABEL:      define{{.*}} void @test3(ptr247void test3(PRECISE_LIFETIME id x) {248  // CHECK:      [[X:%.*]] = alloca ptr,249  // CHECK-NEXT: [[T0:%.*]] = call ptr @llvm.objc.retain(ptr {{%.*}}) [[NUW]]250  // CHECK-NEXT: store ptr [[T0]], ptr [[X]],251 252  // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[X]]253  // CHECK-NEXT: call void @llvm.objc.release(ptr [[T0]]) [[NUW]]254  // CHECK-NOT:  imprecise_release255 256  // CHECK-NEXT: ret void  257}258 259// CHECK: attributes [[NUW]] = { nounwind }260