Reimplement (de-)serialization of Objective-C categories to eliminate
the direct serialization of the linked-list structure. Instead, use a
scheme similar to how we handle redeclarations, with redeclaration
lists on the side. This addresses several issues:
  - In cases involving mixing and matching of many categories across
  many modules, the linked-list structure would not be consistent
  across different modules, and categories would get lost.
  - If a module is loaded after the class definition and its other
  categories have already been loaded, we wouldn't see any categories
  in the newly-loaded module.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149112 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h
index df56d57..c0d9edf 100644
--- a/include/clang/Serialization/ASTBitCodes.h
+++ b/include/clang/Serialization/ASTBitCodes.h
@@ -444,9 +444,9 @@
       /// which stores information about #line directives.
       SOURCE_MANAGER_LINE_TABLE = 48,
 
-      /// \brief Record code for ObjC categories in a module that are chained to
-      /// an interface.
-      OBJC_CHAINED_CATEGORIES = 49,
+      /// \brief Record code for map of Objective-C class definition IDs to the 
+      /// ObjC categories in a module that are attached to that class.
+      OBJC_CATEGORIES_MAP = 49,
 
       /// \brief Record code for a file sorted array of DeclIDs in a module.
       FILE_SORTED_DECLS = 50,
@@ -462,7 +462,14 @@
       ///
       /// This array can only be interpreted properly using the local 
       /// redeclarations map.
-      LOCAL_REDECLARATIONS = 53
+      LOCAL_REDECLARATIONS = 53,
+      
+      /// \brief Record code for the array of Objective-C categories (including
+      /// extensions).
+      ///
+      /// This array can only be interpreted properly using the Objective-C
+      /// categories map.
+      OBJC_CATEGORIES
     };
 
     /// \brief Record types used within a source manager block.
@@ -1225,6 +1232,32 @@
       }
     };
 
+    /// \brief Describes the categories of an Objective-C class.
+    struct ObjCCategoriesInfo {
+      DeclID DefinitionID; // The ID of the definition
+      unsigned Offset;     // Offset into the array of category lists.
+      
+      friend bool operator<(const ObjCCategoriesInfo &X,
+                            const ObjCCategoriesInfo &Y) {
+        return X.DefinitionID < Y.DefinitionID;
+      }
+      
+      friend bool operator>(const ObjCCategoriesInfo &X,
+                            const ObjCCategoriesInfo &Y) {
+        return X.DefinitionID > Y.DefinitionID;
+      }
+      
+      friend bool operator<=(const ObjCCategoriesInfo &X,
+                             const ObjCCategoriesInfo &Y) {
+        return X.DefinitionID <= Y.DefinitionID;
+      }
+      
+      friend bool operator>=(const ObjCCategoriesInfo &X,
+                             const ObjCCategoriesInfo &Y) {
+        return X.DefinitionID >= Y.DefinitionID;
+      }
+    };
+
     /// @}
   }
 } // end namespace clang
diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h
index 91f872b..2ebdd09 100644
--- a/include/clang/Serialization/ASTReader.h
+++ b/include/clang/Serialization/ASTReader.h
@@ -335,10 +335,6 @@
   /// declarations that have not yet been linked to their definitions.
   llvm::SmallPtrSet<Decl *, 4> PendingDefinitions;
   
-  /// \brief Set of ObjC interfaces that have categories chained to them in
-  /// other modules.
-  llvm::DenseSet<serialization::GlobalDeclID> ObjCChainedCategoriesInterfaces;
-
   /// \brief Read the records that describe the contents of declcontexts.
   bool ReadDeclContextStorage(ModuleFile &M,
                               llvm::BitstreamCursor &Cursor,
@@ -687,6 +683,15 @@
   /// \brief Keeps track of the elements added to PendingDeclChains.
   llvm::SmallSet<serialization::DeclID, 16> PendingDeclChainsKnown;
 
+  /// \brief The set of Objective-C categories that have been deserialized
+  /// since the last time the declaration chains were linked.
+  llvm::SmallPtrSet<ObjCCategoryDecl *, 16> CategoriesDeserialized;
+
+  /// \brief The set of Objective-C class definitions that have already been
+  /// loaded, for which we will need to check for categories whenever a new
+  /// module is loaded.
+  llvm::SmallVector<ObjCInterfaceDecl *, 16> ObjCClassesLoaded;
+  
   typedef llvm::DenseMap<Decl *, llvm::SmallVector<serialization::DeclID, 2> >
     MergedDeclsMap;
     
@@ -715,11 +720,6 @@
   MergedDeclsMap::iterator
   combineStoredMergedDecls(Decl *Canon, serialization::GlobalDeclID CanonID);
   
-  /// \brief We delay loading the chain of objc categories after recursive
-  /// loading of declarations is finished.
-  std::vector<std::pair<ObjCInterfaceDecl *, serialization::DeclID> >
-    PendingChainedObjCCategories;
-
   /// \brief Ready to load the previous declaration of the given Decl.
   void loadAndAttachPreviousDecl(Decl *D, serialization::DeclID ID);
 
@@ -801,8 +801,8 @@
                                  unsigned &RawLocation);
   void loadDeclUpdateRecords(serialization::DeclID ID, Decl *D);
   void loadPendingDeclChain(serialization::GlobalDeclID ID);
-  void loadObjCChainedCategories(serialization::GlobalDeclID ID,
-                                 ObjCInterfaceDecl *D);
+  void loadObjCCategories(serialization::GlobalDeclID ID, ObjCInterfaceDecl *D,
+                          unsigned PreviousGeneration = 0);
 
   RecordLocation getLocalBitOffset(uint64_t GlobalOffset);
   uint64_t getGlobalBitOffset(ModuleFile &M, uint32_t LocalOffset);
@@ -1049,6 +1049,10 @@
   /// \arg M.
   bool isDeclIDFromModule(serialization::GlobalDeclID ID, ModuleFile &M) const;
 
+  /// \brief Retrieve the module file that owns the given declaration, or NULL
+  /// if the declaration is not from a module file.
+  ModuleFile *getOwningModuleFile(Decl *D);
+  
   /// \brief Returns the source location for the decl \arg ID.
   SourceLocation getSourceLocationForDeclID(serialization::GlobalDeclID ID);
 
diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h
index 8852d5d..f6a2c48 100644
--- a/include/clang/Serialization/ASTWriter.h
+++ b/include/clang/Serialization/ASTWriter.h
@@ -284,17 +284,10 @@
   /// \brief Decls that will be replaced in the current dependent AST file.
   DeclsToRewriteTy DeclsToRewrite;
 
-  struct ChainedObjCCategoriesData {
-    /// \brief The interface in the imported module.
-    const ObjCInterfaceDecl *Interface;
-    /// \brief The local tail category ID that got chained to the imported
-    /// interface.
-    const ObjCCategoryDecl *TailCategory;
-  };
-  /// \brief ObjC categories that got chained to an interface imported from
-  /// another module.
-  SmallVector<ChainedObjCCategoriesData, 16> LocalChainedObjCCategories;
-
+  /// \brief The set of Objective-C class that have categories we
+  /// should serialize.
+  llvm::SetVector<ObjCInterfaceDecl *> ObjCClassesWithCategories;
+                    
   struct ReplacedDeclInfo {
     serialization::DeclID ID;
     uint64_t Offset;
@@ -413,10 +406,10 @@
   void ResolveDeclUpdatesBlocks();
   void WriteDeclUpdatesBlocks();
   void WriteDeclReplacementsBlock();
-  void WriteChainedObjCCategories();
   void WriteDeclContextVisibleUpdate(const DeclContext *DC);
   void WriteFPPragmaOptions(const FPOptions &Opts);
   void WriteOpenCLExtensions(Sema &SemaRef);
+  void WriteObjCCategories();
   void WriteRedeclarations();
   void WriteMergedDecls();
                         
diff --git a/include/clang/Serialization/Module.h b/include/clang/Serialization/Module.h
index 831a873..34f208d 100644
--- a/include/clang/Serialization/Module.h
+++ b/include/clang/Serialization/Module.h
@@ -286,15 +286,6 @@
   /// for each DeclContext.
   DeclContextInfosMap DeclContextInfos;
 
-  typedef llvm::DenseMap<serialization::GlobalDeclID,
-             std::pair<serialization::LocalDeclID, serialization::LocalDeclID> >
-    ChainedObjCCategoriesMap;
-  /// \brief ObjC categories that got chained to an interface from another
-  /// module.
-  /// Key is the ID of the interface.
-  /// Value is a pair of linked category DeclIDs (head category, tail category).
-  ChainedObjCCategoriesMap ChainedObjCCategories;
-
   /// \brief Array of file-level DeclIDs sorted by file.
   const serialization::DeclID *FileSortedDecls;
 
@@ -302,13 +293,24 @@
   /// module file, sorted by the first declaration ID.
   const serialization::LocalRedeclarationsInfo *RedeclarationsMap;
 
-  /// \brief The number of redeclaration info entries in RedeclarationsInfo.
+  /// \brief The number of redeclaration info entries in RedeclarationsMap.
   unsigned LocalNumRedeclarationsInMap;
   
   /// \brief The redeclaration chains for declarations local to this
   /// module file.
   SmallVector<uint64_t, 1> RedeclarationChains;
   
+  /// \brief Array of category list location information within this 
+  /// module file, sorted by the definition ID.
+  const serialization::ObjCCategoriesInfo *ObjCCategoriesMap;
+  
+  /// \brief The number of redeclaration info entries in ObjCCategoriesMap.
+  unsigned LocalNumObjCCategoriesInMap;
+  
+  /// \brief The Objective-C category lists for categories known to this
+  /// module.
+  SmallVector<uint64_t, 1> ObjCCategories;
+
   // === Types ===
 
   /// \brief The number of types in this AST file.