Index: clang-tools-extra/clangd/Compiler.cpp =================================================================== --- clang-tools-extra/clangd/Compiler.cpp +++ clang-tools-extra/clangd/Compiler.cpp @@ -95,7 +95,7 @@ if (auto VFSWithRemapping = createVFSFromCompilerInvocation( Clang->getInvocation(), Clang->getDiagnostics(), VFS)) VFS = VFSWithRemapping; - Clang->setVirtualFileSystem(VFS); + Clang->createFileManager(VFS); Clang->setTarget(TargetInfo::CreateTargetInfo( Clang->getDiagnostics(), Clang->getInvocation().TargetOpts)); Index: clang/include/clang/Basic/FileManager.h =================================================================== --- clang/include/clang/Basic/FileManager.h +++ clang/include/clang/Basic/FileManager.h @@ -175,6 +175,10 @@ void fillRealPathName(FileEntry *UFE, llvm::StringRef FileName); public: + /// Construct a file manager, optionally with a custom VFS. + /// + /// \param FS if non-null, the VFS to use. Otherwise uses + /// llvm::vfs::getRealFileSystem(). FileManager(const FileSystemOptions &FileSystemOpts, IntrusiveRefCntPtr FS = nullptr); ~FileManager(); Index: clang/include/clang/Frontend/CompilerInstance.h =================================================================== --- clang/include/clang/Frontend/CompilerInstance.h +++ clang/include/clang/Frontend/CompilerInstance.h @@ -82,9 +82,6 @@ /// Auxiliary Target info. IntrusiveRefCntPtr AuxTarget; - /// The virtual file system. - IntrusiveRefCntPtr VirtualFileSystem; - /// The file manager. IntrusiveRefCntPtr FileMgr; @@ -382,20 +379,8 @@ /// @name Virtual File System /// { - bool hasVirtualFileSystem() const { return VirtualFileSystem != nullptr; } - llvm::vfs::FileSystem &getVirtualFileSystem() const { - assert(hasVirtualFileSystem() && - "Compiler instance has no virtual file system"); - return *VirtualFileSystem; - } - - /// Replace the current virtual file system. - /// - /// \note Most clients should use setFileManager, which will implicitly reset - /// the virtual file system to the one contained in the file manager. - void setVirtualFileSystem(IntrusiveRefCntPtr FS) { - VirtualFileSystem = std::move(FS); + return *getFileManager().getVirtualFileSystem(); } /// } @@ -645,7 +630,8 @@ /// Create the file manager and replace any existing one with it. /// /// \return The new file manager on success, or null on failure. - FileManager *createFileManager(); + FileManager * + createFileManager(IntrusiveRefCntPtr VFS = nullptr); /// Create the source manager and replace any existing one with it. void createSourceManager(FileManager &FileMgr); Index: clang/lib/Frontend/ASTUnit.cpp =================================================================== --- clang/lib/Frontend/ASTUnit.cpp +++ clang/lib/Frontend/ASTUnit.cpp @@ -1078,28 +1078,29 @@ if (!Invocation) return true; + if (VFS && FileMgr) + assert(VFS == FileMgr->getVirtualFileSystem() && + "VFS passed to Parse and VFS in FileMgr are different"); + auto CCInvocation = std::make_shared(*Invocation); if (OverrideMainBuffer) { assert(Preamble && "No preamble was built, but OverrideMainBuffer is not null"); - IntrusiveRefCntPtr OldVFS = VFS; Preamble->AddImplicitPreamble(*CCInvocation, VFS, OverrideMainBuffer.get()); - if (OldVFS != VFS && FileMgr) { - assert(OldVFS == FileMgr->getVirtualFileSystem() && - "VFS passed to Parse and VFS in FileMgr are different"); - FileMgr = new FileManager(FileMgr->getFileSystemOpts(), VFS); - } + // VFS may have changed... } // Create the compiler instance to use for building the AST. std::unique_ptr Clang( new CompilerInstance(std::move(PCHContainerOps))); - if (FileMgr && VFS) { - assert(VFS == FileMgr->getVirtualFileSystem() && - "VFS passed to Parse and VFS in FileMgr are different"); - } else if (VFS) { - Clang->setVirtualFileSystem(VFS); - } + + // Ensure that Clang has a FileManager with the right VFS, which may have + // changed above in AddImplicitPreamble. If VFS is nullptr, rely on + // createFileManager to create one. + if (VFS && FileMgr && FileMgr->getVirtualFileSystem() == VFS) + Clang->setFileManager(&*FileMgr); + else + FileMgr = Clang->createFileManager(std::move(VFS)); // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar @@ -1136,10 +1137,6 @@ // Configure the various subsystems. LangOpts = Clang->getInvocation().LangOpts; FileSystemOpts = Clang->getFileSystemOpts(); - if (!FileMgr) { - Clang->createFileManager(); - FileMgr = &Clang->getFileManager(); - } ResetForParse(); Index: clang/lib/Frontend/CompilerInstance.cpp =================================================================== --- clang/lib/Frontend/CompilerInstance.cpp +++ clang/lib/Frontend/CompilerInstance.cpp @@ -89,10 +89,6 @@ void CompilerInstance::setFileManager(FileManager *Value) { FileMgr = Value; - if (Value) - VirtualFileSystem = Value->getVirtualFileSystem(); - else - VirtualFileSystem.reset(); } void CompilerInstance::setSourceManager(SourceManager *Value) { @@ -297,13 +293,14 @@ // File Manager -FileManager *CompilerInstance::createFileManager() { - if (!hasVirtualFileSystem()) { - IntrusiveRefCntPtr VFS = - createVFSFromCompilerInvocation(getInvocation(), getDiagnostics()); - setVirtualFileSystem(VFS); - } - FileMgr = new FileManager(getFileSystemOpts(), VirtualFileSystem); +FileManager *CompilerInstance::createFileManager( + IntrusiveRefCntPtr VFS) { + if (!VFS) + VFS = FileMgr ? FileMgr->getVirtualFileSystem() + : createVFSFromCompilerInvocation(getInvocation(), + getDiagnostics()); + assert(VFS && "FileManager has no VFS?"); + FileMgr = new FileManager(getFileSystemOpts(), std::move(VFS)); return FileMgr.get(); } @@ -1101,8 +1098,6 @@ ImportingInstance.getDiagnosticClient()), /*ShouldOwnClient=*/true); - Instance.setVirtualFileSystem(&ImportingInstance.getVirtualFileSystem()); - // Note that this module is part of the module build stack, so that we // can detect cycles in the module graph. Instance.setFileManager(&ImportingInstance.getFileManager()); Index: clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp =================================================================== --- clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp +++ clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp @@ -82,8 +82,6 @@ Instance.getDiagnostics().setSourceManager(&SM); - Instance.setVirtualFileSystem(&CI.getVirtualFileSystem()); - // The instance wants to take ownership, however DisableFree frontend option // is set to true to avoid double free issues Instance.setFileManager(&CI.getFileManager()); Index: lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp =================================================================== --- lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp +++ lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp @@ -309,8 +309,7 @@ } // Make sure clang uses the same VFS as LLDB. - m_compiler->setVirtualFileSystem( - FileSystem::Instance().GetVirtualFileSystem()); + m_compiler->createFileManager(FileSystem::Instance().GetVirtualFileSystem()); lldb::LanguageType frame_lang = expr.Language(); // defaults to lldb::eLanguageTypeUnknown Index: lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp =================================================================== --- lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp +++ lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp @@ -671,7 +671,7 @@ } // Make sure clang uses the same VFS as LLDB. - instance->setVirtualFileSystem(FileSystem::Instance().GetVirtualFileSystem()); + instance->createFileManager(FileSystem::Instance().GetVirtualFileSystem()); instance->setDiagnostics(diagnostics_engine.get()); instance->setInvocation(invocation);