Skip to content

Commit 30633f3

Browse files
authored
[clang] Initialize the file system explicitly (#158381)
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 call `CompilerInstance::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 the `DiagnosticsEngine`. Both `CompilerInstance::create{FileManager,Diagnostics}()` now just use the VFS already in `CompilerInstance` instead of taking one as a parameter, making the VFS consistent across the instance sub-object.
1 parent 9865f7e commit 30633f3

File tree

33 files changed

+164
-119
lines changed

33 files changed

+164
-119
lines changed

clang-tools-extra/clang-include-fixer/IncludeFixer.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,7 @@ bool IncludeFixerActionFactory::runInvocation(
9494

9595
// Create the compiler's actual diagnostics engine. We want to drop all
9696
// diagnostics here.
97-
Compiler.createDiagnostics(Files->getVirtualFileSystem(),
98-
new clang::IgnoringDiagConsumer,
97+
Compiler.createDiagnostics(new clang::IgnoringDiagConsumer,
9998
/*ShouldOwnClient=*/true);
10099
Compiler.createSourceManager(*Files);
101100

clang-tools-extra/clangd/Compiler.cpp

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -147,13 +147,9 @@ prepareCompilerInstance(std::unique_ptr<clang::CompilerInvocation> CI,
147147
}
148148

149149
auto Clang = std::make_unique<CompilerInstance>(std::move(CI));
150-
Clang->createDiagnostics(*VFS, &DiagsClient, false);
151-
152-
if (auto VFSWithRemapping = createVFSFromCompilerInvocation(
153-
Clang->getInvocation(), Clang->getDiagnostics(), VFS))
154-
VFS = VFSWithRemapping;
155-
Clang->createFileManager(VFS);
156-
150+
Clang->createVirtualFileSystem(VFS, &DiagsClient);
151+
Clang->createDiagnostics(&DiagsClient, false);
152+
Clang->createFileManager();
157153
if (!Clang->createTarget())
158154
return nullptr;
159155

clang-tools-extra/include-cleaner/unittests/RecordTest.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -646,9 +646,10 @@ TEST_F(PragmaIncludeTest, ExportInUnnamedBuffer) {
646646
*Diags, "clang"));
647647

648648
auto Clang = std::make_unique<CompilerInstance>(std::move(Invocation));
649-
Clang->createDiagnostics(*VFS);
649+
Clang->createVirtualFileSystem(VFS);
650+
Clang->createDiagnostics();
650651

651-
auto *FM = Clang->createFileManager(VFS);
652+
auto *FM = Clang->createFileManager();
652653
ASSERT_TRUE(Clang->ExecuteAction(*Inputs.MakeAction()));
653654
EXPECT_THAT(
654655
PI.getExporters(llvm::cantFail(FM->getFileRef("foo.h")), *FM),

clang/include/clang/Frontend/CompilerInstance.h

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ class CompilerInstance : public ModuleLoader {
8383
/// The options used in this compiler instance.
8484
std::shared_ptr<CompilerInvocation> Invocation;
8585

86+
/// The virtual file system instance.
87+
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS;
88+
8689
/// The diagnostics engine instance.
8790
IntrusiveRefCntPtr<DiagnosticsEngine> Diagnostics;
8891

@@ -409,9 +412,31 @@ class CompilerInstance : public ModuleLoader {
409412
/// @name Virtual File System
410413
/// @{
411414

412-
llvm::vfs::FileSystem &getVirtualFileSystem() const;
413-
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
414-
getVirtualFileSystemPtr() const;
415+
bool hasVirtualFileSystem() const { return VFS != nullptr; }
416+
417+
/// Create a virtual file system instance based on the invocation.
418+
///
419+
/// @param BaseFS The file system that may be used when configuring the final
420+
/// file system, and act as the underlying file system. Must not
421+
/// be NULL.
422+
/// @param DC If non-NULL, the diagnostic consumer to be used in case
423+
/// configuring the file system emits diagnostics. Note that the
424+
/// DiagnosticsEngine using the consumer won't obey the
425+
/// --warning-suppression-mappings= flag.
426+
void createVirtualFileSystem(IntrusiveRefCntPtr<llvm::vfs::FileSystem>
427+
BaseFS = llvm::vfs::getRealFileSystem(),
428+
DiagnosticConsumer *DC = nullptr);
429+
430+
/// Use the given file system.
431+
void setVirtualFileSystem(IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS) {
432+
VFS = std::move(FS);
433+
}
434+
435+
llvm::vfs::FileSystem &getVirtualFileSystem() const { return *VFS; }
436+
437+
IntrusiveRefCntPtr<llvm::vfs::FileSystem> getVirtualFileSystemPtr() const {
438+
return VFS;
439+
}
415440

416441
/// @}
417442
/// @name File Manager
@@ -650,32 +675,31 @@ class CompilerInstance : public ModuleLoader {
650675
/// Note that this routine also replaces the diagnostic client,
651676
/// allocating one if one is not provided.
652677
///
653-
/// \param VFS is used for any IO needed when creating DiagnosticsEngine. It
654-
/// doesn't replace VFS in the CompilerInstance (if any).
655-
///
656678
/// \param Client If non-NULL, a diagnostic client that will be
657679
/// attached to (and, then, owned by) the DiagnosticsEngine inside this AST
658680
/// unit.
659681
///
660682
/// \param ShouldOwnClient If Client is non-NULL, specifies whether
661683
/// the diagnostic object should take ownership of the client.
662-
void createDiagnostics(llvm::vfs::FileSystem &VFS,
663-
DiagnosticConsumer *Client = nullptr,
684+
void createDiagnostics(DiagnosticConsumer *Client = nullptr,
664685
bool ShouldOwnClient = true);
665686

666-
/// Create a DiagnosticsEngine object with a the TextDiagnosticPrinter.
687+
/// Create a DiagnosticsEngine object.
667688
///
668689
/// If no diagnostic client is provided, this creates a
669690
/// DiagnosticConsumer that is owned by the returned diagnostic
670691
/// object, if using directly the caller is responsible for
671692
/// releasing the returned DiagnosticsEngine's client eventually.
672693
///
694+
/// \param VFS The file system used to load the suppression mappings file.
695+
///
673696
/// \param Opts - The diagnostic options; note that the created text
674697
/// diagnostic object contains a reference to these options.
675698
///
676699
/// \param Client If non-NULL, a diagnostic client that will be
677700
/// attached to (and, then, owned by) the returned DiagnosticsEngine
678-
/// object.
701+
/// object. If NULL, the returned DiagnosticsEngine will own a newly-created
702+
/// client.
679703
///
680704
/// \param CodeGenOpts If non-NULL, the code gen options in use, which may be
681705
/// used by some diagnostics printers (for logging purposes only).
@@ -690,8 +714,7 @@ class CompilerInstance : public ModuleLoader {
690714
/// Create the file manager and replace any existing one with it.
691715
///
692716
/// \return The new file manager on success, or null on failure.
693-
FileManager *
694-
createFileManager(IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr);
717+
FileManager *createFileManager();
695718

696719
/// Create the source manager and replace any existing one with it.
697720
void createSourceManager(FileManager &FileMgr);

clang/lib/Frontend/ASTUnit.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1189,10 +1189,12 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
11891189
// Ensure that Clang has a FileManager with the right VFS, which may have
11901190
// changed above in AddImplicitPreamble. If VFS is nullptr, rely on
11911191
// createFileManager to create one.
1192-
if (VFS && FileMgr && &FileMgr->getVirtualFileSystem() == VFS)
1192+
if (VFS && FileMgr && &FileMgr->getVirtualFileSystem() == VFS) {
1193+
Clang->setVirtualFileSystem(std::move(VFS));
11931194
Clang->setFileManager(FileMgr);
1194-
else {
1195-
Clang->createFileManager(std::move(VFS));
1195+
} else {
1196+
Clang->setVirtualFileSystem(std::move(VFS));
1197+
Clang->createFileManager();
11961198
FileMgr = Clang->getFileManagerPtr();
11971199
}
11981200

clang/lib/Frontend/ChainedIncludesSource.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ clang::createChainedIncludesSource(CompilerInstance &CI,
124124

125125
auto Clang = std::make_unique<CompilerInstance>(
126126
std::move(CInvok), CI.getPCHContainerOperations());
127+
Clang->createVirtualFileSystem();
127128
Clang->setDiagnostics(Diags);
128129
Clang->setTarget(TargetInfo::CreateTargetInfo(
129130
Clang->getDiagnostics(), Clang->getInvocation().getTargetOpts()));

clang/lib/Frontend/CompilerInstance.cpp

Lines changed: 31 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -159,17 +159,11 @@ bool CompilerInstance::createTarget() {
159159
return true;
160160
}
161161

162-
llvm::vfs::FileSystem &CompilerInstance::getVirtualFileSystem() const {
163-
return getFileManager().getVirtualFileSystem();
164-
}
165-
166-
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
167-
CompilerInstance::getVirtualFileSystemPtr() const {
168-
return getFileManager().getVirtualFileSystemPtr();
169-
}
170-
171-
void CompilerInstance::setFileManager(
172-
llvm::IntrusiveRefCntPtr<FileManager> Value) {
162+
void CompilerInstance::setFileManager(IntrusiveRefCntPtr<FileManager> Value) {
163+
if (!hasVirtualFileSystem())
164+
setVirtualFileSystem(Value->getVirtualFileSystemPtr());
165+
assert(Value == nullptr ||
166+
getVirtualFileSystemPtr() == Value->getVirtualFileSystemPtr());
173167
FileMgr = std::move(Value);
174168
}
175169

@@ -282,6 +276,20 @@ static void collectVFSEntries(CompilerInstance &CI,
282276
MDC->addFile(E.VPath, E.RPath);
283277
}
284278

279+
void CompilerInstance::createVirtualFileSystem(
280+
IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS, DiagnosticConsumer *DC) {
281+
DiagnosticOptions DiagOpts;
282+
DiagnosticsEngine Diags(DiagnosticIDs::create(), DiagOpts, DC,
283+
/*ShouldOwnClient=*/false);
284+
285+
VFS = createVFSFromCompilerInvocation(getInvocation(), Diags,
286+
std::move(BaseFS));
287+
// FIXME: Should this go into createVFSFromCompilerInvocation?
288+
if (getFrontendOpts().ShowStats)
289+
VFS =
290+
llvm::makeIntrusiveRefCnt<llvm::vfs::TracingFileSystem>(std::move(VFS));
291+
}
292+
285293
// Diagnostics
286294
static void SetUpDiagnosticLog(DiagnosticOptions &DiagOpts,
287295
const CodeGenOptions *CodeGenOpts,
@@ -333,11 +341,10 @@ static void SetupSerializedDiagnostics(DiagnosticOptions &DiagOpts,
333341
}
334342
}
335343

336-
void CompilerInstance::createDiagnostics(llvm::vfs::FileSystem &VFS,
337-
DiagnosticConsumer *Client,
344+
void CompilerInstance::createDiagnostics(DiagnosticConsumer *Client,
338345
bool ShouldOwnClient) {
339-
Diagnostics = createDiagnostics(VFS, getDiagnosticOpts(), Client,
340-
ShouldOwnClient, &getCodeGenOpts());
346+
Diagnostics = createDiagnostics(getVirtualFileSystem(), getDiagnosticOpts(),
347+
Client, ShouldOwnClient, &getCodeGenOpts());
341348
}
342349

343350
IntrusiveRefCntPtr<DiagnosticsEngine> CompilerInstance::createDiagnostics(
@@ -375,18 +382,9 @@ IntrusiveRefCntPtr<DiagnosticsEngine> CompilerInstance::createDiagnostics(
375382

376383
// File Manager
377384

378-
FileManager *CompilerInstance::createFileManager(
379-
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
380-
if (!VFS)
381-
VFS = FileMgr ? FileMgr->getVirtualFileSystemPtr()
382-
: createVFSFromCompilerInvocation(getInvocation(),
383-
getDiagnostics());
384-
assert(VFS && "FileManager has no VFS?");
385-
if (getFrontendOpts().ShowStats)
386-
VFS =
387-
llvm::makeIntrusiveRefCnt<llvm::vfs::TracingFileSystem>(std::move(VFS));
388-
FileMgr = llvm::makeIntrusiveRefCnt<FileManager>(getFileSystemOpts(),
389-
std::move(VFS));
385+
FileManager *CompilerInstance::createFileManager() {
386+
assert(VFS && "CompilerInstance needs a VFS for creating FileManager");
387+
FileMgr = llvm::makeIntrusiveRefCnt<FileManager>(getFileSystemOpts(), VFS);
390388
return FileMgr.get();
391389
}
392390

@@ -1167,20 +1165,21 @@ std::unique_ptr<CompilerInstance> CompilerInstance::cloneForModuleCompileImpl(
11671165
auto &Inv = Instance.getInvocation();
11681166

11691167
if (ThreadSafeConfig) {
1170-
Instance.createFileManager(ThreadSafeConfig->getVFS());
1168+
Instance.setVirtualFileSystem(ThreadSafeConfig->getVFS());
1169+
Instance.createFileManager();
11711170
} else if (FrontendOpts.ModulesShareFileManager) {
1171+
Instance.setVirtualFileSystem(getVirtualFileSystemPtr());
11721172
Instance.setFileManager(getFileManagerPtr());
11731173
} else {
1174-
Instance.createFileManager(getVirtualFileSystemPtr());
1174+
Instance.setVirtualFileSystem(getVirtualFileSystemPtr());
1175+
Instance.createFileManager();
11751176
}
11761177

11771178
if (ThreadSafeConfig) {
1178-
Instance.createDiagnostics(Instance.getVirtualFileSystem(),
1179-
&ThreadSafeConfig->getDiagConsumer(),
1179+
Instance.createDiagnostics(&ThreadSafeConfig->getDiagConsumer(),
11801180
/*ShouldOwnClient=*/false);
11811181
} else {
11821182
Instance.createDiagnostics(
1183-
Instance.getVirtualFileSystem(),
11841183
new ForwardingDiagnosticConsumer(getDiagnosticClient()),
11851184
/*ShouldOwnClient=*/true);
11861185
}

clang/lib/Frontend/FrontendAction.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -876,6 +876,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
876876

877877
// Set the shared objects, these are reset when we finish processing the
878878
// file, otherwise the CompilerInstance will happily destroy them.
879+
CI.setVirtualFileSystem(AST->getFileManager().getVirtualFileSystemPtr());
879880
CI.setFileManager(AST->getFileManagerPtr());
880881
CI.createSourceManager(CI.getFileManager());
881882
CI.getSourceManager().initializeForReplay(AST->getSourceManager());
@@ -966,7 +967,9 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
966967
return true;
967968
}
968969

969-
// Set up the file and source managers, if needed.
970+
// Set up the file system, file and source managers, if needed.
971+
if (!CI.hasVirtualFileSystem())
972+
CI.createVirtualFileSystem();
970973
if (!CI.hasFileManager()) {
971974
if (!CI.createFileManager()) {
972975
return false;

clang/lib/Frontend/Rewrite/FrontendActions.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,8 +245,8 @@ class RewriteIncludesAction::RewriteImportsListener : public ASTReaderListener {
245245
CompilerInstance Instance(
246246
std::make_shared<CompilerInvocation>(CI.getInvocation()),
247247
CI.getPCHContainerOperations(), &CI.getModuleCache());
248+
Instance.setVirtualFileSystem(CI.getVirtualFileSystemPtr());
248249
Instance.createDiagnostics(
249-
CI.getVirtualFileSystem(),
250250
new ForwardingDiagnosticConsumer(CI.getDiagnosticClient()),
251251
/*ShouldOwnClient=*/true);
252252
Instance.getFrontendOpts().DisableFree = false;

clang/lib/Interpreter/Interpreter.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,10 @@ CreateCI(const llvm::opt::ArgStringList &Argv) {
107107
Clang->getHeaderSearchOpts().ResourceDir =
108108
CompilerInvocation::GetResourcesPath(Argv[0], nullptr);
109109

110+
Clang->createVirtualFileSystem();
111+
110112
// Create the actual diagnostics engine.
111-
Clang->createDiagnostics(*llvm::vfs::getRealFileSystem());
113+
Clang->createDiagnostics();
112114
if (!Clang->hasDiagnostics())
113115
return llvm::createStringError(llvm::errc::not_supported,
114116
"Initialization failed. "
@@ -475,7 +477,8 @@ Interpreter::createWithCUDA(std::unique_ptr<CompilerInstance> CI,
475477
std::make_unique<llvm::vfs::OverlayFileSystem>(
476478
llvm::vfs::getRealFileSystem());
477479
OverlayVFS->pushOverlay(IMVFS);
478-
CI->createFileManager(OverlayVFS);
480+
CI->createVirtualFileSystem(OverlayVFS);
481+
CI->createFileManager();
479482

480483
llvm::Expected<std::unique_ptr<Interpreter>> InterpOrErr =
481484
Interpreter::create(std::move(CI));

0 commit comments

Comments
 (0)