]> granicus.if.org Git - clang/commitdiff
Patch to implement ivar synthesis of properties declared in protocols
authorFariborz Jahanian <fjahanian@apple.com>
Tue, 12 May 2009 18:14:29 +0000 (18:14 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Tue, 12 May 2009 18:14:29 +0000 (18:14 +0000)
only and used in class imllementations (objc2 Nonfragile ABI specific).

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

include/clang/AST/ASTContext.h
lib/AST/ASTContext.cpp
lib/CodeGen/CGObjCMac.cpp
test/CodeGenObjC/protocol-property-synth.m [new file with mode: 0644]

index 8b4c89b6e8b14a71dd9d1b0a8e1d546754340e5f..335fc40aea29146ddb58970a8448b8a75da93463 100644 (file)
@@ -535,6 +535,11 @@ public:
 
   void CollectObjCIvars(const ObjCInterfaceDecl *OI,
                         llvm::SmallVectorImpl<FieldDecl*> &Fields);
+  
+  void CollectSynthesizedIvars(const ObjCInterfaceDecl *OI,
+                               llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars);
+  void CollectProtocolSynthesizedIvars(const ObjCProtocolDecl *PD,
+                               llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars);
 
   //===--------------------------------------------------------------------===//
   //                            Type Operators
index 52eadef75ab9e60e0f0e745fa7600c2335af4412..ac46180b94d8f97c39e07e717b28dec1f781d60c 100644 (file)
@@ -685,6 +685,38 @@ void ASTContext::CollectObjCIvars(const ObjCInterfaceDecl *OI,
   CollectLocalObjCIvars(this, OI, Fields);
 }
 
+void ASTContext::CollectProtocolSynthesizedIvars(const ObjCProtocolDecl *PD,
+                                llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) {
+  for (ObjCContainerDecl::prop_iterator I = PD->prop_begin(*this),
+       E = PD->prop_end(*this); I != E; ++I)
+    if (ObjCIvarDecl *Ivar = (*I)->getPropertyIvarDecl())
+      Ivars.push_back(Ivar);
+  
+  // Also look into nested protocols.
+  for (ObjCProtocolDecl::protocol_iterator P = PD->protocol_begin(),
+       E = PD->protocol_end(); P != E; ++P)
+    CollectProtocolSynthesizedIvars(*P, Ivars);
+}
+
+/// CollectSynthesizedIvars -
+/// This routine collect synthesized ivars for the designated class.
+///
+void ASTContext::CollectSynthesizedIvars(const ObjCInterfaceDecl *OI,
+                                llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) {
+  for (ObjCInterfaceDecl::prop_iterator I = OI->prop_begin(*this),
+       E = OI->prop_end(*this); I != E; ++I) {
+    if (ObjCIvarDecl *Ivar = (*I)->getPropertyIvarDecl())
+      Ivars.push_back(Ivar);
+  }
+  // Also look into interface's protocol list for properties declared
+  // in the protocol and whose ivars are synthesized.
+  for (ObjCInterfaceDecl::protocol_iterator P = OI->protocol_begin(),
+       PE = OI->protocol_end(); P != PE; ++P) {
+    ObjCProtocolDecl *PD = (*P);
+    CollectProtocolSynthesizedIvars(PD, Ivars);
+  }
+}
+
 /// getInterfaceLayoutImpl - Get or compute information about the
 /// layout of the given interface.
 ///
@@ -704,11 +736,9 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D,
   unsigned FieldCount = D->ivar_size();
   // Add in synthesized ivar count if laying out an implementation.
   if (Impl) {
-    for (ObjCInterfaceDecl::prop_iterator I = D->prop_begin(*this),
-           E = D->prop_end(*this); I != E; ++I)
-      if ((*I)->getPropertyIvarDecl())
-        ++FieldCount;
-
+    llvm::SmallVector<ObjCIvarDecl*, 16> Ivars;
+    CollectSynthesizedIvars(D, Ivars);
+    FieldCount += Ivars.size();
     // If there aren't any sythesized ivars then reuse the interface
     // entry. Note we can't cache this because we simply free all
     // entries later; however we shouldn't look up implementations
@@ -750,11 +780,11 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D,
   }
   // And synthesized ivars, if this is an implementation.
   if (Impl) {
-    for (ObjCInterfaceDecl::prop_iterator I = D->prop_begin(*this),
-           E = D->prop_end(*this); I != E; ++I) {
-      if (ObjCIvarDecl *Ivar = (*I)->getPropertyIvarDecl())
-        NewEntry->LayoutField(Ivar, i++, false, StructPacking, *this);
-    }
+    // FIXME. Do we need to colltect twice?
+    llvm::SmallVector<ObjCIvarDecl*, 16> Ivars;
+    CollectSynthesizedIvars(D, Ivars);
+    for (unsigned k = 0, e = Ivars.size(); k != e; ++k)
+      NewEntry->LayoutField(Ivars[k], i++, false, StructPacking, *this);
   }
   
   // Finally, round the size of the total struct up to the alignment of the
index 9d57fcb786b7516be91d0d3b95615fe933cf1f61..9418d0a25573eea0906d69e1e498c1a512ebea2a 100644 (file)
@@ -53,15 +53,14 @@ static const ObjCInterfaceDecl *FindIvarInterface(ASTContext &Context,
       return OID;
   
   // Also look in synthesized ivars.
-  for (ObjCInterfaceDecl::prop_iterator I = OID->prop_begin(Context),
-         E = OID->prop_end(Context); I != E; ++I) {
-    if (ObjCIvarDecl *Ivar = (*I)->getPropertyIvarDecl()) {
-      if (OIVD == Ivar)
-        return OID;
-      ++Index;
-    }
+  llvm::SmallVector<ObjCIvarDecl*, 16> Ivars;
+  Context.CollectSynthesizedIvars(OID, Ivars);
+  for (unsigned k = 0, e = Ivars.size(); k != e; ++k) {
+    if (OIVD == Ivars[k])
+      return OID;
+    ++Index;
   }
-
+  
   // Otherwise check in the super class.
   if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
     return FindIvarInterface(Context, Super, OIVD, Index);
@@ -3153,14 +3152,13 @@ llvm::Constant *CGObjCCommonMac::BuildIvarLayout(
   llvm::SmallVector<FieldDecl*, 32> RecFields;
   const ObjCInterfaceDecl *OI = OMD->getClassInterface();
   CGM.getContext().CollectObjCIvars(OI, RecFields);
-
+  
   // Add this implementations synthesized ivars.
-  for (ObjCInterfaceDecl::prop_iterator I = OI->prop_begin(CGM.getContext()),
-         E = OI->prop_end(CGM.getContext()); I != E; ++I) {
-    if (ObjCIvarDecl *IV = (*I)->getPropertyIvarDecl())
-      RecFields.push_back(cast<FieldDecl>(IV));
-  }
-
+  llvm::SmallVector<ObjCIvarDecl*, 16> Ivars;
+  CGM.getContext().CollectSynthesizedIvars(OI, Ivars);
+  for (unsigned k = 0, e = Ivars.size(); k != e; ++k)
+    RecFields.push_back(cast<FieldDecl>(Ivars[k]));
+  
   if (RecFields.empty())
     return llvm::Constant::getNullValue(PtrTy);
   
@@ -4677,10 +4675,12 @@ void CGObjCCommonMac::GetNamedIvarList(const ObjCInterfaceDecl *OID,
      Res.push_back(*I);
   }
   
-  for (ObjCInterfaceDecl::prop_iterator I = OID->prop_begin(CGM.getContext()),
-         E = OID->prop_end(CGM.getContext()); I != E; ++I)
-    if (ObjCIvarDecl *IV = (*I)->getPropertyIvarDecl())
-      Res.push_back(IV);
+  // Also save synthesize ivars.
+  // FIXME. Why can't we just use passed in Res small vector?
+  llvm::SmallVector<ObjCIvarDecl*, 16> Ivars;
+  CGM.getContext().CollectSynthesizedIvars(OID, Ivars);
+  for (unsigned k = 0, e = Ivars.size(); k != e; ++k)
+    Res.push_back(Ivars[k]);
 }
 
 llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
diff --git a/test/CodeGenObjC/protocol-property-synth.m b/test/CodeGenObjC/protocol-property-synth.m
new file mode 100644 (file)
index 0000000..e91f355
--- /dev/null
@@ -0,0 +1,33 @@
+// RUN: clang-cc -triple x86_64-apple-darwin10 -emit-llvm -o %t %s
+
+@interface BaseClass {
+    id _delegate;
+}
+@end
+
+@protocol MyProtocol
+@optional
+@property(assign) id delegate;
+@end
+
+@protocol AnotherProtocol
+@optional
+@property(assign) id myanother;
+@end
+
+@protocol SubProtocol <MyProtocol>
+@property(assign) id another;
+@end
+
+@interface SubClass : BaseClass <SubProtocol, AnotherProtocol> {
+}
+
+@end
+
+@implementation BaseClass @end 
+
+@implementation SubClass
+@synthesize delegate = _Subdelegate;
+@synthesize another;
+@synthesize myanother;
+@end