diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h index 266e0826b38f4..f7a0d1064110a 100644 --- a/clang/include/clang/Frontend/CompilerInstance.h +++ b/clang/include/clang/Frontend/CompilerInstance.h @@ -746,11 +746,6 @@ class CompilerInstance : public ModuleLoader { GetDependencyDirectives = std::move(Getter); } - std::string getSpecificModuleCachePath(StringRef ContextHash); - std::string getSpecificModuleCachePath() { - return getSpecificModuleCachePath(getInvocation().computeContextHash()); - } - /// Create the AST context. void createASTContext(); diff --git a/clang/include/clang/Lex/HeaderSearch.h b/clang/include/clang/Lex/HeaderSearch.h index d7000da682c6e..6ca607f83966d 100644 --- a/clang/include/clang/Lex/HeaderSearch.h +++ b/clang/include/clang/Lex/HeaderSearch.h @@ -282,6 +282,10 @@ class HeaderSearch { /// The specific module cache path containing ContextHash (unless suppressed). std::string SpecificModuleCachePath; + /// The length of the normalized module cache path at the start of \c + /// SpecificModuleCachePath. + size_t NormalizedModuleCachePathLen = 0; + /// All of the preprocessor-specific data about files that are /// included, indexed by the FileEntry's UID. mutable std::vector FileInfo; @@ -467,20 +471,23 @@ class HeaderSearch { return {}; } - /// Set the context hash to use for module cache paths. - void setContextHash(StringRef Hash) { ContextHash = std::string(Hash); } + /// Initialize the module cache path. + void initializeModuleCachePath(std::string ContextHash); - /// Set the module cache path with the context hash (unless suppressed). - void setSpecificModuleCachePath(StringRef Path) { - SpecificModuleCachePath = std::string(Path); + /// Retrieve the specific module cache path. This is the normalized module + /// cache path plus the context hash (unless suppressed). + StringRef getSpecificModuleCachePath() const { + return SpecificModuleCachePath; } /// Retrieve the context hash. StringRef getContextHash() const { return ContextHash; } - /// Retrieve the module cache path with the context hash (unless suppressed). - StringRef getSpecificModuleCachePath() const { - return SpecificModuleCachePath; + /// Retrieve the normalized module cache path. This is the path as provided on + /// the command line, but absolute, without './' components, and with + /// preferred path separators. Note that this does not have the context hash. + StringRef getNormalizedModuleCachePath() const { + return getSpecificModuleCachePath().substr(0, NormalizedModuleCachePathLen); } /// Forget everything we know about headers so far. @@ -1042,6 +1049,11 @@ void ApplyHeaderSearchOptions(HeaderSearch &HS, void normalizeModuleCachePath(FileManager &FileMgr, StringRef Path, SmallVectorImpl &NormalizedPath); +std::string createSpecificModuleCachePath(FileManager &FileMgr, + StringRef ModuleCachePath, + bool DisableModuleHash, + std::string ContextHash); + } // namespace clang #endif // LLVM_CLANG_LEX_HEADERSEARCH_H diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 752e7fd288aa6..5db0b08f877ce 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -44,7 +44,7 @@ namespace serialization { /// 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 = 35; +const unsigned VERSION_MAJOR = 36; /// AST file minor version number supported by this version of /// Clang. diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index f254459ce933d..14f7d8a69a1b3 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -185,8 +185,7 @@ class ASTReaderListener { /// otherwise. virtual bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts, StringRef ModuleFilename, - StringRef SpecificModuleCachePath, - bool Complain) { + StringRef ContextHash, bool Complain) { return false; } @@ -304,8 +303,7 @@ class ChainedASTReaderListener : public ASTReaderListener { bool Complain) override; bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts, - StringRef ModuleFilename, - StringRef SpecificModuleCachePath, + StringRef ModuleFilename, StringRef ContextHash, bool Complain) override; bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, StringRef ModuleFilename, bool ReadMacros, @@ -349,8 +347,7 @@ class PCHValidator : public ASTReaderListener { bool Complain, std::string &SuggestedPredefines) override; bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts, - StringRef ModuleFilename, - StringRef SpecificModuleCachePath, + StringRef ModuleFilename, StringRef ContextHash, bool Complain) override; void ReadCounter(const serialization::ModuleFile &M, uint32_t Value) override; }; diff --git a/clang/lib/DependencyScanning/DependencyScannerImpl.cpp b/clang/lib/DependencyScanning/DependencyScannerImpl.cpp index 0e345af8817ae..a38ee690d42de 100644 --- a/clang/lib/DependencyScanning/DependencyScannerImpl.cpp +++ b/clang/lib/DependencyScanning/DependencyScannerImpl.cpp @@ -150,8 +150,7 @@ class PrebuiltModuleListener : public ASTReaderListener { /// Check the header search options for a given module when considering /// if the module comes from stable directories. bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts, - StringRef ModuleFilename, - StringRef SpecificModuleCachePath, + StringRef ModuleFilename, StringRef ContextHash, bool Complain) override { auto PrebuiltMapEntry = PrebuiltModulesASTMap.try_emplace(CurrentFile); diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp index 9fcaf1806fcb1..1d249ebaa1492 100644 --- a/clang/lib/Frontend/ASTUnit.cpp +++ b/clang/lib/Frontend/ASTUnit.cpp @@ -505,7 +505,7 @@ namespace { /// a Preprocessor. class ASTInfoCollector : public ASTReaderListener { HeaderSearchOptions &HSOpts; - std::string &SpecificModuleCachePath; + std::string &ContextHash; PreprocessorOptions &PPOpts; LangOptions &LangOpts; CodeGenOptions &CodeGenOpts; @@ -513,14 +513,13 @@ class ASTInfoCollector : public ASTReaderListener { uint32_t &Counter; public: - ASTInfoCollector(HeaderSearchOptions &HSOpts, - std::string &SpecificModuleCachePath, + ASTInfoCollector(HeaderSearchOptions &HSOpts, std::string &ContextHash, PreprocessorOptions &PPOpts, LangOptions &LangOpts, CodeGenOptions &CodeGenOpts, TargetOptions &TargetOpts, uint32_t &Counter) - : HSOpts(HSOpts), SpecificModuleCachePath(SpecificModuleCachePath), - PPOpts(PPOpts), LangOpts(LangOpts), CodeGenOpts(CodeGenOpts), - TargetOpts(TargetOpts), Counter(Counter) {} + : HSOpts(HSOpts), ContextHash(ContextHash), PPOpts(PPOpts), + LangOpts(LangOpts), CodeGenOpts(CodeGenOpts), TargetOpts(TargetOpts), + Counter(Counter) {} bool ReadLanguageOptions(const LangOptions &NewLangOpts, StringRef ModuleFilename, bool Complain, @@ -538,10 +537,10 @@ class ASTInfoCollector : public ASTReaderListener { bool ReadHeaderSearchOptions(const HeaderSearchOptions &NewHSOpts, StringRef ModuleFilename, - StringRef NewSpecificModuleCachePath, + StringRef NewContextHash, bool Complain) override { HSOpts = NewHSOpts; - SpecificModuleCachePath = NewSpecificModuleCachePath; + ContextHash = NewContextHash; return false; } @@ -733,13 +732,13 @@ std::unique_ptr ASTUnit::LoadFromASTFile( AST->ModCache = createCrossProcessModuleCache(); // Gather info for preprocessor construction later on. - std::string SpecificModuleCachePath; + std::string ContextHash; unsigned Counter = 0; // Using a temporary FileManager since the AST file might specify custom // HeaderSearchOptions::VFSOverlayFiles that affect the underlying VFS. FileManager TmpFileMgr(FileSystemOpts, VFS); - ASTInfoCollector Collector(*AST->HSOpts, SpecificModuleCachePath, - *AST->PPOpts, *AST->LangOpts, *AST->CodeGenOpts, + ASTInfoCollector Collector(*AST->HSOpts, ContextHash, *AST->PPOpts, + *AST->LangOpts, *AST->CodeGenOpts, *AST->TargetOpts, Counter); if (ASTReader::readASTFileControlBlock( Filename, TmpFileMgr, *AST->ModCache, PCHContainerRdr, @@ -763,7 +762,7 @@ std::unique_ptr ASTUnit::LoadFromASTFile( AST->getHeaderSearchOpts(), AST->getSourceManager(), AST->getDiagnostics(), AST->getLangOpts(), /*Target=*/nullptr); - AST->HeaderInfo->setSpecificModuleCachePath(SpecificModuleCachePath); + AST->HeaderInfo->initializeModuleCachePath(std::move(ContextHash)); AST->PP = std::make_shared( *AST->PPOpts, AST->getDiagnostics(), *AST->LangOpts, diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index 60914d9b2cbc7..3330bc55f3f25 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -487,10 +487,11 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) { PP->setPreprocessedOutput(getPreprocessorOutputOpts().ShowCPP); if (PP->getLangOpts().Modules && PP->getLangOpts().ImplicitModules) { - std::string ContextHash = getInvocation().computeContextHash(); - PP->getHeaderSearchInfo().setContextHash(ContextHash); - PP->getHeaderSearchInfo().setSpecificModuleCachePath( - getSpecificModuleCachePath(ContextHash)); + // FIXME: We already might've computed the context hash and the specific + // module cache path in `FrontendAction::BeginSourceFile()` when turning + // "-include-pch " into "-include-pch /". Reuse those here. + PP->getHeaderSearchInfo().initializeModuleCachePath( + getInvocation().computeContextHash()); } // Handle generating dependencies, if requested. @@ -546,19 +547,6 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) { PP->setDependencyDirectivesGetter(*GetDependencyDirectives); } -std::string -CompilerInstance::getSpecificModuleCachePath(StringRef ContextHash) { - assert(FileMgr && "Specific module cache path requires a FileManager"); - - // Set up the module path, including the hash for the module-creation options. - SmallString<256> SpecificModuleCache; - normalizeModuleCachePath(*FileMgr, getHeaderSearchOpts().ModuleCachePath, - SpecificModuleCache); - if (!SpecificModuleCache.empty() && !getHeaderSearchOpts().DisableModuleHash) - llvm::sys::path::append(SpecificModuleCache, ContextHash); - return std::string(SpecificModuleCache); -} - // ASTContext void CompilerInstance::createASTContext() { diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp index 73f092521546f..84ceb22208801 100644 --- a/clang/lib/Frontend/FrontendAction.cpp +++ b/clang/lib/Frontend/FrontendAction.cpp @@ -1040,7 +1040,10 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, llvm::sys::path::native(PCHDir->getName(), DirNative); bool Found = false; llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem(); - std::string SpecificModuleCachePath = CI.getSpecificModuleCachePath(); + std::string SpecificModuleCachePath = createSpecificModuleCachePath( + CI.getFileManager(), CI.getHeaderSearchOpts().ModuleCachePath, + CI.getHeaderSearchOpts().DisableModuleHash, + CI.getInvocation().computeContextHash()); for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd; Dir != DirEnd && !EC; Dir.increment(EC)) { diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp index 492f7b1742bee..7bcb4d7d89db1 100644 --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -623,9 +623,11 @@ namespace { /// file. class DumpModuleInfoListener : public ASTReaderListener { llvm::raw_ostream &Out; + FileManager &FileMgr; public: - DumpModuleInfoListener(llvm::raw_ostream &Out) : Out(Out) { } + DumpModuleInfoListener(llvm::raw_ostream &Out, FileManager &FileMgr) + : Out(Out), FileMgr(FileMgr) {} #define DUMP_BOOLEAN(Value, Text) \ Out.indent(4) << Text << ": " << (Value? "Yes" : "No") << "\n" @@ -716,8 +718,12 @@ namespace { bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts, StringRef ModuleFilename, - StringRef SpecificModuleCachePath, + StringRef ContextHash, bool Complain) override { + std::string SpecificModuleCachePath = createSpecificModuleCachePath( + FileMgr, HSOpts.ModuleCachePath, HSOpts.DisableModuleHash, + std::string(ContextHash)); + Out.indent(2) << "Header search options:\n"; Out.indent(4) << "System root [-isysroot=]: '" << HSOpts.Sysroot << "'\n"; Out.indent(4) << "Resource dir [ -resource-dir=]: '" << HSOpts.ResourceDir << "'\n"; @@ -905,7 +911,7 @@ void DumpModuleInfoAction::ExecuteAction() { Out << " Module format: " << (IsRaw ? "raw" : "obj") << "\n"; Preprocessor &PP = CI.getPreprocessor(); - DumpModuleInfoListener Listener(Out); + DumpModuleInfoListener Listener(Out, CI.getFileManager()); const HeaderSearchOptions &HSOpts = PP.getHeaderSearchInfo().getHeaderSearchOpts(); diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp index 5aee19cd14c51..de26b999683d1 100644 --- a/clang/lib/Lex/HeaderSearch.cpp +++ b/clang/lib/Lex/HeaderSearch.cpp @@ -2471,3 +2471,31 @@ void clang::normalizeModuleCachePath(FileManager &FileMgr, StringRef Path, llvm::sys::path::remove_dots(NormalizedPath); } } + +static std::string createSpecificModuleCachePathImpl( + FileManager &FileMgr, StringRef ModuleCachePath, bool DisableModuleHash, + std::string ContextHash, size_t &NormalizedModuleCachePathLen) { + SmallString<256> SpecificModuleCachePath; + normalizeModuleCachePath(FileMgr, ModuleCachePath, SpecificModuleCachePath); + NormalizedModuleCachePathLen = SpecificModuleCachePath.size(); + if (!SpecificModuleCachePath.empty() && !DisableModuleHash) + llvm::sys::path::append(SpecificModuleCachePath, ContextHash); + return std::string(SpecificModuleCachePath); +} + +void HeaderSearch::initializeModuleCachePath(std::string NewContextHash) { + ContextHash = std::move(NewContextHash); + SpecificModuleCachePath = createSpecificModuleCachePathImpl( + FileMgr, HSOpts.ModuleCachePath, HSOpts.DisableModuleHash, ContextHash, + NormalizedModuleCachePathLen); +} + +std::string clang::createSpecificModuleCachePath(FileManager &FileMgr, + StringRef ModuleCachePath, + bool DisableModuleHash, + std::string ContextHash) { + size_t NormalizedModuleCachePathLen; + return createSpecificModuleCachePathImpl( + FileMgr, ModuleCachePath, DisableModuleHash, std::move(ContextHash), + NormalizedModuleCachePathLen); +} diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index b82ae971bc84d..515eaf8d1caed 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -208,11 +208,11 @@ ChainedASTReaderListener::ReadFileSystemOptions(const FileSystemOptions &FSOpts, bool ChainedASTReaderListener::ReadHeaderSearchOptions( const HeaderSearchOptions &HSOpts, StringRef ModuleFilename, - StringRef SpecificModuleCachePath, bool Complain) { - return First->ReadHeaderSearchOptions(HSOpts, ModuleFilename, - SpecificModuleCachePath, Complain) || - Second->ReadHeaderSearchOptions(HSOpts, ModuleFilename, - SpecificModuleCachePath, Complain); + StringRef ContextHash, bool Complain) { + return First->ReadHeaderSearchOptions(HSOpts, ModuleFilename, ContextHash, + Complain) || + Second->ReadHeaderSearchOptions(HSOpts, ModuleFilename, ContextHash, + Complain); } bool ChainedASTReaderListener::ReadPreprocessorOptions( @@ -960,25 +960,31 @@ bool SimpleASTReaderListener::ReadPreprocessorOptions( /// /// \param Diags If non-null, produce diagnostics for any mismatches incurred. /// \returns true when the module cache paths differ. -static bool checkModuleCachePath( - llvm::vfs::FileSystem &VFS, StringRef SpecificModuleCachePath, - StringRef ExistingSpecificModuleCachePath, StringRef ASTFilename, - DiagnosticsEngine *Diags, const LangOptions &LangOpts, - const PreprocessorOptions &PPOpts, const HeaderSearchOptions &HSOpts, - const HeaderSearchOptions &ASTFileHSOpts) { +static bool checkModuleCachePath(FileManager &FileMgr, StringRef ContextHash, + StringRef ExistingSpecificModuleCachePath, + StringRef ASTFilename, + DiagnosticsEngine *Diags, + const LangOptions &LangOpts, + const PreprocessorOptions &PPOpts, + const HeaderSearchOptions &HSOpts, + const HeaderSearchOptions &ASTFileHSOpts) { + std::string SpecificModuleCachePath = createSpecificModuleCachePath( + FileMgr, ASTFileHSOpts.ModuleCachePath, ASTFileHSOpts.DisableModuleHash, + std::string(ContextHash)); + if (!LangOpts.Modules || PPOpts.AllowPCHWithDifferentModulesCachePath || SpecificModuleCachePath == ExistingSpecificModuleCachePath) return false; - auto EqualOrErr = - VFS.equivalent(SpecificModuleCachePath, ExistingSpecificModuleCachePath); + auto EqualOrErr = FileMgr.getVirtualFileSystem().equivalent( + SpecificModuleCachePath, ExistingSpecificModuleCachePath); if (EqualOrErr && *EqualOrErr) return false; if (Diags) { // If the module cache arguments provided from the command line are the // same, the mismatch must come from other arguments of the configuration // and not directly the cache path. - EqualOrErr = - VFS.equivalent(ASTFileHSOpts.ModuleCachePath, HSOpts.ModuleCachePath); + EqualOrErr = FileMgr.getVirtualFileSystem().equivalent( + ASTFileHSOpts.ModuleCachePath, HSOpts.ModuleCachePath); if (EqualOrErr && *EqualOrErr) Diags->Report(clang::diag::warn_ast_file_config_mismatch) << ASTFilename; else @@ -991,14 +997,14 @@ static bool checkModuleCachePath( bool PCHValidator::ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts, StringRef ASTFilename, - StringRef SpecificModuleCachePath, + StringRef ContextHash, bool Complain) { const HeaderSearch &HeaderSearchInfo = PP.getHeaderSearchInfo(); - return checkModuleCachePath( - Reader.getFileManager().getVirtualFileSystem(), SpecificModuleCachePath, - HeaderSearchInfo.getSpecificModuleCachePath(), ASTFilename, - Complain ? &Reader.Diags : nullptr, PP.getLangOpts(), - PP.getPreprocessorOpts(), HeaderSearchInfo.getHeaderSearchOpts(), HSOpts); + return checkModuleCachePath(Reader.getFileManager(), ContextHash, + HeaderSearchInfo.getSpecificModuleCachePath(), + ASTFilename, Complain ? &Reader.Diags : nullptr, + PP.getLangOpts(), PP.getPreprocessorOpts(), + HeaderSearchInfo.getHeaderSearchOpts(), HSOpts); } void PCHValidator::ReadCounter(const ModuleFile &M, uint32_t Value) { @@ -5877,13 +5883,11 @@ namespace { } bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts, - StringRef ASTFilename, - StringRef SpecificModuleCachePath, + StringRef ASTFilename, StringRef ContextHash, bool Complain) override { return checkModuleCachePath( - FileMgr.getVirtualFileSystem(), SpecificModuleCachePath, - ExistingSpecificModuleCachePath, ASTFilename, nullptr, - ExistingLangOpts, ExistingPPOpts, ExistingHSOpts, HSOpts); + FileMgr, ContextHash, ExistingSpecificModuleCachePath, ASTFilename, + nullptr, ExistingLangOpts, ExistingPPOpts, ExistingHSOpts, HSOpts); } bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, @@ -6705,10 +6709,10 @@ bool ASTReader::ParseHeaderSearchOptions(const RecordData &Record, HSOpts.UseStandardSystemIncludes = Record[Idx++]; HSOpts.UseStandardCXXIncludes = Record[Idx++]; HSOpts.UseLibcxx = Record[Idx++]; - std::string SpecificModuleCachePath = ReadString(Record, Idx); + std::string ContextHash = ReadString(Record, Idx); - return Listener.ReadHeaderSearchOptions(HSOpts, ModuleFilename, - SpecificModuleCachePath, Complain); + return Listener.ReadHeaderSearchOptions(HSOpts, ModuleFilename, ContextHash, + Complain); } bool ASTReader::ParseHeaderSearchPaths(const RecordData &Record, bool Complain, diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index ec718169550aa..2744d70b89aac 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -1694,9 +1694,8 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, StringRef isysroot) { const HeaderSearchOptions &HSOpts = PP.getHeaderSearchInfo().getHeaderSearchOpts(); - SmallString<256> HSOpts_ModuleCachePath; - normalizeModuleCachePath(PP.getFileManager(), HSOpts.ModuleCachePath, - HSOpts_ModuleCachePath); + StringRef HSOpts_ModuleCachePath = + PP.getHeaderSearchInfo().getNormalizedModuleCachePath(); AddString(HSOpts.Sysroot, Record); AddString(HSOpts.ResourceDir, Record); @@ -1710,10 +1709,7 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, StringRef isysroot) { Record.push_back(HSOpts.UseStandardSystemIncludes); Record.push_back(HSOpts.UseStandardCXXIncludes); Record.push_back(HSOpts.UseLibcxx); - // Write out the specific module cache path that contains the module files. - // FIXME: We already wrote out the normalized cache path. Just write the - // context hash (unless suppressed). - AddString(PP.getHeaderSearchInfo().getSpecificModuleCachePath(), Record); + AddString(PP.getHeaderSearchInfo().getContextHash(), Record); Stream.EmitRecord(HEADER_SEARCH_OPTIONS, Record); // Preprocessor options.