[cfe-commits] r120627 - in /cfe/trunk: include/clang/AST/DeclObjC.h include/clang/AST/ExternalASTSource.h lib/AST/DeclObjC.cpp

Douglas Gregor dgregor at apple.com
Wed Dec 1 15:49:53 PST 2010


Author: dgregor
Date: Wed Dec  1 17:49:52 2010
New Revision: 120627

URL: http://llvm.org/viewvc/llvm-project?rev=120627&view=rev
Log:
Extend ExternalASTSource with the ability to lazily complete the
definition of an Objective-C class. Unlike with C/C++ classes, we
don't have a well-defined point in Sema where Objective-C classes are
checked for completeness, nor do we need to involve Sema when
completing a class. Therefore, we take the appropriate of having the
external AST source mark a particular Objective-C class as having an
external declaration; when using one of the accessors of an
Objective-C class that has an external declaration, we request that
the external AST source fill in the Objective-C class definition.

Modified:
    cfe/trunk/include/clang/AST/DeclObjC.h
    cfe/trunk/include/clang/AST/ExternalASTSource.h
    cfe/trunk/lib/AST/DeclObjC.cpp

Modified: cfe/trunk/include/clang/AST/DeclObjC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=120627&r1=120626&r2=120627&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclObjC.h (original)
+++ cfe/trunk/include/clang/AST/DeclObjC.h Wed Dec  1 17:49:52 2010
@@ -459,7 +459,11 @@
 
   bool ForwardDecl:1; // declared with @class.
   bool InternalInterface:1; // true - no @interface for @implementation
-
+  
+  /// \brief Indicates that the contents of this Objective-C class will be
+  /// completed by the external AST source when required.
+  mutable bool ExternallyCompleted : 1;
+  
   SourceLocation ClassLoc; // location of the class identifier.
   SourceLocation SuperClassLoc; // location of the super class identifier.
   SourceLocation EndLoc; // marks the '>', '}', or identifier.
@@ -467,6 +471,7 @@
   ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
                     SourceLocation CLoc, bool FD, bool isInternal);
 
+  void LoadExternalDefinition() const;
 public:
   static ObjCInterfaceDecl *Create(ASTContext &C, DeclContext *DC,
                                    SourceLocation atLoc,
@@ -474,7 +479,16 @@
                                    SourceLocation ClassLoc = SourceLocation(),
                                    bool ForwardDecl = false,
                                    bool isInternal = false);
+  
+  /// \brief Indicate that this Objective-C class is complete, but that
+  /// the external AST source will be responsible for filling in its contents
+  /// when a complete class is required.
+  void setExternallyCompleted();
+  
   const ObjCProtocolList &getReferencedProtocols() const {
+    if (ExternallyCompleted)
+      LoadExternalDefinition();
+    
     return ReferencedProtocols;
   }
 
@@ -494,29 +508,47 @@
   typedef ObjCProtocolList::iterator protocol_iterator;
   
   protocol_iterator protocol_begin() const {
+    if (ExternallyCompleted)
+      LoadExternalDefinition();
+
     return ReferencedProtocols.begin();
   }
   protocol_iterator protocol_end() const {
+    if (ExternallyCompleted)
+      LoadExternalDefinition();
+
     return ReferencedProtocols.end();
   }
 
   typedef ObjCProtocolList::loc_iterator protocol_loc_iterator;
 
   protocol_loc_iterator protocol_loc_begin() const { 
+    if (ExternallyCompleted)
+      LoadExternalDefinition();
+
     return ReferencedProtocols.loc_begin(); 
   }
 
   protocol_loc_iterator protocol_loc_end() const { 
+    if (ExternallyCompleted)
+      LoadExternalDefinition();
+
     return ReferencedProtocols.loc_end(); 
   }
   
   typedef ObjCList<ObjCProtocolDecl>::iterator all_protocol_iterator;
   
   all_protocol_iterator all_referenced_protocol_begin() const {
+    if (ExternallyCompleted)
+      LoadExternalDefinition();
+
     return AllReferencedProtocols.empty() ? protocol_begin()
       : AllReferencedProtocols.begin();
   }
   all_protocol_iterator all_referenced_protocol_end() const {
+    if (ExternallyCompleted)
+      LoadExternalDefinition();
+
     return AllReferencedProtocols.empty() ? protocol_end() 
       : AllReferencedProtocols.end();
   }
@@ -551,10 +583,22 @@
   bool isForwardDecl() const { return ForwardDecl; }
   void setForwardDecl(bool val) { ForwardDecl = val; }
 
-  ObjCInterfaceDecl *getSuperClass() const { return SuperClass; }
+  ObjCInterfaceDecl *getSuperClass() const { 
+    if (ExternallyCompleted)
+      LoadExternalDefinition();
+
+    return SuperClass; 
+  }
+  
   void setSuperClass(ObjCInterfaceDecl * superCls) { SuperClass = superCls; }
 
-  ObjCCategoryDecl* getCategoryList() const { return CategoryList; }
+  ObjCCategoryDecl* getCategoryList() const { 
+    if (ExternallyCompleted)
+      LoadExternalDefinition();
+
+    return CategoryList; 
+  }
+  
   void setCategoryList(ObjCCategoryDecl *category) {
     CategoryList = category;
   }

Modified: cfe/trunk/include/clang/AST/ExternalASTSource.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExternalASTSource.h?rev=120627&r1=120626&r2=120627&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExternalASTSource.h (original)
+++ cfe/trunk/include/clang/AST/ExternalASTSource.h Wed Dec  1 17:49:52 2010
@@ -147,6 +147,14 @@
   /// an incomplete type.
   virtual void CompleteType(TagDecl *Tag) {}
 
+  /// \brief Gives the external AST source an opportunity to complete an
+  /// incomplete Objective-C class.
+  ///
+  /// This routine will only be invoked if the "externally completed" bit is
+  /// set on the ObjCInterfaceDecl via the function 
+  /// \c ObjCInterfaceDecl::setExternallyCompleted().
+  virtual void CompleteType(ObjCInterfaceDecl *Class) { }
+  
   /// \brief Notify ExternalASTSource that we started deserialization of
   /// a decl or type so until FinishedDeserializing is called there may be
   /// decls that are initializing. Must be paired with FinishedDeserializing.

Modified: cfe/trunk/lib/AST/DeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclObjC.cpp?rev=120627&r1=120626&r2=120627&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclObjC.cpp (original)
+++ cfe/trunk/lib/AST/DeclObjC.cpp Wed Dec  1 17:49:52 2010
@@ -153,6 +153,9 @@
 ObjCPropertyDecl *
 ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass(
                                             IdentifierInfo *PropertyId) const {
+  if (ExternallyCompleted)
+    LoadExternalDefinition();
+
   if (ObjCPropertyDecl *PD =
       ObjCPropertyDecl::findPropertyDecl(cast<DeclContext>(this), PropertyId))
     return PD;
@@ -171,6 +174,9 @@
                               ObjCProtocolDecl *const* ExtList, unsigned ExtNum,
                               ASTContext &C)
 {
+  if (ExternallyCompleted)
+    LoadExternalDefinition();
+
   if (AllReferencedProtocols.empty() && ReferencedProtocols.empty()) {
     AllReferencedProtocols.set(ExtList, ExtNum, C);
     return;
@@ -270,6 +276,9 @@
   const ObjCInterfaceDecl* ClassDecl = this;
   ObjCMethodDecl *MethodDecl = 0;
 
+  if (ExternallyCompleted)
+    LoadExternalDefinition();
+
   while (ClassDecl != NULL) {
     if ((MethodDecl = ClassDecl->getMethod(Sel, isInstance)))
       return MethodDecl;
@@ -443,11 +452,29 @@
   : ObjCContainerDecl(ObjCInterface, DC, atLoc, Id),
     TypeForDecl(0), SuperClass(0),
     CategoryList(0), IvarList(0), 
-    ForwardDecl(FD), InternalInterface(isInternal),
+    ForwardDecl(FD), InternalInterface(isInternal), ExternallyCompleted(false),
     ClassLoc(CLoc) {
 }
 
+void ObjCInterfaceDecl::LoadExternalDefinition() const {
+  assert(ExternallyCompleted && "Class is not externally completed");
+  ExternallyCompleted = false;
+  getASTContext().getExternalSource()->CompleteType(
+                                        const_cast<ObjCInterfaceDecl *>(this));
+}
+
+void ObjCInterfaceDecl::setExternallyCompleted() {
+  assert(getASTContext().getExternalSource() && 
+         "Class can't be externally completed without an external source");
+  assert(!ForwardDecl && 
+         "Forward declarations can't be externally completed");
+  ExternallyCompleted = true;
+}
+
 ObjCImplementationDecl *ObjCInterfaceDecl::getImplementation() const {
+  if (ExternallyCompleted)
+    LoadExternalDefinition();
+
   return getASTContext().getObjCImplementation(
                                           const_cast<ObjCInterfaceDecl*>(this));
 }
@@ -506,6 +533,9 @@
 ///
 ObjCCategoryDecl *
 ObjCInterfaceDecl::FindCategoryDeclaration(IdentifierInfo *CategoryId) const {
+  if (ExternallyCompleted)
+    LoadExternalDefinition();
+
   for (ObjCCategoryDecl *Category = getCategoryList();
        Category; Category = Category->getNextClassCategory())
     if (Category->getIdentifier() == CategoryId)





More information about the cfe-commits mailing list