From 39ba639f9d38f69a9a010b736a9e56f660749786 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 llvm-svn: 147956 --- clang/lib/Sema/SemaObjCProperty.cpp | 61 +++++++++++++++++-- .../SemaObjC/arc-readonly-property-ivar-1.m | 29 +++++++++ .../SemaObjC/arc-readonly-property-ivar.m | 16 +++++ 3 files changed, 100 insertions(+), 6 deletions(-) create mode 100644 clang/test/SemaObjC/arc-readonly-property-ivar-1.m create mode 100644 clang/test/SemaObjC/arc-readonly-property-ivar.m diff --git a/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp index bbc6d233854d..52b48cc732d7 100644 --- a/clang/lib/Sema/SemaObjCProperty.cpp +++ b/clang/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; + // 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(); - QualType PropType = property->getType(); - - QualType PropertyIvarType = PropType.getNonReferenceType(); // 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/clang/test/SemaObjC/arc-readonly-property-ivar-1.m b/clang/test/SemaObjC/arc-readonly-property-ivar-1.m new file mode 100644 index 000000000000..38a5ab2dee98 --- /dev/null +++ b/clang/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/clang/test/SemaObjC/arc-readonly-property-ivar.m b/clang/test/SemaObjC/arc-readonly-property-ivar.m new file mode 100644 index 000000000000..adff0e69ae83 --- /dev/null +++ b/clang/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