]> granicus.if.org Git - clang/commitdiff
Implement new default property synthesis rules. Essentially, no longer
authorFariborz Jahanian <fjahanian@apple.com>
Fri, 14 May 2010 18:35:57 +0000 (18:35 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Fri, 14 May 2010 18:35:57 +0000 (18:35 +0000)
user directive is needed to force a property implementation.
It is decided based on those propeties which are declared in
the class (or in its protocols) but not those which must be
default implemented by one of its super classes. Implements radar 7923851.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@103787 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/Sema.h
lib/Sema/SemaDeclObjC.cpp
lib/Sema/SemaObjCProperty.cpp
test/CodeGenObjC/default-property-synthesis.m [new file with mode: 0644]

index 4ef5ebe20a7cc6112940c56213b09e8b2727ac88..d97dc676823f31efd3fcb7bbcc18394f0cbb0c40 100644 (file)
@@ -1542,6 +1542,11 @@ public:
                                        ObjCContainerDecl *CDecl,
                                        const llvm::DenseSet<Selector>& InsMap);
 
+  /// DefaultSynthesizeProperties - This routine default synthesizes all 
+  /// properties which must be synthesized in class's @implementation.
+  void DefaultSynthesizeProperties (Scope *S, ObjCImplDecl* IMPDecl,
+                                    ObjCInterfaceDecl *IDecl);
+  
   /// CollectImmediateProperties - This routine collects all properties in
   /// the class and its conforming protocols; but not those it its super class.
   void CollectImmediateProperties(ObjCContainerDecl *CDecl,
index b7d737984c74698f099d9e3cd861b2ff4dd54cfa..9ed969211419d98c2ba668e6e4d76db8c0b3bbbc 100644 (file)
@@ -938,7 +938,7 @@ void Sema::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl,
   // Check and see if properties declared in the interface have either 1)
   // an implementation or 2) there is a @synthesize/@dynamic implementation
   // of the property in the @implementation.
-  if (isa<ObjCInterfaceDecl>(CDecl))
+  if (isa<ObjCInterfaceDecl>(CDecl) && !LangOpts.ObjCNonFragileABI2)
     DiagnoseUnimplementedProperties(S, IMPDecl, CDecl, InsMap);
       
   llvm::DenseSet<Selector> ClsMap;
@@ -1433,6 +1433,8 @@ void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd,
   if (ObjCImplementationDecl *IC=dyn_cast<ObjCImplementationDecl>(ClassDecl)) {
     IC->setAtEndRange(AtEnd);
     if (ObjCInterfaceDecl* IDecl = IC->getClassInterface()) {
+      if (LangOpts.ObjCNonFragileABI2)
+        DefaultSynthesizeProperties(S, IC, IDecl);
       ImplMethodsVsClassMethods(S, IC, IDecl);
       AtomicPropertySetterGetterRules(IC, IDecl);
       if (LangOpts.ObjCNonFragileABI2)
index f64ee970a95943db2ced6edff8402f242cdc9266..a2aef20f658fe965bd0569f566f6a7a97669ae64 100644 (file)
@@ -802,6 +802,47 @@ void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl,
   }
 }
 
+/// CollectClassPropertyImplementations - This routine collects list of
+/// properties to be implemented in the class. This includes, class's
+/// and its conforming protocols' properties.
+static void CollectClassPropertyImplementations(ObjCContainerDecl *CDecl,
+                llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap) {
+  if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) {
+    for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(),
+         E = IDecl->prop_end(); P != E; ++P) {
+      ObjCPropertyDecl *Prop = (*P);
+      PropMap[Prop->getIdentifier()] = Prop;
+    }
+    for (ObjCInterfaceDecl::protocol_iterator PI = IDecl->protocol_begin(),
+         E = IDecl->protocol_end(); PI != E; ++PI)
+      CollectClassPropertyImplementations((*PI), PropMap);
+  }
+  else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) {
+    for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
+         E = PDecl->prop_end(); P != E; ++P) {
+      ObjCPropertyDecl *Prop = (*P);
+      PropMap[Prop->getIdentifier()] = Prop;
+    }
+    // scan through protocol's protocols.
+    for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(),
+         E = PDecl->protocol_end(); PI != E; ++PI)
+      CollectClassPropertyImplementations((*PI), PropMap);
+  }
+}
+
+/// CollectSuperClassPropertyImplementations - This routine collects list of
+/// properties to be implemented in super class(s) and also coming from their
+/// conforming protocols.
+static void CollectSuperClassPropertyImplementations(ObjCInterfaceDecl *CDecl,
+                llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap) {
+  if (ObjCInterfaceDecl *SDecl = CDecl->getSuperClass()) {
+    while (SDecl) {
+      CollectClassPropertyImplementations(SDecl, PropMap);
+      SDecl = SDecl->getSuperClass();
+    }
+  }
+}
+
 /// ProtocolConformsToSuperClass - Returns true if class's given protocol
 /// conforms to one of its super class's protocols.
 bool Sema::ProtocolConformsToSuperClass(const ObjCInterfaceDecl *IDecl,
@@ -868,6 +909,34 @@ ObjCPropertyDecl *Sema::LookupPropertyDecl(const ObjCContainerDecl *CDecl,
   return 0;
 }
 
+/// DefaultSynthesizeProperties - This routine default synthesizes all
+/// properties which must be synthesized in class's @implementation.
+void Sema::DefaultSynthesizeProperties (Scope *S, ObjCImplDecl* IMPDecl,
+                                        ObjCInterfaceDecl *IDecl) {
+  
+  llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> PropMap;
+  CollectClassPropertyImplementations(IDecl, PropMap);
+  if (PropMap.empty())
+    return;
+  llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> SuperPropMap;
+  CollectSuperClassPropertyImplementations(IDecl, SuperPropMap);
+  
+  for (llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>::iterator
+       P = PropMap.begin(), E = PropMap.end(); P != E; ++P) {
+    ObjCPropertyDecl *Prop = P->second;
+    // If property to be implemented in the super class, ignore.
+    if (SuperPropMap[Prop->getIdentifier()])
+      continue;
+    // Is there a matching propery synthesize/dynamic?
+    if (Prop->isInvalidDecl() ||
+        Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional ||
+        IMPDecl->FindPropertyImplIvarDecl(Prop->getIdentifier()))
+      continue;
+    ActOnPropertyImplDecl(S, IMPDecl->getLocation(), IMPDecl->getLocation(),
+                          true, DeclPtrTy::make(IMPDecl),
+                          Prop->getIdentifier(), Prop->getIdentifier());
+  }    
+}
 
 void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl,
                                       ObjCContainerDecl *CDecl,
@@ -891,14 +960,6 @@ void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl,
         Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional ||
         PropImplMap.count(Prop))
       continue;
-    if (LangOpts.ObjCNonFragileABI2 && !isa<ObjCCategoryImplDecl>(IMPDecl)) {
-      ActOnPropertyImplDecl(S, IMPDecl->getLocation(),
-                            IMPDecl->getLocation(),
-                            true, DeclPtrTy::make(IMPDecl),
-                            Prop->getIdentifier(),
-                            Prop->getIdentifier());
-      continue;
-    }
     if (!InsMap.count(Prop->getGetterName())) {
       Diag(Prop->getLocation(),
            isa<ObjCCategoryDecl>(CDecl) ?
diff --git a/test/CodeGenObjC/default-property-synthesis.m b/test/CodeGenObjC/default-property-synthesis.m
new file mode 100644 (file)
index 0000000..b3eeb22
--- /dev/null
@@ -0,0 +1,38 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi2 -emit-llvm -o %t %s
+// rdar://7923851.
+
+// Superclass declares property. Subclass redeclares the same property.
+// Do not @synthesize-by-default in the subclass. P1
+// Superclass declares a property. Subclass declares a different property with the same name
+// (such as different type or attributes). Do not @synthesize-by-default in the subclass. P2
+// Superclass conforms to a protocol that declares a property. Subclass redeclares the 
+// same property.  Do not @synthesize-by-default in the subclass. P3
+// Superclass conforms to a protocol that declares a property. Subclass conforms to the 
+// same protocol or a derived protocol. Do not @synthesize-by-default in the subclass. P4
+
+
+@protocol PROTO
+  @property int P3;
+  @property int P4;
+@end
+
+@protocol PROTO1 <PROTO> 
+  @property int IMP1;
+@end
+
+@interface Super <PROTO>
+  @property int P1;
+  @property (copy) id P2;
+@end
+
+@interface Sub : Super <PROTO1>
+  @property int P1;
+  @property (nonatomic, retain) id P2; // expected-warning {{property 'P2' 'copy' attribute does not match the property inherited from 'Super'}} \
+                                      // expected-warning {{property 'P2' 'atomic' attribute does not match the property inherited from 'Super'}}
+  @property int P3;
+  @property int IMP2;
+@end
+
+@implementation Sub 
+@end
+