-
Notifications
You must be signed in to change notification settings - Fork 15k
[clang] Initialize the file system explicitly #158381
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-clang-modules @llvm/pr-subscribers-clang Author: Jan Svoboda (jansvoboda11) ChangesThis PR is a part of the effort to make the VFS used in the compiler more explicit and consistent. Instead of creating the VFS deep within the compiler (in This PR also helps in breaking up the dependency cycle where creating a properly configured Both Patch is 36.47 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/158381.diff 27 Files Affected:
diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h
index 9f3d5f97cdff4..a6b6993b708d0 100644
--- a/clang/include/clang/Frontend/CompilerInstance.h
+++ b/clang/include/clang/Frontend/CompilerInstance.h
@@ -83,6 +83,9 @@ class CompilerInstance : public ModuleLoader {
/// The options used in this compiler instance.
std::shared_ptr<CompilerInvocation> Invocation;
+ /// The virtual file system instance.
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS;
+
/// The diagnostics engine instance.
IntrusiveRefCntPtr<DiagnosticsEngine> Diagnostics;
@@ -409,9 +412,31 @@ class CompilerInstance : public ModuleLoader {
/// @name Virtual File System
/// @{
- llvm::vfs::FileSystem &getVirtualFileSystem() const;
- llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
- getVirtualFileSystemPtr() const;
+ bool hasVirtualFileSystem() const { return VFS != nullptr; }
+
+ /// Create a virtual file system instance based on the invocation.
+ ///
+ /// @param BaseFS The file system that may be used when configuring the final
+ /// file system, and act as the underlying file system. Must not
+ /// be NULL.
+ /// @param DC If non-NULL, the diagnostic consumer to be used in case
+ /// configuring the file system emits diagnostics. Note that the
+ /// DiagnosticsEngine using the consumer won't obey the
+ /// --warning-suppression-mappings= flag.
+ void createVirtualFileSystem(IntrusiveRefCntPtr<llvm::vfs::FileSystem>
+ BaseFS = llvm::vfs::getRealFileSystem(),
+ DiagnosticConsumer *DC = nullptr);
+
+ /// Use the given file system.
+ void setVirtualFileSystem(IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS) {
+ VFS = std::move(FS);
+ }
+
+ llvm::vfs::FileSystem &getVirtualFileSystem() const { return *VFS; }
+
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> getVirtualFileSystemPtr() const {
+ return VFS;
+ }
/// @}
/// @name File Manager
@@ -650,32 +675,31 @@ class CompilerInstance : public ModuleLoader {
/// Note that this routine also replaces the diagnostic client,
/// allocating one if one is not provided.
///
- /// \param VFS is used for any IO needed when creating DiagnosticsEngine. It
- /// doesn't replace VFS in the CompilerInstance (if any).
- ///
/// \param Client If non-NULL, a diagnostic client that will be
/// attached to (and, then, owned by) the DiagnosticsEngine inside this AST
/// unit.
///
/// \param ShouldOwnClient If Client is non-NULL, specifies whether
/// the diagnostic object should take ownership of the client.
- void createDiagnostics(llvm::vfs::FileSystem &VFS,
- DiagnosticConsumer *Client = nullptr,
+ void createDiagnostics(DiagnosticConsumer *Client = nullptr,
bool ShouldOwnClient = true);
- /// Create a DiagnosticsEngine object with a the TextDiagnosticPrinter.
+ /// Create a DiagnosticsEngine object.
///
/// If no diagnostic client is provided, this creates a
/// DiagnosticConsumer that is owned by the returned diagnostic
/// object, if using directly the caller is responsible for
/// releasing the returned DiagnosticsEngine's client eventually.
///
+ /// \param VFS The file system used to load the suppression mappings file.
+ ///
/// \param Opts - The diagnostic options; note that the created text
/// diagnostic object contains a reference to these options.
///
/// \param Client If non-NULL, a diagnostic client that will be
/// attached to (and, then, owned by) the returned DiagnosticsEngine
- /// object.
+ /// object. If NULL, the returned DiagnosticsEngine will own a newly-created
+ /// client.
///
/// \param CodeGenOpts If non-NULL, the code gen options in use, which may be
/// used by some diagnostics printers (for logging purposes only).
@@ -690,8 +714,7 @@ class CompilerInstance : public ModuleLoader {
/// Create the file manager and replace any existing one with it.
///
/// \return The new file manager on success, or null on failure.
- FileManager *
- createFileManager(IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr);
+ FileManager *createFileManager();
/// Create the source manager and replace any existing one with it.
void createSourceManager(FileManager &FileMgr);
diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp
index 03b08cdabe39e..8b35af152cbc8 100644
--- a/clang/lib/Frontend/ASTUnit.cpp
+++ b/clang/lib/Frontend/ASTUnit.cpp
@@ -1189,10 +1189,12 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
// 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)
+ if (VFS && FileMgr && &FileMgr->getVirtualFileSystem() == VFS) {
+ Clang->setVirtualFileSystem(std::move(VFS));
Clang->setFileManager(FileMgr);
- else {
- Clang->createFileManager(std::move(VFS));
+ } else {
+ Clang->setVirtualFileSystem(std::move(VFS));
+ Clang->createFileManager();
FileMgr = Clang->getFileManagerPtr();
}
diff --git a/clang/lib/Frontend/ChainedIncludesSource.cpp b/clang/lib/Frontend/ChainedIncludesSource.cpp
index 013814a738a36..82249f893a795 100644
--- a/clang/lib/Frontend/ChainedIncludesSource.cpp
+++ b/clang/lib/Frontend/ChainedIncludesSource.cpp
@@ -124,6 +124,7 @@ clang::createChainedIncludesSource(CompilerInstance &CI,
auto Clang = std::make_unique<CompilerInstance>(
std::move(CInvok), CI.getPCHContainerOperations());
+ Clang->createVirtualFileSystem();
Clang->setDiagnostics(Diags);
Clang->setTarget(TargetInfo::CreateTargetInfo(
Clang->getDiagnostics(), Clang->getInvocation().getTargetOpts()));
diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp
index 31a8d75fec4bd..e8d0bb84c0f45 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -159,17 +159,11 @@ bool CompilerInstance::createTarget() {
return true;
}
-llvm::vfs::FileSystem &CompilerInstance::getVirtualFileSystem() const {
- return getFileManager().getVirtualFileSystem();
-}
-
-llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
-CompilerInstance::getVirtualFileSystemPtr() const {
- return getFileManager().getVirtualFileSystemPtr();
-}
-
-void CompilerInstance::setFileManager(
- llvm::IntrusiveRefCntPtr<FileManager> Value) {
+void CompilerInstance::setFileManager(IntrusiveRefCntPtr<FileManager> Value) {
+ if (!hasVirtualFileSystem())
+ setVirtualFileSystem(Value->getVirtualFileSystemPtr());
+ assert(Value == nullptr ||
+ getVirtualFileSystemPtr() == Value->getVirtualFileSystemPtr());
FileMgr = std::move(Value);
}
@@ -289,6 +283,20 @@ static void collectVFSEntries(CompilerInstance &CI,
MDC->addFile(E.VPath, E.RPath);
}
+void CompilerInstance::createVirtualFileSystem(
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS, DiagnosticConsumer *DC) {
+ DiagnosticOptions DiagOpts;
+ DiagnosticsEngine Diags(DiagnosticIDs::create(), DiagOpts, DC,
+ /*ShouldOwnClient=*/false);
+
+ VFS = createVFSFromCompilerInvocation(getInvocation(), Diags,
+ std::move(BaseFS));
+ // FIXME: Should this go into createVFSFromCompilerInvocation?
+ if (getFrontendOpts().ShowStats)
+ VFS =
+ llvm::makeIntrusiveRefCnt<llvm::vfs::TracingFileSystem>(std::move(VFS));
+}
+
// Diagnostics
static void SetUpDiagnosticLog(DiagnosticOptions &DiagOpts,
const CodeGenOptions *CodeGenOpts,
@@ -340,11 +348,10 @@ static void SetupSerializedDiagnostics(DiagnosticOptions &DiagOpts,
}
}
-void CompilerInstance::createDiagnostics(llvm::vfs::FileSystem &VFS,
- DiagnosticConsumer *Client,
+void CompilerInstance::createDiagnostics(DiagnosticConsumer *Client,
bool ShouldOwnClient) {
- Diagnostics = createDiagnostics(VFS, getDiagnosticOpts(), Client,
- ShouldOwnClient, &getCodeGenOpts());
+ Diagnostics = createDiagnostics(getVirtualFileSystem(), getDiagnosticOpts(),
+ Client, ShouldOwnClient, &getCodeGenOpts());
}
IntrusiveRefCntPtr<DiagnosticsEngine> CompilerInstance::createDiagnostics(
@@ -382,18 +389,9 @@ IntrusiveRefCntPtr<DiagnosticsEngine> CompilerInstance::createDiagnostics(
// File Manager
-FileManager *CompilerInstance::createFileManager(
- IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
- if (!VFS)
- VFS = FileMgr ? FileMgr->getVirtualFileSystemPtr()
- : createVFSFromCompilerInvocation(getInvocation(),
- getDiagnostics());
- assert(VFS && "FileManager has no VFS?");
- if (getFrontendOpts().ShowStats)
- VFS =
- llvm::makeIntrusiveRefCnt<llvm::vfs::TracingFileSystem>(std::move(VFS));
- FileMgr = llvm::makeIntrusiveRefCnt<FileManager>(getFileSystemOpts(),
- std::move(VFS));
+FileManager *CompilerInstance::createFileManager() {
+ assert(VFS && "CompilerInstance needs a VFS for creating FileManager");
+ FileMgr = llvm::makeIntrusiveRefCnt<FileManager>(getFileSystemOpts(), VFS);
return FileMgr.get();
}
@@ -1174,20 +1172,21 @@ std::unique_ptr<CompilerInstance> CompilerInstance::cloneForModuleCompileImpl(
auto &Inv = Instance.getInvocation();
if (ThreadSafeConfig) {
- Instance.createFileManager(ThreadSafeConfig->getVFS());
+ Instance.setVirtualFileSystem(ThreadSafeConfig->getVFS());
+ Instance.createFileManager();
} else if (FrontendOpts.ModulesShareFileManager) {
+ Instance.setVirtualFileSystem(getVirtualFileSystemPtr());
Instance.setFileManager(getFileManagerPtr());
} else {
- Instance.createFileManager(getVirtualFileSystemPtr());
+ Instance.setVirtualFileSystem(getVirtualFileSystemPtr());
+ Instance.createFileManager();
}
if (ThreadSafeConfig) {
- Instance.createDiagnostics(Instance.getVirtualFileSystem(),
- &ThreadSafeConfig->getDiagConsumer(),
+ Instance.createDiagnostics(&ThreadSafeConfig->getDiagConsumer(),
/*ShouldOwnClient=*/false);
} else {
Instance.createDiagnostics(
- Instance.getVirtualFileSystem(),
new ForwardingDiagnosticConsumer(getDiagnosticClient()),
/*ShouldOwnClient=*/true);
}
diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp
index 6b1fcac75ac2b..ca37e0661476d 100644
--- a/clang/lib/Frontend/FrontendAction.cpp
+++ b/clang/lib/Frontend/FrontendAction.cpp
@@ -876,6 +876,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
// Set the shared objects, these are reset when we finish processing the
// file, otherwise the CompilerInstance will happily destroy them.
+ CI.setVirtualFileSystem(AST->getFileManager().getVirtualFileSystemPtr());
CI.setFileManager(AST->getFileManagerPtr());
CI.createSourceManager(CI.getFileManager());
CI.getSourceManager().initializeForReplay(AST->getSourceManager());
@@ -966,7 +967,9 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
return true;
}
- // Set up the file and source managers, if needed.
+ // Set up the file system, file and source managers, if needed.
+ if (!CI.hasVirtualFileSystem())
+ CI.createVirtualFileSystem();
if (!CI.hasFileManager()) {
if (!CI.createFileManager()) {
return false;
diff --git a/clang/lib/Frontend/Rewrite/FrontendActions.cpp b/clang/lib/Frontend/Rewrite/FrontendActions.cpp
index 6c9c9d5b5c8d3..f5656b3b190e9 100644
--- a/clang/lib/Frontend/Rewrite/FrontendActions.cpp
+++ b/clang/lib/Frontend/Rewrite/FrontendActions.cpp
@@ -245,8 +245,8 @@ class RewriteIncludesAction::RewriteImportsListener : public ASTReaderListener {
CompilerInstance Instance(
std::make_shared<CompilerInvocation>(CI.getInvocation()),
CI.getPCHContainerOperations(), &CI.getModuleCache());
+ Instance.setVirtualFileSystem(CI.getVirtualFileSystemPtr());
Instance.createDiagnostics(
- CI.getVirtualFileSystem(),
new ForwardingDiagnosticConsumer(CI.getDiagnosticClient()),
/*ShouldOwnClient=*/true);
Instance.getFrontendOpts().DisableFree = false;
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp
index 84f1c363b5f6f..efb665c95ae7a 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -107,8 +107,10 @@ CreateCI(const llvm::opt::ArgStringList &Argv) {
Clang->getHeaderSearchOpts().ResourceDir =
CompilerInvocation::GetResourcesPath(Argv[0], nullptr);
+ Clang->createVirtualFileSystem();
+
// Create the actual diagnostics engine.
- Clang->createDiagnostics(*llvm::vfs::getRealFileSystem());
+ Clang->createDiagnostics();
if (!Clang->hasDiagnostics())
return llvm::createStringError(llvm::errc::not_supported,
"Initialization failed. "
@@ -474,7 +476,8 @@ Interpreter::createWithCUDA(std::unique_ptr<CompilerInstance> CI,
std::make_unique<llvm::vfs::OverlayFileSystem>(
llvm::vfs::getRealFileSystem());
OverlayVFS->pushOverlay(IMVFS);
- CI->createFileManager(OverlayVFS);
+ CI->createVirtualFileSystem(OverlayVFS);
+ CI->createFileManager();
llvm::Expected<std::unique_ptr<Interpreter>> InterpOrErr =
Interpreter::create(std::move(CI));
diff --git a/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp b/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp
index 975c72af0b031..be74ff2cd4799 100644
--- a/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp
+++ b/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp
@@ -84,8 +84,8 @@ void ModelInjector::onBodySynthesis(const NamedDecl *D) {
// behavior for models
CompilerInstance Instance(std::move(Invocation),
CI.getPCHContainerOperations());
+ Instance.setVirtualFileSystem(CI.getVirtualFileSystemPtr());
Instance.createDiagnostics(
- CI.getVirtualFileSystem(),
new ForwardingDiagnosticConsumer(CI.getDiagnosticClient()),
/*ShouldOwnClient=*/true);
diff --git a/clang/lib/Testing/TestAST.cpp b/clang/lib/Testing/TestAST.cpp
index b59a8d55129de..9ad0de95530fb 100644
--- a/clang/lib/Testing/TestAST.cpp
+++ b/clang/lib/Testing/TestAST.cpp
@@ -54,8 +54,10 @@ class StoreDiagnostics : public DiagnosticConsumer {
// Fills in the bits of a CompilerInstance that weren't initialized yet.
// Provides "empty" ASTContext etc if we fail before parsing gets started.
void createMissingComponents(CompilerInstance &Clang) {
+ if (!Clang.hasVirtualFileSystem())
+ Clang.createVirtualFileSystem();
if (!Clang.hasDiagnostics())
- Clang.createDiagnostics(*llvm::vfs::getRealFileSystem());
+ Clang.createDiagnostics();
if (!Clang.hasFileManager())
Clang.createFileManager();
if (!Clang.hasSourceManager())
@@ -98,7 +100,9 @@ TestAST::TestAST(const TestInputs &In) {
// Extra error conditions are reported through diagnostics, set that up first.
bool ErrorOK = In.ErrorOK || llvm::StringRef(In.Code).contains("error-ok");
- Clang->createDiagnostics(*VFS, new StoreDiagnostics(Diagnostics, !ErrorOK));
+ auto DiagConsumer = new StoreDiagnostics(Diagnostics, !ErrorOK);
+ Clang->createVirtualFileSystem(std::move(VFS), DiagConsumer);
+ Clang->createDiagnostics(DiagConsumer);
// Parse cc1 argv, (typically [-std=c++20 input.cc]) into CompilerInvocation.
std::vector<const char *> Argv;
@@ -115,7 +119,7 @@ TestAST::TestAST(const TestInputs &In) {
}
assert(!Clang->getInvocation().getFrontendOpts().DisableFree);
- Clang->createFileManager(VFS);
+ Clang->createFileManager();
// Running the FrontendAction creates the other components: SourceManager,
// Preprocessor, ASTContext, Sema. Preprocessor needs TargetInfo to be set.
diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
index 0855e6dec6158..0a12c479bf8e3 100644
--- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
+++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
@@ -414,11 +414,12 @@ class DependencyScanningAction {
CompilerInstance &ScanInstance = *ScanInstanceStorage;
ScanInstance.setBuildingModule(false);
+ ScanInstance.createVirtualFileSystem(FS, DiagConsumer);
+
// Create the compiler's actual diagnostics engine.
sanitizeDiagOpts(ScanInstance.getDiagnosticOpts());
assert(!DiagConsumerFinished && "attempt to reuse finished consumer");
- ScanInstance.createDiagnostics(*FS, DiagConsumer,
- /*ShouldOwnClient=*/false);
+ ScanInstance.createDiagnostics(DiagConsumer, /*ShouldOwnClient=*/false);
if (!ScanInstance.hasDiagnostics())
return false;
@@ -439,13 +440,8 @@ class DependencyScanningAction {
ScanInstance.getHeaderSearchOpts().ModulesIncludeVFSUsage =
any(Service.getOptimizeArgs() & ScanningOptimizations::VFS);
- // Support for virtual file system overlays.
- FS = createVFSFromCompilerInvocation(ScanInstance.getInvocation(),
- ScanInstance.getDiagnostics(),
- std::move(FS));
-
// Create a new FileManager to match the invocation's FileSystemOptions.
- auto *FileMgr = ScanInstance.createFileManager(FS);
+ auto *FileMgr = ScanInstance.createFileManager();
// Use the dependency scanning optimized file system if requested to do so.
if (DepFS) {
diff --git a/clang/lib/Tooling/Tooling.cpp b/clang/lib/Tooling/Tooling.cpp
index 0c179b852813d..2d4790b205b1a 100644
--- a/clang/lib/Tooling/Tooling.cpp
+++ b/clang/lib/Tooling/Tooling.cpp
@@ -454,8 +454,7 @@ bool FrontendActionFactory::runInvocation(
std::unique_ptr<FrontendAction> ScopedToolAction(create());
// Create the compiler's actual diagnostics engine.
- Compiler.createDiagnostics(Files->getVirtualFileSystem(), DiagConsumer,
- /*ShouldOwnClient=*/false);
+ Compiler.createDiagnostics(DiagConsumer, /*ShouldOwnClient=*/false);
if (!Compiler.hasDiagnostics())
return false;
diff --git a/clang/tools/clang-import-test/clang-import-test.cpp b/clang/tools/clang-import-test/clang-import-test.cpp
index ab021a51bf295..910e08ca4dffa 100644
--- a/clang/tools/clang-import-test/clang-import-test.cpp
+++ b/clang/tools/clang-import-test/clang-import-test.cpp
@@ -207,8 +207,8 @@ std::unique_ptr<CompilerInstance> BuildCompilerInstance() {
auto Ins = std::make_unique<CompilerInstance>(std::move(Inv));
- Ins->createDiagnostics(*llvm::vfs::getRealFileSystem(), DC.release(),
- /*ShouldOwnClient=*/true);
+ Ins->createVirtualFileSystem(llvm::vfs::getRealFileSystem(), DC.get());
+ Ins->createDiagnostics(DC.release(), /*ShouldOwnClient=*/true);
TargetInfo *TI = TargetInfo::CreateTargetInfo(
Ins->getDiagnostics(), Ins->getInvocation().getTargetOpts());
diff --git a/clang/tools/clang-installapi/ClangInstallAPI.cpp b/clang/tools/clang-installapi/ClangInstallAPI.cpp
index 049b0bd8f8dbf..16abeb10284c0 100644
--- a/clang/tools/clang-installapi/ClangInstallAPI.cpp
+++ b/clang/tools/clang-installapi/ClangInstallAPI.cpp
@@ -115,7 +115,7 @@ static bool run(ArrayRef<const char *> Args, const char *ProgName) {
// Set up compilation.
std::unique_ptr<CompilerInstance> CI(new CompilerInstance());
CI->setFileManager(FM);
- CI->createDiagnostics(FM->getVirtualFileSystem());
+ CI->createDiagnostics();
if (!CI->hasDiagnostics())
return EXIT_FAILURE;
diff --git a/clang/tools/driver/cc1_main.cpp b/clang/tools/driver/cc1_main.cpp
index 854ab3e33555b..49f8843515a35 100644
--- a/clang/tools/driver/cc1_main.cpp
+++ b/clang/tools/driver/cc1_main.cpp
@@ -271,8 +271,11 @@ int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
Clang->getHeaderSearchOpts().ResourceDir =
CompilerInvocation::GetRe...
[truncated]
|
@llvm/pr-subscribers-clang-static-analyzer-1 Author: Jan Svoboda (jansvoboda11) ChangesThis PR is a part of the effort to make the VFS used in the compiler more explicit and consistent. Instead of creating the VFS deep within the compiler (in This PR also helps in breaking up the dependency cycle where creating a properly configured Both Patch is 36.47 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/158381.diff 27 Files Affected:
diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h
index 9f3d5f97cdff4..a6b6993b708d0 100644
--- a/clang/include/clang/Frontend/CompilerInstance.h
+++ b/clang/include/clang/Frontend/CompilerInstance.h
@@ -83,6 +83,9 @@ class CompilerInstance : public ModuleLoader {
/// The options used in this compiler instance.
std::shared_ptr<CompilerInvocation> Invocation;
+ /// The virtual file system instance.
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS;
+
/// The diagnostics engine instance.
IntrusiveRefCntPtr<DiagnosticsEngine> Diagnostics;
@@ -409,9 +412,31 @@ class CompilerInstance : public ModuleLoader {
/// @name Virtual File System
/// @{
- llvm::vfs::FileSystem &getVirtualFileSystem() const;
- llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
- getVirtualFileSystemPtr() const;
+ bool hasVirtualFileSystem() const { return VFS != nullptr; }
+
+ /// Create a virtual file system instance based on the invocation.
+ ///
+ /// @param BaseFS The file system that may be used when configuring the final
+ /// file system, and act as the underlying file system. Must not
+ /// be NULL.
+ /// @param DC If non-NULL, the diagnostic consumer to be used in case
+ /// configuring the file system emits diagnostics. Note that the
+ /// DiagnosticsEngine using the consumer won't obey the
+ /// --warning-suppression-mappings= flag.
+ void createVirtualFileSystem(IntrusiveRefCntPtr<llvm::vfs::FileSystem>
+ BaseFS = llvm::vfs::getRealFileSystem(),
+ DiagnosticConsumer *DC = nullptr);
+
+ /// Use the given file system.
+ void setVirtualFileSystem(IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS) {
+ VFS = std::move(FS);
+ }
+
+ llvm::vfs::FileSystem &getVirtualFileSystem() const { return *VFS; }
+
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> getVirtualFileSystemPtr() const {
+ return VFS;
+ }
/// @}
/// @name File Manager
@@ -650,32 +675,31 @@ class CompilerInstance : public ModuleLoader {
/// Note that this routine also replaces the diagnostic client,
/// allocating one if one is not provided.
///
- /// \param VFS is used for any IO needed when creating DiagnosticsEngine. It
- /// doesn't replace VFS in the CompilerInstance (if any).
- ///
/// \param Client If non-NULL, a diagnostic client that will be
/// attached to (and, then, owned by) the DiagnosticsEngine inside this AST
/// unit.
///
/// \param ShouldOwnClient If Client is non-NULL, specifies whether
/// the diagnostic object should take ownership of the client.
- void createDiagnostics(llvm::vfs::FileSystem &VFS,
- DiagnosticConsumer *Client = nullptr,
+ void createDiagnostics(DiagnosticConsumer *Client = nullptr,
bool ShouldOwnClient = true);
- /// Create a DiagnosticsEngine object with a the TextDiagnosticPrinter.
+ /// Create a DiagnosticsEngine object.
///
/// If no diagnostic client is provided, this creates a
/// DiagnosticConsumer that is owned by the returned diagnostic
/// object, if using directly the caller is responsible for
/// releasing the returned DiagnosticsEngine's client eventually.
///
+ /// \param VFS The file system used to load the suppression mappings file.
+ ///
/// \param Opts - The diagnostic options; note that the created text
/// diagnostic object contains a reference to these options.
///
/// \param Client If non-NULL, a diagnostic client that will be
/// attached to (and, then, owned by) the returned DiagnosticsEngine
- /// object.
+ /// object. If NULL, the returned DiagnosticsEngine will own a newly-created
+ /// client.
///
/// \param CodeGenOpts If non-NULL, the code gen options in use, which may be
/// used by some diagnostics printers (for logging purposes only).
@@ -690,8 +714,7 @@ class CompilerInstance : public ModuleLoader {
/// Create the file manager and replace any existing one with it.
///
/// \return The new file manager on success, or null on failure.
- FileManager *
- createFileManager(IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr);
+ FileManager *createFileManager();
/// Create the source manager and replace any existing one with it.
void createSourceManager(FileManager &FileMgr);
diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp
index 03b08cdabe39e..8b35af152cbc8 100644
--- a/clang/lib/Frontend/ASTUnit.cpp
+++ b/clang/lib/Frontend/ASTUnit.cpp
@@ -1189,10 +1189,12 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
// 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)
+ if (VFS && FileMgr && &FileMgr->getVirtualFileSystem() == VFS) {
+ Clang->setVirtualFileSystem(std::move(VFS));
Clang->setFileManager(FileMgr);
- else {
- Clang->createFileManager(std::move(VFS));
+ } else {
+ Clang->setVirtualFileSystem(std::move(VFS));
+ Clang->createFileManager();
FileMgr = Clang->getFileManagerPtr();
}
diff --git a/clang/lib/Frontend/ChainedIncludesSource.cpp b/clang/lib/Frontend/ChainedIncludesSource.cpp
index 013814a738a36..82249f893a795 100644
--- a/clang/lib/Frontend/ChainedIncludesSource.cpp
+++ b/clang/lib/Frontend/ChainedIncludesSource.cpp
@@ -124,6 +124,7 @@ clang::createChainedIncludesSource(CompilerInstance &CI,
auto Clang = std::make_unique<CompilerInstance>(
std::move(CInvok), CI.getPCHContainerOperations());
+ Clang->createVirtualFileSystem();
Clang->setDiagnostics(Diags);
Clang->setTarget(TargetInfo::CreateTargetInfo(
Clang->getDiagnostics(), Clang->getInvocation().getTargetOpts()));
diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp
index 31a8d75fec4bd..e8d0bb84c0f45 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -159,17 +159,11 @@ bool CompilerInstance::createTarget() {
return true;
}
-llvm::vfs::FileSystem &CompilerInstance::getVirtualFileSystem() const {
- return getFileManager().getVirtualFileSystem();
-}
-
-llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
-CompilerInstance::getVirtualFileSystemPtr() const {
- return getFileManager().getVirtualFileSystemPtr();
-}
-
-void CompilerInstance::setFileManager(
- llvm::IntrusiveRefCntPtr<FileManager> Value) {
+void CompilerInstance::setFileManager(IntrusiveRefCntPtr<FileManager> Value) {
+ if (!hasVirtualFileSystem())
+ setVirtualFileSystem(Value->getVirtualFileSystemPtr());
+ assert(Value == nullptr ||
+ getVirtualFileSystemPtr() == Value->getVirtualFileSystemPtr());
FileMgr = std::move(Value);
}
@@ -289,6 +283,20 @@ static void collectVFSEntries(CompilerInstance &CI,
MDC->addFile(E.VPath, E.RPath);
}
+void CompilerInstance::createVirtualFileSystem(
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS, DiagnosticConsumer *DC) {
+ DiagnosticOptions DiagOpts;
+ DiagnosticsEngine Diags(DiagnosticIDs::create(), DiagOpts, DC,
+ /*ShouldOwnClient=*/false);
+
+ VFS = createVFSFromCompilerInvocation(getInvocation(), Diags,
+ std::move(BaseFS));
+ // FIXME: Should this go into createVFSFromCompilerInvocation?
+ if (getFrontendOpts().ShowStats)
+ VFS =
+ llvm::makeIntrusiveRefCnt<llvm::vfs::TracingFileSystem>(std::move(VFS));
+}
+
// Diagnostics
static void SetUpDiagnosticLog(DiagnosticOptions &DiagOpts,
const CodeGenOptions *CodeGenOpts,
@@ -340,11 +348,10 @@ static void SetupSerializedDiagnostics(DiagnosticOptions &DiagOpts,
}
}
-void CompilerInstance::createDiagnostics(llvm::vfs::FileSystem &VFS,
- DiagnosticConsumer *Client,
+void CompilerInstance::createDiagnostics(DiagnosticConsumer *Client,
bool ShouldOwnClient) {
- Diagnostics = createDiagnostics(VFS, getDiagnosticOpts(), Client,
- ShouldOwnClient, &getCodeGenOpts());
+ Diagnostics = createDiagnostics(getVirtualFileSystem(), getDiagnosticOpts(),
+ Client, ShouldOwnClient, &getCodeGenOpts());
}
IntrusiveRefCntPtr<DiagnosticsEngine> CompilerInstance::createDiagnostics(
@@ -382,18 +389,9 @@ IntrusiveRefCntPtr<DiagnosticsEngine> CompilerInstance::createDiagnostics(
// File Manager
-FileManager *CompilerInstance::createFileManager(
- IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
- if (!VFS)
- VFS = FileMgr ? FileMgr->getVirtualFileSystemPtr()
- : createVFSFromCompilerInvocation(getInvocation(),
- getDiagnostics());
- assert(VFS && "FileManager has no VFS?");
- if (getFrontendOpts().ShowStats)
- VFS =
- llvm::makeIntrusiveRefCnt<llvm::vfs::TracingFileSystem>(std::move(VFS));
- FileMgr = llvm::makeIntrusiveRefCnt<FileManager>(getFileSystemOpts(),
- std::move(VFS));
+FileManager *CompilerInstance::createFileManager() {
+ assert(VFS && "CompilerInstance needs a VFS for creating FileManager");
+ FileMgr = llvm::makeIntrusiveRefCnt<FileManager>(getFileSystemOpts(), VFS);
return FileMgr.get();
}
@@ -1174,20 +1172,21 @@ std::unique_ptr<CompilerInstance> CompilerInstance::cloneForModuleCompileImpl(
auto &Inv = Instance.getInvocation();
if (ThreadSafeConfig) {
- Instance.createFileManager(ThreadSafeConfig->getVFS());
+ Instance.setVirtualFileSystem(ThreadSafeConfig->getVFS());
+ Instance.createFileManager();
} else if (FrontendOpts.ModulesShareFileManager) {
+ Instance.setVirtualFileSystem(getVirtualFileSystemPtr());
Instance.setFileManager(getFileManagerPtr());
} else {
- Instance.createFileManager(getVirtualFileSystemPtr());
+ Instance.setVirtualFileSystem(getVirtualFileSystemPtr());
+ Instance.createFileManager();
}
if (ThreadSafeConfig) {
- Instance.createDiagnostics(Instance.getVirtualFileSystem(),
- &ThreadSafeConfig->getDiagConsumer(),
+ Instance.createDiagnostics(&ThreadSafeConfig->getDiagConsumer(),
/*ShouldOwnClient=*/false);
} else {
Instance.createDiagnostics(
- Instance.getVirtualFileSystem(),
new ForwardingDiagnosticConsumer(getDiagnosticClient()),
/*ShouldOwnClient=*/true);
}
diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp
index 6b1fcac75ac2b..ca37e0661476d 100644
--- a/clang/lib/Frontend/FrontendAction.cpp
+++ b/clang/lib/Frontend/FrontendAction.cpp
@@ -876,6 +876,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
// Set the shared objects, these are reset when we finish processing the
// file, otherwise the CompilerInstance will happily destroy them.
+ CI.setVirtualFileSystem(AST->getFileManager().getVirtualFileSystemPtr());
CI.setFileManager(AST->getFileManagerPtr());
CI.createSourceManager(CI.getFileManager());
CI.getSourceManager().initializeForReplay(AST->getSourceManager());
@@ -966,7 +967,9 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
return true;
}
- // Set up the file and source managers, if needed.
+ // Set up the file system, file and source managers, if needed.
+ if (!CI.hasVirtualFileSystem())
+ CI.createVirtualFileSystem();
if (!CI.hasFileManager()) {
if (!CI.createFileManager()) {
return false;
diff --git a/clang/lib/Frontend/Rewrite/FrontendActions.cpp b/clang/lib/Frontend/Rewrite/FrontendActions.cpp
index 6c9c9d5b5c8d3..f5656b3b190e9 100644
--- a/clang/lib/Frontend/Rewrite/FrontendActions.cpp
+++ b/clang/lib/Frontend/Rewrite/FrontendActions.cpp
@@ -245,8 +245,8 @@ class RewriteIncludesAction::RewriteImportsListener : public ASTReaderListener {
CompilerInstance Instance(
std::make_shared<CompilerInvocation>(CI.getInvocation()),
CI.getPCHContainerOperations(), &CI.getModuleCache());
+ Instance.setVirtualFileSystem(CI.getVirtualFileSystemPtr());
Instance.createDiagnostics(
- CI.getVirtualFileSystem(),
new ForwardingDiagnosticConsumer(CI.getDiagnosticClient()),
/*ShouldOwnClient=*/true);
Instance.getFrontendOpts().DisableFree = false;
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp
index 84f1c363b5f6f..efb665c95ae7a 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -107,8 +107,10 @@ CreateCI(const llvm::opt::ArgStringList &Argv) {
Clang->getHeaderSearchOpts().ResourceDir =
CompilerInvocation::GetResourcesPath(Argv[0], nullptr);
+ Clang->createVirtualFileSystem();
+
// Create the actual diagnostics engine.
- Clang->createDiagnostics(*llvm::vfs::getRealFileSystem());
+ Clang->createDiagnostics();
if (!Clang->hasDiagnostics())
return llvm::createStringError(llvm::errc::not_supported,
"Initialization failed. "
@@ -474,7 +476,8 @@ Interpreter::createWithCUDA(std::unique_ptr<CompilerInstance> CI,
std::make_unique<llvm::vfs::OverlayFileSystem>(
llvm::vfs::getRealFileSystem());
OverlayVFS->pushOverlay(IMVFS);
- CI->createFileManager(OverlayVFS);
+ CI->createVirtualFileSystem(OverlayVFS);
+ CI->createFileManager();
llvm::Expected<std::unique_ptr<Interpreter>> InterpOrErr =
Interpreter::create(std::move(CI));
diff --git a/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp b/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp
index 975c72af0b031..be74ff2cd4799 100644
--- a/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp
+++ b/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp
@@ -84,8 +84,8 @@ void ModelInjector::onBodySynthesis(const NamedDecl *D) {
// behavior for models
CompilerInstance Instance(std::move(Invocation),
CI.getPCHContainerOperations());
+ Instance.setVirtualFileSystem(CI.getVirtualFileSystemPtr());
Instance.createDiagnostics(
- CI.getVirtualFileSystem(),
new ForwardingDiagnosticConsumer(CI.getDiagnosticClient()),
/*ShouldOwnClient=*/true);
diff --git a/clang/lib/Testing/TestAST.cpp b/clang/lib/Testing/TestAST.cpp
index b59a8d55129de..9ad0de95530fb 100644
--- a/clang/lib/Testing/TestAST.cpp
+++ b/clang/lib/Testing/TestAST.cpp
@@ -54,8 +54,10 @@ class StoreDiagnostics : public DiagnosticConsumer {
// Fills in the bits of a CompilerInstance that weren't initialized yet.
// Provides "empty" ASTContext etc if we fail before parsing gets started.
void createMissingComponents(CompilerInstance &Clang) {
+ if (!Clang.hasVirtualFileSystem())
+ Clang.createVirtualFileSystem();
if (!Clang.hasDiagnostics())
- Clang.createDiagnostics(*llvm::vfs::getRealFileSystem());
+ Clang.createDiagnostics();
if (!Clang.hasFileManager())
Clang.createFileManager();
if (!Clang.hasSourceManager())
@@ -98,7 +100,9 @@ TestAST::TestAST(const TestInputs &In) {
// Extra error conditions are reported through diagnostics, set that up first.
bool ErrorOK = In.ErrorOK || llvm::StringRef(In.Code).contains("error-ok");
- Clang->createDiagnostics(*VFS, new StoreDiagnostics(Diagnostics, !ErrorOK));
+ auto DiagConsumer = new StoreDiagnostics(Diagnostics, !ErrorOK);
+ Clang->createVirtualFileSystem(std::move(VFS), DiagConsumer);
+ Clang->createDiagnostics(DiagConsumer);
// Parse cc1 argv, (typically [-std=c++20 input.cc]) into CompilerInvocation.
std::vector<const char *> Argv;
@@ -115,7 +119,7 @@ TestAST::TestAST(const TestInputs &In) {
}
assert(!Clang->getInvocation().getFrontendOpts().DisableFree);
- Clang->createFileManager(VFS);
+ Clang->createFileManager();
// Running the FrontendAction creates the other components: SourceManager,
// Preprocessor, ASTContext, Sema. Preprocessor needs TargetInfo to be set.
diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
index 0855e6dec6158..0a12c479bf8e3 100644
--- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
+++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
@@ -414,11 +414,12 @@ class DependencyScanningAction {
CompilerInstance &ScanInstance = *ScanInstanceStorage;
ScanInstance.setBuildingModule(false);
+ ScanInstance.createVirtualFileSystem(FS, DiagConsumer);
+
// Create the compiler's actual diagnostics engine.
sanitizeDiagOpts(ScanInstance.getDiagnosticOpts());
assert(!DiagConsumerFinished && "attempt to reuse finished consumer");
- ScanInstance.createDiagnostics(*FS, DiagConsumer,
- /*ShouldOwnClient=*/false);
+ ScanInstance.createDiagnostics(DiagConsumer, /*ShouldOwnClient=*/false);
if (!ScanInstance.hasDiagnostics())
return false;
@@ -439,13 +440,8 @@ class DependencyScanningAction {
ScanInstance.getHeaderSearchOpts().ModulesIncludeVFSUsage =
any(Service.getOptimizeArgs() & ScanningOptimizations::VFS);
- // Support for virtual file system overlays.
- FS = createVFSFromCompilerInvocation(ScanInstance.getInvocation(),
- ScanInstance.getDiagnostics(),
- std::move(FS));
-
// Create a new FileManager to match the invocation's FileSystemOptions.
- auto *FileMgr = ScanInstance.createFileManager(FS);
+ auto *FileMgr = ScanInstance.createFileManager();
// Use the dependency scanning optimized file system if requested to do so.
if (DepFS) {
diff --git a/clang/lib/Tooling/Tooling.cpp b/clang/lib/Tooling/Tooling.cpp
index 0c179b852813d..2d4790b205b1a 100644
--- a/clang/lib/Tooling/Tooling.cpp
+++ b/clang/lib/Tooling/Tooling.cpp
@@ -454,8 +454,7 @@ bool FrontendActionFactory::runInvocation(
std::unique_ptr<FrontendAction> ScopedToolAction(create());
// Create the compiler's actual diagnostics engine.
- Compiler.createDiagnostics(Files->getVirtualFileSystem(), DiagConsumer,
- /*ShouldOwnClient=*/false);
+ Compiler.createDiagnostics(DiagConsumer, /*ShouldOwnClient=*/false);
if (!Compiler.hasDiagnostics())
return false;
diff --git a/clang/tools/clang-import-test/clang-import-test.cpp b/clang/tools/clang-import-test/clang-import-test.cpp
index ab021a51bf295..910e08ca4dffa 100644
--- a/clang/tools/clang-import-test/clang-import-test.cpp
+++ b/clang/tools/clang-import-test/clang-import-test.cpp
@@ -207,8 +207,8 @@ std::unique_ptr<CompilerInstance> BuildCompilerInstance() {
auto Ins = std::make_unique<CompilerInstance>(std::move(Inv));
- Ins->createDiagnostics(*llvm::vfs::getRealFileSystem(), DC.release(),
- /*ShouldOwnClient=*/true);
+ Ins->createVirtualFileSystem(llvm::vfs::getRealFileSystem(), DC.get());
+ Ins->createDiagnostics(DC.release(), /*ShouldOwnClient=*/true);
TargetInfo *TI = TargetInfo::CreateTargetInfo(
Ins->getDiagnostics(), Ins->getInvocation().getTargetOpts());
diff --git a/clang/tools/clang-installapi/ClangInstallAPI.cpp b/clang/tools/clang-installapi/ClangInstallAPI.cpp
index 049b0bd8f8dbf..16abeb10284c0 100644
--- a/clang/tools/clang-installapi/ClangInstallAPI.cpp
+++ b/clang/tools/clang-installapi/ClangInstallAPI.cpp
@@ -115,7 +115,7 @@ static bool run(ArrayRef<const char *> Args, const char *ProgName) {
// Set up compilation.
std::unique_ptr<CompilerInstance> CI(new CompilerInstance());
CI->setFileManager(FM);
- CI->createDiagnostics(FM->getVirtualFileSystem());
+ CI->createDiagnostics();
if (!CI->hasDiagnostics())
return EXIT_FAILURE;
diff --git a/clang/tools/driver/cc1_main.cpp b/clang/tools/driver/cc1_main.cpp
index 854ab3e33555b..49f8843515a35 100644
--- a/clang/tools/driver/cc1_main.cpp
+++ b/clang/tools/driver/cc1_main.cpp
@@ -271,8 +271,11 @@ int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
Clang->getHeaderSearchOpts().ResourceDir =
CompilerInvocation::GetRe...
[truncated]
|
@llvm/pr-subscribers-clang-driver Author: Jan Svoboda (jansvoboda11) ChangesThis PR is a part of the effort to make the VFS used in the compiler more explicit and consistent. Instead of creating the VFS deep within the compiler (in This PR also helps in breaking up the dependency cycle where creating a properly configured Both Patch is 36.47 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/158381.diff 27 Files Affected:
diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h
index 9f3d5f97cdff4..a6b6993b708d0 100644
--- a/clang/include/clang/Frontend/CompilerInstance.h
+++ b/clang/include/clang/Frontend/CompilerInstance.h
@@ -83,6 +83,9 @@ class CompilerInstance : public ModuleLoader {
/// The options used in this compiler instance.
std::shared_ptr<CompilerInvocation> Invocation;
+ /// The virtual file system instance.
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS;
+
/// The diagnostics engine instance.
IntrusiveRefCntPtr<DiagnosticsEngine> Diagnostics;
@@ -409,9 +412,31 @@ class CompilerInstance : public ModuleLoader {
/// @name Virtual File System
/// @{
- llvm::vfs::FileSystem &getVirtualFileSystem() const;
- llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
- getVirtualFileSystemPtr() const;
+ bool hasVirtualFileSystem() const { return VFS != nullptr; }
+
+ /// Create a virtual file system instance based on the invocation.
+ ///
+ /// @param BaseFS The file system that may be used when configuring the final
+ /// file system, and act as the underlying file system. Must not
+ /// be NULL.
+ /// @param DC If non-NULL, the diagnostic consumer to be used in case
+ /// configuring the file system emits diagnostics. Note that the
+ /// DiagnosticsEngine using the consumer won't obey the
+ /// --warning-suppression-mappings= flag.
+ void createVirtualFileSystem(IntrusiveRefCntPtr<llvm::vfs::FileSystem>
+ BaseFS = llvm::vfs::getRealFileSystem(),
+ DiagnosticConsumer *DC = nullptr);
+
+ /// Use the given file system.
+ void setVirtualFileSystem(IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS) {
+ VFS = std::move(FS);
+ }
+
+ llvm::vfs::FileSystem &getVirtualFileSystem() const { return *VFS; }
+
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> getVirtualFileSystemPtr() const {
+ return VFS;
+ }
/// @}
/// @name File Manager
@@ -650,32 +675,31 @@ class CompilerInstance : public ModuleLoader {
/// Note that this routine also replaces the diagnostic client,
/// allocating one if one is not provided.
///
- /// \param VFS is used for any IO needed when creating DiagnosticsEngine. It
- /// doesn't replace VFS in the CompilerInstance (if any).
- ///
/// \param Client If non-NULL, a diagnostic client that will be
/// attached to (and, then, owned by) the DiagnosticsEngine inside this AST
/// unit.
///
/// \param ShouldOwnClient If Client is non-NULL, specifies whether
/// the diagnostic object should take ownership of the client.
- void createDiagnostics(llvm::vfs::FileSystem &VFS,
- DiagnosticConsumer *Client = nullptr,
+ void createDiagnostics(DiagnosticConsumer *Client = nullptr,
bool ShouldOwnClient = true);
- /// Create a DiagnosticsEngine object with a the TextDiagnosticPrinter.
+ /// Create a DiagnosticsEngine object.
///
/// If no diagnostic client is provided, this creates a
/// DiagnosticConsumer that is owned by the returned diagnostic
/// object, if using directly the caller is responsible for
/// releasing the returned DiagnosticsEngine's client eventually.
///
+ /// \param VFS The file system used to load the suppression mappings file.
+ ///
/// \param Opts - The diagnostic options; note that the created text
/// diagnostic object contains a reference to these options.
///
/// \param Client If non-NULL, a diagnostic client that will be
/// attached to (and, then, owned by) the returned DiagnosticsEngine
- /// object.
+ /// object. If NULL, the returned DiagnosticsEngine will own a newly-created
+ /// client.
///
/// \param CodeGenOpts If non-NULL, the code gen options in use, which may be
/// used by some diagnostics printers (for logging purposes only).
@@ -690,8 +714,7 @@ class CompilerInstance : public ModuleLoader {
/// Create the file manager and replace any existing one with it.
///
/// \return The new file manager on success, or null on failure.
- FileManager *
- createFileManager(IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr);
+ FileManager *createFileManager();
/// Create the source manager and replace any existing one with it.
void createSourceManager(FileManager &FileMgr);
diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp
index 03b08cdabe39e..8b35af152cbc8 100644
--- a/clang/lib/Frontend/ASTUnit.cpp
+++ b/clang/lib/Frontend/ASTUnit.cpp
@@ -1189,10 +1189,12 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
// 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)
+ if (VFS && FileMgr && &FileMgr->getVirtualFileSystem() == VFS) {
+ Clang->setVirtualFileSystem(std::move(VFS));
Clang->setFileManager(FileMgr);
- else {
- Clang->createFileManager(std::move(VFS));
+ } else {
+ Clang->setVirtualFileSystem(std::move(VFS));
+ Clang->createFileManager();
FileMgr = Clang->getFileManagerPtr();
}
diff --git a/clang/lib/Frontend/ChainedIncludesSource.cpp b/clang/lib/Frontend/ChainedIncludesSource.cpp
index 013814a738a36..82249f893a795 100644
--- a/clang/lib/Frontend/ChainedIncludesSource.cpp
+++ b/clang/lib/Frontend/ChainedIncludesSource.cpp
@@ -124,6 +124,7 @@ clang::createChainedIncludesSource(CompilerInstance &CI,
auto Clang = std::make_unique<CompilerInstance>(
std::move(CInvok), CI.getPCHContainerOperations());
+ Clang->createVirtualFileSystem();
Clang->setDiagnostics(Diags);
Clang->setTarget(TargetInfo::CreateTargetInfo(
Clang->getDiagnostics(), Clang->getInvocation().getTargetOpts()));
diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp
index 31a8d75fec4bd..e8d0bb84c0f45 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -159,17 +159,11 @@ bool CompilerInstance::createTarget() {
return true;
}
-llvm::vfs::FileSystem &CompilerInstance::getVirtualFileSystem() const {
- return getFileManager().getVirtualFileSystem();
-}
-
-llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
-CompilerInstance::getVirtualFileSystemPtr() const {
- return getFileManager().getVirtualFileSystemPtr();
-}
-
-void CompilerInstance::setFileManager(
- llvm::IntrusiveRefCntPtr<FileManager> Value) {
+void CompilerInstance::setFileManager(IntrusiveRefCntPtr<FileManager> Value) {
+ if (!hasVirtualFileSystem())
+ setVirtualFileSystem(Value->getVirtualFileSystemPtr());
+ assert(Value == nullptr ||
+ getVirtualFileSystemPtr() == Value->getVirtualFileSystemPtr());
FileMgr = std::move(Value);
}
@@ -289,6 +283,20 @@ static void collectVFSEntries(CompilerInstance &CI,
MDC->addFile(E.VPath, E.RPath);
}
+void CompilerInstance::createVirtualFileSystem(
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS, DiagnosticConsumer *DC) {
+ DiagnosticOptions DiagOpts;
+ DiagnosticsEngine Diags(DiagnosticIDs::create(), DiagOpts, DC,
+ /*ShouldOwnClient=*/false);
+
+ VFS = createVFSFromCompilerInvocation(getInvocation(), Diags,
+ std::move(BaseFS));
+ // FIXME: Should this go into createVFSFromCompilerInvocation?
+ if (getFrontendOpts().ShowStats)
+ VFS =
+ llvm::makeIntrusiveRefCnt<llvm::vfs::TracingFileSystem>(std::move(VFS));
+}
+
// Diagnostics
static void SetUpDiagnosticLog(DiagnosticOptions &DiagOpts,
const CodeGenOptions *CodeGenOpts,
@@ -340,11 +348,10 @@ static void SetupSerializedDiagnostics(DiagnosticOptions &DiagOpts,
}
}
-void CompilerInstance::createDiagnostics(llvm::vfs::FileSystem &VFS,
- DiagnosticConsumer *Client,
+void CompilerInstance::createDiagnostics(DiagnosticConsumer *Client,
bool ShouldOwnClient) {
- Diagnostics = createDiagnostics(VFS, getDiagnosticOpts(), Client,
- ShouldOwnClient, &getCodeGenOpts());
+ Diagnostics = createDiagnostics(getVirtualFileSystem(), getDiagnosticOpts(),
+ Client, ShouldOwnClient, &getCodeGenOpts());
}
IntrusiveRefCntPtr<DiagnosticsEngine> CompilerInstance::createDiagnostics(
@@ -382,18 +389,9 @@ IntrusiveRefCntPtr<DiagnosticsEngine> CompilerInstance::createDiagnostics(
// File Manager
-FileManager *CompilerInstance::createFileManager(
- IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
- if (!VFS)
- VFS = FileMgr ? FileMgr->getVirtualFileSystemPtr()
- : createVFSFromCompilerInvocation(getInvocation(),
- getDiagnostics());
- assert(VFS && "FileManager has no VFS?");
- if (getFrontendOpts().ShowStats)
- VFS =
- llvm::makeIntrusiveRefCnt<llvm::vfs::TracingFileSystem>(std::move(VFS));
- FileMgr = llvm::makeIntrusiveRefCnt<FileManager>(getFileSystemOpts(),
- std::move(VFS));
+FileManager *CompilerInstance::createFileManager() {
+ assert(VFS && "CompilerInstance needs a VFS for creating FileManager");
+ FileMgr = llvm::makeIntrusiveRefCnt<FileManager>(getFileSystemOpts(), VFS);
return FileMgr.get();
}
@@ -1174,20 +1172,21 @@ std::unique_ptr<CompilerInstance> CompilerInstance::cloneForModuleCompileImpl(
auto &Inv = Instance.getInvocation();
if (ThreadSafeConfig) {
- Instance.createFileManager(ThreadSafeConfig->getVFS());
+ Instance.setVirtualFileSystem(ThreadSafeConfig->getVFS());
+ Instance.createFileManager();
} else if (FrontendOpts.ModulesShareFileManager) {
+ Instance.setVirtualFileSystem(getVirtualFileSystemPtr());
Instance.setFileManager(getFileManagerPtr());
} else {
- Instance.createFileManager(getVirtualFileSystemPtr());
+ Instance.setVirtualFileSystem(getVirtualFileSystemPtr());
+ Instance.createFileManager();
}
if (ThreadSafeConfig) {
- Instance.createDiagnostics(Instance.getVirtualFileSystem(),
- &ThreadSafeConfig->getDiagConsumer(),
+ Instance.createDiagnostics(&ThreadSafeConfig->getDiagConsumer(),
/*ShouldOwnClient=*/false);
} else {
Instance.createDiagnostics(
- Instance.getVirtualFileSystem(),
new ForwardingDiagnosticConsumer(getDiagnosticClient()),
/*ShouldOwnClient=*/true);
}
diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp
index 6b1fcac75ac2b..ca37e0661476d 100644
--- a/clang/lib/Frontend/FrontendAction.cpp
+++ b/clang/lib/Frontend/FrontendAction.cpp
@@ -876,6 +876,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
// Set the shared objects, these are reset when we finish processing the
// file, otherwise the CompilerInstance will happily destroy them.
+ CI.setVirtualFileSystem(AST->getFileManager().getVirtualFileSystemPtr());
CI.setFileManager(AST->getFileManagerPtr());
CI.createSourceManager(CI.getFileManager());
CI.getSourceManager().initializeForReplay(AST->getSourceManager());
@@ -966,7 +967,9 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
return true;
}
- // Set up the file and source managers, if needed.
+ // Set up the file system, file and source managers, if needed.
+ if (!CI.hasVirtualFileSystem())
+ CI.createVirtualFileSystem();
if (!CI.hasFileManager()) {
if (!CI.createFileManager()) {
return false;
diff --git a/clang/lib/Frontend/Rewrite/FrontendActions.cpp b/clang/lib/Frontend/Rewrite/FrontendActions.cpp
index 6c9c9d5b5c8d3..f5656b3b190e9 100644
--- a/clang/lib/Frontend/Rewrite/FrontendActions.cpp
+++ b/clang/lib/Frontend/Rewrite/FrontendActions.cpp
@@ -245,8 +245,8 @@ class RewriteIncludesAction::RewriteImportsListener : public ASTReaderListener {
CompilerInstance Instance(
std::make_shared<CompilerInvocation>(CI.getInvocation()),
CI.getPCHContainerOperations(), &CI.getModuleCache());
+ Instance.setVirtualFileSystem(CI.getVirtualFileSystemPtr());
Instance.createDiagnostics(
- CI.getVirtualFileSystem(),
new ForwardingDiagnosticConsumer(CI.getDiagnosticClient()),
/*ShouldOwnClient=*/true);
Instance.getFrontendOpts().DisableFree = false;
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp
index 84f1c363b5f6f..efb665c95ae7a 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -107,8 +107,10 @@ CreateCI(const llvm::opt::ArgStringList &Argv) {
Clang->getHeaderSearchOpts().ResourceDir =
CompilerInvocation::GetResourcesPath(Argv[0], nullptr);
+ Clang->createVirtualFileSystem();
+
// Create the actual diagnostics engine.
- Clang->createDiagnostics(*llvm::vfs::getRealFileSystem());
+ Clang->createDiagnostics();
if (!Clang->hasDiagnostics())
return llvm::createStringError(llvm::errc::not_supported,
"Initialization failed. "
@@ -474,7 +476,8 @@ Interpreter::createWithCUDA(std::unique_ptr<CompilerInstance> CI,
std::make_unique<llvm::vfs::OverlayFileSystem>(
llvm::vfs::getRealFileSystem());
OverlayVFS->pushOverlay(IMVFS);
- CI->createFileManager(OverlayVFS);
+ CI->createVirtualFileSystem(OverlayVFS);
+ CI->createFileManager();
llvm::Expected<std::unique_ptr<Interpreter>> InterpOrErr =
Interpreter::create(std::move(CI));
diff --git a/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp b/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp
index 975c72af0b031..be74ff2cd4799 100644
--- a/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp
+++ b/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp
@@ -84,8 +84,8 @@ void ModelInjector::onBodySynthesis(const NamedDecl *D) {
// behavior for models
CompilerInstance Instance(std::move(Invocation),
CI.getPCHContainerOperations());
+ Instance.setVirtualFileSystem(CI.getVirtualFileSystemPtr());
Instance.createDiagnostics(
- CI.getVirtualFileSystem(),
new ForwardingDiagnosticConsumer(CI.getDiagnosticClient()),
/*ShouldOwnClient=*/true);
diff --git a/clang/lib/Testing/TestAST.cpp b/clang/lib/Testing/TestAST.cpp
index b59a8d55129de..9ad0de95530fb 100644
--- a/clang/lib/Testing/TestAST.cpp
+++ b/clang/lib/Testing/TestAST.cpp
@@ -54,8 +54,10 @@ class StoreDiagnostics : public DiagnosticConsumer {
// Fills in the bits of a CompilerInstance that weren't initialized yet.
// Provides "empty" ASTContext etc if we fail before parsing gets started.
void createMissingComponents(CompilerInstance &Clang) {
+ if (!Clang.hasVirtualFileSystem())
+ Clang.createVirtualFileSystem();
if (!Clang.hasDiagnostics())
- Clang.createDiagnostics(*llvm::vfs::getRealFileSystem());
+ Clang.createDiagnostics();
if (!Clang.hasFileManager())
Clang.createFileManager();
if (!Clang.hasSourceManager())
@@ -98,7 +100,9 @@ TestAST::TestAST(const TestInputs &In) {
// Extra error conditions are reported through diagnostics, set that up first.
bool ErrorOK = In.ErrorOK || llvm::StringRef(In.Code).contains("error-ok");
- Clang->createDiagnostics(*VFS, new StoreDiagnostics(Diagnostics, !ErrorOK));
+ auto DiagConsumer = new StoreDiagnostics(Diagnostics, !ErrorOK);
+ Clang->createVirtualFileSystem(std::move(VFS), DiagConsumer);
+ Clang->createDiagnostics(DiagConsumer);
// Parse cc1 argv, (typically [-std=c++20 input.cc]) into CompilerInvocation.
std::vector<const char *> Argv;
@@ -115,7 +119,7 @@ TestAST::TestAST(const TestInputs &In) {
}
assert(!Clang->getInvocation().getFrontendOpts().DisableFree);
- Clang->createFileManager(VFS);
+ Clang->createFileManager();
// Running the FrontendAction creates the other components: SourceManager,
// Preprocessor, ASTContext, Sema. Preprocessor needs TargetInfo to be set.
diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
index 0855e6dec6158..0a12c479bf8e3 100644
--- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
+++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
@@ -414,11 +414,12 @@ class DependencyScanningAction {
CompilerInstance &ScanInstance = *ScanInstanceStorage;
ScanInstance.setBuildingModule(false);
+ ScanInstance.createVirtualFileSystem(FS, DiagConsumer);
+
// Create the compiler's actual diagnostics engine.
sanitizeDiagOpts(ScanInstance.getDiagnosticOpts());
assert(!DiagConsumerFinished && "attempt to reuse finished consumer");
- ScanInstance.createDiagnostics(*FS, DiagConsumer,
- /*ShouldOwnClient=*/false);
+ ScanInstance.createDiagnostics(DiagConsumer, /*ShouldOwnClient=*/false);
if (!ScanInstance.hasDiagnostics())
return false;
@@ -439,13 +440,8 @@ class DependencyScanningAction {
ScanInstance.getHeaderSearchOpts().ModulesIncludeVFSUsage =
any(Service.getOptimizeArgs() & ScanningOptimizations::VFS);
- // Support for virtual file system overlays.
- FS = createVFSFromCompilerInvocation(ScanInstance.getInvocation(),
- ScanInstance.getDiagnostics(),
- std::move(FS));
-
// Create a new FileManager to match the invocation's FileSystemOptions.
- auto *FileMgr = ScanInstance.createFileManager(FS);
+ auto *FileMgr = ScanInstance.createFileManager();
// Use the dependency scanning optimized file system if requested to do so.
if (DepFS) {
diff --git a/clang/lib/Tooling/Tooling.cpp b/clang/lib/Tooling/Tooling.cpp
index 0c179b852813d..2d4790b205b1a 100644
--- a/clang/lib/Tooling/Tooling.cpp
+++ b/clang/lib/Tooling/Tooling.cpp
@@ -454,8 +454,7 @@ bool FrontendActionFactory::runInvocation(
std::unique_ptr<FrontendAction> ScopedToolAction(create());
// Create the compiler's actual diagnostics engine.
- Compiler.createDiagnostics(Files->getVirtualFileSystem(), DiagConsumer,
- /*ShouldOwnClient=*/false);
+ Compiler.createDiagnostics(DiagConsumer, /*ShouldOwnClient=*/false);
if (!Compiler.hasDiagnostics())
return false;
diff --git a/clang/tools/clang-import-test/clang-import-test.cpp b/clang/tools/clang-import-test/clang-import-test.cpp
index ab021a51bf295..910e08ca4dffa 100644
--- a/clang/tools/clang-import-test/clang-import-test.cpp
+++ b/clang/tools/clang-import-test/clang-import-test.cpp
@@ -207,8 +207,8 @@ std::unique_ptr<CompilerInstance> BuildCompilerInstance() {
auto Ins = std::make_unique<CompilerInstance>(std::move(Inv));
- Ins->createDiagnostics(*llvm::vfs::getRealFileSystem(), DC.release(),
- /*ShouldOwnClient=*/true);
+ Ins->createVirtualFileSystem(llvm::vfs::getRealFileSystem(), DC.get());
+ Ins->createDiagnostics(DC.release(), /*ShouldOwnClient=*/true);
TargetInfo *TI = TargetInfo::CreateTargetInfo(
Ins->getDiagnostics(), Ins->getInvocation().getTargetOpts());
diff --git a/clang/tools/clang-installapi/ClangInstallAPI.cpp b/clang/tools/clang-installapi/ClangInstallAPI.cpp
index 049b0bd8f8dbf..16abeb10284c0 100644
--- a/clang/tools/clang-installapi/ClangInstallAPI.cpp
+++ b/clang/tools/clang-installapi/ClangInstallAPI.cpp
@@ -115,7 +115,7 @@ static bool run(ArrayRef<const char *> Args, const char *ProgName) {
// Set up compilation.
std::unique_ptr<CompilerInstance> CI(new CompilerInstance());
CI->setFileManager(FM);
- CI->createDiagnostics(FM->getVirtualFileSystem());
+ CI->createDiagnostics();
if (!CI->hasDiagnostics())
return EXIT_FAILURE;
diff --git a/clang/tools/driver/cc1_main.cpp b/clang/tools/driver/cc1_main.cpp
index 854ab3e33555b..49f8843515a35 100644
--- a/clang/tools/driver/cc1_main.cpp
+++ b/clang/tools/driver/cc1_main.cpp
@@ -271,8 +271,11 @@ int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
Clang->getHeaderSearchOpts().ResourceDir =
CompilerInvocation::GetRe...
[truncated]
|
This PR is a part of the effort to make the VFS used in the compiler more explicit and consistent.
Instead of creating the VFS deep within the compiler (in
CompilerInstance::createFileManager()
), clients are now required to explicitly callCompilerInstance::createVirtualFileSystem()
and provide the base VFS from the outside.This PR also helps in breaking up the dependency cycle where creating a properly configured
DiagnosticsEngine
requires a properly configured VFS, but creating properly configuring a VFS requires theDiagnosticsEngine
.Both
CompilerInstance::create{FileManager,Diagnostics}()
now just use the VFS already inCompilerInstance
instead of taking one as a parameter, making the VFS consistent across the instance sub-object.