]> granicus.if.org Git - clang/commitdiff
objective-c ivar refactoring patch. Iterations
authorFariborz Jahanian <fjahanian@apple.com>
Fri, 20 Aug 2010 21:21:08 +0000 (21:21 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Fri, 20 Aug 2010 21:21:08 +0000 (21:21 +0000)
over ivars for a varienty of puposes is now
consolidated into two small routines; DeepCollectObjCIvars
and ShallowCollectObjCIvars.

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

include/clang/AST/ASTContext.h
include/clang/AST/DeclObjC.h
include/clang/Sema/Sema.h
lib/AST/ASTContext.cpp
lib/AST/DeclObjC.cpp
lib/CodeGen/CGObjCMac.cpp
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaDeclObjC.cpp
lib/Serialization/ASTReaderDecl.cpp

index ab7202c2851c6d1131bc301e4e7457d1ecdf1ac9..2790c7941705f065b7c4e3c37ba9ac9cecb72a6c 100644 (file)
@@ -1009,13 +1009,12 @@ public:
   /// of class definition.
   const CXXMethodDecl *getKeyFunction(const CXXRecordDecl *RD);
 
-  void CollectObjCIvars(const ObjCInterfaceDecl *OI,
-                        llvm::SmallVectorImpl<FieldDecl*> &Fields);
-
   void ShallowCollectObjCIvars(const ObjCInterfaceDecl *OI,
                                llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars);
-  void CollectNonClassIvars(const ObjCInterfaceDecl *OI,
-                               llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars);
+  
+  void DeepCollectObjCIvars(const ObjCInterfaceDecl *OI, bool leafClass,
+                            llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars);
+  
   unsigned CountNonClassIvars(const ObjCInterfaceDecl *OI);
   void CollectInheritedProtocols(const Decl *CDecl,
                           llvm::SmallPtrSet<ObjCProtocolDecl*, 8> &Protocols);
index 26e8d3ee89b3438eacef647af24faf88fac8a2e5..c48e2295993d7ddd8d9bc8e8806b8efe57fdefb0 100644 (file)
@@ -464,6 +464,10 @@ class ObjCInterfaceDecl : public ObjCContainerDecl {
   /// List of categories defined for this class.
   /// FIXME: Why is this a linked list??
   ObjCCategoryDecl *CategoryList;
+  
+  /// IvarList - List of all ivars defined by this class; including class
+  /// extensions and implementation. This list is built lazily.
+  ObjCIvarDecl *IvarList;
 
   bool ForwardDecl:1; // declared with @class.
   bool InternalInterface:1; // true - no @interface for @implementation
@@ -518,7 +522,10 @@ public:
     return std::distance(ivar_begin(), ivar_end());
   }
   bool ivar_empty() const { return ivar_begin() == ivar_end(); }
-
+  
+  ObjCIvarDecl  *all_declared_ivar_begin();
+  void setIvarList(ObjCIvarDecl *ivar) { IvarList = ivar; }
+  
   /// setProtocolList - Set the list of protocols that this interface
   /// implements.
   void setProtocolList(ObjCProtocolDecl *const* List, unsigned Num,
@@ -640,7 +647,7 @@ private:
                QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW,
                bool synthesized)
     : FieldDecl(ObjCIvar, DC, L, Id, T, TInfo, BW, /*Mutable=*/false),
-      DeclAccess(ac),  Synthesized(synthesized) {}
+      NextIvar(0), DeclAccess(ac),  Synthesized(synthesized) {}
 
 public:
   static ObjCIvarDecl *Create(ASTContext &C, ObjCContainerDecl *DC,
@@ -654,6 +661,9 @@ public:
   /// interface the ivar is conceptually a part of in the case of synthesized
   /// ivars.
   const ObjCInterfaceDecl *getContainingInterface() const;
+  
+  ObjCIvarDecl *getNextIvar() { return NextIvar; }
+  void setNextIvar(ObjCIvarDecl *ivar) { NextIvar = ivar; }
 
   void setAccessControl(AccessControl ac) { DeclAccess = ac; }
 
@@ -671,6 +681,10 @@ public:
   static bool classof(const ObjCIvarDecl *D) { return true; }
   static bool classofKind(Kind K) { return K == ObjCIvar; }
 private:
+  /// NextIvar - Next Ivar in the list of ivars declared in class; class's 
+  /// extensions and class's implementation
+  ObjCIvarDecl *NextIvar;
+  
   // NOTE: VC++ treats enums as signed, avoid using the AccessControl enum
   unsigned DeclAccess : 3;
   unsigned Synthesized : 1;
index 4940216d88a8cfb737ffde4b44ea8311041f5a09..511f2321a717c09cdb82669b7f36989dcbf941d4 100644 (file)
@@ -1754,7 +1754,7 @@ public:
 
   /// CollectIvarsToConstructOrDestruct - Collect those ivars which require
   /// initialization.
-  void CollectIvarsToConstructOrDestruct(const ObjCInterfaceDecl *OI,
+  void CollectIvarsToConstructOrDestruct(ObjCInterfaceDecl *OI,
                                   llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars);
   //===--------------------------------------------------------------------===//
   // Statement Parsing Callbacks: SemaStmt.cpp.
index 95893a46164ad86e82a19ef1ea784b03593a5fde..ee4608badc05fd3074b9a9c68bb04babe4d51b50 100644 (file)
@@ -829,60 +829,37 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) {
   return ABIAlign;
 }
 
-static void CollectLocalObjCIvars(ASTContext *Ctx,
-                                  const ObjCInterfaceDecl *OI,
-                                  llvm::SmallVectorImpl<FieldDecl*> &Fields) {
-  for (ObjCInterfaceDecl::ivar_iterator I = OI->ivar_begin(),
-       E = OI->ivar_end(); I != E; ++I) {
-    ObjCIvarDecl *IVDecl = *I;
-    if (!IVDecl->isInvalidDecl())
-      Fields.push_back(cast<FieldDecl>(IVDecl));
-  }
-}
-
-void ASTContext::CollectObjCIvars(const ObjCInterfaceDecl *OI,
-                             llvm::SmallVectorImpl<FieldDecl*> &Fields) {
-  if (const ObjCInterfaceDecl *SuperClass = OI->getSuperClass())
-    CollectObjCIvars(SuperClass, Fields);
-  CollectLocalObjCIvars(this, OI, Fields);
-}
-
 /// ShallowCollectObjCIvars -
 /// Collect all ivars, including those synthesized, in the current class.
 ///
 void ASTContext::ShallowCollectObjCIvars(const ObjCInterfaceDecl *OI,
                                  llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) {
-  for (ObjCInterfaceDecl::ivar_iterator I = OI->ivar_begin(),
-         E = OI->ivar_end(); I != E; ++I) {
-     Ivars.push_back(*I);
-  }
-
-  CollectNonClassIvars(OI, Ivars);
-}
-
-/// CollectNonClassIvars -
-/// This routine collects all other ivars which are not declared in the class.
-/// This includes synthesized ivars (via @synthesize) and those in
-//  class's @implementation.
+  // FIXME. This need be removed but there are two many places which
+  // assume const-ness of ObjCInterfaceDecl
+  ObjCInterfaceDecl *IDecl = const_cast<ObjCInterfaceDecl *>(OI);
+  for (ObjCIvarDecl *Iv = IDecl->all_declared_ivar_begin(); Iv; 
+        Iv= Iv->getNextIvar())
+    Ivars.push_back(Iv);
+}
+
+/// DeepCollectObjCIvars -
+/// This routine first collects all declared, but not synthesized, ivars in
+/// super class and then collects all ivars, including those synthesized for
+/// current class. This routine is used for implementation of current class
+/// when all ivars, declared and synthesized are known.
 ///
-void ASTContext::CollectNonClassIvars(const ObjCInterfaceDecl *OI,
+void ASTContext::DeepCollectObjCIvars(const ObjCInterfaceDecl *OI,
+                                      bool leafClass,
                                 llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) {
-  // Find ivars declared in class extension.
-  for (const ObjCCategoryDecl *CDecl = OI->getFirstClassExtension(); CDecl;
-       CDecl = CDecl->getNextClassExtension()) {
-    for (ObjCCategoryDecl::ivar_iterator I = CDecl->ivar_begin(),
-         E = CDecl->ivar_end(); I != E; ++I) {
-      Ivars.push_back(*I);
-    }
-  }
-
-  // Also add any ivar defined in this class's implementation.  This
-  // includes synthesized ivars.
-  if (ObjCImplementationDecl *ImplDecl = OI->getImplementation()) {
-    for (ObjCImplementationDecl::ivar_iterator I = ImplDecl->ivar_begin(),
-         E = ImplDecl->ivar_end(); I != E; ++I)
+  if (const ObjCInterfaceDecl *SuperClass = OI->getSuperClass())
+    DeepCollectObjCIvars(SuperClass, false, Ivars);
+  if (!leafClass) {
+    for (ObjCInterfaceDecl::ivar_iterator I = OI->ivar_begin(),
+         E = OI->ivar_end(); I != E; ++I)
       Ivars.push_back(*I);
   }
+  else
+    ShallowCollectObjCIvars(OI, Ivars);
 }
 
 /// CollectInheritedProtocols - Collect all protocols in current class and
@@ -3853,15 +3830,14 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
     const IdentifierInfo *II = OI->getIdentifier();
     S += II->getName();
     S += '=';
-    llvm::SmallVector<FieldDecl*, 32> RecFields;
-    CollectObjCIvars(OI, RecFields);
-    for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
-      if (RecFields[i]->isBitField())
-        getObjCEncodingForTypeImpl(RecFields[i]->getType(), S, false, true,
-                                   RecFields[i]);
+    llvm::SmallVector<ObjCIvarDecl*, 32> Ivars;
+    DeepCollectObjCIvars(OI, true, Ivars);
+    for (unsigned i = 0, e = Ivars.size(); i != e; ++i) {
+      FieldDecl *Field = cast<FieldDecl>(Ivars[i]);
+      if (Field->isBitField())
+        getObjCEncodingForTypeImpl(Field->getType(), S, false, true, Field);
       else
-        getObjCEncodingForTypeImpl(RecFields[i]->getType(), S, false, true,
-                                   FD);
+        getObjCEncodingForTypeImpl(Field->getType(), S, false, true, FD);
     }
     S += '}';
     return;
index 32f9433d9a8a2a382ea1c9466ee01e0d6adcb41f..41678418380e864540022625c5e7170398830c79 100644 (file)
@@ -442,7 +442,8 @@ ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
                   SourceLocation CLoc, bool FD, bool isInternal)
   : ObjCContainerDecl(ObjCInterface, DC, atLoc, Id),
     TypeForDecl(0), SuperClass(0),
-    CategoryList(0), ForwardDecl(FD), InternalInterface(isInternal),
+    CategoryList(0), IvarList(0), 
+    ForwardDecl(FD), InternalInterface(isInternal),
     ClassLoc(CLoc) {
 }
 
@@ -455,6 +456,49 @@ void ObjCInterfaceDecl::setImplementation(ObjCImplementationDecl *ImplD) {
   getASTContext().setObjCImplementation(this, ImplD);
 }
 
+/// all_declared_ivar_begin - return first ivar declared in this class,
+/// its extensions and its implementation. Lazily build the list on first
+/// access.
+ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() {
+  if (IvarList)
+    return IvarList;
+  
+  ObjCIvarDecl *curIvar = 0;
+  if (!ivar_empty()) {
+    ObjCInterfaceDecl::ivar_iterator I = ivar_begin(), E = ivar_end();
+    IvarList = (*I); ++I;
+    for (curIvar = IvarList; I != E; curIvar = *I, ++I)
+      curIvar->setNextIvar(*I);
+  }
+  
+  for (const ObjCCategoryDecl *CDecl = getFirstClassExtension(); CDecl;
+       CDecl = CDecl->getNextClassExtension()) {
+    if (!CDecl->ivar_empty()) {
+      ObjCCategoryDecl::ivar_iterator I = CDecl->ivar_begin(),
+                                          E = CDecl->ivar_end();
+      if (!IvarList) {
+        IvarList = (*I); ++I;
+        curIvar = IvarList;
+      }
+      for ( ;I != E; curIvar = *I, ++I)
+        curIvar->setNextIvar(*I);
+    }
+  }
+  
+  if (ObjCImplementationDecl *ImplDecl = getImplementation()) {
+    if (!ImplDecl->ivar_empty()) {
+      ObjCImplementationDecl::ivar_iterator I = ImplDecl->ivar_begin(),
+                                            E = ImplDecl->ivar_end();
+      if (!IvarList) {
+        IvarList = (*I); ++I;
+        curIvar = IvarList;
+      }
+      for ( ;I != E; curIvar = *I, ++I)
+        curIvar->setNextIvar(*I);
+    }
+  }
+  return IvarList;
+}
 
 /// FindCategoryDeclaration - Finds category declaration in the list of
 /// categories for this class and returns it. Name of the category is passed
@@ -556,6 +600,16 @@ ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC,
     assert((isa<ObjCInterfaceDecl>(DC) || isa<ObjCImplementationDecl>(DC) ||
             isa<ObjCCategoryDecl>(DC)) &&
            "Invalid ivar decl context!");
+    // Once a new ivar is created in any of class/class-extension/implementation
+    // decl contexts, the previously built IvarList must be rebuilt.
+    ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(DC);
+    if (!ID) {
+      if (ObjCImplementationDecl *IM = dyn_cast<ObjCImplementationDecl>(DC))
+        ID = IM->getClassInterface();
+      else
+        ID = (cast<ObjCCategoryDecl>(DC))->getClassInterface();
+    }
+    ID->setIvarList(0);
   }
 
   return new (C) ObjCIvarDecl(DC, L, Id, T, TInfo, ac, BW, synthesized);
index ec13dd1cd2735e4351c337af3520e718b6f76308..57e36d9f94687158eef265a18de43bfe4886cbe9 100644 (file)
@@ -3871,13 +3871,11 @@ llvm::Constant *CGObjCCommonMac::BuildIvarLayout(
   if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC)
     return llvm::Constant::getNullValue(PtrTy);
 
-  llvm::SmallVector<FieldDecl*, 32> RecFields;
+  llvm::SmallVector<ObjCIvarDecl*, 32> Ivars;
   const ObjCInterfaceDecl *OI = OMD->getClassInterface();
-  CGM.getContext().CollectObjCIvars(OI, RecFields);
+  CGM.getContext().DeepCollectObjCIvars(OI, true, Ivars);
 
-  // Add this implementations synthesized ivars.
-  llvm::SmallVector<ObjCIvarDecl*, 16> Ivars;
-  CGM.getContext().CollectNonClassIvars(OI, Ivars);
+  llvm::SmallVector<FieldDecl*, 32> RecFields;
   for (unsigned k = 0, e = Ivars.size(); k != e; ++k)
     RecFields.push_back(cast<FieldDecl>(Ivars[k]));
 
index fa87b77957141c5cab7a5188c91be35cce113bbe..cf3112dd5186e4ca396e0b43576609fff464129b 100644 (file)
@@ -6921,7 +6921,7 @@ void Sema::MarkVirtualMembersReferenced(SourceLocation Loc,
 void Sema::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) {
   if (!getLangOptions().CPlusPlus)
     return;
-  if (const ObjCInterfaceDecl *OID = ObjCImplementation->getClassInterface()) {
+  if (ObjCInterfaceDecl *OID = ObjCImplementation->getClassInterface()) {
     llvm::SmallVector<ObjCIvarDecl*, 8> ivars;
     CollectIvarsToConstructOrDestruct(OID, ivars);
     if (ivars.empty())
index 2d3da3c9aaae8bf17a316295e8cf4459d2ff8c26..dda36e92ce47def23f00877612283d070bcd021d 100644 (file)
@@ -1395,6 +1395,7 @@ void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd,
         DefaultSynthesizeProperties(S, IC, IDecl);
       ImplMethodsVsClassMethods(S, IC, IDecl);
       AtomicPropertySetterGetterRules(IC, IDecl);
+  
       if (LangOpts.ObjCNonFragileABI2)
         while (IDecl->getSuperClass()) {
           DiagnoseDuplicateIvars(IDecl, IDecl->getSuperClass());
@@ -1651,11 +1652,11 @@ void Sema::ActOnDefs(Scope *S, DeclPtrTy TagD, SourceLocation DeclStart,
   }
 
   // Collect the instance variables
-  llvm::SmallVector<FieldDecl*, 32> RecFields;
-  Context.CollectObjCIvars(Class, RecFields);
+  llvm::SmallVector<ObjCIvarDecl*, 32> Ivars;
+  Context.DeepCollectObjCIvars(Class, true, Ivars);
   // For each ivar, create a fresh ObjCAtDefsFieldDecl.
-  for (unsigned i = 0; i < RecFields.size(); i++) {
-    FieldDecl* ID = RecFields[i];
+  for (unsigned i = 0; i < Ivars.size(); i++) {
+    FieldDecl* ID = cast<FieldDecl>(Ivars[i]);
     RecordDecl *Record = dyn_cast<RecordDecl>(TagD.getAs<Decl>());
     Decl *FD = ObjCAtDefsFieldDecl::Create(Context, Record, ID->getLocation(),
                                            ID->getIdentifier(), ID->getType(),
@@ -1770,38 +1771,13 @@ Sema::DeclPtrTy Sema::ActOnObjCExceptionDecl(Scope *S, Declarator &D) {
 
 /// CollectIvarsToConstructOrDestruct - Collect those ivars which require
 /// initialization.
-void Sema::CollectIvarsToConstructOrDestruct(const ObjCInterfaceDecl *OI,
+void Sema::CollectIvarsToConstructOrDestruct(ObjCInterfaceDecl *OI,
                                 llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) {
-  for (ObjCInterfaceDecl::ivar_iterator I = OI->ivar_begin(),
-       E = OI->ivar_end(); I != E; ++I) {
-    ObjCIvarDecl *Iv = (*I);
+  for (ObjCIvarDecl *Iv = OI->all_declared_ivar_begin(); Iv; 
+       Iv= Iv->getNextIvar()) {
     QualType QT = Context.getBaseElementType(Iv->getType());
     if (QT->isRecordType())
-      Ivars.push_back(*I);
-  }
-  
-  // Find ivars to construct/destruct in class extension.
-  for (const ObjCCategoryDecl *CDecl = OI->getFirstClassExtension(); CDecl;
-      CDecl = CDecl->getNextClassExtension()) {
-    for (ObjCCategoryDecl::ivar_iterator I = CDecl->ivar_begin(),
-         E = CDecl->ivar_end(); I != E; ++I) {
-      ObjCIvarDecl *Iv = (*I);
-      QualType QT = Context.getBaseElementType(Iv->getType());
-      if (QT->isRecordType())
-        Ivars.push_back(*I);
-    }
-  }
-  
-  // Also add any ivar defined in this class's implementation.  This
-  // includes synthesized ivars.
-  if (ObjCImplementationDecl *ImplDecl = OI->getImplementation()) {
-    for (ObjCImplementationDecl::ivar_iterator I = ImplDecl->ivar_begin(),
-         E = ImplDecl->ivar_end(); I != E; ++I) {
-      ObjCIvarDecl *Iv = (*I);
-      QualType QT = Context.getBaseElementType(Iv->getType());
-      if (QT->isRecordType())
-        Ivars.push_back(*I);
-    }
+      Ivars.push_back(Iv);
   }
 }
 
index bc68e91e3edfcf66a39eb2d101b484905af66a54..e8bf195787b45d0013795c7f7d5141663b472086 100644 (file)
@@ -392,6 +392,8 @@ void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
     IVars.push_back(cast<ObjCIvarDecl>(Reader.GetDecl(Record[Idx++])));
   ID->setCategoryList(
                cast_or_null<ObjCCategoryDecl>(Reader.GetDecl(Record[Idx++])));
+  // We will rebuild this list lazily.
+  ID->setIvarList(0);
   ID->setForwardDecl(Record[Idx++]);
   ID->setImplicitInterfaceDecl(Record[Idx++]);
   ID->setClassLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
@@ -402,6 +404,8 @@ void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
 void ASTDeclReader::VisitObjCIvarDecl(ObjCIvarDecl *IVD) {
   VisitFieldDecl(IVD);
   IVD->setAccessControl((ObjCIvarDecl::AccessControl)Record[Idx++]);
+  // This field will be built lazily.
+  IVD->setNextIvar(0);
   bool synth = Record[Idx++];
   IVD->setSynthesize(synth);
 }