r191009 - ObjectiveC: Allow NS_RETURNS_INNER_POINTER annotation
Aaron Ballman
aaron at aaronballman.com
Thu Sep 19 10:47:19 PDT 2013
Thank you for indulging me. :-)
~Aaron
On Thu, Sep 19, 2013 at 1:22 PM, jahanian <fjahanian at apple.com> wrote:
>
> On Sep 19, 2013, at 9:46 AM, Aaron Ballman <aaron at aaronballman.com> wrote:
>
> On Thu, Sep 19, 2013 at 12:37 PM, Fariborz Jahanian <fjahanian at apple.com>
> wrote:
>
> 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();
>
>
> Please update the subjects in Attr.td for this attribute so it stays
> in sync with what the semantics are checking for.
>
> }
> + 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;
>
>
> A local enumeration would be better than comments, but meh.
>
>
> // 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 {
>
>
> Missing test cases for the changes in SemaDeclAttr.cpp; please add.
>
>
> Sure. In r191016.
> - Fariborz
>
>
> Thanks!
>
> ~Aaron
>
>
More information about the cfe-commits
mailing list