r247209 - ARC: Fix the precise-lifetime suppression of returns_inner_pointer
John McCall via cfe-commits
cfe-commits at lists.llvm.org
Wed Sep 9 16:37:17 PDT 2015
Author: rjmccall
Date: Wed Sep 9 18:37:17 2015
New Revision: 247209
URL: http://llvm.org/viewvc/llvm-project?rev=247209&view=rev
Log:
ARC: Fix the precise-lifetime suppression of returns_inner_pointer
receiver extension for message sends via property syntax.
rdar://22172983
Modified:
cfe/trunk/lib/CodeGen/CGObjC.cpp
cfe/trunk/test/CodeGenObjC/arc-precise-lifetime.m
Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=247209&r1=247208&r2=247209&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjC.cpp Wed Sep 9 18:37:17 2015
@@ -273,10 +273,23 @@ shouldExtendReceiverForInnerPointerMessa
// receiver is loaded from a variable with precise lifetime.
case ObjCMessageExpr::Instance: {
const Expr *receiver = message->getInstanceReceiver();
+
+ // Look through OVEs.
+ if (auto opaque = dyn_cast<OpaqueValueExpr>(receiver)) {
+ if (opaque->getSourceExpr())
+ receiver = opaque->getSourceExpr()->IgnoreParens();
+ }
+
const ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(receiver);
if (!ice || ice->getCastKind() != CK_LValueToRValue) return true;
receiver = ice->getSubExpr()->IgnoreParens();
+ // Look through OVEs.
+ if (auto opaque = dyn_cast<OpaqueValueExpr>(receiver)) {
+ if (opaque->getSourceExpr())
+ receiver = opaque->getSourceExpr()->IgnoreParens();
+ }
+
// Only __strong variables.
if (receiver->getType().getObjCLifetime() != Qualifiers::OCL_Strong)
return true;
Modified: cfe/trunk/test/CodeGenObjC/arc-precise-lifetime.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/arc-precise-lifetime.m?rev=247209&r1=247208&r2=247209&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjC/arc-precise-lifetime.m (original)
+++ cfe/trunk/test/CodeGenObjC/arc-precise-lifetime.m Wed Sep 9 18:37:17 2015
@@ -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;
}
More information about the cfe-commits
mailing list