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.