r191009 - ObjectiveC: Allow NS_RETURNS_INNER_POINTER annotation
Fariborz Jahanian
fjahanian at apple.com
Thu Sep 19 09:37:20 PDT 2013
Author: fjahanian
Date: Thu Sep 19 11:37:20 2013
New Revision: 191009
URL: http://llvm.org/viewvc/llvm-project?rev=191009&view=rev
Log:
ObjectiveC: Allow NS_RETURNS_INNER_POINTER annotation
of ObjectiveC properties to mean annotation of
NS_RETURNS_INNER_POINTER on its synthesized getter.
This also facilitates more migration to properties when
methods are annotated with NS_RETURNS_INNER_POINTER.
// rdar://14990439
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Sema/SemaDeclAttr.cpp
cfe/trunk/lib/Sema/SemaObjCProperty.cpp
cfe/trunk/test/CodeGenObjC/arc-precise-lifetime.m
cfe/trunk/test/SemaObjC/arc-property-lifetime.m
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=191009&r1=191008&r2=191009&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Sep 19 11:37:20 2013
@@ -2027,7 +2027,8 @@ def err_attribute_wrong_decl_type : Erro
"variables, functions and labels|fields and global variables|structs|"
"variables, functions and tag types|thread-local variables|"
"variables and fields|variables, data members and tag types|"
- "types and namespaces|Objective-C interfaces}1">;
+ "types and namespaces|Objective-C interfaces|"
+ "methods and properties}1">;
def warn_type_attribute_wrong_type : Warning<
"'%0' only applies to %select{function|pointer|"
"Objective-C object or block pointer}1 types; type here is %2">,
@@ -2395,7 +2396,7 @@ def note_attribute_overloadable_prev_ove
def err_attribute_overloadable_no_prototype : Error<
"'overloadable' function %0 must have a prototype">;
def warn_ns_attribute_wrong_return_type : Warning<
- "%0 attribute only applies to %select{functions|methods}1 that "
+ "%0 attribute only applies to %select{functions|methods|properties}1 that "
"return %select{an Objective-C object|a pointer|a non-retainable pointer}2">,
InGroup<IgnoredAttributes>;
def warn_ns_attribute_wrong_parameter_type : Warning<
Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=191009&r1=191008&r2=191009&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Thu Sep 19 11:37:20 2013
@@ -54,7 +54,8 @@ enum AttributeDeclKind {
ExpectedVariableOrField,
ExpectedVariableFieldOrTag,
ExpectedTypeOrNamespace,
- ExpectedObjectiveCInterface
+ ExpectedObjectiveCInterface,
+ ExpectedMethodOrProperty
};
//===----------------------------------------------------------------------===//
@@ -1476,7 +1477,7 @@ static void handleOwnershipAttr(Sema &S,
break;
}
if (-1 != Err) {
- S.Diag(AL.getLoc(), diag::err_ownership_type) << AL.getName() << Err
+ S.Diag(AL.getLoc(), diag::err_ownership_type) << AL.getName() << Err
<< Ex->getSourceRange();
return;
}
@@ -4145,29 +4146,34 @@ static void handleNSReturnsRetainedAttr(
static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D,
const AttributeList &attr) {
SourceLocation loc = attr.getLoc();
-
+ QualType resultType;
+
ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(D);
if (!method) {
- S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type)
- << SourceRange(loc, loc) << attr.getName() << ExpectedMethod;
- return;
+ ObjCPropertyDecl *property = dyn_cast<ObjCPropertyDecl>(D);
+ if (!property) {
+ S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type)
+ << SourceRange(loc, loc) << attr.getName() << ExpectedMethodOrProperty;
+ return;
+ }
+ resultType = property->getType();
}
+ else
+ // Check that the method returns a normal pointer.
+ resultType = method->getResultType();
- // Check that the method returns a normal pointer.
- QualType resultType = method->getResultType();
-
if (!resultType->isReferenceType() &&
(!resultType->isPointerType() || resultType->isObjCRetainableType())) {
- S.Diag(method->getLocStart(), diag::warn_ns_attribute_wrong_return_type)
+ S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_return_type)
<< SourceRange(loc)
- << attr.getName() << /*method*/ 1 << /*non-retainable pointer*/ 2;
+ << attr.getName() << (method ? /*method*/ 1 : /*property*/ 2) << /*non-retainable pointer*/ 2;
// Drop the attribute.
return;
}
- method->addAttr(::new (S.Context)
+ D->addAttr(::new (S.Context)
ObjCReturnsInnerPointerAttr(attr.getRange(), S.Context,
attr.getAttributeSpellingListIndex()));
}
Modified: cfe/trunk/lib/Sema/SemaObjCProperty.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaObjCProperty.cpp?rev=191009&r1=191008&r2=191009&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaObjCProperty.cpp (original)
+++ cfe/trunk/lib/Sema/SemaObjCProperty.cpp Thu Sep 19 11:37:20 2013
@@ -1943,6 +1943,10 @@ void Sema::ProcessPropertyDecl(ObjCPrope
if (property->hasAttr<NSReturnsNotRetainedAttr>())
GetterMethod->addAttr(
::new (Context) NSReturnsNotRetainedAttr(Loc, Context));
+
+ if (property->hasAttr<ObjCReturnsInnerPointerAttr>())
+ GetterMethod->addAttr(
+ ::new (Context) ObjCReturnsInnerPointerAttr(Loc, Context));
if (getLangOpts().ObjCAutoRefCount)
CheckARCMethodDecl(GetterMethod);
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=191009&r1=191008&r2=191009&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjC/arc-precise-lifetime.m (original)
+++ cfe/trunk/test/CodeGenObjC/arc-precise-lifetime.m Thu Sep 19 11:37:20 2013
@@ -25,7 +25,8 @@ void test0() {
// rdar://problem/9821110
@interface Test1
- (char*) interior __attribute__((objc_returns_inner_pointer));
-// Should we allow this on properties?
+// Should we allow this on properties? Yes! see // rdar://14990439
+ at property (nonatomic, readonly) char * PropertyReturnsInnerPointer __attribute__((objc_returns_inner_pointer));
@end
extern Test1 *test1_helper(void);
@@ -73,6 +74,50 @@ void test1b(void) {
char *c = [ptr interior];
}
+void test1c(void) {
+ // 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: [[T0:%.*]] = load [[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** @"\01L_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: [[T0:%.*]] = load [[TEST1]]**
+ // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
+ // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release
+ // CHECK-NEXT: ret void
+ Test1 *ptr = test1_helper();
+ char *pc = ptr.PropertyReturnsInnerPointer;
+}
+
+void test1d(void) {
+ // 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: [[T0:%.*]] = load [[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** @"\01L_OBJC_SELECTOR_REFERENCES_
+ // CHECK-NEXT: [[EIGHT:%.*]] = bitcast [[TEST1]]* [[SIX]] 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: [[NINE:%.*]] = load [[TEST1]]**
+ // CHECK-NEXT: [[TEN:%.*]] = bitcast [[TEST1]]* [[NINE]] to i8*
+ // CHECK-NEXT: call void @objc_release(i8* [[TEN]])
+ // CHECK-NEXT: ret void
+ __attribute__((objc_precise_lifetime)) Test1 *ptr = test1_helper();
+ char *pc = ptr.PropertyReturnsInnerPointer;
+}
+
@interface Test2 {
@public
id ivar;
Modified: cfe/trunk/test/SemaObjC/arc-property-lifetime.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/arc-property-lifetime.m?rev=191009&r1=191008&r2=191009&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/arc-property-lifetime.m (original)
+++ cfe/trunk/test/SemaObjC/arc-property-lifetime.m Thu Sep 19 11:37:20 2013
@@ -171,7 +171,10 @@ void foo(Baz *f) {
// rdar://11253688
@interface Boom
- at property (readonly) const void * innerPointer __attribute__((objc_returns_inner_pointer)); // expected-error {{'objc_returns_inner_pointer' attribute only applies to methods}}
+{
+ const void * innerPointerIvar __attribute__((objc_returns_inner_pointer)); // expected-error {{'objc_returns_inner_pointer' attribute only applies to methods and properties}}
+}
+ at property (readonly) const void * innerPointer __attribute__((objc_returns_inner_pointer));
@end
@interface Foo2 {
More information about the cfe-commits
mailing list