]> granicus.if.org Git - clang/commitdiff
objc-arc: evaluate 'readonly' property with no known
authorFariborz Jahanian <fjahanian@apple.com>
Wed, 11 Jan 2012 18:26:06 +0000 (18:26 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Wed, 11 Jan 2012 18:26:06 +0000 (18:26 +0000)
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
test/SemaObjC/arc-readonly-property-ivar-1.m [new file with mode: 0644]
test/SemaObjC/arc-readonly-property-ivar.m [new file with mode: 0644]

index bbc6d233854d4228dae3f513f4d6ee7d1ccc7dea..52b48cc732d73f71c57f9ce1184599a0f8d25590 100644 (file)
@@ -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<ObjCPropertyDecl>(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 (file)
index 0000000..38a5ab2
--- /dev/null
@@ -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 (file)
index 0000000..adff0e6
--- /dev/null
@@ -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