-
Couldn't load subscription status.
- 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
Conversation
|
@llvm/pr-subscribers-lldb @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]
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Clang Static Analyzer change looks good to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Other than the build failure, the current change LGTM.
With the early initialization of the VFS, the CAS is now being initialized too late. This PR initializes CAS along with the VFS so that the CAS filesystem can sit at the bottom.
[clang] Fix CAS initialization after upstream llvm#158381
…y-vfs [clang] Fix CAS initialization after upstream llvm#158381 (cherry picked from commit 6d73002)
…llvm#158695) This PR changes the behavior of `clang::ExecuteCompilerInvocation()` so that it only returns early when the `DiagnosticsEngine` emitted errors **within** the function. Handling errors emitted before the function got called is a responsibility of the caller. Necessary for llvm#158381. (cherry picked from commit f33fb0d)
…llvm#158695) This PR changes the behavior of `clang::ExecuteCompilerInvocation()` so that it only returns early when the `DiagnosticsEngine` emitted errors **within** the function. Handling errors emitted before the function got called is a responsibility of the caller. Necessary for llvm#158381. (cherry picked from commit f33fb0d)
…llvm#158695) This PR changes the behavior of `clang::ExecuteCompilerInvocation()` so that it only returns early when the `DiagnosticsEngine` emitted errors **within** the function. Handling errors emitted before the function got called is a responsibility of the caller. Necessary for llvm#158381. (cherry picked from commit f33fb0d)
[clang] Fix CAS initialization after upstream llvm#158381 (cherry picked from commit 6d73002)
Since #158381 the `CompilerInstance` is aware of the VFS and co-owns it. To reduce scope of that PR, the VFS was being inherited from the `FileManager` during `setFileManager()` if it wasn't configured before. However, the implementation of that setter was buggy. This PR fixes the bug, and moves us closer to the long-term goal of `CompilerInstance` requiring the VFS to be configured explicitly and owned by the instance.
…(#164323) Since llvm/llvm-project#158381 the `CompilerInstance` is aware of the VFS and co-owns it. To reduce scope of that PR, the VFS was being inherited from the `FileManager` during `setFileManager()` if it wasn't configured before. However, the implementation of that setter was buggy. This PR fixes the bug, and moves us closer to the long-term goal of `CompilerInstance` requiring the VFS to be configured explicitly and owned by the instance.
Since llvm#158381 the `CompilerInstance` is aware of the VFS and co-owns it. To reduce scope of that PR, the VFS was being inherited from the `FileManager` during `setFileManager()` if it wasn't configured before. However, the implementation of that setter was buggy. This PR fixes the bug, and moves us closer to the long-term goal of `CompilerInstance` requiring the VFS to be configured explicitly and owned by the instance.
…llvm#158695) This PR changes the behavior of `clang::ExecuteCompilerInvocation()` so that it only returns early when the `DiagnosticsEngine` emitted errors **within** the function. Handling errors emitted before the function got called is a responsibility of the caller. Necessary for llvm#158381. (cherry picked from commit f33fb0d)
[clang] Fix CAS initialization after upstream llvm#158381 (cherry picked from commit 6d73002)
Since llvm#158381 the `CompilerInstance` is aware of the VFS and co-owns it. To reduce scope of that PR, the VFS was being inherited from the `FileManager` during `setFileManager()` if it wasn't configured before. However, the implementation of that setter was buggy. This PR fixes the bug, and moves us closer to the long-term goal of `CompilerInstance` requiring the VFS to be configured explicitly and owned by the instance.
Since llvm#158381 the `CompilerInstance` is aware of the VFS and co-owns it. To reduce scope of that PR, the VFS was being inherited from the `FileManager` during `setFileManager()` if it wasn't configured before. However, the implementation of that setter was buggy. This PR fixes the bug, and moves us closer to the long-term goal of `CompilerInstance` requiring the VFS to be configured explicitly and owned by the instance.
…Instance Sharing (#11631) * [clang][deps] Remove dependency on `tooling::ToolAction` (llvm#149904) The dependency scanner was initially using a fair amount of infrastructure provided by the `clangTooling` library. Over time, the needs for bespoke handling of command lines grew and the overlap with the tooling library kept shrinking. I don't think the library provides any value anymore. I decided to remove the dependency and only reimplement the small bits required by the scanner. This allowed for a nice simplification, where we no longer need to create temporary dummy `FileManager` instances (mis-named as `DriverFileMgr` in some parts) and `SourceManager` instances to attach to the `DiagnosticsEngine`. That code was copied from the tooling library to support `DiagnosticConsumers` that expect these to exist. The scanner uses a closed set of consumers and none need these objects to exist. The motivation for this (hopefully NFC) patch are some new restrictions to how VFS's can be propagated in Clang that I'm working on. (cherry picked from commit aa1b416) * Reland "[clang] Delay normalization of `-fmodules-cache-path` (llvm#150123)" This reverts commit 613caa9, essentially reapplying 4a4bdde after moving `normalizeModuleCachePath` from clangFrontend to clangLex. This PR is part of an effort to remove file system usage from the command line parsing code. The reason for that is that it's impossible to do file system access correctly without a configured VFS, and the VFS can only be configured after the command line is parsed. I don't want to intertwine command line parsing and VFS configuration, so I decided to perform the file system access after the command line is parsed and the VFS is configured - ideally right before the file system entity is used for the first time. This patch delays normalization of the module cache path until `CompilerInstance` is asked for the cache path in the current compilation context. (cherry picked from commit 55bef46) * NFC: Clean up of IntrusiveRefCntPtr construction from raw pointers. (llvm#151545) Handles clang::DiagnosticsEngine and clang::DiagnosticIDs. For DiagnosticIDs, this mostly migrates from `new DiagnosticIDs` to convenience method `DiagnosticIDs::create()`. Part of cleanup llvm#151026 (cherry picked from commit c7f3437) Conflicts: clang/tools/driver/cc1_main.cpp clang/unittests/Driver/DXCModeTest.cpp clang/unittests/Driver/SimpleDiagnosticConsumer.h clang/unittests/Frontend/SearchPathTest.cpp clang/unittests/Lex/HeaderSearchTest.cpp clang/unittests/Tooling/RewriterTestContext.h * NFC: Clean up of IntrusiveRefCntPtr construction from raw pointers. (llvm#151782) This commit handles the following types: - clang::ExternalASTSource - clang::TargetInfo - clang::ASTContext - clang::SourceManager - clang::FileManager Part of cleanup llvm#151026 (cherry picked from commit 4205da0) Conflicts: clang/lib/Frontend/ASTUnit.cpp clang/lib/Frontend/ChainedIncludesSource.cpp clang/lib/Frontend/CompilerInstance.cpp * Merge commit '30633f308941' from llvm.org/main into next (cherry picked from commit 95ea104) Conflicts: clang/include/clang/Frontend/CompilerInstance.h clang/lib/Frontend/CompilerInstance.cpp * Merge pull request #11450 from swiftlang/jan_svoboda/cas-fix-early-vfs [clang] Fix CAS initialization after upstream llvm#158381 (cherry picked from commit 6d73002) * [clang] Avoid reparsing VFS overlay files for module dep collector (llvm#158372) This PR uses the new-ish `llvm::vfs::FileSystem::visit()` interface to collect VFS overlay entries from an existing `FileSystem` instance rather than parsing the VFS YAML file anew. This prevents duplicate diagnostics as observed by `clang/test/VFS/broken-vfs-module-dep.c`. (cherry picked from commit 4957c47) * [clang] Don't fail `ExecuteCompilerInvocation()` due to caller errors (llvm#158695) This PR changes the behavior of `clang::ExecuteCompilerInvocation()` so that it only returns early when the `DiagnosticsEngine` emitted errors **within** the function. Handling errors emitted before the function got called is a responsibility of the caller. Necessary for llvm#158381. (cherry picked from commit f33fb0d) * [clang] Only set non-empty bypass to scan VFS (llvm#159605) Normalizing an empty modules cache path results in an incorrect non-empty path (the working directory). This PR conditionalizes more code to avoid this. Tested downstream by swift/llvm-project and the `DependencyScanningCAPITests.DependencyScanningFSCacheOutOfDate` unit test. (cherry picked from commit 5a339b0) * Merge commit '0e35f56d40d3' from llvm.org/main into next (cherry picked from commit 3efcc0f) Conflicts: clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp * [clang] NFCI: Clean up `CompilerInstance::create{File,Source}Manager()` (llvm#160748) The `CompilerInstance::createSourceManager()` function currently accepts the `FileManager` to be used. However, all clients call `CompilerInstance::createFileManager()` prior to creating the `SourceManager`, and it never makes sense to use a `FileManager` in the `SourceManager` that's different from the rest of the compiler. Passing the `FileManager` explicitly is redundant, error-prone, and deviates from the style of other `CompilerInstance` initialization APIs. This PR therefore removes the `FileManager` parameter from `createSourceManager()` and also stops returning the `FileManager` pointer from `createFileManager()`, since that was its primary use. Now, `createSourceManager()` internally calls `getFileManager()` instead. (cherry picked from commit b86ddae) Conflicts: clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.cpp * Merge commit '436861645247' from llvm.org/main into next (cherry picked from commit 286ea7d) Conflicts: clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp * [clang] Pass VFS into `ASTUnit::LoadFromASTFile()` (llvm#159166) This PR makes the `VFS` parameter to `ASTUnit::LoadFromASTFile()` required and explicit, rather than silently defaulting to the real file system. This makes it easy to correctly propagate the fully-configured VFS and load any input files like the rest of the compiler does. (cherry picked from commit cda542d) * Fix a line missing when merging 30633f3 * [clang][deps] Fix a use-after-free from expanding response files (llvm#164676) In 4368616 we accidentally moved uses of command-line args saved into a bump pointer allocator during response file expansion out of scope of the allocator. Also, the test that should have caught this (at least with asan) was not working correctly because clang-scan-deps was expanding response files itself during argument adjustment rather than the underlying scanner library. rdar://162720059 (cherry picked from commit 3e6f696) --------- Co-authored-by: Jan Svoboda <jan_svoboda@apple.com> Co-authored-by: James Y Knight <jyknight@google.com> Co-authored-by: git apple-llvm automerger <am@git-apple-llvm> Co-authored-by: Ben Langmuir <blangmuir@apple.com>
Since llvm#158381 the `CompilerInstance` is aware of the VFS and co-owns it. To reduce scope of that PR, the VFS was being inherited from the `FileManager` during `setFileManager()` if it wasn't configured before. However, the implementation of that setter was buggy. This PR fixes the bug, and moves us closer to the long-term goal of `CompilerInstance` requiring the VFS to be configured explicitly and owned by the instance.
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
DiagnosticsEnginerequires a properly configured VFS, but creating properly configuring a VFS requires theDiagnosticsEngine.Both
CompilerInstance::create{FileManager,Diagnostics}()now just use the VFS already inCompilerInstanceinstead of taking one as a parameter, making the VFS consistent across the instance sub-object.