diff options
Diffstat (limited to 'include/clang/Serialization')
-rw-r--r-- | include/clang/Serialization/ASTBitCodes.h | 260 | ||||
-rw-r--r-- | include/clang/Serialization/ASTReader.h | 167 | ||||
-rw-r--r-- | include/clang/Serialization/ASTWriter.h | 106 | ||||
-rw-r--r-- | include/clang/Serialization/GlobalModuleIndex.h | 3 | ||||
-rw-r--r-- | include/clang/Serialization/Module.h | 48 | ||||
-rw-r--r-- | include/clang/Serialization/ModuleFileExtension.h | 149 | ||||
-rw-r--r-- | include/clang/Serialization/ModuleManager.h | 88 |
7 files changed, 534 insertions, 287 deletions
diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h index 4b66207..16bda6e 100644 --- a/include/clang/Serialization/ASTBitCodes.h +++ b/include/clang/Serialization/ASTBitCodes.h @@ -17,6 +17,7 @@ #ifndef LLVM_CLANG_SERIALIZATION_ASTBITCODES_H #define LLVM_CLANG_SERIALIZATION_ASTBITCODES_H +#include "clang/AST/DeclarationName.h" #include "clang/AST/Type.h" #include "llvm/ADT/DenseMap.h" #include "llvm/Bitcode/BitCodes.h" @@ -61,9 +62,6 @@ namespace clang { /// used for the translation unit declaration. typedef uint32_t DeclID; - /// \brief a Decl::Kind/DeclID pair. - typedef std::pair<uint32_t, DeclID> KindDeclIDPair; - // FIXME: Turn these into classes so we can have some type safety when // we go from local ID to global and vice-versa. typedef DeclID LocalDeclID; @@ -235,7 +233,17 @@ namespace clang { /// to create this AST file. /// /// This block is part of the control block. - INPUT_FILES_BLOCK_ID + INPUT_FILES_BLOCK_ID, + + /// \brief The block of configuration options, used to check that + /// a module is being used in a configuration compatible with the + /// configuration in which it was built. + /// + /// This block is part of the control block. + OPTIONS_BLOCK_ID, + + /// \brief A block containing a module file extension. + EXTENSION_BLOCK_ID, }; /// \brief Record types that occur within the control block. @@ -246,63 +254,72 @@ namespace clang { /// \brief Record code for the list of other AST files imported by /// this AST file. - IMPORTS = 2, - - /// \brief Record code for the language options table. - /// - /// The record with this code contains the contents of the - /// LangOptions structure. We serialize the entire contents of - /// the structure, and let the reader decide which options are - /// actually important to check. - LANGUAGE_OPTIONS = 3, - - /// \brief Record code for the target options table. - TARGET_OPTIONS = 4, + IMPORTS, /// \brief Record code for the original file that was used to /// generate the AST file, including both its file ID and its /// name. - ORIGINAL_FILE = 5, + ORIGINAL_FILE, /// \brief The directory that the PCH was originally created in. - ORIGINAL_PCH_DIR = 6, + ORIGINAL_PCH_DIR, /// \brief Record code for file ID of the file or buffer that was used to /// generate the AST file. - ORIGINAL_FILE_ID = 7, + ORIGINAL_FILE_ID, /// \brief Offsets into the input-files block where input files /// reside. - INPUT_FILE_OFFSETS = 8, - - /// \brief Record code for the diagnostic options table. - DIAGNOSTIC_OPTIONS = 9, - - /// \brief Record code for the filesystem options table. - FILE_SYSTEM_OPTIONS = 10, - - /// \brief Record code for the headers search options table. - HEADER_SEARCH_OPTIONS = 11, - - /// \brief Record code for the preprocessor options table. - PREPROCESSOR_OPTIONS = 12, + INPUT_FILE_OFFSETS, /// \brief Record code for the module name. - MODULE_NAME = 13, + MODULE_NAME, /// \brief Record code for the module map file that was used to build this /// AST file. - MODULE_MAP_FILE = 14, + MODULE_MAP_FILE, /// \brief Record code for the signature that identifiers this AST file. - SIGNATURE = 15, + SIGNATURE, /// \brief Record code for the module build directory. - MODULE_DIRECTORY = 16, + MODULE_DIRECTORY, + }; + + /// \brief Record types that occur within the options block inside + /// the control block. + enum OptionsRecordTypes { + /// \brief Record code for the language options table. + /// + /// The record with this code contains the contents of the + /// LangOptions structure. We serialize the entire contents of + /// the structure, and let the reader decide which options are + /// actually important to check. + LANGUAGE_OPTIONS = 1, - /// \brief Record code for the list of other AST files made available by - /// this AST file but not actually used by it. - KNOWN_MODULE_FILES = 17, + /// \brief Record code for the target options table. + TARGET_OPTIONS, + + /// \brief Record code for the diagnostic options table. + DIAGNOSTIC_OPTIONS, + + /// \brief Record code for the filesystem options table. + FILE_SYSTEM_OPTIONS, + + /// \brief Record code for the headers search options table. + HEADER_SEARCH_OPTIONS, + + /// \brief Record code for the preprocessor options table. + PREPROCESSOR_OPTIONS, + }; + + /// \brief Record code for extension blocks. + enum ExtensionBlockRecordTypes { + /// Metadata describing this particular extension. + EXTENSION_METADATA = 1, + + /// The first record ID allocated to the extensions themselves. + FIRST_EXTENSION_RECORD_ID = 4 }; /// \brief Record types that occur within the input-files block @@ -350,7 +367,7 @@ namespace clang { /// \brief This is so that older clang versions, before the introduction /// of the control block, can read and reject the newer PCH format. - /// *DON"T CHANGE THIS NUMBER*. + /// *DON'T CHANGE THIS NUMBER*. METADATA_OLD_FORMAT = 4, /// \brief Record code for the identifier table. @@ -440,10 +457,7 @@ namespace clang { /// declarations. TU_UPDATE_LEXICAL = 22, - /// \brief Record code for the array describing the locations (in the - /// LOCAL_REDECLARATIONS record) of the redeclaration chains, indexed by - /// the first known ID. - LOCAL_REDECLARATIONS_MAP = 23, + // ID 23 used to be for a list of local redeclarations. /// \brief Record code for declarations that Sema keeps references of. SEMA_DECL_REFS = 24, @@ -521,13 +535,8 @@ namespace clang { /// imported by the AST file. IMPORTED_MODULES = 43, - // ID 40 used to be a table of merged canonical declarations. - - /// \brief Record code for the array of redeclaration chains. - /// - /// This array can only be interpreted properly using the local - /// redeclarations map. - LOCAL_REDECLARATIONS = 45, + // ID 44 used to be a table of merged canonical declarations. + // ID 45 used to be a list of declaration IDs of local redeclarations. /// \brief Record code for the array of Objective-C categories (including /// extensions). @@ -543,7 +552,10 @@ namespace clang { /// macro definition. MACRO_OFFSET = 47, - // ID 48 used to be a table of macros. + /// \brief A list of "interesting" identifiers. Only used in C++ (where we + /// don't normally do lookups into the serialized identifier table). These + /// are eagerly deserialized. + INTERESTING_IDENTIFIERS = 48, /// \brief Record code for undefined but used functions and variables that /// need a definition in this TU. @@ -758,26 +770,46 @@ namespace clang { PREDEF_TYPE_ARC_UNBRIDGED_CAST = 34, /// \brief The pseudo-object placeholder type. PREDEF_TYPE_PSEUDO_OBJECT = 35, - /// \brief The __va_list_tag placeholder type. - PREDEF_TYPE_VA_LIST_TAG = 36, /// \brief The placeholder type for builtin functions. - PREDEF_TYPE_BUILTIN_FN = 37, + PREDEF_TYPE_BUILTIN_FN = 36, /// \brief OpenCL 1d image type. - PREDEF_TYPE_IMAGE1D_ID = 38, + PREDEF_TYPE_IMAGE1D_ID = 37, /// \brief OpenCL 1d image array type. - PREDEF_TYPE_IMAGE1D_ARR_ID = 39, + PREDEF_TYPE_IMAGE1D_ARR_ID = 38, /// \brief OpenCL 1d image buffer type. - PREDEF_TYPE_IMAGE1D_BUFF_ID = 40, + PREDEF_TYPE_IMAGE1D_BUFF_ID = 39, /// \brief OpenCL 2d image type. - PREDEF_TYPE_IMAGE2D_ID = 41, + PREDEF_TYPE_IMAGE2D_ID = 40, /// \brief OpenCL 2d image array type. - PREDEF_TYPE_IMAGE2D_ARR_ID = 42, + PREDEF_TYPE_IMAGE2D_ARR_ID = 41, + /// \brief OpenCL 2d image depth type. + PREDEF_TYPE_IMAGE2D_DEP_ID = 42, + /// \brief OpenCL 2d image array depth type. + PREDEF_TYPE_IMAGE2D_ARR_DEP_ID = 43, + /// \brief OpenCL 2d image MSAA type. + PREDEF_TYPE_IMAGE2D_MSAA_ID = 44, + /// \brief OpenCL 2d image array MSAA type. + PREDEF_TYPE_IMAGE2D_ARR_MSAA_ID = 45, + /// \brief OpenCL 2d image MSAA depth type. + PREDEF_TYPE_IMAGE2D_MSAA_DEP_ID = 46, + /// \brief OpenCL 2d image array MSAA depth type. + PREDEF_TYPE_IMAGE2D_ARR_MSAA_DEPTH_ID = 47, /// \brief OpenCL 3d image type. - PREDEF_TYPE_IMAGE3D_ID = 43, + PREDEF_TYPE_IMAGE3D_ID = 48, /// \brief OpenCL event type. - PREDEF_TYPE_EVENT_ID = 44, + PREDEF_TYPE_EVENT_ID = 49, + /// \brief OpenCL clk event type. + PREDEF_TYPE_CLK_EVENT_ID = 50, /// \brief OpenCL sampler type. - PREDEF_TYPE_SAMPLER_ID = 45 + PREDEF_TYPE_SAMPLER_ID = 51, + /// \brief OpenCL queue type. + PREDEF_TYPE_QUEUE_ID = 52, + /// \brief OpenCL ndrange type. + PREDEF_TYPE_NDRANGE_ID = 53, + /// \brief OpenCL reserve_id type. + PREDEF_TYPE_RESERVE_ID_ID = 54, + /// \brief The placeholder type for OpenMP array section. + PREDEF_TYPE_OMP_ARRAY_SECTION = 55 }; /// \brief The number of predefined type IDs that are reserved for @@ -913,44 +945,56 @@ namespace clang { /// it is created. enum PredefinedDeclIDs { /// \brief The NULL declaration. - PREDEF_DECL_NULL_ID = 0, - + PREDEF_DECL_NULL_ID = 0, + /// \brief The translation unit. PREDEF_DECL_TRANSLATION_UNIT_ID = 1, - + /// \brief The Objective-C 'id' type. PREDEF_DECL_OBJC_ID_ID = 2, - + /// \brief The Objective-C 'SEL' type. PREDEF_DECL_OBJC_SEL_ID = 3, - + /// \brief The Objective-C 'Class' type. PREDEF_DECL_OBJC_CLASS_ID = 4, - + /// \brief The Objective-C 'Protocol' type. PREDEF_DECL_OBJC_PROTOCOL_ID = 5, - + /// \brief The signed 128-bit integer type. PREDEF_DECL_INT_128_ID = 6, /// \brief The unsigned 128-bit integer type. PREDEF_DECL_UNSIGNED_INT_128_ID = 7, - + /// \brief The internal 'instancetype' typedef. PREDEF_DECL_OBJC_INSTANCETYPE_ID = 8, /// \brief The internal '__builtin_va_list' typedef. PREDEF_DECL_BUILTIN_VA_LIST_ID = 9, + /// \brief The internal '__va_list_tag' struct, if any. + PREDEF_DECL_VA_LIST_TAG = 10, + + /// \brief The internal '__builtin_ms_va_list' typedef. + PREDEF_DECL_BUILTIN_MS_VA_LIST_ID = 11, + /// \brief The extern "C" context. - PREDEF_DECL_EXTERN_C_CONTEXT_ID = 10, + PREDEF_DECL_EXTERN_C_CONTEXT_ID = 12, + + /// \brief The internal '__make_integer_seq' template. + PREDEF_DECL_MAKE_INTEGER_SEQ_ID = 13, }; /// \brief The number of declaration IDs that are predefined. /// /// For more information about predefined declarations, see the /// \c PredefinedDeclIDs type and the PREDEF_DECL_*_ID constants. - const unsigned int NUM_PREDEF_DECL_IDS = 11; + const unsigned int NUM_PREDEF_DECL_IDS = 14; + + /// \brief Record code for a list of local redeclarations of a declaration. + const unsigned int LOCAL_REDECLARATIONS = 50; /// \brief Record codes for each kind of declaration. /// @@ -1369,6 +1413,7 @@ namespace clang { // Microsoft EXPR_CXX_PROPERTY_REF_EXPR, // MSPropertyRefExpr + EXPR_CXX_PROPERTY_SUBSCRIPT_EXPR, // MSPropertySubscriptExpr EXPR_CXX_UUIDOF_EXPR, // CXXUuidofExpr (of expr). EXPR_CXX_UUIDOF_TYPE, // CXXUuidofExpr (of type). STMT_SEH_LEAVE, // SEHLeaveStmt @@ -1397,10 +1442,15 @@ namespace clang { STMT_OMP_ORDERED_DIRECTIVE, STMT_OMP_ATOMIC_DIRECTIVE, STMT_OMP_TARGET_DIRECTIVE, + STMT_OMP_TARGET_DATA_DIRECTIVE, STMT_OMP_TEAMS_DIRECTIVE, STMT_OMP_TASKGROUP_DIRECTIVE, STMT_OMP_CANCELLATION_POINT_DIRECTIVE, STMT_OMP_CANCEL_DIRECTIVE, + STMT_OMP_TASKLOOP_DIRECTIVE, + STMT_OMP_TASKLOOP_SIMD_DIRECTIVE, + STMT_OMP_DISTRIBUTE_DIRECTIVE, + EXPR_OMP_ARRAY_SECTION, // ARC EXPR_OBJC_BRIDGED_CAST, // ObjCBridgedCastExpr @@ -1484,8 +1534,72 @@ namespace clang { } }; + /// \brief A key used when looking up entities by \ref DeclarationName. + /// + /// Different \ref DeclarationNames are mapped to different keys, but the + /// same key can occasionally represent multiple names (for names that + /// contain types, in particular). + class DeclarationNameKey { + typedef unsigned NameKind; + + NameKind Kind; + uint64_t Data; + + public: + DeclarationNameKey() : Kind(), Data() {} + DeclarationNameKey(DeclarationName Name); + + DeclarationNameKey(NameKind Kind, uint64_t Data) + : Kind(Kind), Data(Data) {} + + NameKind getKind() const { return Kind; } + + IdentifierInfo *getIdentifier() const { + assert(Kind == DeclarationName::Identifier || + Kind == DeclarationName::CXXLiteralOperatorName); + return (IdentifierInfo *)Data; + } + Selector getSelector() const { + assert(Kind == DeclarationName::ObjCZeroArgSelector || + Kind == DeclarationName::ObjCOneArgSelector || + Kind == DeclarationName::ObjCMultiArgSelector); + return Selector(Data); + } + OverloadedOperatorKind getOperatorKind() const { + assert(Kind == DeclarationName::CXXOperatorName); + return (OverloadedOperatorKind)Data; + } + + /// Compute a fingerprint of this key for use in on-disk hash table. + unsigned getHash() const; + + friend bool operator==(const DeclarationNameKey &A, + const DeclarationNameKey &B) { + return A.Kind == B.Kind && A.Data == B.Data; + } + }; + /// @} } } // end namespace clang +namespace llvm { + template <> struct DenseMapInfo<clang::serialization::DeclarationNameKey> { + static clang::serialization::DeclarationNameKey getEmptyKey() { + return clang::serialization::DeclarationNameKey(-1, 1); + } + static clang::serialization::DeclarationNameKey getTombstoneKey() { + return clang::serialization::DeclarationNameKey(-1, 2); + } + static unsigned + getHashValue(const clang::serialization::DeclarationNameKey &Key) { + return Key.getHash(); + } + static bool isEqual(const clang::serialization::DeclarationNameKey &L, + const clang::serialization::DeclarationNameKey &R) { + return L == R; + } + }; +} + #endif diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index 840655e..588a6a9 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -30,6 +30,7 @@ #include "clang/Serialization/ASTBitCodes.h" #include "clang/Serialization/ContinuousRangeMap.h" #include "clang/Serialization/Module.h" +#include "clang/Serialization/ModuleFileExtension.h" #include "clang/Serialization/ModuleManager.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APInt.h" @@ -38,6 +39,7 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/TinyPtrVector.h" #include "llvm/Bitcode/BitstreamReader.h" @@ -179,7 +181,8 @@ public: unsigned Value) {} /// This is called for each AST file loaded. - virtual void visitModuleFile(StringRef Filename) {} + virtual void visitModuleFile(StringRef Filename, + serialization::ModuleKind Kind) {} /// \brief Returns true if this \c ASTReaderListener wants to receive the /// input files of the AST file via \c visitInputFile, false otherwise. @@ -194,7 +197,7 @@ public: /// /// \returns true to continue receiving the next input file, false to stop. virtual bool visitInputFile(StringRef Filename, bool isSystem, - bool isOverridden) { + bool isOverridden, bool isExplicitModule) { return true; } @@ -204,6 +207,10 @@ public: /// \brief If needsImportVisitation returns \c true, this is called for each /// AST file imported by this AST file. virtual void visitImport(StringRef Filename) {} + + /// Indicates that a particular module file extension has been read. + virtual void readModuleFileExtension( + const ModuleFileExtensionMetadata &Metadata) {} }; /// \brief Simple wrapper class for chaining listeners. @@ -242,9 +249,12 @@ public: void ReadCounter(const serialization::ModuleFile &M, unsigned Value) override; bool needsInputFileVisitation() override; bool needsSystemInputFileVisitation() override; - void visitModuleFile(StringRef Filename) override; + void visitModuleFile(StringRef Filename, + serialization::ModuleKind Kind) override; bool visitInputFile(StringRef Filename, bool isSystem, - bool isOverridden) override; + bool isOverridden, bool isExplicitModule) override; + void readModuleFileExtension( + const ModuleFileExtensionMetadata &Metadata) override; }; /// \brief ASTReaderListener implementation to validate the information of @@ -280,9 +290,8 @@ class ReadMethodPoolVisitor; namespace reader { class ASTIdentifierLookupTrait; - /// \brief The on-disk hash table used for the DeclContext's Name lookup table. - typedef llvm::OnDiskIterableChainedHashTable<ASTDeclContextNameLookupTrait> - ASTDeclContextNameLookupTable; + /// \brief The on-disk hash table(s) used for DeclContext name lookup. + struct DeclContextLookupTable; } } // end namespace serialization @@ -381,6 +390,9 @@ private: /// \brief The module manager which manages modules and their dependencies ModuleManager ModuleMgr; + /// A mapping from extension block names to module file extensions. + llvm::StringMap<IntrusiveRefCntPtr<ModuleFileExtension>> ModuleFileExtensions; + /// \brief A timer used to track the time spent deserializing. std::unique_ptr<llvm::Timer> ReadTimer; @@ -494,20 +506,36 @@ private: /// \brief Map from a FileID to the file-level declarations that it contains. llvm::DenseMap<FileID, FileDeclsInfo> FileDeclIDs; + /// \brief An array of lexical contents of a declaration context, as a sequence of + /// Decl::Kind, DeclID pairs. + typedef ArrayRef<llvm::support::unaligned_uint32_t> LexicalContents; + + /// \brief Map from a DeclContext to its lexical contents. + llvm::DenseMap<const DeclContext*, std::pair<ModuleFile*, LexicalContents>> + LexicalDecls; + + /// \brief Map from the TU to its lexical contents from each module file. + std::vector<std::pair<ModuleFile*, LexicalContents>> TULexicalDecls; + + /// \brief Map from a DeclContext to its lookup tables. + llvm::DenseMap<const DeclContext *, + serialization::reader::DeclContextLookupTable> Lookups; + // Updates for visible decls can occur for other contexts than just the - // TU, and when we read those update records, the actual context will not - // be available yet (unless it's the TU), so have this pending map using the - // ID as a key. It will be realized when the context is actually loaded. - typedef - SmallVector<std::pair<serialization::reader::ASTDeclContextNameLookupTable *, - ModuleFile*>, 1> DeclContextVisibleUpdates; - typedef llvm::DenseMap<serialization::DeclID, DeclContextVisibleUpdates> - DeclContextVisibleUpdatesPending; + // TU, and when we read those update records, the actual context may not + // be available yet, so have this pending map using the ID as a key. It + // will be realized when the context is actually loaded. + struct PendingVisibleUpdate { + ModuleFile *Mod; + const unsigned char *Data; + }; + typedef SmallVector<PendingVisibleUpdate, 1> DeclContextVisibleUpdates; /// \brief Updates to the visible declarations of declaration contexts that /// haven't been loaded yet. - DeclContextVisibleUpdatesPending PendingVisibleUpdates; - + llvm::DenseMap<serialization::DeclID, DeclContextVisibleUpdates> + PendingVisibleUpdates; + /// \brief The set of C++ or Objective-C classes that have forward /// declarations that have not yet been linked to their definitions. llvm::SmallPtrSet<Decl *, 4> PendingDefinitions; @@ -524,11 +552,14 @@ private: /// performed deduplication. llvm::SetVector<NamedDecl*> PendingMergedDefinitionsToDeduplicate; - /// \brief Read the records that describe the contents of declcontexts. - bool ReadDeclContextStorage(ModuleFile &M, - llvm::BitstreamCursor &Cursor, - const std::pair<uint64_t, uint64_t> &Offsets, - serialization::DeclContextInfo &Info); + /// \brief Read the record that describes the lexical contents of a DC. + bool ReadLexicalDeclContextStorage(ModuleFile &M, + llvm::BitstreamCursor &Cursor, + uint64_t Offset, DeclContext *DC); + /// \brief Read the record that describes the visible contents of a DC. + bool ReadVisibleDeclContextStorage(ModuleFile &M, + llvm::BitstreamCursor &Cursor, + uint64_t Offset, serialization::DeclID ID); /// \brief A vector containing identifiers that have already been /// loaded. @@ -914,20 +945,10 @@ private: /// Objective-C protocols. std::deque<Decl *> InterestingDecls; - /// \brief The set of redeclarable declarations that have been deserialized - /// since the last time the declaration chains were linked. - llvm::SmallPtrSet<Decl *, 16> RedeclsDeserialized; - /// \brief The list of redeclaration chains that still need to be - /// reconstructed. - /// - /// Each element is the canonical declaration of the chain. - /// Elements in this vector should be unique; use - /// PendingDeclChainsKnown to ensure uniqueness. - SmallVector<Decl *, 16> PendingDeclChains; - - /// \brief Keeps track of the elements added to PendingDeclChains. - llvm::SmallSet<Decl *, 16> PendingDeclChainsKnown; + /// reconstructed, and the local offset to the corresponding list + /// of redeclarations. + SmallVector<std::pair<Decl *, uint64_t>, 16> PendingDeclChains; /// \brief The list of canonical declarations whose redeclaration chains /// need to be marked as incomplete once we're done deserializing things. @@ -972,13 +993,6 @@ private: /// module is loaded. SmallVector<ObjCInterfaceDecl *, 16> ObjCClassesLoaded; - /// \brief A mapping from a primary context for a declaration chain to the - /// other declarations of that entity that also have name lookup tables. - /// Used when we merge together two class definitions that have different - /// sets of declared special member functions. - llvm::DenseMap<const DeclContext*, SmallVector<const DeclContext*, 2>> - MergedLookups; - typedef llvm::DenseMap<Decl *, SmallVector<serialization::DeclID, 2> > KeyDeclsMap; @@ -1044,12 +1058,11 @@ private: off_t StoredSize; time_t StoredTime; bool Overridden; + bool Transient; }; /// \brief Reads the stored information about an input file. InputFileInfo readInputFileInfo(ModuleFile &F, unsigned ID); - /// \brief A convenience method to read the filename from an input file. - std::string getInputFileName(ModuleFile &F, unsigned ID); /// \brief Retrieve the file entry and 'overridden' bit for an input /// file in the given module file. @@ -1090,6 +1103,10 @@ public: Visit(GetExistingDecl(ID)); } + /// \brief Get the loaded lookup tables for \p Primary, if any. + const serialization::reader::DeclContextLookupTable * + getLoadedLookupTables(DeclContext *Primary) const; + private: struct ImportedModule { ModuleFile *Mod; @@ -1112,7 +1129,12 @@ private: SmallVectorImpl<ImportedModule> &Loaded, const ModuleFile *ImportedBy, unsigned ClientLoadCapabilities); + static ASTReadResult ReadOptionsBlock( + llvm::BitstreamCursor &Stream, unsigned ClientLoadCapabilities, + bool AllowCompatibleConfigurationMismatch, ASTReaderListener &Listener, + std::string &SuggestedPredefines); ASTReadResult ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities); + ASTReadResult ReadExtensionBlock(ModuleFile &F); bool ParseLineTable(ModuleFile &F, const RecordData &Record); bool ReadSourceManagerBlock(ModuleFile &F); llvm::BitstreamCursor &SLocCursorForID(int ID); @@ -1163,7 +1185,7 @@ private: RecordLocation DeclCursorForID(serialization::DeclID ID, unsigned &RawLocation); void loadDeclUpdateRecords(serialization::DeclID ID, Decl *D); - void loadPendingDeclChain(Decl *D); + void loadPendingDeclChain(Decl *D, uint64_t LocalOffset); void loadObjCCategories(serialization::GlobalDeclID ID, ObjCInterfaceDecl *D, unsigned PreviousGeneration = 0); @@ -1261,9 +1283,12 @@ public: /// \param Context the AST context that this precompiled header will be /// loaded into. /// - /// \param PCHContainerOps the PCHContainerOperations to use for loading and + /// \param PCHContainerRdr the PCHContainerOperations to use for loading and /// creating modules. /// + /// \param Extensions the list of module file extensions that can be loaded + /// from the AST files. + /// /// \param isysroot If non-NULL, the system include path specified by the /// user. This is only used with relocatable PCH files. If non-NULL, /// a relocatable PCH file will use the default path "/". @@ -1290,6 +1315,7 @@ public: /// deserializing. ASTReader(Preprocessor &PP, ASTContext &Context, const PCHContainerReader &PCHContainerRdr, + ArrayRef<IntrusiveRefCntPtr<ModuleFileExtension>> Extensions, StringRef isysroot = "", bool DisableValidation = false, bool AllowASTWithCompilerErrors = false, bool AllowConfigurationMismatch = false, @@ -1300,6 +1326,7 @@ public: SourceManager &getSourceManager() const { return SourceMgr; } FileManager &getFileManager() const { return FileMgr; } + DiagnosticsEngine &getDiags() const { return Diags; } /// \brief Flags that indicate what kind of AST loading failures the client /// of the AST reader can directly handle. @@ -1467,6 +1494,7 @@ public: static bool readASTFileControlBlock(StringRef Filename, FileManager &FileMgr, const PCHContainerReader &PCHContainerRdr, + bool FindModuleFileExtensions, ASTReaderListener &Listener); /// \brief Determine whether the given AST file is acceptable to load into a @@ -1684,7 +1712,7 @@ public: /// ReadBlockAbbrevs - Enter a subblock of the specified BlockID with the /// specified cursor. Read the abbreviations that are at the top of the block /// and then leave the cursor pointing into the block. - bool ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor, unsigned BlockID); + static bool ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor, unsigned BlockID); /// \brief Finds all the visible declarations with a given name. /// The current implementation of this method just loads the entire @@ -1698,16 +1726,17 @@ public: /// \param DC The declaration context whose declarations will be /// read. /// + /// \param IsKindWeWant A predicate indicating which declaration kinds + /// we are interested in. + /// /// \param Decls Vector that will contain the declarations loaded /// from the external source. The caller is responsible for merging /// these declarations with any declarations already stored in the /// declaration context. - /// - /// \returns true if there was an error while reading the - /// declarations for this declaration context. - ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC, - bool (*isKindWeWant)(Decl::Kind), - SmallVectorImpl<Decl*> &Decls) override; + void + FindExternalLexicalDecls(const DeclContext *DC, + llvm::function_ref<bool(Decl::Kind)> IsKindWeWant, + SmallVectorImpl<Decl *> &Decls) override; /// \brief Get the decls that are contained in a file in the Offset/Length /// range. \p Length can be 0 to indicate a point at \p Offset instead of @@ -1755,10 +1784,7 @@ public: /// declarations with this name are visible from translation unit scope, their /// declarations will be deserialized and introduced into the declaration /// chain of the identifier. - virtual IdentifierInfo *get(const char *NameStart, const char *NameEnd); - IdentifierInfo *get(StringRef Name) override { - return get(Name.begin(), Name.end()); - } + IdentifierInfo *get(StringRef Name) override; /// \brief Retrieve an iterator into the set of all identifiers /// in all loaded AST files. @@ -1873,10 +1899,15 @@ public: /// Note: overrides method in ExternalASTSource Module *getModule(unsigned ID) override; + /// \brief Retrieve the module file with a given local ID within the specified + /// ModuleFile. + ModuleFile *getLocalModuleFile(ModuleFile &M, unsigned ID); + + /// \brief Get an ID for the given module file. + unsigned getModuleFileID(ModuleFile *M); + /// \brief Return a descriptor for the corresponding module. llvm::Optional<ASTSourceDescriptor> getSourceDescriptor(unsigned ID) override; - /// \brief Return a descriptor for the module. - ASTSourceDescriptor getSourceDescriptor(const Module &M) override; /// \brief Retrieve a selector from the given module with its local ID /// number. @@ -1921,8 +1952,9 @@ public: unsigned &Idx); /// \brief Read a template argument. - TemplateArgument ReadTemplateArgument(ModuleFile &F, - const RecordData &Record,unsigned &Idx); + TemplateArgument ReadTemplateArgument(ModuleFile &F, const RecordData &Record, + unsigned &Idx, + bool Canonicalize = false); /// \brief Read a template parameter list. TemplateParameterList *ReadTemplateParameterList(ModuleFile &F, @@ -1930,10 +1962,9 @@ public: unsigned &Idx); /// \brief Read a template argument array. - void - ReadTemplateArgumentList(SmallVectorImpl<TemplateArgument> &TemplArgs, - ModuleFile &F, const RecordData &Record, - unsigned &Idx); + void ReadTemplateArgumentList(SmallVectorImpl<TemplateArgument> &TemplArgs, + ModuleFile &F, const RecordData &Record, + unsigned &Idx, bool Canonicalize = false); /// \brief Read a UnresolvedSet structure. void ReadUnresolvedSet(ModuleFile &F, LazyASTUnresolvedSet &Set, @@ -2082,12 +2113,8 @@ public: SmallVector<std::pair<llvm::BitstreamCursor, serialization::ModuleFile *>, 8> CommentsCursors; - //RIDErief Loads comments ranges. + /// \brief Loads comments ranges. void ReadComments() override; - - /// Return all input files for the given module file. - void getInputFiles(ModuleFile &F, - SmallVectorImpl<serialization::InputFile> &Files); }; /// \brief Helper class that saves the current stream position and diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h index e830fdc..ed34547 100644 --- a/include/clang/Serialization/ASTWriter.h +++ b/include/clang/Serialization/ASTWriter.h @@ -58,6 +58,8 @@ class OpaqueValueExpr; class OpenCLOptions; class ASTReader; class Module; +class ModuleFileExtension; +class ModuleFileExtensionWriter; class PreprocessedEntity; class PreprocessingRecord; class Preprocessor; @@ -84,6 +86,7 @@ class ASTWriter : public ASTDeserializationListener, public: typedef SmallVector<uint64_t, 64> RecordData; typedef SmallVectorImpl<uint64_t> RecordDataImpl; + typedef ArrayRef<uint64_t> RecordDataRef; friend class ASTDeclWriter; friend class ASTStmtWriter; @@ -119,6 +122,12 @@ private: /// \brief The base directory for any relative paths we emit. std::string BaseDirectory; + /// \brief Indicates whether timestamps should be written to the produced + /// module file. This is the case for files implicitly written to the + /// module cache, where we need the timestamps to determine if the module + /// file is up to date, but not otherwise. + bool IncludeTimestamps; + /// \brief Indicates when the AST writing is actively performing /// serialization, rather than just queueing updates. bool WritingAST; @@ -369,10 +378,6 @@ private: /// coming from another AST file. SmallVector<const Decl *, 16> UpdatingVisibleDecls; - typedef llvm::SmallSetVector<const Decl *, 16> DeclsToRewriteTy; - /// \brief Decls that will be replaced in the current dependent AST file. - DeclsToRewriteTy DeclsToRewrite; - /// \brief The set of Objective-C class that have categories we /// should serialize. llvm::SetVector<ObjCInterfaceDecl *> ObjCClassesWithCategories; @@ -399,6 +404,10 @@ private: /// \brief The set of declarations that may have redeclaration chains that /// need to be serialized. llvm::SmallVector<const Decl *, 16> Redeclarations; + + /// \brief A cache of the first local declaration for "interesting" + /// redeclaration chains. + llvm::DenseMap<const Decl *, const Decl *> FirstLocalDeclCache; /// \brief Statements that we've encountered while serializing a /// declaration or type. @@ -484,20 +493,23 @@ private: /// \brief A mapping from each known submodule to its ID number, which will /// be a positive integer. llvm::DenseMap<Module *, unsigned> SubmoduleIDs; - + + /// \brief A list of the module file extension writers. + std::vector<std::unique_ptr<ModuleFileExtensionWriter>> + ModuleFileExtensionWriters; + /// \brief Retrieve or create a submodule ID for this module. unsigned getSubmoduleID(Module *Mod); - + /// \brief Write the given subexpression to the bitstream. void WriteSubStmt(Stmt *S, llvm::DenseMap<Stmt *, uint64_t> &SubStmtEntries, llvm::DenseSet<Stmt *> &ParentStmts); void WriteBlockInfoBlock(); - void WriteControlBlock(Preprocessor &PP, ASTContext &Context, - StringRef isysroot, const std::string &OutputFile); - void WriteInputFiles(SourceManager &SourceMgr, - HeaderSearchOptions &HSOpts, + uint64_t WriteControlBlock(Preprocessor &PP, ASTContext &Context, + StringRef isysroot, const std::string &OutputFile); + void WriteInputFiles(SourceManager &SourceMgr, HeaderSearchOptions &HSOpts, bool Modules); void WriteSourceManagerBlock(SourceManager &SourceMgr, const Preprocessor &PP); @@ -519,8 +531,8 @@ private: bool isLookupResultExternal(StoredDeclsList &Result, DeclContext *DC); bool isLookupResultEntirelyExternal(StoredDeclsList &Result, DeclContext *DC); - uint32_t GenerateNameLookupTable(const DeclContext *DC, - llvm::SmallVectorImpl<char> &LookupTable); + void GenerateNameLookupTable(const DeclContext *DC, + llvm::SmallVectorImpl<char> &LookupTable); uint64_t WriteDeclContextLexicalBlock(ASTContext &Context, DeclContext *DC); uint64_t WriteDeclContextVisibleBlock(ASTContext &Context, DeclContext *DC); void WriteTypeDeclOffsets(); @@ -537,9 +549,10 @@ private: void WriteFPPragmaOptions(const FPOptions &Opts); void WriteOpenCLExtensions(Sema &SemaRef); void WriteObjCCategories(); - void WriteRedeclarations(); void WriteLateParsedTemplates(Sema &SemaRef); void WriteOptimizePragmaOptions(Sema &SemaRef); + void WriteModuleFileExtension(Sema &SemaRef, + ModuleFileExtensionWriter &Writer); unsigned DeclParmVarAbbrev; unsigned DeclContextLexicalAbbrev; @@ -562,18 +575,25 @@ private: void WriteDecl(ASTContext &Context, Decl *D); void AddFunctionDefinition(const FunctionDecl *FD, RecordData &Record); - void WriteASTCore(Sema &SemaRef, - StringRef isysroot, const std::string &OutputFile, - Module *WritingModule); + uint64_t WriteASTCore(Sema &SemaRef, + StringRef isysroot, const std::string &OutputFile, + Module *WritingModule); public: /// \brief Create a new precompiled header writer that outputs to /// the given bitstream. - ASTWriter(llvm::BitstreamWriter &Stream); + ASTWriter(llvm::BitstreamWriter &Stream, + ArrayRef<llvm::IntrusiveRefCntPtr<ModuleFileExtension>> Extensions, + bool IncludeTimestamps = true); ~ASTWriter() override; const LangOptions &getLangOpts() const; + /// \brief Get a timestamp for output into the AST file. The actual timestamp + /// of the specified file may be ignored if we have been instructed to not + /// include timestamps in the output file. + time_t getTimestampForOutput(const FileEntry *E) const; + /// \brief Write a precompiled header for the given semantic analysis. /// /// \param SemaRef a reference to the semantic analysis object that processed @@ -585,10 +605,12 @@ public: /// \param isysroot if non-empty, write a relocatable file whose headers /// are relative to the given system root. If we're writing a module, its /// build directory will be used in preference to this if both are available. - void WriteAST(Sema &SemaRef, - const std::string &OutputFile, - Module *WritingModule, StringRef isysroot, - bool hasErrors = false); + /// + /// \return the module signature, which eventually will be a hash of + /// the module but currently is merely a random 32-bit number. + uint64_t WriteAST(Sema &SemaRef, const std::string &OutputFile, + Module *WritingModule, StringRef isysroot, + bool hasErrors = false); /// \brief Emit a token. void AddToken(const Token &Tok, RecordDataImpl &Record); @@ -665,6 +687,10 @@ public: const ASTTemplateArgumentListInfo *ASTTemplArgList, RecordDataImpl &Record); + /// \brief Find the first local declaration of a given local redeclarable + /// decl. + const Decl *getFirstLocalDecl(const Decl *D); + /// \brief Emit a reference to a declaration. void AddDeclRef(const Decl *D, RecordDataImpl &Record); @@ -738,27 +764,20 @@ public: void AddPath(StringRef Path, RecordDataImpl &Record); /// \brief Emit the current record with the given path as a blob. - void EmitRecordWithPath(unsigned Abbrev, RecordDataImpl &Record, + void EmitRecordWithPath(unsigned Abbrev, RecordDataRef Record, StringRef Path); /// \brief Add a version tuple to the given record void AddVersionTuple(const VersionTuple &Version, RecordDataImpl &Record); - void RewriteDecl(const Decl *D) { - DeclsToRewrite.insert(D); - } - - bool isRewritten(const Decl *D) const { - return DeclsToRewrite.count(D); - } - /// \brief Infer the submodule ID that contains an entity at the given /// source location. serialization::SubmoduleID inferSubmoduleIDFromLocation(SourceLocation Loc); - /// \brief Retrieve a submodule ID for this module. - /// Returns 0 If no ID has been associated with the module. - unsigned getExistingSubmoduleID(Module *Mod) const; + /// \brief Retrieve or create a submodule ID for this module, or return 0 if + /// the submodule is neither local (a submodle of the currently-written module) + /// nor from an imported module. + unsigned getLocalOrImportedSubmoduleID(Module *Mod); /// \brief Note that the identifier II occurs at the given offset /// within the identifier table. @@ -830,6 +849,7 @@ public: unsigned getExprImplicitCastAbbrev() const { return ExprImplicitCastAbbrev; } bool hasChain() const { return Chain; } + ASTReader *getChain() const { return Chain; } // ASTDeserializationListener implementation void ReaderInitialized(ASTReader *Reader) override; @@ -845,12 +865,6 @@ public: void CompletedTagDefinition(const TagDecl *D) override; void AddedVisibleDecl(const DeclContext *DC, const Decl *D) override; void AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) override; - void AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD, - const ClassTemplateSpecializationDecl *D) override; - void AddedCXXTemplateSpecialization(const VarTemplateDecl *TD, - const VarTemplateSpecializationDecl *D) override; - void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD, - const FunctionDecl *D) override; void ResolvedExceptionSpec(const FunctionDecl *FD) override; void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) override; void ResolvedOperatorDelete(const CXXDestructorDecl *DD, @@ -860,9 +874,6 @@ public: void FunctionDefinitionInstantiated(const FunctionDecl *D) override; void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD, const ObjCInterfaceDecl *IFD) override; - void AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop, - const ObjCPropertyDecl *OrigProp, - const ObjCCategoryDecl *ClassExt) override; void DeclarationMarkedUsed(const Decl *D) override; void DeclarationMarkedOpenMPThreadPrivate(const Decl *D) override; void RedefinedHiddenDefinition(const NamedDecl *D, Module *M) override; @@ -889,10 +900,13 @@ protected: SmallVectorImpl<char> &getPCH() const { return Buffer->Data; } public: - PCHGenerator(const Preprocessor &PP, StringRef OutputFile, - clang::Module *Module, StringRef isysroot, - std::shared_ptr<PCHBuffer> Buffer, - bool AllowASTWithErrors = false); + PCHGenerator( + const Preprocessor &PP, StringRef OutputFile, + clang::Module *Module, StringRef isysroot, + std::shared_ptr<PCHBuffer> Buffer, + ArrayRef<llvm::IntrusiveRefCntPtr<ModuleFileExtension>> Extensions, + bool AllowASTWithErrors = false, + bool IncludeTimestamps = true); ~PCHGenerator() override; void InitializeSema(Sema &S) override { SemaPtr = &S; } void HandleTranslationUnit(ASTContext &Ctx) override; diff --git a/include/clang/Serialization/GlobalModuleIndex.h b/include/clang/Serialization/GlobalModuleIndex.h index ba4f7e2..0f14eca 100644 --- a/include/clang/Serialization/GlobalModuleIndex.h +++ b/include/clang/Serialization/GlobalModuleIndex.h @@ -36,6 +36,7 @@ class FileEntry; class FileManager; class IdentifierIterator; class PCHContainerOperations; +class PCHContainerReader; namespace serialization { class ModuleFile; @@ -193,7 +194,7 @@ public: /// \brief Write a global index into the given /// /// \param FileMgr The file manager to use to load module files. - /// \param PCHContainerOps - The PCHContainerOperations to use for loading and + /// \param PCHContainerRdr - The PCHContainerOperations to use for loading and /// creating modules. /// \param Path The path to the directory containing module files, into /// which the global index will be written. diff --git a/include/clang/Serialization/Module.h b/include/clang/Serialization/Module.h index c98ced4..d6d16a0 100644 --- a/include/clang/Serialization/Module.h +++ b/include/clang/Serialization/Module.h @@ -15,9 +15,11 @@ #ifndef LLVM_CLANG_SERIALIZATION_MODULE_H #define LLVM_CLANG_SERIALIZATION_MODULE_H +#include "clang/Basic/FileManager.h" #include "clang/Basic/SourceLocation.h" #include "clang/Serialization/ASTBitCodes.h" #include "clang/Serialization/ContinuousRangeMap.h" +#include "clang/Serialization/ModuleFileExtension.h" #include "llvm/ADT/SetVector.h" #include "llvm/Bitcode/BitstreamReader.h" #include "llvm/Support/Endian.h" @@ -31,7 +33,6 @@ template <typename Info> class OnDiskIterableChainedHashTable; namespace clang { -class FileEntry; class DeclContext; class Module; @@ -50,17 +51,6 @@ enum ModuleKind { MK_MainFile ///< File is a PCH file treated as the actual main file. }; -/// \brief Information about the contents of a DeclContext. -struct DeclContextInfo { - DeclContextInfo() - : NameLookupTableData(), LexicalDecls(), NumLexicalDecls() {} - - llvm::OnDiskIterableChainedHashTable<reader::ASTDeclContextNameLookupTrait> - *NameLookupTableData; // an ASTDeclContextNameLookupTable. - const KindDeclIDPair *LexicalDecls; - unsigned NumLexicalDecls; -}; - /// \brief The input file that has been loaded from this AST file, along with /// bools indicating whether this was an overridden buffer or if it was /// out-of-date or not-found. @@ -155,6 +145,9 @@ public: /// \brief Whether this precompiled header is a relocatable PCH file. bool RelocatablePCH; + /// \brief Whether timestamps are included in this module file. + bool HasTimestamps; + /// \brief The file entry for the module file. const FileEntry *File; @@ -202,6 +195,10 @@ public: /// \brief The first source location in this module. SourceLocation FirstLoc; + /// The list of extension readers that are attached to this module + /// file. + std::vector<std::unique_ptr<ModuleFileExtensionReader>> ExtensionReaders; + // === Input Files === /// \brief The cursor to the start of the input-files block. llvm::BitstreamCursor InputFilesCursor; @@ -270,6 +267,10 @@ public: /// IdentifierHashTable. void *IdentifierLookupTable; + /// \brief Offsets of identifiers that we're going to preload within + /// IdentifierTableData. + std::vector<unsigned> PreloadIdentifierOffsets; + // === Macros === /// \brief The cursor to the start of the preprocessor block, which stores @@ -412,28 +413,10 @@ public: /// indexed by the C++ ctor initializer list ID minus 1. const uint32_t *CXXCtorInitializersOffsets; - typedef llvm::DenseMap<const DeclContext *, DeclContextInfo> - DeclContextInfosMap; - - /// \brief Information about the lexical and visible declarations - /// for each DeclContext. - DeclContextInfosMap DeclContextInfos; - /// \brief Array of file-level DeclIDs sorted by file. const serialization::DeclID *FileSortedDecls; unsigned NumFileSortedDecls; - /// \brief Array of redeclaration chain location information within this - /// module file, sorted by the first declaration ID. - const serialization::LocalRedeclarationsInfo *RedeclarationsMap; - - /// \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; @@ -476,6 +459,11 @@ public: /// any point during translation. bool isDirectlyImported() const { return DirectlyImported; } + /// \brief Is this a module file for a module (rather than a PCH or similar). + bool isModule() const { + return Kind == MK_ImplicitModule || Kind == MK_ExplicitModule; + } + /// \brief Dump debugging output for this module. void dump(); }; diff --git a/include/clang/Serialization/ModuleFileExtension.h b/include/clang/Serialization/ModuleFileExtension.h new file mode 100644 index 0000000..ba2e2fd --- /dev/null +++ b/include/clang/Serialization/ModuleFileExtension.h @@ -0,0 +1,149 @@ +//===-- ModuleFileExtension.h - Module File Extensions ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SERIALIZATION_MODULEFILEEXTENSION_H +#define LLVM_CLANG_SERIALIZATION_MODULEFILEEXTENSION_H + +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include <memory> +#include <string> + +namespace llvm { +class BitstreamCursor; +class BitstreamWriter; +class hash_code; +class raw_ostream; +} + +namespace clang { + +class ASTReader; +class ASTWriter; +class Sema; + +namespace serialization { + class ModuleFile; +} // end namespace serialization + +/// Metadata for a module file extension. +struct ModuleFileExtensionMetadata { + /// The name used to identify this particular extension block within + /// the resulting module file. It should be unique to the particular + /// extension, because this name will be used to match the name of + /// an extension block to the appropriate reader. + std::string BlockName; + + /// The major version of the extension data. + unsigned MajorVersion; + + /// The minor version of the extension data. + unsigned MinorVersion; + + /// A string containing additional user information that will be + /// stored with the metadata. + std::string UserInfo; +}; + +class ModuleFileExtensionReader; +class ModuleFileExtensionWriter; + +/// An abstract superclass that describes a custom extension to the +/// module/precompiled header file format. +/// +/// A module file extension can introduce additional information into +/// compiled module files (.pcm) and precompiled headers (.pch) via a +/// custom writer that can then be accessed via a custom reader when +/// the module file or precompiled header is loaded. +class ModuleFileExtension : public llvm::RefCountedBase<ModuleFileExtension> { +public: + virtual ~ModuleFileExtension(); + + /// Retrieves the metadata for this module file extension. + virtual ModuleFileExtensionMetadata getExtensionMetadata() const = 0; + + /// Hash information about the presence of this extension into the + /// module hash code. + /// + /// The module hash code is used to distinguish different variants + /// of a module that are incompatible. If the presence, absence, or + /// version of the module file extension should force the creation + /// of a separate set of module files, override this method to + /// combine that distinguishing information into the module hash + /// code. + /// + /// The default implementation of this function simply returns the + /// hash code as given, so the presence/absence of this extension + /// does not distinguish module files. + virtual llvm::hash_code hashExtension(llvm::hash_code c) const; + + /// Create a new module file extension writer, which will be + /// responsible for writing the extension contents into a particular + /// module file. + virtual std::unique_ptr<ModuleFileExtensionWriter> + createExtensionWriter(ASTWriter &Writer) = 0; + + /// Create a new module file extension reader, given the + /// metadata read from the block and the cursor into the extension + /// block. + /// + /// May return null to indicate that an extension block with the + /// given metadata cannot be read. + virtual std::unique_ptr<ModuleFileExtensionReader> + createExtensionReader(const ModuleFileExtensionMetadata &Metadata, + ASTReader &Reader, serialization::ModuleFile &Mod, + const llvm::BitstreamCursor &Stream) = 0; +}; + +/// Abstract base class that writes a module file extension block into +/// a module file. +class ModuleFileExtensionWriter { + ModuleFileExtension *Extension; + +protected: + ModuleFileExtensionWriter(ModuleFileExtension *Extension) + : Extension(Extension) { } + +public: + virtual ~ModuleFileExtensionWriter(); + + /// Retrieve the module file extension with which this writer is + /// associated. + ModuleFileExtension *getExtension() const { return Extension; } + + /// Write the contents of the extension block into the given bitstream. + /// + /// Responsible for writing the contents of the extension into the + /// given stream. All of the contents should be written into custom + /// records with IDs >= FIRST_EXTENSION_RECORD_ID. + virtual void writeExtensionContents(Sema &SemaRef, + llvm::BitstreamWriter &Stream) = 0; +}; + +/// Abstract base class that reads a module file extension block from +/// a module file. +/// +/// Subclasses +class ModuleFileExtensionReader { + ModuleFileExtension *Extension; + +protected: + ModuleFileExtensionReader(ModuleFileExtension *Extension) + : Extension(Extension) { } + +public: + /// Retrieve the module file extension with which this reader is + /// associated. + ModuleFileExtension *getExtension() const { return Extension; } + + virtual ~ModuleFileExtensionReader(); +}; + +} // end namespace clang + +#endif // LLVM_CLANG_FRONTEND_MODULEFILEEXTENSION_H diff --git a/include/clang/Serialization/ModuleManager.h b/include/clang/Serialization/ModuleManager.h index ab39aef..08e7d40 100644 --- a/include/clang/Serialization/ModuleManager.h +++ b/include/clang/Serialization/ModuleManager.h @@ -30,23 +30,22 @@ namespace serialization { /// \brief Manages the set of modules loaded by an AST reader. class ModuleManager { - /// \brief The chain of AST files. The first entry is the one named by the - /// user, the last one is the one that doesn't depend on anything further. + /// \brief The chain of AST files, in the order in which we started to load + /// them (this order isn't really useful for anything). SmallVector<ModuleFile *, 2> Chain; + /// \brief The chain of non-module PCH files. The first entry is the one named + /// by the user, the last one is the one that doesn't depend on anything + /// further. + SmallVector<ModuleFile *, 2> PCHChain; + // \brief The roots of the dependency DAG of AST files. This is used // to implement short-circuiting logic when running DFS over the dependencies. SmallVector<ModuleFile *, 2> Roots; - + /// \brief All loaded modules, indexed by name. llvm::DenseMap<const FileEntry *, ModuleFile *> Modules; - typedef llvm::SetVector<const FileEntry *> AdditionalKnownModuleFileSet; - - /// \brief Additional module files that are known but not loaded. Tracked - /// here so that we can re-export them if necessary. - AdditionalKnownModuleFileSet AdditionalKnownModuleFiles; - /// \brief FileManager that handles translating between filenames and /// FileEntry *. FileManager &FileMgr; @@ -121,24 +120,26 @@ public: const PCHContainerReader &PCHContainerRdr); ~ModuleManager(); - /// \brief Forward iterator to traverse all loaded modules. This is reverse - /// source-order. + /// \brief Forward iterator to traverse all loaded modules. ModuleIterator begin() { return Chain.begin(); } /// \brief Forward iterator end-point to traverse all loaded modules ModuleIterator end() { return Chain.end(); } - /// \brief Const forward iterator to traverse all loaded modules. This is - /// in reverse source-order. + /// \brief Const forward iterator to traverse all loaded modules. ModuleConstIterator begin() const { return Chain.begin(); } /// \brief Const forward iterator end-point to traverse all loaded modules ModuleConstIterator end() const { return Chain.end(); } - /// \brief Reverse iterator to traverse all loaded modules. This is in - /// source order. + /// \brief Reverse iterator to traverse all loaded modules. ModuleReverseIterator rbegin() { return Chain.rbegin(); } /// \brief Reverse iterator end-point to traverse all loaded modules. ModuleReverseIterator rend() { return Chain.rend(); } - + + /// \brief A range covering the PCH and preamble module files loaded. + llvm::iterator_range<ModuleConstIterator> pch_modules() const { + return llvm::make_range(PCHChain.begin(), PCHChain.end()); + } + /// \brief Returns the primary module associated with the manager, that is, /// the first module loaded ModuleFile &getPrimaryModule() { return *Chain[0]; } @@ -235,19 +236,6 @@ public: /// has been "accepted", and will not (can not) be unloaded. void moduleFileAccepted(ModuleFile *MF); - /// \brief Notification from the frontend that the given module file is - /// part of this compilation (even if not imported) and, if this compilation - /// is exported, should be made available to importers of it. - bool addKnownModuleFile(StringRef FileName); - - /// \brief Get a list of additional module files that are not currently - /// loaded but are considered to be part of the current compilation. - llvm::iterator_range<AdditionalKnownModuleFileSet::const_iterator> - getAdditionalKnownModuleFiles() { - return llvm::make_range(AdditionalKnownModuleFiles.begin(), - AdditionalKnownModuleFiles.end()); - } - /// \brief Visit each of the modules. /// /// This routine visits each of the modules, starting with the @@ -259,51 +247,17 @@ public: /// operations that can find data in any of the loaded modules. /// /// \param Visitor A visitor function that will be invoked with each - /// module and the given user data pointer. The return value must be - /// convertible to bool; when false, the visitation continues to - /// modules that the current module depends on. When true, the - /// visitation skips any modules that the current module depends on. - /// - /// \param UserData User data associated with the visitor object, which - /// will be passed along to the visitor. + /// module. The return value must be convertible to bool; when false, the + /// visitation continues to modules that the current module depends on. When + /// true, the visitation skips any modules that the current module depends on. /// /// \param ModuleFilesHit If non-NULL, contains the set of module files /// that we know we need to visit because the global module index told us to. /// Any module that is known to both the global module index and the module /// manager that is *not* in this set can be skipped. - void visit(bool (*Visitor)(ModuleFile &M, void *UserData), void *UserData, + void visit(llvm::function_ref<bool(ModuleFile &M)> Visitor, llvm::SmallPtrSetImpl<ModuleFile *> *ModuleFilesHit = nullptr); - /// \brief Control DFS behavior during preorder visitation. - enum DFSPreorderControl { - Continue, /// Continue visiting all nodes. - Abort, /// Stop the visitation immediately. - SkipImports, /// Do not visit imports of the current node. - }; - - /// \brief Visit each of the modules with a depth-first traversal. - /// - /// This routine visits each of the modules known to the module - /// manager using a depth-first search, starting with the first - /// loaded module. The traversal invokes one callback before - /// traversing the imports (preorder traversal) and one after - /// traversing the imports (postorder traversal). - /// - /// \param PreorderVisitor A visitor function that will be invoked with each - /// module before visiting its imports. The visitor can control how to - /// continue the visitation through its return value. - /// - /// \param PostorderVisitor A visitor function taht will be invoked with each - /// module after visiting its imports. The visitor may return true at any time - /// to abort the depth-first visitation. - /// - /// \param UserData User data ssociated with the visitor object, - /// which will be passed along to the user. - void visitDepthFirst(DFSPreorderControl (*PreorderVisitor)(ModuleFile &M, - void *UserData), - bool (*PostorderVisitor)(ModuleFile &M, void *UserData), - void *UserData); - /// \brief Attempt to resolve the given module file name to a file entry. /// /// \param FileName The name of the module file. |