diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -1731,16 +1731,17 @@ /// Read the control block for the named AST file. /// /// \returns true if an error occurred, false otherwise. - static bool - readASTFileControlBlock(StringRef Filename, FileManager &FileMgr, - const PCHContainerReader &PCHContainerRdr, - bool FindModuleFileExtensions, - ASTReaderListener &Listener, - bool ValidateDiagnosticOptions); + static bool readASTFileControlBlock(StringRef Filename, FileManager &FileMgr, + const InMemoryModuleCache &ModuleCache, + const PCHContainerReader &PCHContainerRdr, + bool FindModuleFileExtensions, + ASTReaderListener &Listener, + bool ValidateDiagnosticOptions); /// Determine whether the given AST file is acceptable to load into a /// translation unit with the given language and target options. static bool isAcceptableASTFile(StringRef Filename, FileManager &FileMgr, + const InMemoryModuleCache &ModuleCache, const PCHContainerReader &PCHContainerRdr, const LangOptions &LangOpts, const TargetOptions &TargetOpts, diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -252,7 +252,8 @@ // used here since we're not interested in validating the PCH at this time, // but only to check whether this is a file containing an AST. if (!ASTReader::readASTFileControlBlock( - Dir->path(), FileMgr, CI.getPCHContainerReader(), + Dir->path(), FileMgr, CI.getModuleCache(), + CI.getPCHContainerReader(), /*FindModuleFileExtensions=*/false, Validator, /*ValidateDiagnosticOptions=*/false)) MDC->addFile(Dir->path()); diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp --- a/clang/lib/Frontend/FrontendAction.cpp +++ b/clang/lib/Frontend/FrontendAction.cpp @@ -778,8 +778,9 @@ Dir != DirEnd && !EC; Dir.increment(EC)) { // Check whether this is an acceptable AST file. if (ASTReader::isAcceptableASTFile( - Dir->path(), FileMgr, CI.getPCHContainerReader(), - CI.getLangOpts(), CI.getTargetOpts(), CI.getPreprocessorOpts(), + Dir->path(), FileMgr, CI.getModuleCache(), + CI.getPCHContainerReader(), CI.getLangOpts(), + CI.getTargetOpts(), CI.getPreprocessorOpts(), SpecificModuleCachePath, /*RequireStrictOptionMatches=*/true)) { PPOpts.ImplicitPCHInclude = std::string(Dir->path()); Found = true; diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -851,7 +851,8 @@ assert(isCurrentFileAST() && "dumping non-AST?"); // Set up the output file. std::unique_ptr OutFile; - StringRef OutputFileName = getCompilerInstance().getFrontendOpts().OutputFile; + CompilerInstance &CI = getCompilerInstance(); + StringRef OutputFileName = CI.getFrontendOpts().OutputFile; if (!OutputFileName.empty() && OutputFileName != "-") { std::error_code EC; OutFile.reset(new llvm::raw_fd_ostream(OutputFileName.str(), EC, @@ -861,14 +862,14 @@ llvm::raw_ostream &Out = OutputStream ? *OutputStream : llvm::outs(); Out << "Information for module file '" << getCurrentFile() << "':\n"; - auto &FileMgr = getCompilerInstance().getFileManager(); + auto &FileMgr = CI.getFileManager(); auto Buffer = FileMgr.getBufferForFile(getCurrentFile()); StringRef Magic = (*Buffer)->getMemBufferRef().getBuffer(); bool IsRaw = (Magic.size() >= 4 && Magic[0] == 'C' && Magic[1] == 'P' && Magic[2] == 'C' && Magic[3] == 'H'); Out << " Module format: " << (IsRaw ? "raw" : "obj") << "\n"; - Preprocessor &PP = getCompilerInstance().getPreprocessor(); + Preprocessor &PP = CI.getPreprocessor(); DumpModuleInfoListener Listener(Out); HeaderSearchOptions &HSOpts = PP.getHeaderSearchInfo().getHeaderSearchOpts(); @@ -966,7 +967,8 @@ // The reminder of the output is produced from the listener as the AST // FileCcontrolBlock is (re-)parsed. ASTReader::readASTFileControlBlock( - getCurrentFile(), FileMgr, getCompilerInstance().getPCHContainerReader(), + getCurrentFile(), FileMgr, CI.getModuleCache(), + CI.getPCHContainerReader(), /*FindModuleFileExtensions=*/true, Listener, HSOpts.ModulesValidateDiagnosticOptions); } diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -5169,19 +5169,28 @@ bool ASTReader::readASTFileControlBlock( StringRef Filename, FileManager &FileMgr, - const PCHContainerReader &PCHContainerRdr, - bool FindModuleFileExtensions, + const InMemoryModuleCache &ModuleCache, + const PCHContainerReader &PCHContainerRdr, bool FindModuleFileExtensions, ASTReaderListener &Listener, bool ValidateDiagnosticOptions) { // Open the AST file. - // FIXME: This allows use of the VFS; we do not allow use of the - // VFS when actually loading a module. - auto Buffer = FileMgr.getBufferForFile(Filename); + std::unique_ptr OwnedBuffer; + llvm::MemoryBuffer *Buffer = ModuleCache.lookupPCM(Filename); if (!Buffer) { - return true; + // FIXME: We should add the pcm to the InMemoryModuleCache if it could be + // read again later, but we do not have the context here to determine if it + // is safe to change the result of InMemoryModuleCache::getPCMState(). + + // FIXME: This allows use of the VFS; we do not allow use of the + // VFS when actually loading a module. + auto BufferOrErr = FileMgr.getBufferForFile(Filename); + if (!BufferOrErr) + return true; + OwnedBuffer = std::move(*BufferOrErr); + Buffer = OwnedBuffer.get(); } // Initialize the stream - StringRef Bytes = PCHContainerRdr.ExtractPCH(**Buffer); + StringRef Bytes = PCHContainerRdr.ExtractPCH(*Buffer); BitstreamCursor Stream(Bytes); // Sniff for the signature. @@ -5434,6 +5443,7 @@ } bool ASTReader::isAcceptableASTFile(StringRef Filename, FileManager &FileMgr, + const InMemoryModuleCache &ModuleCache, const PCHContainerReader &PCHContainerRdr, const LangOptions &LangOpts, const TargetOptions &TargetOpts, @@ -5443,9 +5453,9 @@ SimplePCHValidator validator(LangOpts, TargetOpts, PPOpts, ExistingModuleCachePath, FileMgr, RequireStrictOptionMatches); - return !readASTFileControlBlock(Filename, FileMgr, PCHContainerRdr, - /*FindModuleFileExtensions=*/false, - validator, + return !readASTFileControlBlock(Filename, FileMgr, ModuleCache, + PCHContainerRdr, + /*FindModuleFileExtensions=*/false, validator, /*ValidateDiagnosticOptions=*/true); } diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp @@ -103,7 +103,7 @@ while (!Worklist.empty()) ASTReader::readASTFileControlBlock( - Worklist.pop_back_val(), CI.getFileManager(), + Worklist.pop_back_val(), CI.getFileManager(), CI.getModuleCache(), CI.getPCHContainerReader(), /*FindModuleFileExtensions=*/false, Listener, /*ValidateDiagnosticOptions=*/false);