[clang] [clang] Enable making `CompilerInstance` VFS thread-safe (PR #135737)
Jan Svoboda via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 14 20:06:47 PDT 2025
https://github.com/jansvoboda11 created https://github.com/llvm/llvm-project/pull/135737
The `llvm::vfs::FileSystem` interface makes no promises around thread-safety. To enable making `CompilerInstance` thread-safe, this PR allows passing an explicit VFS to `cloneForModuleCompile()`. This will be used from the dependency scanner.
>From 388447be4ef30fdf0470cf21db1a9675519d894d Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Fri, 11 Apr 2025 10:13:49 -0700
Subject: [PATCH] [clang] Enable making `CompilerInstance` VFS thread-safe
The `llvm::vfs::FileSystem` interface makes no promises around thread-safety. To enable making `CompilerInstance` thread-safe, this PR allows passing an explicit VFS to `cloneForModuleCompile()`. This will be used from the dependency scanner.
---
.../include/clang/Frontend/CompilerInstance.h | 15 +++++++---
clang/lib/Frontend/CompilerInstance.cpp | 28 +++++++++++--------
2 files changed, 28 insertions(+), 15 deletions(-)
diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h
index 41dc7f1fef461..d70f5c45b3d38 100644
--- a/clang/include/clang/Frontend/CompilerInstance.h
+++ b/clang/include/clang/Frontend/CompilerInstance.h
@@ -845,18 +845,25 @@ class CompilerInstance : public ModuleLoader {
/// Creates a \c CompilerInstance for compiling a module.
///
/// This expects a properly initialized \c FrontendInputFile.
+ ///
+ /// Explicitly-specified \c VFS takes precedence over the VFS of this instance
+ /// when creating the clone and also prevents \c FileManager sharing.
std::unique_ptr<CompilerInstance> cloneForModuleCompileImpl(
SourceLocation ImportLoc, StringRef ModuleName, FrontendInputFile Input,
- StringRef OriginalModuleMapFile, StringRef ModuleFileName);
+ StringRef OriginalModuleMapFile, StringRef ModuleFileName,
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr);
public:
/// Creates a new \c CompilerInstance for compiling a module.
///
/// This takes care of creating appropriate \c FrontendInputFile for
/// public/private frameworks, inferred modules and such.
- std::unique_ptr<CompilerInstance>
- cloneForModuleCompile(SourceLocation ImportLoc, Module *Module,
- StringRef ModuleFileName);
+ ///
+ /// Explicitly-specified \c VFS takes precedence over the VFS of this instance
+ /// when creating the clone and also prevents \c FileManager sharing.
+ std::unique_ptr<CompilerInstance> cloneForModuleCompile(
+ SourceLocation ImportLoc, Module *Module, StringRef ModuleFileName,
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr);
/// Compile a module file for the given module, using the options
/// provided by the importing compiler instance. Returns true if the module
diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp
index 243e0a3c15b05..fa6b137338f26 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -1152,7 +1152,8 @@ static Language getLanguageFromOptions(const LangOptions &LangOpts) {
std::unique_ptr<CompilerInstance> CompilerInstance::cloneForModuleCompileImpl(
SourceLocation ImportLoc, StringRef ModuleName, FrontendInputFile Input,
- StringRef OriginalModuleMapFile, StringRef ModuleFileName) {
+ StringRef OriginalModuleMapFile, StringRef ModuleFileName,
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
// Construct a compiler invocation for creating this module.
auto Invocation = std::make_shared<CompilerInvocation>(getInvocation());
@@ -1212,19 +1213,21 @@ std::unique_ptr<CompilerInstance> CompilerInstance::cloneForModuleCompileImpl(
auto &Inv = *Invocation;
Instance.setInvocation(std::move(Invocation));
+ if (VFS) {
+ Instance.createFileManager(std::move(VFS));
+ } else if (FrontendOpts.ModulesShareFileManager) {
+ Instance.setFileManager(&getFileManager());
+ } else {
+ Instance.createFileManager(&getVirtualFileSystem());
+ }
+
Instance.createDiagnostics(
- getVirtualFileSystem(),
+ Instance.getVirtualFileSystem(),
new ForwardingDiagnosticConsumer(getDiagnosticClient()),
/*ShouldOwnClient=*/true);
-
if (llvm::is_contained(DiagOpts.SystemHeaderWarningsModules, ModuleName))
Instance.getDiagnostics().setSuppressSystemWarnings(false);
- if (FrontendOpts.ModulesShareFileManager) {
- Instance.setFileManager(&getFileManager());
- } else {
- Instance.createFileManager(&getVirtualFileSystem());
- }
Instance.createSourceManager(Instance.getFileManager());
SourceManager &SourceMgr = Instance.getSourceManager();
@@ -1318,7 +1321,8 @@ static OptionalFileEntryRef getPublicModuleMap(FileEntryRef File,
}
std::unique_ptr<CompilerInstance> CompilerInstance::cloneForModuleCompile(
- SourceLocation ImportLoc, Module *Module, StringRef ModuleFileName) {
+ SourceLocation ImportLoc, Module *Module, StringRef ModuleFileName,
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
StringRef ModuleName = Module->getTopLevelModuleName();
InputKind IK(getLanguageFromOptions(getLangOpts()), InputKind::ModuleMap);
@@ -1363,7 +1367,8 @@ std::unique_ptr<CompilerInstance> CompilerInstance::cloneForModuleCompile(
return cloneForModuleCompileImpl(
ImportLoc, ModuleName,
FrontendInputFile(ModuleMapFilePath, IK, IsSystem),
- ModMap.getModuleMapFileForUniquing(Module)->getName(), ModuleFileName);
+ ModMap.getModuleMapFileForUniquing(Module)->getName(), ModuleFileName,
+ std::move(VFS));
}
// FIXME: We only need to fake up an input file here as a way of
@@ -1380,7 +1385,8 @@ std::unique_ptr<CompilerInstance> CompilerInstance::cloneForModuleCompile(
auto Instance = cloneForModuleCompileImpl(
ImportLoc, ModuleName,
FrontendInputFile(FakeModuleMapFile, IK, +Module->IsSystem),
- ModMap.getModuleMapFileForUniquing(Module)->getName(), ModuleFileName);
+ ModMap.getModuleMapFileForUniquing(Module)->getName(), ModuleFileName,
+ std::move(VFS));
std::unique_ptr<llvm::MemoryBuffer> ModuleMapBuffer =
llvm::MemoryBuffer::getMemBufferCopy(InferredModuleMapContent);
More information about the cfe-commits
mailing list