summaryrefslogtreecommitdiffstats
path: root/test/CodeGenObjC/arc-precise-lifetime.m
diff options
context:
space:
mode:
Diffstat (limited to 'test/CodeGenObjC/arc-precise-lifetime.m')
-rw-r--r--test/CodeGenObjC/arc-precise-lifetime.m155
1 files changed, 142 insertions, 13 deletions
diff --git a/test/CodeGenObjC/arc-precise-lifetime.m b/test/CodeGenObjC/arc-precise-lifetime.m
index 6dc3ebf..42a0483 100644
--- a/test/CodeGenObjC/arc-precise-lifetime.m
+++ b/test/CodeGenObjC/arc-precise-lifetime.m
@@ -26,7 +26,8 @@ void test0() {
// CHECK-NEXT: ret void
}
-// rdar://problem/9821110
+// rdar://problem/9821110 - precise lifetime should suppress extension
+// rdar://problem/22172983 - should work for calls via property syntax, too
@interface Test1
- (char*) interior __attribute__((objc_returns_inner_pointer));
// Should we allow this on properties? Yes! see // rdar://14990439
@@ -34,8 +35,8 @@ void test0() {
@end
extern Test1 *test1_helper(void);
-// CHECK-LABEL: define void @test1a()
-void test1a(void) {
+// CHECK-LABEL: define void @test1a_message()
+void test1a_message(void) {
// CHECK: [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8
// CHECK: [[C:%.*]] = alloca i8*, align 8
// CHECK: [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
@@ -67,8 +68,43 @@ void test1a(void) {
char *c = [(ptr) interior];
}
-// CHECK-LABEL: define void @test1b()
-void test1b(void) {
+
+// CHECK-LABEL: define void @test1a_property()
+void test1a_property(void) {
+ // CHECK: [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8
+ // CHECK: [[C:%.*]] = alloca i8*, align 8
+ // CHECK: [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
+ // CHECK: call void @llvm.lifetime.start(i64 8, i8* [[PTRPTR1]])
+ // CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
+ // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
+ // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
+ // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
+ // CHECK-NEXT: store [[TEST1]]* [[T3]]
+ // CHECK-NEXT: [[CPTR1:%.*]] = bitcast i8** [[C]] to i8*
+ // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[CPTR1]])
+ // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
+ // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
+ // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutorelease(i8* [[T1]])
+ // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
+ // CHECK-NEXT: [[T4:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
+ // CHECK-NEXT: [[T5:%.*]] = bitcast [[TEST1]]* [[T3]] to i8*
+ // CHECK-NEXT: [[T6:%.*]] = call i8* bitcast
+ // CHECK-NEXT: store i8* [[T6]], i8**
+ // CHECK-NEXT: [[CPTR2:%.*]] = bitcast i8** [[C]] to i8*
+ // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[CPTR2]])
+ // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
+ // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
+ // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release
+ // CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
+ // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTRPTR2]])
+ // CHECK-NEXT: ret void
+ Test1 *ptr = test1_helper();
+ char *c = ptr.interior;
+}
+
+
+// CHECK-LABEL: define void @test1b_message()
+void test1b_message(void) {
// CHECK: [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8
// CHECK: [[C:%.*]] = alloca i8*, align 8
// CHECK: [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
@@ -94,11 +130,76 @@ void test1b(void) {
// CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTRPTR2]])
// CHECK-NEXT: ret void
- __attribute__((objc_precise_lifetime)) Test1 *ptr = test1_helper();
+ PRECISE_LIFETIME Test1 *ptr = test1_helper();
char *c = [ptr interior];
}
-void test1c(void) {
+// CHECK-LABEL: define void @test1b_property()
+void test1b_property(void) {
+ // CHECK: [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8
+ // CHECK: [[C:%.*]] = alloca i8*, align 8
+ // CHECK: [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
+ // CHECK: call void @llvm.lifetime.start(i64 8, i8* [[PTRPTR1]])
+ // CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
+ // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
+ // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
+ // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
+ // CHECK-NEXT: store [[TEST1]]* [[T3]]
+ // CHECK-NEXT: [[CPTR1:%.*]] = bitcast i8** [[C]] to i8*
+ // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[CPTR1]])
+ // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
+ // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
+ // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
+ // CHECK-NEXT: [[T3:%.*]] = call i8* bitcast
+ // CHECK-NEXT: store i8* [[T3]], i8**
+ // CHECK-NEXT: [[CPTR2:%.*]] = bitcast i8** [[C]] to i8*
+ // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[CPTR2]])
+ // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
+ // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
+ // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]]
+ // CHECK-NOT: clang.imprecise_release
+ // CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
+ // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTRPTR2]])
+ // CHECK-NEXT: ret void
+ PRECISE_LIFETIME Test1 *ptr = test1_helper();
+ char *c = ptr.interior;
+}
+
+// CHECK-LABEL: define void @test1c_message()
+void test1c_message(void) {
+ // CHECK: [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8
+ // CHECK: [[PC:%.*]] = alloca i8*, align 8
+ // CHECK: [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
+ // CHECK: call void @llvm.lifetime.start(i64 8, i8* [[PTRPTR1]])
+ // CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
+ // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
+ // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
+ // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
+ // CHECK-NEXT: store [[TEST1]]* [[T3]]
+ // CHECK-NEXT: [[PCPTR1:%.*]] = bitcast i8** [[PC]] to i8*
+ // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[PCPTR1]])
+ // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
+ // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
+ // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutorelease(i8* [[T1]])
+ // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
+ // CHECK-NEXT: [[T4:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
+ // CHECK-NEXT: [[T5:%.*]] = bitcast [[TEST1]]* [[T3]] to i8*
+ // CHECK-NEXT: [[T6:%.*]] = call i8* bitcast
+ // CHECK-NEXT: store i8* [[T6]], i8**
+ // CHECK-NEXT: [[PCPTR2:%.*]] = bitcast i8** [[PC]] to i8*
+ // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PCPTR2]])
+ // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
+ // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
+ // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release
+ // CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
+ // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTRPTR2]])
+ // CHECK-NEXT: ret void
+ Test1 *ptr = test1_helper();
+ char *pc = [ptr PropertyReturnsInnerPointer];
+}
+
+// CHECK-LABEL: define void @test1c_property()
+void test1c_property(void) {
// CHECK: [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8
// CHECK: [[PC:%.*]] = alloca i8*, align 8
// CHECK: [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
@@ -130,7 +231,38 @@ void test1c(void) {
char *pc = ptr.PropertyReturnsInnerPointer;
}
-void test1d(void) {
+// CHECK-LABEL: define void @test1d_message()
+void test1d_message(void) {
+ // CHECK: [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8
+ // CHECK: [[PC:%.*]] = alloca i8*, align 8
+ // CHECK: [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
+ // CHECK: call void @llvm.lifetime.start(i64 8, i8* [[PTRPTR1]])
+ // CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
+ // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
+ // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
+ // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
+ // CHECK-NEXT: store [[TEST1]]* [[T3]]
+ // CHECK-NEXT: [[PCPTR1:%.*]] = bitcast i8** [[PC]] to i8*
+ // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[PCPTR1]])
+ // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
+ // CHECK-NEXT: [[SEVEN:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
+ // CHECK-NEXT: [[EIGHT:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
+ // CHECK-NEXT: [[CALL1:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* [[EIGHT]], i8* [[SEVEN]])
+ // CHECK-NEXT: store i8* [[CALL1]], i8**
+ // CHECK-NEXT: [[PCPTR2:%.*]] = bitcast i8** [[PC]] to i8*
+ // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PCPTR2]])
+ // CHECK-NEXT: [[NINE:%.*]] = load [[TEST1]]*, [[TEST1]]**
+ // CHECK-NEXT: [[TEN:%.*]] = bitcast [[TEST1]]* [[NINE]] to i8*
+ // CHECK-NEXT: call void @objc_release(i8* [[TEN]])
+ // CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
+ // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTRPTR2]])
+ // CHECK-NEXT: ret void
+ PRECISE_LIFETIME Test1 *ptr = test1_helper();
+ char *pc = [ptr PropertyReturnsInnerPointer];
+}
+
+// CHECK-LABEL: define void @test1d_property()
+void test1d_property(void) {
// CHECK: [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8
// CHECK: [[PC:%.*]] = alloca i8*, align 8
// CHECK: [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
@@ -143,11 +275,8 @@ void test1d(void) {
// CHECK-NEXT: [[PCPTR1:%.*]] = bitcast i8** [[PC]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[PCPTR1]])
// CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
- // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
- // CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retainAutorelease
- // CHECK-NEXT: [[SIX:%.*]] = bitcast i8* [[T3]] to [[TEST1]]*
// CHECK-NEXT: [[SEVEN:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
- // CHECK-NEXT: [[EIGHT:%.*]] = bitcast [[TEST1]]* [[SIX]] to i8*
+ // CHECK-NEXT: [[EIGHT:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
// CHECK-NEXT: [[CALL1:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* [[EIGHT]], i8* [[SEVEN]])
// CHECK-NEXT: store i8* [[CALL1]], i8**
// CHECK-NEXT: [[PCPTR2:%.*]] = bitcast i8** [[PC]] to i8*
@@ -158,7 +287,7 @@ void test1d(void) {
// CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTRPTR2]])
// CHECK-NEXT: ret void
- __attribute__((objc_precise_lifetime)) Test1 *ptr = test1_helper();
+ PRECISE_LIFETIME Test1 *ptr = test1_helper();
char *pc = ptr.PropertyReturnsInnerPointer;
}
OpenPOWER on IntegriCloud