diff options
Diffstat (limited to 'include/clang/Serialization')
-rw-r--r-- | include/clang/Serialization/ASTBitCodes.h | 103 | ||||
-rw-r--r-- | include/clang/Serialization/ASTReader.h | 347 | ||||
-rw-r--r-- | include/clang/Serialization/ASTWriter.h | 62 | ||||
-rw-r--r-- | include/clang/Serialization/ContinuousRangeMap.h | 1 | ||||
-rw-r--r-- | include/clang/Serialization/GlobalModuleIndex.h | 194 | ||||
-rw-r--r-- | include/clang/Serialization/Module.h | 53 | ||||
-rw-r--r-- | include/clang/Serialization/ModuleManager.h | 148 |
7 files changed, 730 insertions, 178 deletions
diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h index 8c58fb2..9b685ba 100644 --- a/include/clang/Serialization/ASTBitCodes.h +++ b/include/clang/Serialization/ASTBitCodes.h @@ -18,9 +18,9 @@ #define LLVM_CLANG_FRONTEND_PCHBITCODES_H #include "clang/AST/Type.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/Bitcode/BitCodes.h" #include "llvm/Support/DataTypes.h" -#include "llvm/ADT/DenseMap.h" namespace clang { namespace serialization { @@ -35,7 +35,7 @@ namespace clang { /// Version 4 of AST files also requires that the version control branch and /// revision match exactly, since there is no backward compatibility of /// AST files at this time. - const unsigned VERSION_MAJOR = 4; + const unsigned VERSION_MAJOR = 5; /// \brief AST file minor version number supported by this version of /// Clang. @@ -129,7 +129,14 @@ namespace clang { /// \brief An ID number that refers to a macro in an AST file. typedef uint32_t MacroID; - + + /// \brief A global ID number that refers to a macro in an AST file. + typedef uint32_t GlobalMacroID; + + /// \brief A local to a module ID number that refers to a macro in an + /// AST file. + typedef uint32_t LocalMacroID; + /// \brief The number of predefined macro IDs. const unsigned int NUM_PREDEF_MACRO_IDS = 1; @@ -259,21 +266,25 @@ namespace clang { /// \brief The directory that the PCH was originally created in. ORIGINAL_PCH_DIR = 6, + /// \brief Record code for file ID of the file or buffer that was used to + /// generate the AST file. + ORIGINAL_FILE_ID = 7, + /// \brief Offsets into the input-files block where input files /// reside. - INPUT_FILE_OFFSETS = 7, + INPUT_FILE_OFFSETS = 8, /// \brief Record code for the diagnostic options table. - DIAGNOSTIC_OPTIONS = 8, + DIAGNOSTIC_OPTIONS = 9, /// \brief Record code for the filesystem options table. - FILE_SYSTEM_OPTIONS = 9, + FILE_SYSTEM_OPTIONS = 10, /// \brief Record code for the headers search options table. - HEADER_SEARCH_OPTIONS = 10, + HEADER_SEARCH_OPTIONS = 11, /// \brief Record code for the preprocessor options table. - PREPROCESSOR_OPTIONS = 11 + PREPROCESSOR_OPTIONS = 12 }; /// \brief Record types that occur within the input-files block @@ -319,6 +330,11 @@ namespace clang { /// NULL-terminated string that corresponds to that identifier. IDENTIFIER_OFFSET = 3, + /// \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*. + METADATA_OLD_FORMAT = 4, + /// \brief Record code for the identifier table. /// /// The identifier table is a simple blob that contains @@ -331,7 +347,7 @@ namespace clang { /// between offsets (for unresolved identifier IDs) and /// IdentifierInfo pointers (for already-resolved identifier /// IDs). - IDENTIFIER_TABLE = 4, + IDENTIFIER_TABLE = 5, /// \brief Record code for the array of external definitions. /// @@ -341,7 +357,7 @@ namespace clang { /// reported to the AST consumer after the AST file has been /// read, since their presence can affect the semantics of the /// program (e.g., for code generation). - EXTERNAL_DEFINITIONS = 5, + EXTERNAL_DEFINITIONS = 6, /// \brief Record code for the set of non-builtin, special /// types. @@ -350,33 +366,33 @@ namespace clang { /// that are constructed during semantic analysis (e.g., /// __builtin_va_list). The SPECIAL_TYPE_* constants provide /// offsets into this record. - SPECIAL_TYPES = 6, + SPECIAL_TYPES = 7, /// \brief Record code for the extra statistics we gather while /// generating an AST file. - STATISTICS = 7, + STATISTICS = 8, /// \brief Record code for the array of tentative definitions. - TENTATIVE_DEFINITIONS = 8, + TENTATIVE_DEFINITIONS = 9, - /// \brief Record code for the array of locally-scoped external + /// \brief Record code for the array of locally-scoped extern "C" /// declarations. - LOCALLY_SCOPED_EXTERNAL_DECLS = 9, + LOCALLY_SCOPED_EXTERN_C_DECLS = 10, /// \brief Record code for the table of offsets into the /// Objective-C method pool. - SELECTOR_OFFSETS = 10, + SELECTOR_OFFSETS = 11, /// \brief Record code for the Objective-C method pool, - METHOD_POOL = 11, + METHOD_POOL = 12, /// \brief The value of the next __COUNTER__ to dispense. /// [PP_COUNTER_VALUE, Val] - PP_COUNTER_VALUE = 12, + PP_COUNTER_VALUE = 13, /// \brief Record code for the table of offsets into the block /// of source-location information. - SOURCE_LOCATION_OFFSETS = 13, + SOURCE_LOCATION_OFFSETS = 14, /// \brief Record code for the set of source location entries /// that need to be preloaded by the AST reader. @@ -384,7 +400,7 @@ namespace clang { /// This set contains the source location entry for the /// predefines buffer and for any file entries that need to be /// preloaded. - SOURCE_LOCATION_PRELOADS = 14, + SOURCE_LOCATION_PRELOADS = 15, /// \brief Record code for the set of ext_vector type names. EXT_VECTOR_DECLS = 16, @@ -513,9 +529,13 @@ namespace clang { /// macro definition. MACRO_OFFSET = 47, - /// \brief Record of updates for a macro that was modified after - /// being deserialized. - MACRO_UPDATES = 48 + /// \brief Mapping table from the identifier ID to the offset of the + /// macro directive history for the identifier. + MACRO_TABLE = 48, + + /// \brief Record code for undefined but used functions and variables that + /// need a definition in this TU. + UNDEFINED_BUT_USED = 49 }; /// \brief Record types used within a source manager block. @@ -552,7 +572,10 @@ namespace clang { /// \brief Describes one token. /// [PP_TOKEN, SLoc, Length, IdentInfoID, Kind, Flags] - PP_TOKEN = 3 + PP_TOKEN = 3, + + /// \brief The macro directives history for a particular identifier. + PP_MACRO_DIRECTIVE_HISTORY = 4 }; /// \brief Record types used within a preprocessor detail block. @@ -594,7 +617,13 @@ namespace clang { SUBMODULE_REQUIRES = 8, /// \brief Specifies a header that has been explicitly excluded /// from this submodule. - SUBMODULE_EXCLUDED_HEADER = 9 + SUBMODULE_EXCLUDED_HEADER = 9, + /// \brief Specifies a library or framework to link against. + SUBMODULE_LINK_LIBRARY = 10, + /// \brief Specifies a configuration macro for this module. + SUBMODULE_CONFIG_MACRO = 11, + /// \brief Specifies a conflict with another module. + SUBMODULE_CONFLICT = 12 }; /// \brief Record types used within a comments block. @@ -692,7 +721,23 @@ namespace clang { /// \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 = 37, + /// \brief OpenCL 1d image type. + PREDEF_TYPE_IMAGE1D_ID = 38, + /// \brief OpenCL 1d image array type. + PREDEF_TYPE_IMAGE1D_ARR_ID = 39, + /// \brief OpenCL 1d image buffer type. + PREDEF_TYPE_IMAGE1D_BUFF_ID = 40, + /// \brief OpenCL 2d image type. + PREDEF_TYPE_IMAGE2D_ID = 41, + /// \brief OpenCL 2d image array type. + PREDEF_TYPE_IMAGE2D_ARR_ID = 42, + /// \brief OpenCL 3d image type. + PREDEF_TYPE_IMAGE3D_ID = 43, + /// \brief OpenCL event type. + PREDEF_TYPE_EVENT_ID = 44, + /// \brief OpenCL sampler type. + PREDEF_TYPE_SAMPLER_ID = 45 }; /// \brief The number of predefined type IDs that are reserved for @@ -1000,7 +1045,11 @@ namespace clang { /// function specialization. (Microsoft extension). DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION, /// \brief An ImportDecl recording a module import. - DECL_IMPORT + DECL_IMPORT, + /// \brief A OMPThreadPrivateDecl record. + DECL_OMP_THREADPRIVATE, + /// \brief An EmptyDecl record. + DECL_EMPTY }; /// \brief Record codes for each kind of statement or expression. diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index e23ea5c..9255336 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -14,33 +14,33 @@ #ifndef LLVM_CLANG_FRONTEND_AST_READER_H #define LLVM_CLANG_FRONTEND_AST_READER_H -#include "clang/Serialization/ASTBitCodes.h" -#include "clang/Serialization/ContinuousRangeMap.h" -#include "clang/Serialization/Module.h" -#include "clang/Serialization/ModuleManager.h" -#include "clang/Sema/ExternalSemaSource.h" -#include "clang/AST/DeclarationName.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclarationName.h" #include "clang/AST/TemplateBase.h" -#include "clang/Lex/ExternalPreprocessorSource.h" -#include "clang/Lex/HeaderSearch.h" -#include "clang/Lex/PPMutationListener.h" -#include "clang/Lex/PreprocessingRecord.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/FileSystemOptions.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/SourceManager.h" +#include "clang/Basic/Version.h" +#include "clang/Lex/ExternalPreprocessorSource.h" +#include "clang/Lex/HeaderSearch.h" +#include "clang/Lex/PreprocessingRecord.h" +#include "clang/Sema/ExternalSemaSource.h" +#include "clang/Serialization/ASTBitCodes.h" +#include "clang/Serialization/ContinuousRangeMap.h" +#include "clang/Serialization/Module.h" +#include "clang/Serialization/ModuleManager.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/APSInt.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/DenseSet.h" #include "llvm/Bitcode/BitstreamReader.h" #include "llvm/Support/DataTypes.h" #include <deque> @@ -48,6 +48,7 @@ #include <string> #include <utility> #include <vector> +#include <sys/stat.h> namespace llvm { class MemoryBuffer; @@ -68,8 +69,10 @@ class NestedNameSpecifier; class CXXBaseSpecifier; class CXXConstructorDecl; class CXXCtorInitializer; +class GlobalModuleIndex; class GotoStmt; class MacroDefinition; +class MacroDirective; class NamedDecl; class OpaqueValueExpr; class Preprocessor; @@ -85,6 +88,7 @@ class TypeLocReader; struct HeaderFileInfo; class VersionTuple; class TargetOptions; +class ASTUnresolvedSet; /// \brief Abstract interface for callback invocations by the ASTReader. /// @@ -96,6 +100,14 @@ class ASTReaderListener { public: virtual ~ASTReaderListener(); + /// \brief Receives the full Clang version information. + /// + /// \returns true to indicate that the version is invalid. Subclasses should + /// generally defer to this implementation. + virtual bool ReadFullVersionInformation(StringRef FullVersion) { + return FullVersion != getClangFullRepositoryVersion(); + } + /// \brief Receives the language options. /// /// \returns true to indicate the options are invalid or false otherwise. @@ -233,6 +245,8 @@ public: Success, /// \brief The AST file itself appears corrupted. Failure, + /// \brief The AST file was missing. + Missing, /// \brief The AST file is out-of-date relative to its input files, /// and needs to be regenerated. OutOfDate, @@ -291,6 +305,9 @@ private: /// \brief The module manager which manages modules and their dependencies ModuleManager ModuleMgr; + /// \brief The global module index, if loaded. + llvm::OwningPtr<GlobalModuleIndex> GlobalIndex; + /// \brief A map of global bit offsets to the module that stores entities /// at those bit offsets. ContinuousRangeMap<uint64_t, ModuleFile*, 4> GlobalBitOffsetsMap; @@ -387,7 +404,7 @@ private: typedef llvm::MapVector<Decl *, uint64_t, llvm::SmallDenseMap<Decl *, unsigned, 4>, - llvm::SmallVector<std::pair<Decl *, uint64_t>, 4> > + SmallVector<std::pair<Decl *, uint64_t>, 4> > PendingBodiesMap; /// \brief Functions or methods that have bodies that will be attached. @@ -431,15 +448,6 @@ private: /// global macro ID to produce a local ID. GlobalMacroMapType GlobalMacroMap; - typedef llvm::DenseMap<serialization::MacroID, - llvm::SmallVector<std::pair<serialization::SubmoduleID, - MacroUpdate>, 1> > - MacroUpdatesMap; - - /// \brief Mapping from (global) macro IDs to the set of updates to be - /// performed to the corresponding macro. - MacroUpdatesMap MacroUpdates; - /// \brief A vector containing submodules that have already been loaded. /// /// This vector is indexed by the Submodule ID (-1). NULL submodule entries @@ -459,28 +467,22 @@ private: public: enum NameKind { Declaration, - MacroVisibility, - MacroUndef + MacroVisibility } Kind; private: - unsigned Loc; - union { Decl *D; - MacroInfo *MI; + MacroDirective *MD; }; IdentifierInfo *Id; public: - HiddenName(Decl *D) : Kind(Declaration), Loc(), D(D), Id() { } + HiddenName(Decl *D) : Kind(Declaration), D(D), Id() { } - HiddenName(IdentifierInfo *II, MacroInfo *MI) - : Kind(MacroVisibility), Loc(), MI(MI), Id(II) { } - - HiddenName(IdentifierInfo *II, MacroInfo *MI, SourceLocation Loc) - : Kind(MacroUndef), Loc(Loc.getRawEncoding()), MI(MI), Id(II) { } + HiddenName(IdentifierInfo *II, MacroDirective *MD) + : Kind(MacroVisibility), MD(MD), Id(II) { } NameKind getKind() const { return Kind; } @@ -489,21 +491,14 @@ private: return D; } - std::pair<IdentifierInfo *, MacroInfo *> getMacro() const { - assert((getKind() == MacroUndef || getKind() == MacroVisibility) - && "Hidden name is not a macro!"); - return std::make_pair(Id, MI); - } - - SourceLocation getMacroUndefLoc() const { - assert(getKind() == MacroUndef && "Hidden name is not an undef!"); - return SourceLocation::getFromRawEncoding(Loc); + std::pair<IdentifierInfo *, MacroDirective *> getMacro() const { + assert(getKind() == MacroVisibility && "Hidden name is not a macro!"); + return std::make_pair(Id, MD); } }; /// \brief A set of hidden declarations. - typedef llvm::SmallVector<HiddenName, 2> - HiddenNames; + typedef SmallVector<HiddenName, 2> HiddenNames; typedef llvm::DenseMap<Module *, HiddenNames> HiddenNamesMapType; @@ -512,28 +507,30 @@ private: HiddenNamesMapType HiddenNamesMap; - /// \brief A module import or export that hasn't yet been resolved. - struct UnresolvedModuleImportExport { + /// \brief A module import, export, or conflict that hasn't yet been resolved. + struct UnresolvedModuleRef { /// \brief The file in which this module resides. ModuleFile *File; /// \brief The module that is importing or exporting. Module *Mod; - + + /// \brief The kind of module reference. + enum { Import, Export, Conflict } Kind; + /// \brief The local ID of the module that is being exported. unsigned ID; - - /// \brief Whether this is an import (vs. an export). - unsigned IsImport : 1; - + /// \brief Whether this is a wildcard export. unsigned IsWildcard : 1; + + /// \brief String data. + StringRef String; }; /// \brief The set of module imports and exports that still need to be /// resolved. - llvm::SmallVector<UnresolvedModuleImportExport, 2> - UnresolvedModuleImportExports; + SmallVector<UnresolvedModuleRef, 2> UnresolvedModuleRefs; /// \brief A vector containing selectors that have already been loaded. /// @@ -546,7 +543,7 @@ private: GlobalSelectorMapType; /// \brief Mapping from global selector IDs to the module in which the - /// selector resides along with the offset that should be added to the + /// global selector ID to produce a local ID. GlobalSelectorMapType GlobalSelectorMap; @@ -554,8 +551,35 @@ private: /// global method pool for this selector. llvm::DenseMap<Selector, unsigned> SelectorGeneration; - typedef llvm::MapVector<IdentifierInfo *, - llvm::SmallVector<serialization::MacroID, 2> > + struct PendingMacroInfo { + ModuleFile *M; + + struct ModuleMacroDataTy { + serialization::GlobalMacroID GMacID; + unsigned ImportLoc; + }; + struct PCHMacroDataTy { + uint64_t MacroDirectivesOffset; + }; + + union { + ModuleMacroDataTy ModuleMacroData; + PCHMacroDataTy PCHMacroData; + }; + + PendingMacroInfo(ModuleFile *M, + serialization::GlobalMacroID GMacID, + SourceLocation ImportLoc) : M(M) { + ModuleMacroData.GMacID = GMacID; + ModuleMacroData.ImportLoc = ImportLoc.getRawEncoding(); + } + + PendingMacroInfo(ModuleFile *M, uint64_t MacroDirectivesOffset) : M(M) { + PCHMacroData.MacroDirectivesOffset = MacroDirectivesOffset; + } + }; + + typedef llvm::MapVector<IdentifierInfo *, SmallVector<PendingMacroInfo, 2> > PendingMacroIDsMap; /// \brief Mapping from identifiers that have a macro history to the global @@ -637,11 +661,11 @@ private: /// \brief Fields containing data that is used for semantic analysis //@{ - /// \brief The IDs of all locally scoped external decls in the chain. + /// \brief The IDs of all locally scoped extern "C" decls in the chain. /// /// Sema tracks these to validate that the types are consistent across all - /// local external declarations. - SmallVector<uint64_t, 16> LocallyScopedExternalDecls; + /// local extern "C" declarations. + SmallVector<uint64_t, 16> LocallyScopedExternCDecls; /// \brief The IDs of all dynamic class declarations in the chain. /// @@ -674,6 +698,10 @@ private: /// \brief A list of the namespaces we've seen. SmallVector<uint64_t, 4> KnownNamespaces; + /// \brief A list of undefined decls with internal linkage followed by the + /// SourceLocation of a matching ODR-use. + SmallVector<uint64_t, 8> UndefinedButUsed; + /// \brief A list of modules that were imported by precompiled headers or /// any other non-module AST file. SmallVector<serialization::SubmoduleID, 2> ImportedModules; @@ -693,6 +721,12 @@ private: /// \brief Whether to accept an AST file with compiler errors. bool AllowASTWithCompilerErrors; + /// \brief Whether we are allowed to use the global module index. + bool UseGlobalIndex; + + /// \brief Whether we have tried loading the global module index yet. + bool TriedLoadingGlobalIndex; + /// \brief The current "generation" of the module file import stack, which /// indicates how many separate module file load operations have occurred. unsigned CurrentGeneration; @@ -727,6 +761,12 @@ private: /// \brief The total number of macros stored in the chain. unsigned TotalNumMacros; + /// \brief The number of lookups into identifier tables. + unsigned NumIdentifierLookups; + + /// \brief The number of lookups into identifier tables that succeed. + unsigned NumIdentifierLookupHits; + /// \brief The number of selectors that have been read. unsigned NumSelectorsRead; @@ -734,8 +774,20 @@ private: unsigned NumMethodPoolEntriesRead; /// \brief The number of times we have looked up a selector in the method - /// pool and not found anything interesting. - unsigned NumMethodPoolMisses; + /// pool. + unsigned NumMethodPoolLookups; + + /// \brief The number of times we have looked up a selector in the method + /// pool and found something. + unsigned NumMethodPoolHits; + + /// \brief The number of times we have looked up a selector in the method + /// pool within a specific module. + unsigned NumMethodPoolTableLookups; + + /// \brief The number of times we have looked up a selector in the method + /// pool within a specific module and found something. + unsigned NumMethodPoolTableHits; /// \brief The total number of method pool entries in the selector table. unsigned TotalNumMethodPoolEntries; @@ -761,19 +813,13 @@ private: /// Number of CXX base specifiers currently loaded unsigned NumCXXBaseSpecifiersLoaded; - /// \brief An IdentifierInfo that has been loaded but whose top-level - /// declarations of the same name have not (yet) been loaded. - struct PendingIdentifierInfo { - IdentifierInfo *II; - SmallVector<uint32_t, 4> DeclIDs; - }; - /// \brief The set of identifiers that were read while the AST reader was /// (recursively) loading declarations. /// /// The declarations on the identifier chain for these identifiers will be /// loaded once the recursive loading has completed. - std::deque<PendingIdentifierInfo> PendingIdentifierInfos; + llvm::MapVector<IdentifierInfo *, SmallVector<uint32_t, 4> > + PendingIdentifierInfos; /// \brief The generation number of each identifier, which keeps track of /// the last time we loaded information about this identifier. @@ -797,11 +843,26 @@ private: /// Each element is the global declaration ID of the first declaration in /// the chain. Elements in this vector should be unique; use /// PendingDeclChainsKnown to ensure uniqueness. - llvm::SmallVector<serialization::DeclID, 16> PendingDeclChains; + SmallVector<serialization::DeclID, 16> PendingDeclChains; /// \brief Keeps track of the elements added to PendingDeclChains. llvm::SmallSet<serialization::DeclID, 16> PendingDeclChainsKnown; + /// \brief The Decl IDs for the Sema/Lexical DeclContext of a Decl that has + /// been loaded but its DeclContext was not set yet. + struct PendingDeclContextInfo { + Decl *D; + serialization::GlobalDeclID SemaDC; + serialization::GlobalDeclID LexicalDC; + }; + + /// \brief The set of Decls that have been loaded but their DeclContexts are + /// not set yet. + /// + /// The DeclContexts for these Decls will be set once recursive loading has + /// been completed. + std::deque<PendingDeclContextInfo> PendingDeclContextInfos; + /// \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; @@ -809,9 +870,9 @@ private: /// \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; + SmallVector<ObjCInterfaceDecl *, 16> ObjCClassesLoaded; - typedef llvm::DenseMap<Decl *, llvm::SmallVector<serialization::DeclID, 2> > + typedef llvm::DenseMap<Decl *, SmallVector<serialization::DeclID, 2> > MergedDeclsMap; /// \brief A mapping from canonical declarations to the set of additional @@ -820,7 +881,7 @@ private: MergedDeclsMap MergedDecls; typedef llvm::DenseMap<serialization::GlobalDeclID, - llvm::SmallVector<serialization::DeclID, 2> > + SmallVector<serialization::DeclID, 2> > StoredMergedDeclsMap; /// \brief A mapping from canonical declaration IDs to the set of additional @@ -883,11 +944,10 @@ private: /// \brief Reads a statement from the specified cursor. Stmt *ReadStmtFromStream(ModuleFile &F); - typedef llvm::PointerIntPair<const FileEntry *, 1, bool> InputFile; - /// \brief Retrieve the file entry and 'overridden' bit for an input /// file in the given module file. - InputFile getInputFile(ModuleFile &F, unsigned ID, bool Complain = true); + serialization::InputFile getInputFile(ModuleFile &F, unsigned ID, + bool Complain = true); /// \brief Get a FileEntry out of stored-in-PCH filename, making sure we take /// into account all the necessary relocations. @@ -895,12 +955,24 @@ private: void MaybeAddSystemRootToFilename(ModuleFile &M, std::string &Filename); + struct ImportedModule { + ModuleFile *Mod; + ModuleFile *ImportedBy; + SourceLocation ImportLoc; + + ImportedModule(ModuleFile *Mod, + ModuleFile *ImportedBy, + SourceLocation ImportLoc) + : Mod(Mod), ImportedBy(ImportedBy), ImportLoc(ImportLoc) { } + }; + ASTReadResult ReadASTCore(StringRef FileName, ModuleKind Type, - ModuleFile *ImportedBy, - llvm::SmallVectorImpl<ModuleFile *> &Loaded, + SourceLocation ImportLoc, ModuleFile *ImportedBy, + SmallVectorImpl<ImportedModule> &Loaded, + off_t ExpectedSize, time_t ExpectedModTime, unsigned ClientLoadCapabilities); ASTReadResult ReadControlBlock(ModuleFile &F, - llvm::SmallVectorImpl<ModuleFile *> &Loaded, + SmallVectorImpl<ImportedModule> &Loaded, unsigned ClientLoadCapabilities); bool ReadASTBlock(ModuleFile &F); bool ParseLineTable(ModuleFile &F, SmallVectorImpl<uint64_t> &Record); @@ -1034,6 +1106,14 @@ private: void finishPendingActions(); + void addPendingDeclContextInfo(Decl *D, + serialization::GlobalDeclID SemaDC, + serialization::GlobalDeclID LexicalDC) { + assert(D); + PendingDeclContextInfo Info = { D, SemaDC, LexicalDC }; + PendingDeclContextInfos.push_back(Info); + } + /// \brief Produce an error diagnostic and return true. /// /// This routine should only be used for fatal errors that have to @@ -1065,13 +1145,18 @@ public: /// \param AllowASTWithCompilerErrors If true, the AST reader will accept an /// AST file the was created out of an AST with compiler errors, /// otherwise it will reject it. + /// + /// \param UseGlobalIndex If true, the AST reader will try to load and use + /// the global module index. ASTReader(Preprocessor &PP, ASTContext &Context, StringRef isysroot = "", bool DisableValidation = false, - bool AllowASTWithCompilerErrors = false); + bool AllowASTWithCompilerErrors = false, + bool UseGlobalIndex = true); ~ASTReader(); SourceManager &getSourceManager() const { return SourceMgr; } + FileManager &getFileManager() const { return FileMgr; } /// \brief Flags that indicate what kind of AST loading failures the client /// of the AST reader can directly handle. @@ -1082,15 +1167,18 @@ public: /// \brief The client can't handle any AST loading failures. ARR_None = 0, /// \brief The client can handle an AST file that cannot load because it + /// is missing. + ARR_Missing = 0x1, + /// \brief The client can handle an AST file that cannot load because it /// is out-of-date relative to its input files. - ARR_OutOfDate = 0x1, + ARR_OutOfDate = 0x2, /// \brief The client can handle an AST file that cannot load because it /// was built with a different version of Clang. - ARR_VersionMismatch = 0x2, + ARR_VersionMismatch = 0x4, /// \brief The client can handle an AST file that cannot load because it's /// compiled configuration doesn't match that of the context it was /// loaded into. - ARR_ConfigurationMismatch = 0x4 + ARR_ConfigurationMismatch = 0x8 }; /// \brief Load the AST file designated by the given file name. @@ -1100,10 +1188,14 @@ public: /// \param Type The kind of AST being loaded, e.g., PCH, module, main file, /// or preamble. /// + /// \param ImportLoc the location where the module file will be considered as + /// imported from. For non-module AST types it should be invalid. + /// /// \param ClientLoadCapabilities The set of client load-failure /// capabilities, represented as a bitset of the enumerators of /// LoadFailureCapabilities. ASTReadResult ReadAST(const std::string &FileName, ModuleKind Type, + SourceLocation ImportLoc, unsigned ClientLoadCapabilities); /// \brief Make the entities in the given module and any of its (non-explicit) @@ -1113,11 +1205,17 @@ public: /// /// \param NameVisibility The level of visibility to give the names in the /// module. Visibility can only be increased over time. + /// + /// \param ImportLoc The location at which the import occurs. + /// + /// \param Complain Whether to complain about conflicting module imports. void makeModuleVisible(Module *Mod, - Module::NameVisibilityKind NameVisibility); + Module::NameVisibilityKind NameVisibility, + SourceLocation ImportLoc, + bool Complain); /// \brief Make the names within this set of hidden names visible. - void makeNamesVisible(const HiddenNames &Names); + void makeNamesVisible(const HiddenNames &Names, Module *Owner); /// \brief Set the AST callbacks listener. void setListener(ASTReaderListener *listener) { @@ -1127,6 +1225,18 @@ public: /// \brief Set the AST deserialization listener. void setDeserializationListener(ASTDeserializationListener *Listener); + /// \brief Determine whether this AST reader has a global index. + bool hasGlobalIndex() const { return GlobalIndex; } + + /// \brief Attempts to load the global index. + /// + /// \returns true if loading the global index has failed for any reason. + bool loadGlobalIndex(); + + /// \brief Determine whether we tried to load the global index, but failed, + /// e.g., because it is out-of-date or does not exist. + bool isGlobalIndexUnavailable() const; + /// \brief Initializes the ASTContext void InitializeContext(); @@ -1193,8 +1303,8 @@ public: /// \brief Optionally returns true or false if the preallocated preprocessed /// entity with index \p Index came from file \p FID. - virtual llvm::Optional<bool> isPreprocessedEntityInFileID(unsigned Index, - FileID FID); + virtual Optional<bool> isPreprocessedEntityInFileID(unsigned Index, + FileID FID); /// \brief Read the header file information for the given file entry. virtual HeaderFileInfo GetHeaderFileInfo(const FileEntry *FE); @@ -1297,7 +1407,7 @@ public: /// \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); + ModuleFile *getOwningModuleFile(const Decl *D); /// \brief Returns the source location for the decl \p ID. SourceLocation getSourceLocationForDeclID(serialization::GlobalDeclID ID); @@ -1374,7 +1484,7 @@ public: /// \brief Finds all the visible declarations with a given name. /// The current implementation of this method just loads the entire /// lookup table as unmaterialized references. - virtual DeclContext::lookup_result + virtual bool FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name); @@ -1459,6 +1569,9 @@ public: virtual void ReadKnownNamespaces( SmallVectorImpl<NamespaceDecl *> &Namespaces); + virtual void ReadUndefinedButUsed( + llvm::DenseMap<NamedDecl *, SourceLocation> &Undefined); + virtual void ReadTentativeDefinitions( SmallVectorImpl<VarDecl *> &TentativeDefs); @@ -1472,7 +1585,7 @@ public: virtual void ReadDynamicClasses(SmallVectorImpl<CXXRecordDecl *> &Decls); - virtual void ReadLocallyScopedExternalDecls( + virtual void ReadLocallyScopedExternCDecls( SmallVectorImpl<NamedDecl *> &Decls); virtual void ReadReferencedSelectors( @@ -1493,7 +1606,7 @@ public: void SetIdentifierInfo(unsigned ID, IdentifierInfo *II); void SetGloballyVisibleDecls(IdentifierInfo *II, const SmallVectorImpl<uint32_t> &DeclIDs, - bool Nonrecursive = false); + SmallVectorImpl<Decl *> *Decls = 0); /// \brief Report a diagnostic. DiagnosticBuilder Diag(unsigned DiagID); @@ -1520,8 +1633,16 @@ public: serialization::IdentifierID getGlobalIdentifierID(ModuleFile &M, unsigned LocalID); + void resolvePendingMacro(IdentifierInfo *II, const PendingMacroInfo &PMInfo); + + void installPCHMacroDirectives(IdentifierInfo *II, + ModuleFile &M, uint64_t Offset); + + void installImportedMacro(IdentifierInfo *II, MacroDirective *MD, + Module *Owner); + /// \brief Retrieve the macro with the given ID. - MacroInfo *getMacro(serialization::MacroID ID, MacroInfo *Hint = 0); + MacroInfo *getMacro(serialization::MacroID ID); /// \brief Retrieve the global macro ID corresponding to the given local /// ID within the given module file. @@ -1530,6 +1651,10 @@ public: /// \brief Read the source location entry with index ID. virtual bool ReadSLocEntry(int ID); + /// \brief Retrieve the module import location and module name for the + /// given source manager entry ID. + virtual std::pair<SourceLocation, StringRef> getModuleImportLoc(int ID); + /// \brief Retrieve the global submodule ID given a module and its local ID /// number. serialization::SubmoduleID @@ -1538,7 +1663,12 @@ public: /// \brief Retrieve the submodule that corresponds to a global submodule ID. /// Module *getSubmodule(serialization::SubmoduleID GlobalID); - + + /// \brief Retrieve the module that corresponds to the given module ID. + /// + /// Note: overrides method in ExternalASTSource + virtual Module *getModule(unsigned ID); + /// \brief Retrieve a selector from the given module with its local ID /// number. Selector getLocalSelector(ModuleFile &M, unsigned LocalID); @@ -1597,7 +1727,7 @@ public: unsigned &Idx); /// \brief Read a UnresolvedSet structure. - void ReadUnresolvedSet(ModuleFile &F, UnresolvedSetImpl &Set, + void ReadUnresolvedSet(ModuleFile &F, ASTUnresolvedSet &Set, const RecordData &Record, unsigned &Idx); /// \brief Read a C++ base specifier. @@ -1620,13 +1750,13 @@ public: /// \brief Read a source location. SourceLocation ReadSourceLocation(ModuleFile &ModuleFile, - const RecordData &Record, unsigned& Idx) { + const RecordData &Record, unsigned &Idx) { return ReadSourceLocation(ModuleFile, Record[Idx++]); } /// \brief Read a source range. SourceRange ReadSourceRange(ModuleFile &F, - const RecordData &Record, unsigned& Idx); + const RecordData &Record, unsigned &Idx); /// \brief Read an integral value llvm::APInt ReadAPInt(const RecordData &Record, unsigned &Idx); @@ -1635,7 +1765,8 @@ public: llvm::APSInt ReadAPSInt(const RecordData &Record, unsigned &Idx); /// \brief Read a floating-point value - llvm::APFloat ReadAPFloat(const RecordData &Record, unsigned &Idx); + llvm::APFloat ReadAPFloat(const RecordData &Record, + const llvm::fltSemantics &Sem, unsigned &Idx); // \brief Read a string static std::string ReadString(const RecordData &Record, unsigned &Idx); @@ -1670,20 +1801,32 @@ public: Expr *ReadSubExpr(); /// \brief Reads the macro record located at the given offset. - void ReadMacroRecord(ModuleFile &F, uint64_t Offset, MacroInfo *Hint = 0); + MacroInfo *ReadMacroRecord(ModuleFile &F, uint64_t Offset); /// \brief Determine the global preprocessed entity ID that corresponds to /// the given local ID within the given module. serialization::PreprocessedEntityID getGlobalPreprocessedEntityID(ModuleFile &M, unsigned LocalID) const; - /// \brief Note that the identifier has a macro history. + /// \brief Add a macro to resolve imported from a module. /// /// \param II The name of the macro. + /// \param M The module file. + /// \param GMacID The global macro ID that is associated with this identifier. + /// \param ImportLoc The location where the module is imported. + void addPendingMacroFromModule(IdentifierInfo *II, + ModuleFile *M, + serialization::GlobalMacroID GMacID, + SourceLocation ImportLoc); + + /// \brief Add a macro to deserialize its macro directive history from a PCH. /// - /// \param IDs The global macro IDs that are associated with this identifier. - void setIdentifierIsMacro(IdentifierInfo *II, - ArrayRef<serialization::MacroID> IDs); + /// \param II The name of the macro. + /// \param M The module file. + /// \param MacroDirectivesOffset Offset of the serialized macro directive + /// history. + void addPendingMacroFromPCH(IdentifierInfo *II, + ModuleFile *M, uint64_t MacroDirectivesOffset); /// \brief Read the set of macros defined by this external macro source. virtual void ReadDefinedMacros(); @@ -1734,7 +1877,7 @@ public: /// then restores it when destroyed. struct SavedStreamPosition { explicit SavedStreamPosition(llvm::BitstreamCursor &Cursor) - : Cursor(Cursor), Offset(Cursor.GetCurrentBitNo()) { } + : Cursor(Cursor), Offset(Cursor.GetCurrentBitNo()) { } ~SavedStreamPosition() { Cursor.JumpToBit(Offset); diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h index ac81e21..2938dc7 100644 --- a/include/clang/Serialization/ASTWriter.h +++ b/include/clang/Serialization/ASTWriter.h @@ -14,20 +14,19 @@ #ifndef LLVM_CLANG_FRONTEND_AST_WRITER_H #define LLVM_CLANG_FRONTEND_AST_WRITER_H +#include "clang/AST/ASTMutationListener.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/TemplateBase.h" -#include "clang/AST/ASTMutationListener.h" -#include "clang/Lex/PPMutationListener.h" +#include "clang/Sema/SemaConsumer.h" #include "clang/Serialization/ASTBitCodes.h" #include "clang/Serialization/ASTDeserializationListener.h" -#include "clang/Sema/SemaConsumer.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/Bitcode/BitstreamWriter.h" #include <map> #include <queue> @@ -48,12 +47,14 @@ class CXXCtorInitializer; class FileEntry; class FPOptions; class HeaderSearch; +class HeaderSearchOptions; class IdentifierResolver; class MacroDefinition; +class MacroDirective; +class MacroInfo; class OpaqueValueExpr; class OpenCLOptions; class ASTReader; -class MacroInfo; class Module; class PreprocessedEntity; class PreprocessingRecord; @@ -63,6 +64,7 @@ class SourceManager; class SwitchCase; class TargetInfo; class VersionTuple; +class ASTUnresolvedSet; namespace SrcMgr { class SLocEntry; } @@ -73,7 +75,6 @@ namespace SrcMgr { class SLocEntry; } /// data structures. This bitstream can be de-serialized via an /// instance of the ASTReader class. class ASTWriter : public ASTDeserializationListener, - public PPMutationListener, public ASTMutationListener { public: typedef SmallVector<uint64_t, 64> RecordData; @@ -231,6 +232,16 @@ private: /// \brief Map that provides the ID numbers of each macro. llvm::DenseMap<MacroInfo *, serialization::MacroID> MacroIDs; + struct MacroInfoToEmitData { + const IdentifierInfo *Name; + MacroInfo *MI; + serialization::MacroID ID; + }; + /// \brief The macro infos to emit. + std::vector<MacroInfoToEmitData> MacroInfosToEmit; + + llvm::DenseMap<const IdentifierInfo *, uint64_t> IdentMacroDirectivesOffsetMap; + /// @name FlushStmt Caches /// @{ @@ -266,11 +277,6 @@ private: /// table, indexed by the Selector ID (-1). std::vector<uint32_t> SelectorOffsets; - typedef llvm::MapVector<MacroInfo *, MacroUpdate> MacroUpdatesMap; - - /// \brief Updates to macro definitions that were loaded from an AST file. - MacroUpdatesMap MacroUpdates; - /// \brief Mapping from macro definitions (as they occur in the preprocessing /// record) to the macro IDs. llvm::DenseMap<const MacroDefinition *, serialization::PreprocessedEntityID> @@ -343,7 +349,7 @@ private: /// \brief The set of declarations that may have redeclaration chains that /// need to be serialized. - llvm::SetVector<Decl *, llvm::SmallVector<Decl *, 4>, + llvm::SetVector<Decl *, SmallVector<Decl *, 4>, llvm::SmallPtrSet<Decl *, 4> > Redeclarations; /// \brief Statements that we've encountered while serializing a @@ -415,7 +421,9 @@ private: void WriteBlockInfoBlock(); void WriteControlBlock(Preprocessor &PP, ASTContext &Context, StringRef isysroot, const std::string &OutputFile); - void WriteInputFiles(SourceManager &SourceMgr, StringRef isysroot); + void WriteInputFiles(SourceManager &SourceMgr, + HeaderSearchOptions &HSOpts, + StringRef isysroot); void WriteSourceManagerBlock(SourceManager &SourceMgr, const Preprocessor &PP, StringRef isysroot); @@ -424,7 +432,8 @@ private: void WritePreprocessorDetail(PreprocessingRecord &PPRec); void WriteSubmodules(Module *WritingModule); - void WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag); + void WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag, + bool isModule); void WriteCXXBaseSpecifiersOffsets(); void WriteType(QualType T); uint64_t WriteDeclContextLexicalBlock(ASTContext &Context, DeclContext *DC); @@ -437,7 +446,6 @@ private: void WriteIdentifierTable(Preprocessor &PP, IdentifierResolver &IdResolver, bool IsModule); void WriteAttributes(ArrayRef<const Attr*> Attrs, RecordDataImpl &Record); - void WriteMacroUpdates(); void ResolveDeclUpdatesBlocks(); void WriteDeclUpdatesBlocks(); void WriteDeclReplacementsBlock(); @@ -508,9 +516,6 @@ public: /// \brief Emit a reference to an identifier. void AddIdentifierRef(const IdentifierInfo *II, RecordDataImpl &Record); - /// \brief Emit a reference to a macro. - void addMacroRef(MacroInfo *MI, RecordDataImpl &Record); - /// \brief Emit a Selector (which is a smart pointer reference). void AddSelectorRef(Selector, RecordDataImpl &Record); @@ -529,7 +534,12 @@ public: serialization::IdentID getIdentifierRef(const IdentifierInfo *II); /// \brief Get the unique number used to refer to the given macro. - serialization::MacroID getMacroRef(MacroInfo *MI); + serialization::MacroID getMacroRef(MacroInfo *MI, const IdentifierInfo *Name); + + /// \brief Determine the ID of an already-emitted macro. + serialization::MacroID getMacroID(MacroInfo *MI); + + uint64_t getMacroDirectivesOffset(const IdentifierInfo *Name); /// \brief Emit a reference to a type. void AddTypeRef(QualType T, RecordDataImpl &Record); @@ -603,7 +613,7 @@ public: RecordDataImpl &Record); /// \brief Emit a UnresolvedSet structure. - void AddUnresolvedSet(const UnresolvedSetImpl &Set, RecordDataImpl &Record); + void AddUnresolvedSet(const ASTUnresolvedSet &Set, RecordDataImpl &Record); /// \brief Emit a C++ base specifier. void AddCXXBaseSpecifier(const CXXBaseSpecifier &Base, @@ -640,6 +650,10 @@ public: /// 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 Note that the identifier II occurs at the given offset /// within the identifier table. void SetIdentifierOffset(const IdentifierInfo *II, uint32_t Offset); @@ -699,9 +713,6 @@ public: MacroDefinition *MD); void ModuleRead(serialization::SubmoduleID ID, Module *Mod); - // PPMutationListener implementation. - virtual void UndefinedMacro(MacroInfo *MI); - // ASTMutationListener implementation. virtual void CompletedTagDefinition(const TagDecl *D); virtual void AddedVisibleDecl(const DeclContext *DC, const Decl *D); @@ -728,7 +739,7 @@ class PCHGenerator : public SemaConsumer { std::string isysroot; raw_ostream *Out; Sema *SemaPtr; - llvm::SmallVector<char, 128> Buffer; + SmallVector<char, 128> Buffer; llvm::BitstreamWriter Stream; ASTWriter Writer; @@ -743,7 +754,6 @@ public: ~PCHGenerator(); virtual void InitializeSema(Sema &S) { SemaPtr = &S; } virtual void HandleTranslationUnit(ASTContext &Ctx); - virtual PPMutationListener *GetPPMutationListener(); virtual ASTMutationListener *GetASTMutationListener(); virtual ASTDeserializationListener *GetASTDeserializationListener(); }; diff --git a/include/clang/Serialization/ContinuousRangeMap.h b/include/clang/Serialization/ContinuousRangeMap.h index d89cd02..f8ef8a1 100644 --- a/include/clang/Serialization/ContinuousRangeMap.h +++ b/include/clang/Serialization/ContinuousRangeMap.h @@ -15,6 +15,7 @@ #ifndef LLVM_CLANG_SERIALIZATION_CONTINUOUS_RANGE_MAP_H #define LLVM_CLANG_SERIALIZATION_CONTINUOUS_RANGE_MAP_H +#include "clang/Basic/LLVM.h" #include "llvm/ADT/SmallVector.h" #include <algorithm> #include <utility> diff --git a/include/clang/Serialization/GlobalModuleIndex.h b/include/clang/Serialization/GlobalModuleIndex.h new file mode 100644 index 0000000..eaf26d1 --- /dev/null +++ b/include/clang/Serialization/GlobalModuleIndex.h @@ -0,0 +1,194 @@ +//===--- GlobalModuleIndex.h - Global Module Index --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the GlobalModuleIndex class, which manages a global index +// containing all of the identifiers known to the various modules within a given +// subdirectory of the module cache. It is used to improve the performance of +// queries such as "do any modules know about this identifier?" +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_SERIALIZATION_GLOBAL_MODULE_INDEX_H +#define LLVM_CLANG_SERIALIZATION_GLOBAL_MODULE_INDEX_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include <utility> + +namespace llvm { +class BitstreamCursor; +class MemoryBuffer; +} + +namespace clang { + +class DirectoryEntry; +class FileEntry; +class FileManager; + +namespace serialization { + class ModuleFile; +} + +using llvm::SmallVector; +using llvm::SmallVectorImpl; +using llvm::StringRef; +using serialization::ModuleFile; + +/// \brief A global index for a set of module files, providing information about +/// the identifiers within those module files. +/// +/// The global index is an aid for name lookup into modules, offering a central +/// place where one can look for identifiers determine which +/// module files contain any information about that identifier. This +/// allows the client to restrict the search to only those module files known +/// to have a information about that identifier, improving performance. Moreover, +/// the global module index may know about module files that have not been +/// imported, and can be queried to determine which modules the current +/// translation could or should load to fix a problem. +class GlobalModuleIndex { + /// \brief Buffer containing the index file, which is lazily accessed so long + /// as the global module index is live. + llvm::OwningPtr<llvm::MemoryBuffer> Buffer; + + /// \brief The hash table. + /// + /// This pointer actually points to a IdentifierIndexTable object, + /// but that type is only accessible within the implementation of + /// GlobalModuleIndex. + void *IdentifierIndex; + + /// \brief Information about a given module file. + struct ModuleInfo { + ModuleInfo() : File(), Size(), ModTime() { } + + /// \brief The module file, once it has been resolved. + ModuleFile *File; + + /// \brief The module file name. + std::string FileName; + + /// \brief Size of the module file at the time the global index was built. + off_t Size; + + /// \brief Modification time of the module file at the time the global + /// index was built. + time_t ModTime; + + /// \brief The module IDs on which this module directly depends. + /// FIXME: We don't really need a vector here. + llvm::SmallVector<unsigned, 4> Dependencies; + }; + + /// \brief A mapping from module IDs to information about each module. + /// + /// This vector may have gaps, if module files have been removed or have + /// been updated since the index was built. A gap is indicated by an empty + /// file name. + llvm::SmallVector<ModuleInfo, 16> Modules; + + /// \brief Lazily-populated mapping from module files to their + /// corresponding index into the \c Modules vector. + llvm::DenseMap<ModuleFile *, unsigned> ModulesByFile; + + /// \brief The set of modules that have not yet been resolved. + /// + /// The string is just the name of the module itself, which maps to the + /// module ID. + llvm::StringMap<unsigned> UnresolvedModules; + + /// \brief The number of identifier lookups we performed. + unsigned NumIdentifierLookups; + + /// \brief The number of identifier lookup hits, where we recognize the + /// identifier. + unsigned NumIdentifierLookupHits; + + /// \brief Internal constructor. Use \c readIndex() to read an index. + explicit GlobalModuleIndex(llvm::MemoryBuffer *Buffer, + llvm::BitstreamCursor Cursor); + + GlobalModuleIndex(const GlobalModuleIndex &) LLVM_DELETED_FUNCTION; + GlobalModuleIndex &operator=(const GlobalModuleIndex &) LLVM_DELETED_FUNCTION; + +public: + ~GlobalModuleIndex(); + + /// \brief An error code returned when trying to read an index. + enum ErrorCode { + /// \brief No error occurred. + EC_None, + /// \brief No index was found. + EC_NotFound, + /// \brief Some other process is currently building the index; it is not + /// available yet. + EC_Building, + /// \brief There was an unspecified I/O error reading or writing the index. + EC_IOError + }; + + /// \brief Read a global index file for the given directory. + /// + /// \param Path The path to the specific module cache where the module files + /// for the intended configuration reside. + /// + /// \returns A pair containing the global module index (if it exists) and + /// the error code. + static std::pair<GlobalModuleIndex *, ErrorCode> + readIndex(StringRef Path); + + /// \brief Retrieve the set of modules that have up-to-date indexes. + /// + /// \param ModuleFiles Will be populated with the set of module files that + /// have been indexed. + void getKnownModules(SmallVectorImpl<ModuleFile *> &ModuleFiles); + + /// \brief Retrieve the set of module files on which the given module file + /// directly depends. + void getModuleDependencies(ModuleFile *File, + SmallVectorImpl<ModuleFile *> &Dependencies); + + /// \brief A set of module files in which we found a result. + typedef llvm::SmallPtrSet<ModuleFile *, 4> HitSet; + + /// \brief Look for all of the module files with information about the given + /// identifier, e.g., a global function, variable, or type with that name. + /// + /// \param Name The identifier to look for. + /// + /// \param Hits Will be populated with the set of module files that have + /// information about this name. + /// + /// \returns true if the identifier is known to the index, false otherwise. + bool lookupIdentifier(StringRef Name, HitSet &Hits); + + /// \brief Note that the given module file has been loaded. + /// + /// \returns false if the global module index has information about this + /// module file, and true otherwise. + bool loadedModuleFile(ModuleFile *File); + + /// \brief Print statistics to standard error. + void printStats(); + + /// \brief Write a global index into the given + /// + /// \param FileMgr The file manager to use to load module files. + /// + /// \param Path The path to the directory containing module files, into + /// which the global index will be written. + static ErrorCode writeIndex(FileManager &FileMgr, StringRef Path); +}; + +} + +#endif diff --git a/include/clang/Serialization/Module.h b/include/clang/Serialization/Module.h index 39fa3d9..89c604f 100644 --- a/include/clang/Serialization/Module.h +++ b/include/clang/Serialization/Module.h @@ -15,9 +15,9 @@ #ifndef LLVM_CLANG_SERIALIZATION_MODULE_H #define LLVM_CLANG_SERIALIZATION_MODULE_H +#include "clang/Basic/SourceLocation.h" #include "clang/Serialization/ASTBitCodes.h" #include "clang/Serialization/ContinuousRangeMap.h" -#include "clang/Basic/SourceLocation.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SetVector.h" #include "llvm/Bitcode/BitstreamReader.h" @@ -55,6 +55,35 @@ struct DeclContextInfo { 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. +class InputFile { + enum { + Overridden = 1, + OutOfDate = 2 + }; + llvm::PointerIntPair<const FileEntry *, 2, unsigned> Val; + +public: + InputFile() {} + InputFile(const FileEntry *File, + bool isOverridden = false, bool isOutOfDate = false) { + assert(!(isOverridden && isOutOfDate) && + "an overridden cannot be out-of-date"); + unsigned intVal = 0; + if (isOverridden) + intVal = Overridden; + else if (isOutOfDate) + intVal = OutOfDate; + Val.setPointerAndInt(File, intVal); + } + + const FileEntry *getFile() const { return Val.getPointer(); } + bool isOverridden() const { return Val.getInt() == Overridden; } + bool isOutOfDate() const { return Val.getInt() == OutOfDate; } +}; + /// \brief Information about a module that has been loaded by the ASTReader. /// /// Each instance of the Module class corresponds to a single AST file, which @@ -69,6 +98,9 @@ public: // === General information === + /// \brief The index of this module in the list of modules. + unsigned Index; + /// \brief The type of this module. ModuleKind Kind; @@ -121,8 +153,15 @@ public: /// \brief The main bitstream cursor for the main block. llvm::BitstreamCursor Stream; + /// \brief The source location where the module was explicitly or implicitly + /// imported in the local translation unit. + /// + /// If module A depends on and imports module B, both modules will have the + /// same DirectImportLoc, but different ImportLoc (B's ImportLoc will be a + /// source location inside module A). + SourceLocation DirectImportLoc; + /// \brief The source location where this module was first imported. - /// FIXME: This is not properly initialized yet. SourceLocation ImportLoc; /// \brief The first source location in this module. @@ -135,10 +174,8 @@ public: /// \brief Offsets for all of the input file entries in the AST file. const uint32_t *InputFileOffsets; - /// \brief The input files that have been loaded from this AST file, along - /// with a bool indicating whether this was an overridden buffer. - std::vector<llvm::PointerIntPair<const FileEntry *, 1, bool> > - InputFilesLoaded; + /// \brief The input files that have been loaded from this AST file. + std::vector<InputFile> InputFilesLoaded; // === Source Locations === @@ -252,10 +289,6 @@ public: /// the header files. void *HeaderFileInfoTable; - /// \brief Actual data for the list of framework names used in the header - /// search information. - const char *HeaderFileFrameworkStrings; - // === Submodule information === /// \brief The number of submodules in this module. unsigned LocalNumSubmodules; diff --git a/include/clang/Serialization/ModuleManager.h b/include/clang/Serialization/ModuleManager.h index 6dcaa21..b2c4063 100644 --- a/include/clang/Serialization/ModuleManager.h +++ b/include/clang/Serialization/ModuleManager.h @@ -15,19 +15,22 @@ #ifndef LLVM_CLANG_SERIALIZATION_MODULE_MANAGER_H #define LLVM_CLANG_SERIALIZATION_MODULE_MANAGER_H -#include "clang/Serialization/Module.h" #include "clang/Basic/FileManager.h" +#include "clang/Serialization/Module.h" #include "llvm/ADT/DenseMap.h" namespace clang { +class GlobalModuleIndex; +class ModuleMap; + 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. - llvm::SmallVector<ModuleFile*, 2> Chain; + SmallVector<ModuleFile *, 2> Chain; /// \brief All loaded modules, indexed by name. llvm::DenseMap<const FileEntry *, ModuleFile *> Modules; @@ -38,7 +41,60 @@ class ModuleManager { /// \brief A lookup of in-memory (virtual file) buffers llvm::DenseMap<const FileEntry *, llvm::MemoryBuffer *> InMemoryBuffers; - + + /// \brief The visitation order. + SmallVector<ModuleFile *, 4> VisitOrder; + + /// \brief The list of module files that both we and the global module index + /// know about. + /// + /// Either the global index or the module manager may have modules that the + /// other does not know about, because the global index can be out-of-date + /// (in which case the module manager could have modules it does not) and + /// this particular translation unit might not have loaded all of the modules + /// known to the global index. + SmallVector<ModuleFile *, 4> ModulesInCommonWithGlobalIndex; + + /// \brief The global module index, if one is attached. + /// + /// The global module index will actually be owned by the ASTReader; this is + /// just an non-owning pointer. + GlobalModuleIndex *GlobalIndex; + + /// \brief State used by the "visit" operation to avoid malloc traffic in + /// calls to visit(). + struct VisitState { + explicit VisitState(unsigned N) + : VisitNumber(N, 0), NextVisitNumber(1), NextState(0) + { + Stack.reserve(N); + } + + ~VisitState() { + delete NextState; + } + + /// \brief The stack used when marking the imports of a particular module + /// as not-to-be-visited. + SmallVector<ModuleFile *, 4> Stack; + + /// \brief The visit number of each module file, which indicates when + /// this module file was last visited. + SmallVector<unsigned, 4> VisitNumber; + + /// \brief The next visit number to use to mark visited module files. + unsigned NextVisitNumber; + + /// \brief The next visit state. + VisitState *NextState; + }; + + /// \brief The first visit() state in the chain. + VisitState *FirstVisitState; + + VisitState *allocateVisitState(); + void returnVisitState(VisitState *State); + public: typedef SmallVector<ModuleFile*, 2>::iterator ModuleIterator; typedef SmallVector<ModuleFile*, 2>::const_iterator ModuleConstIterator; @@ -79,12 +135,28 @@ public: /// \brief Returns the module associated with the given name ModuleFile *lookup(StringRef Name); - + + /// \brief Returns the module associated with the given module file. + ModuleFile *lookup(const FileEntry *File); + /// \brief Returns the in-memory (virtual file) buffer with the given name llvm::MemoryBuffer *lookupBuffer(StringRef Name); /// \brief Number of modules loaded unsigned size() const { return Chain.size(); } + + /// \brief The result of attempting to add a new module. + enum AddModuleResult { + /// \brief The module file had already been loaded. + AlreadyLoaded, + /// \brief The module file was just loaded in response to this call. + NewlyLoaded, + /// \brief The module file is missing. + Missing, + /// \brief The module file is out-of-date. + OutOfDate + }; + /// \brief Attempts to create a new module and add it to the list of known /// modules. /// @@ -92,26 +164,48 @@ public: /// /// \param Type The kind of module being loaded. /// + /// \param ImportLoc The location at which the module is imported. + /// /// \param ImportedBy The module that is importing this module, or NULL if /// this module is imported directly by the user. /// /// \param Generation The generation in which this module was loaded. /// + /// \param ExpectedSize The expected size of the module file, used for + /// validation. This will be zero if unknown. + /// + /// \param ExpectedModTime The expected modification time of the module + /// file, used for validation. This will be zero if unknown. + /// + /// \param Module A pointer to the module file if the module was successfully + /// loaded. + /// /// \param ErrorStr Will be set to a non-empty string if any errors occurred /// while trying to load the module. /// /// \return A pointer to the module that corresponds to this file name, - /// and a boolean indicating whether the module was newly added. - std::pair<ModuleFile *, bool> - addModule(StringRef FileName, ModuleKind Type, ModuleFile *ImportedBy, - unsigned Generation, std::string &ErrorStr); + /// and a value indicating whether the module was loaded. + AddModuleResult addModule(StringRef FileName, ModuleKind Type, + SourceLocation ImportLoc, + ModuleFile *ImportedBy, unsigned Generation, + off_t ExpectedSize, time_t ExpectedModTime, + ModuleFile *&Module, + std::string &ErrorStr); /// \brief Remove the given set of modules. - void removeModules(ModuleIterator first, ModuleIterator last); + void removeModules(ModuleIterator first, ModuleIterator last, + ModuleMap *modMap); /// \brief Add an in-memory buffer the list of known buffers void addInMemoryBuffer(StringRef FileName, llvm::MemoryBuffer *Buffer); - + + /// \brief Set the global module index. + void setGlobalIndex(GlobalModuleIndex *Index); + + /// \brief Notification from the AST reader that the given module file + /// has been "accepted", and will not (can not) be unloaded. + void moduleFileAccepted(ModuleFile *MF); + /// \brief Visit each of the modules. /// /// This routine visits each of the modules, starting with the @@ -130,7 +224,13 @@ public: /// /// \param UserData User data associated with the visitor object, which /// will be passed along to the visitor. - void visit(bool (*Visitor)(ModuleFile &M, void *UserData), void *UserData); + /// + /// \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, + llvm::SmallPtrSet<ModuleFile *, 4> *ModuleFilesHit = 0); /// \brief Visit each of the modules with a depth-first traversal. /// @@ -151,7 +251,29 @@ public: void visitDepthFirst(bool (*Visitor)(ModuleFile &M, bool Preorder, 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. + /// + /// \param ExpectedSize The size that the module file is expected to have. + /// If the actual size differs, the resolver should return \c true. + /// + /// \param ExpectedModTime The modification time that the module file is + /// expected to have. If the actual modification time differs, the resolver + /// should return \c true. + /// + /// \param File Will be set to the file if there is one, or null + /// otherwise. + /// + /// \returns True if a file exists but does not meet the size/ + /// modification time criteria, false if the file is either available and + /// suitable, or is missing. + bool lookupModuleFile(StringRef FileName, + off_t ExpectedSize, + time_t ExpectedModTime, + const FileEntry *&File); + /// \brief View the graphviz representation of the module graph. void viewGraph(); }; |