From 015f608042a1d247899866849e69a4e9a1aff6a8 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Wed, 11 Jan 2012 18:26:06 +0000 Subject: [PATCH] objc-arc: evaluate 'readonly' property with no known life-time to that of its backing 'ivar's lifetime. // rdar://10558871 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147956 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaObjCProperty.cpp | 61 ++++++++++++++++++-- test/SemaObjC/arc-readonly-property-ivar-1.m | 29 ++++++++++ test/SemaObjC/arc-readonly-property-ivar.m | 16 +++++ 3 files changed, 100 insertions(+), 6 deletions(-) create mode 100644 test/SemaObjC/arc-readonly-property-ivar-1.m create mode 100644 test/SemaObjC/arc-readonly-property-ivar.m diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp index bbc6d23385..52b48cc732 100644 --- a/lib/Sema/SemaObjCProperty.cpp +++ b/lib/Sema/SemaObjCProperty.cpp @@ -518,6 +518,33 @@ static void checkARCPropertyImpl(Sema &S, SourceLocation propertyImplLoc, S.Diag(property->getLocation(), diag::note_property_declare); } +/// setImpliedPropertyAttributeForReadOnlyProperty - +/// This routine evaludates life-time attributes for a 'readonly' +/// property with no known lifetime of its own, using backing +/// 'ivar's attribute, if any. If no backing 'ivar', property's +/// life-time is assumed 'strong'. +static void setImpliedPropertyAttributeForReadOnlyProperty( + ObjCPropertyDecl *property, ObjCIvarDecl *ivar) { + Qualifiers::ObjCLifetime propertyLifetime = + getImpliedARCOwnership(property->getPropertyAttributes(), + property->getType()); + if (propertyLifetime != Qualifiers::OCL_None) + return; + + if (!ivar) { + // if no backing ivar, make property 'strong'. + property->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong); + return; + } + // property assumes owenership of backing ivar. + QualType ivarType = ivar->getType(); + Qualifiers::ObjCLifetime ivarLifetime = ivarType.getObjCLifetime(); + if (ivarLifetime == Qualifiers::OCL_Strong) + property->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong); + else if (ivarLifetime == Qualifiers::OCL_Weak) + property->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_weak); + return; +} /// ActOnPropertyImplDecl - This routine performs semantic checks and /// builds the AST node for a property implementation declaration; declared @@ -608,11 +635,21 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, // @synthesize if (!PropertyIvar) PropertyIvar = PropertyId; - ObjCPropertyDecl::PropertyAttributeKind kind - = property->getPropertyAttributes(); + // Check that this is a previously declared 'ivar' in 'IDecl' interface + ObjCInterfaceDecl *ClassDeclared; + Ivar = IDecl->lookupInstanceVariable(PropertyIvar, ClassDeclared); QualType PropType = property->getType(); - QualType PropertyIvarType = PropType.getNonReferenceType(); + + if (getLangOptions().ObjCAutoRefCount && + PropertyIvarType->isObjCRetainableType() && + (property->getPropertyAttributesAsWritten() & + ObjCPropertyDecl::OBJC_PR_readonly)) { + setImpliedPropertyAttributeForReadOnlyProperty(property, Ivar); + } + + ObjCPropertyDecl::PropertyAttributeKind kind + = property->getPropertyAttributes(); // Add GC __weak to the ivar type if the property is weak. if ((kind & ObjCPropertyDecl::OBJC_PR_weak) && @@ -627,9 +664,6 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, } } - // Check that this is a previously declared 'ivar' in 'IDecl' interface - ObjCInterfaceDecl *ClassDeclared; - Ivar = IDecl->lookupInstanceVariable(PropertyIvar, ClassDeclared); if (!Ivar) { // In ARC, give the ivar a lifetime qualifier based on the // property attributes. @@ -1681,6 +1715,21 @@ void Sema::CheckObjCPropertyAttributes(Decl *PDecl, ObjCPropertyDecl *PropertyDecl = cast(PDecl); QualType PropertyTy = PropertyDecl->getType(); + if (getLangOptions().ObjCAutoRefCount && + (Attributes & ObjCDeclSpec::DQ_PR_readonly) && + PropertyTy->isObjCRetainableType()) { + // 'readonly' property with no obvious lifetime. + // its life time will be determined by its backing ivar. + unsigned rel = (ObjCDeclSpec::DQ_PR_unsafe_unretained | + ObjCDeclSpec::DQ_PR_copy | + ObjCDeclSpec::DQ_PR_retain | + ObjCDeclSpec::DQ_PR_strong | + ObjCDeclSpec::DQ_PR_weak | + ObjCDeclSpec::DQ_PR_assign); + if ((Attributes & rel) == 0) + return; + } + // readonly and readwrite/assign/retain/copy conflict. if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) && (Attributes & (ObjCDeclSpec::DQ_PR_readwrite | diff --git a/test/SemaObjC/arc-readonly-property-ivar-1.m b/test/SemaObjC/arc-readonly-property-ivar-1.m new file mode 100644 index 0000000000..38a5ab2dee --- /dev/null +++ b/test/SemaObjC/arc-readonly-property-ivar-1.m @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -fobjc-default-synthesize-properties -triple x86_64-apple-darwin11 -fobjc-runtime-has-weak -fobjc-arc -fsyntax-only -verify %s +// RUN: %clang_cc1 -x objective-c++ -fobjc-default-synthesize-properties -triple x86_64-apple-darwin11 -fobjc-runtime-has-weak -fobjc-arc -fsyntax-only -verify %s +// rdar:// 10558871 + +@interface PP +@property (readonly) id ReadOnlyPropertyNoBackingIvar; +@property (readonly) id ReadOnlyProperty; +@property (readonly) id ReadOnlyPropertyX; +@end + +@implementation PP { +__weak id _ReadOnlyProperty; +} +@synthesize ReadOnlyPropertyNoBackingIvar; +@synthesize ReadOnlyProperty = _ReadOnlyProperty; +@synthesize ReadOnlyPropertyX = _ReadOnlyPropertyX; +@end + +@interface DD +@property (readonly) id ReadOnlyProperty; +@property (readonly) id ReadOnlyPropertyStrong; +@property (readonly) id ReadOnlyPropertyNoBackingIvar; +@end + +@implementation DD { +__weak id _ReadOnlyProperty; +__strong id _ReadOnlyPropertyStrong; +} +@end diff --git a/test/SemaObjC/arc-readonly-property-ivar.m b/test/SemaObjC/arc-readonly-property-ivar.m new file mode 100644 index 0000000000..adff0e69ae --- /dev/null +++ b/test/SemaObjC/arc-readonly-property-ivar.m @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fobjc-runtime-has-weak -fobjc-arc -fsyntax-only -verify %s +// rdar:// 10558871 + +@interface PP +@property (readonly) id ReadOnlyPropertyNoBackingIvar; +@property (readonly) id ReadOnlyProperty; +@property (readonly) id ReadOnlyPropertyX; +@end + +@implementation PP { +__weak id _ReadOnlyProperty; +} +@synthesize ReadOnlyPropertyNoBackingIvar; +@synthesize ReadOnlyProperty = _ReadOnlyProperty; +@synthesize ReadOnlyPropertyX = _ReadOnlyPropertyX; +@end -- 2.40.0