Move the definition-specific data of ObjCInterfaceDecl into a
separately-allocated DefinitionData structure, which we manage the
same way as CXXRecordDecl::DefinitionData. This prepares the way for
making ObjCInterfaceDecls redeclarable, to more accurately model
forward declarations of Objective-C classes and eliminate the mutation
of ObjCInterfaceDecl that causes us serious trouble in the AST reader.

Note that ObjCInterfaceDecl's accessors are fairly robust against
being applied to forward declarations, because Clang (and Sema in
particular) doesn't perform RequireCompleteType/hasDefinition() checks
everywhere it has to. Each of these overly-robust cases is marked with
a FIXME, which we can tackle over time.




git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@146644 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h
index 597eb45..06fa4cb 100644
--- a/include/clang/AST/DeclObjC.h
+++ b/include/clang/AST/DeclObjC.h
@@ -545,45 +545,63 @@
   /// TypeDecl.  It is a cache maintained by ASTContext::getObjCInterfaceType
   mutable const Type *TypeForDecl;
   friend class ASTContext;
+  
+  struct DefinitionData {
+    /// Class's super class.
+    ObjCInterfaceDecl *SuperClass;
 
-  /// Class's super class.
-  ObjCInterfaceDecl *SuperClass;
+    /// Protocols referenced in the @interface  declaration
+    ObjCProtocolList ReferencedProtocols;
 
-  /// Protocols referenced in the @interface  declaration
-  ObjCProtocolList ReferencedProtocols;
+    /// Protocols reference in both the @interface and class extensions.
+    ObjCList<ObjCProtocolDecl> AllReferencedProtocols;
 
-  /// Protocols reference in both the @interface and class extensions.
-  ObjCList<ObjCProtocolDecl> AllReferencedProtocols;
+    /// \brief List of categories and class extensions defined for this class.
+    ///
+    /// Categories are stored as a linked list in the AST, since the categories
+    /// and class extensions come long after the initial interface declaration,
+    /// and we avoid dynamically-resized arrays in the AST wherever possible.
+    ObjCCategoryDecl *CategoryList;
 
-  /// \brief List of categories and class extensions defined for this class.
-  ///
-  /// Categories are stored as a linked list in the AST, since the categories
-  /// and class extensions come long after the initial interface declaration,
-  /// and we avoid dynamically-resized arrays in the AST wherever possible.
-  ObjCCategoryDecl *CategoryList;
+    /// IvarList - List of all ivars defined by this class; including class
+    /// extensions and implementation. This list is built lazily.
+    ObjCIvarDecl *IvarList;
 
-  /// IvarList - List of all ivars defined by this class; including class
-  /// extensions and implementation. This list is built lazily.
-  ObjCIvarDecl *IvarList;
+    /// \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 SuperClassLoc; // location of the super class identifier.
+  };
+
+  ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
+                    SourceLocation CLoc, bool FD, bool isInternal);
+
+  void LoadExternalDefinition() const;
+
+  /// \brief Contains a pointer to the data associated with this class,
+  /// which will be NULL if this class has not yet been defined.
+  DefinitionData *Definition;
+
+  /// \brief The location of the last location in this declaration, e.g.,
+  /// the '>', '}', or identifier.
+  /// FIXME: This seems like the wrong location to care about.
+  SourceLocation EndLoc; 
 
   /// \brief True if it was initially declared with @class.
   /// Differs with \see ForwardDecl in that \see ForwardDecl will change to
   /// false when we see the @interface, but InitiallyForwardDecl will remain
   /// true.
   bool InitiallyForwardDecl : 1;
-  bool ForwardDecl:1; // declared with @class.
 
-  /// \brief Indicates that the contents of this Objective-C class will be
-  /// completed by the external AST source when required.
-  mutable bool ExternallyCompleted : 1;
+  DefinitionData &data() const {
+    assert(Definition != 0 && "Declaration is not a definition!");
+    return *Definition;
+  }
 
-  SourceLocation SuperClassLoc; // location of the super class identifier.
-  SourceLocation EndLoc; // marks the '>', '}', or identifier.
-
-  ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
-                    SourceLocation CLoc, bool FD, bool isInternal);
-
-  void LoadExternalDefinition() const;
+  /// \brief Allocate the definition data for this class.
+  void allocateDefinitionData();
+  
 public:
   static ObjCInterfaceDecl *Create(ASTContext &C, DeclContext *DC,
                                    SourceLocation atLoc,
@@ -604,10 +622,10 @@
   void setExternallyCompleted();
 
   const ObjCProtocolList &getReferencedProtocols() const {
-    if (ExternallyCompleted)
+    if (data().ExternallyCompleted)
       LoadExternalDefinition();
 
-    return ReferencedProtocols;
+    return data().ReferencedProtocols;
   }
 
   ObjCImplementationDecl *getImplementation() const;
@@ -626,55 +644,93 @@
   typedef ObjCProtocolList::iterator protocol_iterator;
 
   protocol_iterator protocol_begin() const {
-    if (ExternallyCompleted)
+    // FIXME: Should make sure no callers ever do this.
+    if (!hasDefinition())
+      return protocol_iterator();
+    
+    if (data().ExternallyCompleted)
       LoadExternalDefinition();
 
-    return ReferencedProtocols.begin();
+    return data().ReferencedProtocols.begin();
   }
   protocol_iterator protocol_end() const {
-    if (ExternallyCompleted)
+    // FIXME: Should make sure no callers ever do this.
+    if (!hasDefinition())
+      return protocol_iterator();
+
+    if (data().ExternallyCompleted)
       LoadExternalDefinition();
 
-    return ReferencedProtocols.end();
+    return data().ReferencedProtocols.end();
   }
 
   typedef ObjCProtocolList::loc_iterator protocol_loc_iterator;
 
   protocol_loc_iterator protocol_loc_begin() const {
-    if (ExternallyCompleted)
+    // FIXME: Should make sure no callers ever do this.
+    if (!hasDefinition())
+      return protocol_loc_iterator();
+
+    if (data().ExternallyCompleted)
       LoadExternalDefinition();
 
-    return ReferencedProtocols.loc_begin();
+    return data().ReferencedProtocols.loc_begin();
   }
 
   protocol_loc_iterator protocol_loc_end() const {
-    if (ExternallyCompleted)
+    // FIXME: Should make sure no callers ever do this.
+    if (!hasDefinition())
+      return protocol_loc_iterator();
+
+    if (data().ExternallyCompleted)
       LoadExternalDefinition();
 
-    return ReferencedProtocols.loc_end();
+    return data().ReferencedProtocols.loc_end();
   }
 
   typedef ObjCList<ObjCProtocolDecl>::iterator all_protocol_iterator;
 
   all_protocol_iterator all_referenced_protocol_begin() const {
-    if (ExternallyCompleted)
+    // FIXME: Should make sure no callers ever do this.
+    if (!hasDefinition())
+      return all_protocol_iterator();
+
+    if (data().ExternallyCompleted)
       LoadExternalDefinition();
 
-    return AllReferencedProtocols.empty() ? protocol_begin()
-      : AllReferencedProtocols.begin();
+    return data().AllReferencedProtocols.empty()  
+             ? protocol_begin()
+             : data().AllReferencedProtocols.begin();
   }
   all_protocol_iterator all_referenced_protocol_end() const {
-    if (ExternallyCompleted)
+    // FIXME: Should make sure no callers ever do this.
+    if (!hasDefinition())
+      return all_protocol_iterator();
+    
+    if (data().ExternallyCompleted)
       LoadExternalDefinition();
 
-    return AllReferencedProtocols.empty() ? protocol_end()
-      : AllReferencedProtocols.end();
+    return data().AllReferencedProtocols.empty() 
+             ? protocol_end()
+             : data().AllReferencedProtocols.end();
   }
 
   typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator;
 
-  ivar_iterator ivar_begin() const { return ivar_iterator(decls_begin()); }
-  ivar_iterator ivar_end() const { return ivar_iterator(decls_end()); }
+  ivar_iterator ivar_begin() const { 
+    if (const ObjCInterfaceDecl *Def = getDefinition())
+      return ivar_iterator(Def->decls_begin()); 
+    
+    // FIXME: Should make sure no callers ever do this.
+    return ivar_iterator();
+  }
+  ivar_iterator ivar_end() const { 
+    if (const ObjCInterfaceDecl *Def = getDefinition())
+      return ivar_iterator(Def->decls_end()); 
+
+    // FIXME: Should make sure no callers ever do this.
+    return ivar_iterator();
+  }
 
   unsigned ivar_size() const {
     return std::distance(ivar_begin(), ivar_end());
@@ -688,13 +744,13 @@
     // the ivar chain is essentially a cached property of ObjCInterfaceDecl.
     return const_cast<ObjCInterfaceDecl *>(this)->all_declared_ivar_begin();
   }
-  void setIvarList(ObjCIvarDecl *ivar) { IvarList = ivar; }
+  void setIvarList(ObjCIvarDecl *ivar) { data().IvarList = ivar; }
 
   /// setProtocolList - Set the list of protocols that this interface
   /// implements.
   void setProtocolList(ObjCProtocolDecl *const* List, unsigned Num,
                        const SourceLocation *Locs, ASTContext &C) {
-    ReferencedProtocols.set(List, Num, Locs, C);
+    data().ReferencedProtocols.set(List, Num, Locs, C);
   }
 
   /// mergeClassExtensionProtocolList - Merge class extension's protocol list
@@ -706,30 +762,63 @@
   /// \brief True if it was initially declared with @class.
   /// Differs with \see isForwardDecl in that \see isForwardDecl will change to
   /// false when we see the @interface, but this will remain true.
-  bool isInitiallyForwardDecl() const { return InitiallyForwardDecl; }
-
-  bool isForwardDecl() const { return ForwardDecl; }
-
-  void completedForwardDecl();
-
-  ObjCInterfaceDecl *getSuperClass() const {
-    if (ExternallyCompleted)
-      LoadExternalDefinition();
-
-    return SuperClass;
+  bool isInitiallyForwardDecl() const { 
+    return InitiallyForwardDecl; 
   }
 
-  void setSuperClass(ObjCInterfaceDecl * superCls) { SuperClass = superCls; }
+  /// \brief Determine whether this declaration is a forward declaration of
+  /// the class.
+  bool isForwardDecl() const { return Definition == 0; }
 
-  ObjCCategoryDecl* getCategoryList() const {
-    if (ExternallyCompleted)
+  /// \brief Determine whether this class has been defined.
+  bool hasDefinition() const { return Definition != 0; }
+  
+  /// \brief Retrieve the definition of this class, or NULL if this class 
+  /// has been forward-declared (with @class) but not yet defined (with 
+  /// @interface).
+  ObjCInterfaceDecl *getDefinition() {
+    return hasDefinition()? this : 0;
+  }
+
+  /// \brief Retrieve the definition of this class, or NULL if this class 
+  /// has been forward-declared (with @class) but not yet defined (with 
+  /// @interface).
+  const ObjCInterfaceDecl *getDefinition() const {
+    return hasDefinition()? this : 0;
+  }
+
+  /// \brief Starts the definition of this Objective-C class, taking it from
+  /// a forward declaration (@class) to a definition (@interface).
+  void startDefinition();
+  
+  ObjCInterfaceDecl *getSuperClass() const {
+    // FIXME: Should make sure no callers ever do this.
+    if (!hasDefinition())
+      return 0;
+    
+    if (data().ExternallyCompleted)
       LoadExternalDefinition();
 
-    return CategoryList;
+    return data().SuperClass;
+  }
+
+  void setSuperClass(ObjCInterfaceDecl * superCls) { 
+    data().SuperClass = superCls; 
+  }
+
+  ObjCCategoryDecl* getCategoryList() const {
+    // FIXME: Should make sure no callers ever do this.
+    if (!hasDefinition())
+      return 0;
+    
+    if (data().ExternallyCompleted)
+      LoadExternalDefinition();
+
+    return data().CategoryList;
   }
 
   void setCategoryList(ObjCCategoryDecl *category) {
-    CategoryList = category;
+    data().CategoryList = category;
   }
 
   ObjCCategoryDecl* getFirstClassExtension() const;
@@ -744,6 +833,7 @@
     while (I != NULL) {
       if (declaresSameEntity(this, I))
         return true;
+      
       I = I->getSuperClass();
     }
     return false;
@@ -787,8 +877,8 @@
   SourceLocation getLocEnd() const { return EndLoc; }
   void setLocEnd(SourceLocation LE) { EndLoc = LE; }
 
-  void setSuperClassLoc(SourceLocation Loc) { SuperClassLoc = Loc; }
-  SourceLocation getSuperClassLoc() const { return SuperClassLoc; }
+  void setSuperClassLoc(SourceLocation Loc) { data().SuperClassLoc = Loc; }
+  SourceLocation getSuperClassLoc() const { return data().SuperClassLoc; }
 
   /// isImplicitInterfaceDecl - check that this is an implicitly declared
   /// ObjCInterfaceDecl node. This is for legacy objective-c @implementation
diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h
index 5e9da51..e145cb7 100644
--- a/include/clang/Serialization/ASTReader.h
+++ b/include/clang/Serialization/ASTReader.h
@@ -329,14 +329,16 @@
   /// haven't been loaded yet.
   DeclContextVisibleUpdatesPending PendingVisibleUpdates;
 
-  typedef SmallVector<CXXRecordDecl *, 4> ForwardRefs;
-  typedef llvm::DenseMap<const CXXRecordDecl *, ForwardRefs>
+  typedef SmallVector<Decl *, 4> ForwardRefs;
+  typedef llvm::DenseMap<const Decl *, ForwardRefs>
       PendingForwardRefsMap;
+  
   /// \brief Forward references that have a definition but the definition decl
   /// is still initializing. When the definition gets read it will update
   /// the DefinitionData pointer of all pending references.
   PendingForwardRefsMap PendingForwardRefs;
 
+
   typedef llvm::DenseMap<serialization::DeclID, serialization::DeclID>
       FirstLatestDeclIDMap;
   /// \brief Map of first declarations from a chained PCH that point to the
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index e409f0a..949db79 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -3178,7 +3178,7 @@
   }
   
   ObjCInterfaceDecl *ToIface = MergeWithIface;
-  if (!ToIface || ToIface->isForwardDecl()) {
+  if (!ToIface || !ToIface->hasDefinition()) {
     if (!ToIface) {
       ToIface = ObjCInterfaceDecl::Create(Importer.getToContext(), DC,
                                           Importer.Import(D->getAtStartLoc()),
@@ -3187,88 +3187,98 @@
                                           D->isImplicitInterfaceDecl());
       ToIface->setLexicalDeclContext(LexicalDC);
       LexicalDC->addDeclInternal(ToIface);
-      if (D->isInitiallyForwardDecl() && !D->isForwardDecl())
-        ToIface->completedForwardDecl();
     }
     Importer.Imported(D, ToIface);
 
-    if (D->getSuperClass()) {
-      ObjCInterfaceDecl *Super
-        = cast_or_null<ObjCInterfaceDecl>(Importer.Import(D->getSuperClass()));
-      if (!Super)
-        return 0;
+    if (D->hasDefinition()) {
+      if (!ToIface->hasDefinition())
+        ToIface->startDefinition();
       
-      ToIface->setSuperClass(Super);
-      ToIface->setSuperClassLoc(Importer.Import(D->getSuperClassLoc()));
+      if (D->getSuperClass()) {
+        ObjCInterfaceDecl *Super
+          = cast_or_null<ObjCInterfaceDecl>(
+              Importer.Import(D->getSuperClass()));
+        if (!Super)
+          return 0;
+        
+        ToIface->setSuperClass(Super);
+        ToIface->setSuperClassLoc(Importer.Import(D->getSuperClassLoc()));
+      }
+      
+      // Import protocols
+      SmallVector<ObjCProtocolDecl *, 4> Protocols;
+      SmallVector<SourceLocation, 4> ProtocolLocs;
+      ObjCInterfaceDecl::protocol_loc_iterator 
+        FromProtoLoc = D->protocol_loc_begin();
+      
+      for (ObjCInterfaceDecl::protocol_iterator FromProto = D->protocol_begin(),
+                                             FromProtoEnd = D->protocol_end();
+         FromProto != FromProtoEnd;
+         ++FromProto, ++FromProtoLoc) {
+        ObjCProtocolDecl *ToProto
+          = cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto));
+        if (!ToProto)
+          return 0;
+        Protocols.push_back(ToProto);
+        ProtocolLocs.push_back(Importer.Import(*FromProtoLoc));
+      }
+      
+      // FIXME: If we're merging, make sure that the protocol list is the same.
+      ToIface->setProtocolList(Protocols.data(), Protocols.size(),
+                               ProtocolLocs.data(), Importer.getToContext());
     }
     
-    // Import protocols
-    SmallVector<ObjCProtocolDecl *, 4> Protocols;
-    SmallVector<SourceLocation, 4> ProtocolLocs;
-    ObjCInterfaceDecl::protocol_loc_iterator 
-      FromProtoLoc = D->protocol_loc_begin();
-    
-    // FIXME: Should we be usng all_referenced_protocol_begin() here?
-    for (ObjCInterfaceDecl::protocol_iterator FromProto = D->protocol_begin(),
-                                           FromProtoEnd = D->protocol_end();
-       FromProto != FromProtoEnd;
-       ++FromProto, ++FromProtoLoc) {
-      ObjCProtocolDecl *ToProto
-        = cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto));
-      if (!ToProto)
-        return 0;
-      Protocols.push_back(ToProto);
-      ProtocolLocs.push_back(Importer.Import(*FromProtoLoc));
-    }
-    
-    // FIXME: If we're merging, make sure that the protocol list is the same.
-    ToIface->setProtocolList(Protocols.data(), Protocols.size(),
-                             ProtocolLocs.data(), Importer.getToContext());
-    
     // Import @end range
     ToIface->setAtEndRange(Importer.Import(D->getAtEndRange()));
   } else {
     Importer.Imported(D, ToIface);
 
-    // Check for consistency of superclasses.
-    DeclarationName FromSuperName, ToSuperName;
-    
-    // If the superclass hasn't been imported yet, do so before checking.
-    ObjCInterfaceDecl *DSuperClass = D->getSuperClass();
-    ObjCInterfaceDecl *ToIfaceSuperClass = ToIface->getSuperClass();
-    
-    if (DSuperClass && !ToIfaceSuperClass) {
-      Decl *ImportedSuperClass = Importer.Import(DSuperClass);
-      ObjCInterfaceDecl *ImportedSuperIface = cast<ObjCInterfaceDecl>(ImportedSuperClass);
-      ToIface->setSuperClass(ImportedSuperIface);
-    }
+    if (D->hasDefinition()) {
+      // Check for consistency of superclasses.
+      DeclarationName FromSuperName, ToSuperName;
+      
+      // If the superclass hasn't been imported yet, do so before checking.
+      ObjCInterfaceDecl *DSuperClass = D->getSuperClass();
+      ObjCInterfaceDecl *ToIfaceSuperClass = ToIface->getSuperClass();
+      
+      if (DSuperClass && !ToIfaceSuperClass) {
+        Decl *ImportedSuperClass = Importer.Import(DSuperClass);
+        ObjCInterfaceDecl *ImportedSuperIface
+          = cast<ObjCInterfaceDecl>(ImportedSuperClass);
+        
+        ToIface->setSuperClass(ImportedSuperIface);
+      }
 
-    if (D->getSuperClass())
-      FromSuperName = Importer.Import(D->getSuperClass()->getDeclName());
-    if (ToIface->getSuperClass())
-      ToSuperName = ToIface->getSuperClass()->getDeclName();
-    if (FromSuperName != ToSuperName) {
-      Importer.ToDiag(ToIface->getLocation(), 
-                      diag::err_odr_objc_superclass_inconsistent)
-        << ToIface->getDeclName();
-      if (ToIface->getSuperClass())
-        Importer.ToDiag(ToIface->getSuperClassLoc(), 
-                        diag::note_odr_objc_superclass)
-          << ToIface->getSuperClass()->getDeclName();
-      else
-        Importer.ToDiag(ToIface->getLocation(), 
-                        diag::note_odr_objc_missing_superclass);
       if (D->getSuperClass())
-        Importer.FromDiag(D->getSuperClassLoc(), 
+        FromSuperName = Importer.Import(D->getSuperClass()->getDeclName());
+      if (ToIface->getSuperClass())
+        ToSuperName = ToIface->getSuperClass()->getDeclName();
+      if (FromSuperName != ToSuperName) {
+        Importer.ToDiag(ToIface->getLocation(), 
+                        diag::err_odr_objc_superclass_inconsistent)
+          << ToIface->getDeclName();
+        if (ToIface->getSuperClass())
+          Importer.ToDiag(ToIface->getSuperClassLoc(), 
                           diag::note_odr_objc_superclass)
-          << D->getSuperClass()->getDeclName();
-      else
-        Importer.FromDiag(D->getLocation(), 
+            << ToIface->getSuperClass()->getDeclName();
+        else
+          Importer.ToDiag(ToIface->getLocation(), 
                           diag::note_odr_objc_missing_superclass);
-      return 0;
+        if (D->getSuperClass())
+          Importer.FromDiag(D->getSuperClassLoc(), 
+                            diag::note_odr_objc_superclass)
+            << D->getSuperClass()->getDeclName();
+        else
+          Importer.FromDiag(D->getLocation(), 
+                            diag::note_odr_objc_missing_superclass);
+        return 0;
+      }
     }
   }
   
+  if (!D->hasDefinition())
+    return ToIface;
+  
   // Import categories. When the categories themselves are imported, they'll
   // hook themselves into this interface.
   for (ObjCCategoryDecl *FromCat = D->getCategoryList(); FromCat;
@@ -3279,7 +3289,7 @@
   ImportDeclContext(D);
   
   // If we have an @implementation, import it as well.
-  if (D->getImplementation()) {
+  if ( D->getImplementation()) {
     ObjCImplementationDecl *Impl = cast_or_null<ObjCImplementationDecl>(
                                        Importer.Import(D->getImplementation()));
     if (!Impl)
diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp
index 38efadf..decbd54 100644
--- a/lib/AST/DeclObjC.cpp
+++ b/lib/AST/DeclObjC.cpp
@@ -154,7 +154,11 @@
 ObjCPropertyDecl *
 ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass(
                                             IdentifierInfo *PropertyId) const {
-  if (ExternallyCompleted)
+  // FIXME: Should make sure no callers ever do this.
+  if (!hasDefinition())
+    return 0;
+  
+  if (data().ExternallyCompleted)
     LoadExternalDefinition();
 
   if (ObjCPropertyDecl *PD =
@@ -175,11 +179,12 @@
                               ObjCProtocolDecl *const* ExtList, unsigned ExtNum,
                               ASTContext &C)
 {
-  if (ExternallyCompleted)
+  if (data().ExternallyCompleted)
     LoadExternalDefinition();
 
-  if (AllReferencedProtocols.empty() && ReferencedProtocols.empty()) {
-    AllReferencedProtocols.set(ExtList, ExtNum, C);
+  if (data().AllReferencedProtocols.empty() && 
+      data().ReferencedProtocols.empty()) {
+    data().AllReferencedProtocols.set(ExtList, ExtNum, C);
     return;
   }
   
@@ -214,12 +219,16 @@
     ProtocolRefs.push_back(*p);
   }
 
-  AllReferencedProtocols.set(ProtocolRefs.data(), ProtocolRefs.size(), C);
+  data().AllReferencedProtocols.set(ProtocolRefs.data(), ProtocolRefs.size(),C);
 }
 
-void ObjCInterfaceDecl::completedForwardDecl() {
-  assert(isForwardDecl() && "Only valid to call for forward refs");
-  ForwardDecl = false;
+void ObjCInterfaceDecl::allocateDefinitionData() {
+  assert(!hasDefinition() && "ObjC class already has a definition");
+  Definition = new (getASTContext()) DefinitionData();  
+}
+
+void ObjCInterfaceDecl::startDefinition() {
+  allocateDefinitionData();
   if (ASTMutationListener *L = getASTContext().getASTMutationListener())
     L->CompletedObjCForwardRef(this);
 }
@@ -244,7 +253,11 @@
 
 ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(IdentifierInfo *ID,
                                               ObjCInterfaceDecl *&clsDeclared) {
-  if (ExternallyCompleted)
+  // FIXME: Should make sure no callers ever do this.
+  if (!hasDefinition())
+    return 0;  
+
+  if (data().ExternallyCompleted)
     LoadExternalDefinition();
 
   ObjCInterfaceDecl* ClassDecl = this;
@@ -271,7 +284,11 @@
 /// the it returns NULL.
 ObjCInterfaceDecl *ObjCInterfaceDecl::lookupInheritedClass(
                                         const IdentifierInfo*ICName) {
-  if (ExternallyCompleted)
+  // FIXME: Should make sure no callers ever do this.
+  if (!hasDefinition())
+    return 0;
+
+  if (data().ExternallyCompleted)
     LoadExternalDefinition();
 
   ObjCInterfaceDecl* ClassDecl = this;
@@ -287,10 +304,14 @@
 /// the class, its categories, and its super classes (using a linear search).
 ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel,
                                                 bool isInstance) const {
+  // FIXME: Should make sure no callers ever do this.
+  if (!hasDefinition())
+    return 0;
+
   const ObjCInterfaceDecl* ClassDecl = this;
   ObjCMethodDecl *MethodDecl = 0;
 
-  if (ExternallyCompleted)
+  if (data().ExternallyCompleted)
     LoadExternalDefinition();
 
   while (ClassDecl != NULL) {
@@ -328,7 +349,11 @@
 ObjCMethodDecl *ObjCInterfaceDecl::lookupPrivateMethod(
                                    const Selector &Sel,
                                    bool Instance) {
-  if (ExternallyCompleted)
+  // FIXME: Should make sure no callers ever do this.
+  if (!hasDefinition())
+    return 0;
+
+  if (data().ExternallyCompleted)
     LoadExternalDefinition();
 
   ObjCMethodDecl *Method = 0;
@@ -651,16 +676,14 @@
 ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
                   SourceLocation CLoc, bool FD, bool isInternal)
   : ObjCContainerDecl(ObjCInterface, DC, Id, CLoc, atLoc),
-    TypeForDecl(0), SuperClass(0),
-    CategoryList(0), IvarList(0),
-    InitiallyForwardDecl(FD), ForwardDecl(FD),
-    ExternallyCompleted(false) {
+    TypeForDecl(0), Definition(), InitiallyForwardDecl(FD) 
+{
   setImplicit(isInternal);
 }
 
 void ObjCInterfaceDecl::LoadExternalDefinition() const {
-  assert(ExternallyCompleted && "Class is not externally completed");
-  ExternallyCompleted = false;
+  assert(data().ExternallyCompleted && "Class is not externally completed");
+  data().ExternallyCompleted = false;
   getASTContext().getExternalSource()->CompleteType(
                                         const_cast<ObjCInterfaceDecl *>(this));
 }
@@ -668,13 +691,17 @@
 void ObjCInterfaceDecl::setExternallyCompleted() {
   assert(getASTContext().getExternalSource() && 
          "Class can't be externally completed without an external source");
-  assert(!ForwardDecl && 
+  assert(hasDefinition() && 
          "Forward declarations can't be externally completed");
-  ExternallyCompleted = true;
+  data().ExternallyCompleted = true;
 }
 
 ObjCImplementationDecl *ObjCInterfaceDecl::getImplementation() const {
-  if (ExternallyCompleted)
+  // FIXME: Should make sure no callers ever do this.
+  if (!hasDefinition())
+    return 0;
+      
+  if (data().ExternallyCompleted)
     LoadExternalDefinition();
 
   return getASTContext().getObjCImplementation(
@@ -689,14 +716,18 @@
 /// its extensions and its implementation. Lazily build the list on first
 /// access.
 ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() {
-  if (IvarList)
-    return IvarList;
+  // FIXME: Should make sure no callers ever do this.
+  if (!hasDefinition())
+    return 0;
+  
+  if (data().IvarList)
+    return data().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)
+    data().IvarList = (*I); ++I;
+    for (curIvar = data().IvarList; I != E; curIvar = *I, ++I)
       curIvar->setNextIvar(*I);
   }
   
@@ -705,9 +736,9 @@
     if (!CDecl->ivar_empty()) {
       ObjCCategoryDecl::ivar_iterator I = CDecl->ivar_begin(),
                                           E = CDecl->ivar_end();
-      if (!IvarList) {
-        IvarList = (*I); ++I;
-        curIvar = IvarList;
+      if (!data().IvarList) {
+        data().IvarList = (*I); ++I;
+        curIvar = data().IvarList;
       }
       for ( ;I != E; curIvar = *I, ++I)
         curIvar->setNextIvar(*I);
@@ -718,15 +749,15 @@
     if (!ImplDecl->ivar_empty()) {
       ObjCImplementationDecl::ivar_iterator I = ImplDecl->ivar_begin(),
                                             E = ImplDecl->ivar_end();
-      if (!IvarList) {
-        IvarList = (*I); ++I;
-        curIvar = IvarList;
+      if (!data().IvarList) {
+        data().IvarList = (*I); ++I;
+        curIvar = data().IvarList;
       }
       for ( ;I != E; curIvar = *I, ++I)
         curIvar->setNextIvar(*I);
     }
   }
-  return IvarList;
+  return data().IvarList;
 }
 
 /// FindCategoryDeclaration - Finds category declaration in the list of
@@ -735,7 +766,7 @@
 ///
 ObjCCategoryDecl *
 ObjCInterfaceDecl::FindCategoryDeclaration(IdentifierInfo *CategoryId) const {
-  if (ExternallyCompleted)
+  if (data().ExternallyCompleted)
     LoadExternalDefinition();
 
   for (ObjCCategoryDecl *Category = getCategoryList();
@@ -770,6 +801,9 @@
 bool ObjCInterfaceDecl::ClassImplementsProtocol(ObjCProtocolDecl *lProto,
                                     bool lookupCategory,
                                     bool RHSIsQualifiedID) {
+  if (!hasDefinition())
+    return false;
+  
   ObjCInterfaceDecl *IDecl = this;
   // 1st, look up the class.
   const ObjCList<ObjCProtocolDecl> &Protocols =
@@ -997,9 +1031,11 @@
   if (IDecl) {
     // Link this category into its class's category list.
     CatDecl->NextClassCategory = IDecl->getCategoryList();
-    IDecl->setCategoryList(CatDecl);
-    if (ASTMutationListener *L = C.getASTMutationListener())
-      L->AddedObjCCategoryToInterface(CatDecl, IDecl);
+    if (IDecl->hasDefinition()) {
+      IDecl->setCategoryList(CatDecl);
+      if (ASTMutationListener *L = C.getASTMutationListener())
+        L->AddedObjCCategoryToInterface(CatDecl, IDecl);
+    }
   }
 
   return CatDecl;
diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp
index 91b011f..ec7d6de 100644
--- a/lib/AST/DeclPrinter.cpp
+++ b/lib/AST/DeclPrinter.cpp
@@ -905,6 +905,11 @@
   else
     Out << "@interface " << I;
 
+  if (OID->isForwardDecl()) {
+    Out << "@end";
+    return;
+  }
+  
   // Protocols?
   const ObjCList<ObjCProtocolDecl> &Protocols = OID->getReferencedProtocols();
   if (!Protocols.empty()) {
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 3d2d093..7e7e87a 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -4558,7 +4558,7 @@
   }
   
   ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
-  if (!IFace)
+  if (!IFace || !IFace->hasDefinition())
     return;
   
   // Add methods in protocols.
@@ -5783,6 +5783,9 @@
                                      bool InOriginalClass = true) {
   if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
     // Recurse into protocols.
+    if (!IFace->hasDefinition())
+      return;
+    
     const ObjCList<ObjCProtocolDecl> &Protocols
       = IFace->getReferencedProtocols();
     for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index b70c982..6947d7e 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -368,10 +368,10 @@
   ObjCInterfaceDecl* IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
   if (IDecl) {
     // Class already seen. Is it a forward declaration?
-    if (!IDecl->isForwardDecl()) {
+    if (ObjCInterfaceDecl *Def = IDecl->getDefinition()) {
       IDecl->setInvalidDecl();
       Diag(AtInterfaceLoc, diag::err_duplicate_class_def)<<IDecl->getDeclName();
-      Diag(IDecl->getLocation(), diag::note_previous_definition);
+      Diag(Def->getLocation(), diag::note_previous_definition);
 
       // Create a new one; the other may be in a different DeclContex, (e.g.
       // this one may be in a LinkageSpecDecl while the other is not) which
@@ -392,8 +392,6 @@
       IDecl->setLexicalDeclContext(CurContext);
       CurContext->addDecl(IDecl);
 
-      IDecl->completedForwardDecl();
-
       if (AttrList)
         ProcessDeclAttributeList(TUScope, IDecl, AttrList);
     }
@@ -406,6 +404,9 @@
     PushOnScopeChains(IDecl, TUScope);
   }
 
+  if (!IDecl->hasDefinition())
+    IDecl->startDefinition();
+  
   if (SuperName) {
     // Check if a different kind of symbol declared in this scope.
     PrevDecl = LookupSingleName(TUScope, SuperName, SuperLoc,
@@ -942,6 +943,7 @@
     // copy them over.
     IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtClassImplLoc,
                                       ClassName, ClassLoc, false, true);
+    IDecl->startDefinition();
     IDecl->setSuperClass(SDecl);
     IDecl->setLocEnd(ClassLoc);
 
@@ -950,8 +952,8 @@
     // Mark the interface as being completed, even if it was just as
     //   @class ....;
     // declaration; the user cannot reopen it.
-    if (IDecl->isForwardDecl())
-      IDecl->completedForwardDecl();
+    if (!IDecl->hasDefinition())
+      IDecl->startDefinition();
   }
 
   ObjCImplementationDecl* IMPDecl =
@@ -2540,7 +2542,9 @@
 
   void searchFrom(ObjCInterfaceDecl *iface) {
     // A method in a class declaration overrides declarations from
-
+    if (!iface->hasDefinition())
+      return;
+    
     //   - categories,
     for (ObjCCategoryDecl *category = iface->getCategoryList();
            category; category = category->getNextClassCategory())
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index fbae960..20c3b75 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -512,6 +512,9 @@
 
 ObjCMethodDecl *Sema::LookupPrivateInstanceMethod(Selector Sel,
                                               ObjCInterfaceDecl *ClassDecl) {
+  if (!ClassDecl->hasDefinition())
+    return 0;
+
   ObjCMethodDecl *Method = 0;
   while (ClassDecl && !Method) {
     // If we have implementations in scope, check "private" methods.
@@ -1339,12 +1342,10 @@
             return ExprError();
           
           forwardClass = OCIType->getInterfaceDecl();
+          Method = 0;
+        } else {
+          Method = ClassDecl->lookupInstanceMethod(Sel);
         }
-        
-        // FIXME: consider using LookupInstanceMethodInGlobalPool, since it will be
-        // faster than the following method (which can do *many* linear searches).
-        // The idea is to add class info to MethodPool.
-        Method = ClassDecl->lookupInstanceMethod(Sel);
 
         if (!Method)
           // Search protocol qualifiers.
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index bdedf8a..f7f93af 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -556,43 +556,80 @@
 void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
   VisitObjCContainerDecl(ID);
   ID->setTypeForDecl(Reader.readType(F, Record, Idx).getTypePtrOrNull());
-  ID->setSuperClass(ReadDeclAs<ObjCInterfaceDecl>(Record, Idx));
   
-  // Read the directly referenced protocols and their SourceLocations.
-  unsigned NumProtocols = Record[Idx++];
-  SmallVector<ObjCProtocolDecl *, 16> Protocols;
-  Protocols.reserve(NumProtocols);
-  for (unsigned I = 0; I != NumProtocols; ++I)
-    Protocols.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx));
-  SmallVector<SourceLocation, 16> ProtoLocs;
-  ProtoLocs.reserve(NumProtocols);
-  for (unsigned I = 0; I != NumProtocols; ++I)
-    ProtoLocs.push_back(ReadSourceLocation(Record, Idx));
-  ID->setProtocolList(Protocols.data(), NumProtocols, ProtoLocs.data(),
-                      Reader.getContext());
+  ObjCInterfaceDecl *Def = ReadDeclAs<ObjCInterfaceDecl>(Record, Idx);
+  if (ID == Def) {
+    // Read the definition.
+    ID->allocateDefinitionData();
+    
+    ObjCInterfaceDecl::DefinitionData &Data = ID->data();
+    
+    // Read the superclass.
+    Data.SuperClass = ReadDeclAs<ObjCInterfaceDecl>(Record, Idx);
+    Data.SuperClassLoc = ReadSourceLocation(Record, Idx);
+
+    // Read the directly referenced protocols and their SourceLocations.
+    unsigned NumProtocols = Record[Idx++];
+    SmallVector<ObjCProtocolDecl *, 16> Protocols;
+    Protocols.reserve(NumProtocols);
+    for (unsigned I = 0; I != NumProtocols; ++I)
+      Protocols.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx));
+    SmallVector<SourceLocation, 16> ProtoLocs;
+    ProtoLocs.reserve(NumProtocols);
+    for (unsigned I = 0; I != NumProtocols; ++I)
+      ProtoLocs.push_back(ReadSourceLocation(Record, Idx));
+    ID->setProtocolList(Protocols.data(), NumProtocols, ProtoLocs.data(),
+                        Reader.getContext());
   
-  // Read the transitive closure of protocols referenced by this class.
-  NumProtocols = Record[Idx++];
-  Protocols.clear();
-  Protocols.reserve(NumProtocols);
-  for (unsigned I = 0; I != NumProtocols; ++I)
-    Protocols.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx));
-  ID->AllReferencedProtocols.set(Protocols.data(), NumProtocols,
-                                 Reader.getContext());
+    // Read the transitive closure of protocols referenced by this class.
+    NumProtocols = Record[Idx++];
+    Protocols.clear();
+    Protocols.reserve(NumProtocols);
+    for (unsigned I = 0; I != NumProtocols; ++I)
+      Protocols.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx));
+    ID->data().AllReferencedProtocols.set(Protocols.data(), NumProtocols,
+                                          Reader.getContext());
   
-  // Read the ivars.
-  unsigned NumIvars = Record[Idx++];
-  SmallVector<ObjCIvarDecl *, 16> IVars;
-  IVars.reserve(NumIvars);
-  for (unsigned I = 0; I != NumIvars; ++I)
-    IVars.push_back(ReadDeclAs<ObjCIvarDecl>(Record, Idx));
-  ID->setCategoryList(ReadDeclAs<ObjCCategoryDecl>(Record, Idx));
+    // Read the ivars.
+    unsigned NumIvars = Record[Idx++];
+    SmallVector<ObjCIvarDecl *, 16> IVars;
+    IVars.reserve(NumIvars);
+    for (unsigned I = 0; I != NumIvars; ++I)
+      IVars.push_back(ReadDeclAs<ObjCIvarDecl>(Record, Idx));
+    
+    // Read the categories.
+    ID->setCategoryList(ReadDeclAs<ObjCCategoryDecl>(Record, Idx));
   
-  // We will rebuild this list lazily.
-  ID->setIvarList(0);
+    // We will rebuild this list lazily.
+    ID->setIvarList(0);
+    
+    // If there are any pending forward references, make their definition data
+    // pointers point at the newly-allocated data.
+    ASTReader::PendingForwardRefsMap::iterator
+    FindI = Reader.PendingForwardRefs.find(ID);
+    if (FindI != Reader.PendingForwardRefs.end()) {
+      ASTReader::ForwardRefs &Refs = FindI->second;
+      for (ASTReader::ForwardRefs::iterator I = Refs.begin(), 
+                                            E = Refs.end(); 
+           I != E; ++I)
+        cast<ObjCInterfaceDecl>(*I)->Definition = ID->Definition;
+#ifndef NDEBUG
+      // We later check whether PendingForwardRefs is empty to make sure all
+      // pending references were linked.
+      Reader.PendingForwardRefs.erase(ID);
+#endif
+    
+    } else if (Def) {
+      if (Def->Definition) {
+        ID->Definition = Def->Definition;
+      } else {
+        // The definition is still initializing.
+        Reader.PendingForwardRefs[Def].push_back(ID);
+      }
+    }
+  }
+  
   ID->InitiallyForwardDecl = Record[Idx++];
-  ID->ForwardDecl = Record[Idx++];
-  ID->setSuperClassLoc(ReadSourceLocation(Record, Idx));
   ID->setLocEnd(ReadSourceLocation(Record, Idx));
 }
 
@@ -972,7 +1009,7 @@
       ASTReader::ForwardRefs &Refs = FindI->second;
       for (ASTReader::ForwardRefs::iterator
              I = Refs.begin(), E = Refs.end(); I != E; ++I)
-        (*I)->DefinitionData = D->DefinitionData;
+        cast<CXXRecordDecl>(*I)->DefinitionData = D->DefinitionData;
 #ifndef NDEBUG
       // We later check whether PendingForwardRefs is empty to make sure all
       // pending references were linked.
diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp
index 1448e59..9396958 100644
--- a/lib/Serialization/ASTWriterDecl.cpp
+++ b/lib/Serialization/ASTWriterDecl.cpp
@@ -449,36 +449,46 @@
 void ASTDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
   VisitObjCContainerDecl(D);
   Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record);
-  Writer.AddDeclRef(D->getSuperClass(), Record);
 
-  // Write out the protocols that are directly referenced by the @interface.
-  Record.push_back(D->ReferencedProtocols.size());
-  for (ObjCInterfaceDecl::protocol_iterator P = D->protocol_begin(),
-         PEnd = D->protocol_end();
-       P != PEnd; ++P)
-    Writer.AddDeclRef(*P, Record);
-  for (ObjCInterfaceDecl::protocol_loc_iterator PL = D->protocol_loc_begin(),
-         PLEnd = D->protocol_loc_end();
-       PL != PLEnd; ++PL)
-    Writer.AddSourceLocation(*PL, Record);
-
-  // Write out the protocols that are transitively referenced.
-  Record.push_back(D->AllReferencedProtocols.size());
-  for (ObjCList<ObjCProtocolDecl>::iterator
-        P = D->AllReferencedProtocols.begin(),
-        PEnd = D->AllReferencedProtocols.end();
-       P != PEnd; ++P)
-    Writer.AddDeclRef(*P, Record);
+  ObjCInterfaceDecl *Def = D->getDefinition();
+  Writer.AddDeclRef(Def, Record);
   
-  // Write out the ivars.
-  Record.push_back(D->ivar_size());
-  for (ObjCInterfaceDecl::ivar_iterator I = D->ivar_begin(),
-                                     IEnd = D->ivar_end(); I != IEnd; ++I)
-    Writer.AddDeclRef(*I, Record);
-  Writer.AddDeclRef(D->getCategoryList(), Record);
+  if (D == Def) {
+    // Write the DefinitionData
+    ObjCInterfaceDecl::DefinitionData &Data = D->data();
+    
+    Writer.AddDeclRef(D->getSuperClass(), Record);
+    Writer.AddSourceLocation(D->getSuperClassLoc(), Record);
+    
+    // Write out the protocols that are directly referenced by the @interface.
+    Record.push_back(Data.ReferencedProtocols.size());
+    for (ObjCInterfaceDecl::protocol_iterator P = D->protocol_begin(),
+                                           PEnd = D->protocol_end();
+         P != PEnd; ++P)
+      Writer.AddDeclRef(*P, Record);
+    for (ObjCInterfaceDecl::protocol_loc_iterator PL = D->protocol_loc_begin(),
+         PLEnd = D->protocol_loc_end();
+         PL != PLEnd; ++PL)
+      Writer.AddSourceLocation(*PL, Record);
+    
+    // Write out the protocols that are transitively referenced.
+    Record.push_back(Data.AllReferencedProtocols.size());
+    for (ObjCList<ObjCProtocolDecl>::iterator
+              P = Data.AllReferencedProtocols.begin(),
+           PEnd = Data.AllReferencedProtocols.end();
+         P != PEnd; ++P)
+      Writer.AddDeclRef(*P, Record);
+    
+    // Write out the ivars.
+    Record.push_back(D->ivar_size());
+    for (ObjCInterfaceDecl::ivar_iterator I = D->ivar_begin(),
+                                       IEnd = D->ivar_end(); I != IEnd; ++I)
+      Writer.AddDeclRef(*I, Record);
+    
+    Writer.AddDeclRef(D->getCategoryList(), Record);
+  }  
+  
   Record.push_back(D->isInitiallyForwardDecl());
-  Record.push_back(D->isForwardDecl());
-  Writer.AddSourceLocation(D->getSuperClassLoc(), Record);
   Writer.AddSourceLocation(D->getLocEnd(), Record);
   Code = serialization::DECL_OBJC_INTERFACE;
 }
diff --git a/tools/libclang/IndexingContext.cpp b/tools/libclang/IndexingContext.cpp
index 23d8e7e..11b2ed3 100644
--- a/tools/libclang/IndexingContext.cpp
+++ b/tools/libclang/IndexingContext.cpp
@@ -369,7 +369,10 @@
       markEntityOccurrenceInFile(SuperD, SuperLoc);
   }
   
-  ObjCProtocolListInfo ProtInfo(D->getReferencedProtocols(), *this, SA);
+  ObjCProtocolList EmptyProtoList;
+  ObjCProtocolListInfo ProtInfo(D->hasDefinition()? D->getReferencedProtocols()
+                                                  : EmptyProtoList, 
+                                *this, SA);
   
   ObjCInterfaceDeclInfo InterInfo(D);
   InterInfo.ObjCProtoListInfo = ProtInfo.getListInfo();