Skip to content

Commit aa1b416

Browse files
authored
[clang][deps] Remove dependency on tooling::ToolAction (#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.
1 parent b3e720b commit aa1b416

File tree

1 file changed

+36
-47
lines changed

1 file changed

+36
-47
lines changed

clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp

Lines changed: 36 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
#include "clang/Tooling/DependencyScanning/DependencyScanningService.h"
2525
#include "clang/Tooling/DependencyScanning/InProcessModuleCache.h"
2626
#include "clang/Tooling/DependencyScanning/ModuleDepCollector.h"
27-
#include "clang/Tooling/Tooling.h"
2827
#include "llvm/ADT/IntrusiveRefCntPtr.h"
2928
#include "llvm/Support/Allocator.h"
3029
#include "llvm/Support/Error.h"
@@ -376,25 +375,23 @@ class ScanningDependencyDirectivesGetter : public DependencyDirectivesGetter {
376375

377376
/// A clang tool that runs the preprocessor in a mode that's optimized for
378377
/// dependency scanning for the given compiler invocation.
379-
class DependencyScanningAction : public tooling::ToolAction {
378+
class DependencyScanningAction {
380379
public:
381380
DependencyScanningAction(
382381
DependencyScanningService &Service, StringRef WorkingDirectory,
383382
DependencyConsumer &Consumer, DependencyActionController &Controller,
384383
llvm::IntrusiveRefCntPtr<DependencyScanningWorkerFilesystem> DepFS,
385-
bool DisableFree, std::optional<StringRef> ModuleName = std::nullopt)
384+
std::optional<StringRef> ModuleName = std::nullopt)
386385
: Service(Service), WorkingDirectory(WorkingDirectory),
387386
Consumer(Consumer), Controller(Controller), DepFS(std::move(DepFS)),
388-
DisableFree(DisableFree), ModuleName(ModuleName) {}
387+
ModuleName(ModuleName) {}
389388

390389
bool runInvocation(std::shared_ptr<CompilerInvocation> Invocation,
391-
FileManager *DriverFileMgr,
390+
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
392391
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
393-
DiagnosticConsumer *DiagConsumer) override {
392+
DiagnosticConsumer *DiagConsumer) {
394393
// Make a deep copy of the original Clang invocation.
395394
CompilerInvocation OriginalInvocation(*Invocation);
396-
// Restore the value of DisableFree, which may be modified by Tooling.
397-
OriginalInvocation.getFrontendOpts().DisableFree = DisableFree;
398395
if (any(Service.getOptimizeArgs() & ScanningOptimizations::Macros))
399396
canonicalizeDefines(OriginalInvocation.getPreprocessorOpts());
400397

@@ -419,8 +416,8 @@ class DependencyScanningAction : public tooling::ToolAction {
419416
// Create the compiler's actual diagnostics engine.
420417
sanitizeDiagOpts(ScanInstance.getDiagnosticOpts());
421418
assert(!DiagConsumerFinished && "attempt to reuse finished consumer");
422-
ScanInstance.createDiagnostics(DriverFileMgr->getVirtualFileSystem(),
423-
DiagConsumer, /*ShouldOwnClient=*/false);
419+
ScanInstance.createDiagnostics(*FS, DiagConsumer,
420+
/*ShouldOwnClient=*/false);
424421
if (!ScanInstance.hasDiagnostics())
425422
return false;
426423

@@ -431,6 +428,7 @@ class DependencyScanningAction : public tooling::ToolAction {
431428
ScanInstance.getHeaderSearchOpts().BuildSessionTimestamp =
432429
Service.getBuildSessionTimestamp();
433430

431+
ScanInstance.getFrontendOpts().DisableFree = false;
434432
ScanInstance.getFrontendOpts().GenerateGlobalModuleIndex = false;
435433
ScanInstance.getFrontendOpts().UseGlobalModuleIndex = false;
436434
// This will prevent us compiling individual modules asynchronously since
@@ -441,9 +439,9 @@ class DependencyScanningAction : public tooling::ToolAction {
441439
any(Service.getOptimizeArgs() & ScanningOptimizations::VFS);
442440

443441
// Support for virtual file system overlays.
444-
auto FS = createVFSFromCompilerInvocation(
445-
ScanInstance.getInvocation(), ScanInstance.getDiagnostics(),
446-
DriverFileMgr->getVirtualFileSystemPtr());
442+
FS = createVFSFromCompilerInvocation(ScanInstance.getInvocation(),
443+
ScanInstance.getDiagnostics(),
444+
std::move(FS));
447445

448446
// Create a new FileManager to match the invocation's FileSystemOptions.
449447
auto *FileMgr = ScanInstance.createFileManager(FS);
@@ -554,9 +552,6 @@ class DependencyScanningAction : public tooling::ToolAction {
554552
if (Result)
555553
setLastCC1Arguments(std::move(OriginalInvocation));
556554

557-
// Propagate the statistics to the parent FileManager.
558-
DriverFileMgr->AddStats(ScanInstance.getFileManager());
559-
560555
return Result;
561556
}
562557

@@ -584,7 +579,6 @@ class DependencyScanningAction : public tooling::ToolAction {
584579
DependencyConsumer &Consumer;
585580
DependencyActionController &Controller;
586581
llvm::IntrusiveRefCntPtr<DependencyScanningWorkerFilesystem> DepFS;
587-
bool DisableFree;
588582
std::optional<StringRef> ModuleName;
589583
std::optional<CompilerInstance> ScanInstanceStorage;
590584
std::shared_ptr<ModuleDepCollector> MDC;
@@ -669,15 +663,14 @@ llvm::Error DependencyScanningWorker::computeDependencies(
669663
}
670664

671665
static bool forEachDriverJob(
672-
ArrayRef<std::string> ArgStrs, DiagnosticsEngine &Diags, FileManager &FM,
666+
ArrayRef<std::string> ArgStrs, DiagnosticsEngine &Diags,
667+
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
673668
llvm::function_ref<bool(const driver::Command &Cmd)> Callback) {
674669
SmallVector<const char *, 256> Argv;
675670
Argv.reserve(ArgStrs.size());
676671
for (const std::string &Arg : ArgStrs)
677672
Argv.push_back(Arg.c_str());
678673

679-
llvm::vfs::FileSystem *FS = &FM.getVirtualFileSystem();
680-
681674
std::unique_ptr<driver::Driver> Driver = std::make_unique<driver::Driver>(
682675
Argv[0], llvm::sys::getDefaultTargetTriple(), Diags,
683676
"clang LLVM compiler", FS);
@@ -687,7 +680,8 @@ static bool forEachDriverJob(
687680
bool CLMode = driver::IsClangCL(
688681
driver::getDriverMode(Argv[0], ArrayRef(Argv).slice(1)));
689682

690-
if (llvm::Error E = driver::expandResponseFiles(Argv, CLMode, Alloc, FS)) {
683+
if (llvm::Error E =
684+
driver::expandResponseFiles(Argv, CLMode, Alloc, FS.get())) {
691685
Diags.Report(diag::err_drv_expand_response_file)
692686
<< llvm::toString(std::move(E));
693687
return false;
@@ -710,17 +704,25 @@ static bool forEachDriverJob(
710704

711705
static bool createAndRunToolInvocation(
712706
std::vector<std::string> CommandLine, DependencyScanningAction &Action,
713-
FileManager &FM,
707+
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
714708
std::shared_ptr<clang::PCHContainerOperations> &PCHContainerOps,
715709
DiagnosticsEngine &Diags, DependencyConsumer &Consumer) {
716710

717711
// Save executable path before providing CommandLine to ToolInvocation
718712
std::string Executable = CommandLine[0];
719-
ToolInvocation Invocation(std::move(CommandLine), &Action, &FM,
720-
PCHContainerOps);
721-
Invocation.setDiagnosticConsumer(Diags.getClient());
722-
Invocation.setDiagnosticOptions(&Diags.getDiagnosticOptions());
723-
if (!Invocation.run())
713+
714+
llvm::opt::ArgStringList Argv;
715+
for (const std::string &Str : ArrayRef(CommandLine).drop_front())
716+
Argv.push_back(Str.c_str());
717+
718+
auto Invocation = std::make_shared<CompilerInvocation>();
719+
if (!CompilerInvocation::CreateFromArgs(*Invocation, Argv, Diags)) {
720+
// FIXME: Should we just go on like cc1_main does?
721+
return false;
722+
}
723+
724+
if (!Action.runInvocation(std::move(Invocation), std::move(FS),
725+
PCHContainerOps, Diags.getClient()))
724726
return false;
725727

726728
std::vector<std::string> Args = Action.takeLastCC1Arguments();
@@ -733,37 +735,24 @@ bool DependencyScanningWorker::scanDependencies(
733735
DependencyConsumer &Consumer, DependencyActionController &Controller,
734736
DiagnosticConsumer &DC, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
735737
std::optional<StringRef> ModuleName) {
736-
auto FileMgr =
737-
llvm::makeIntrusiveRefCnt<FileManager>(FileSystemOptions{}, FS);
738-
739738
std::vector<const char *> CCommandLine(CommandLine.size(), nullptr);
740739
llvm::transform(CommandLine, CCommandLine.begin(),
741740
[](const std::string &Str) { return Str.c_str(); });
742741
auto DiagOpts = CreateAndPopulateDiagOpts(CCommandLine);
743742
sanitizeDiagOpts(*DiagOpts);
744-
IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
745-
CompilerInstance::createDiagnostics(FileMgr->getVirtualFileSystem(),
746-
*DiagOpts, &DC,
747-
/*ShouldOwnClient=*/false);
748-
749-
// Although `Diagnostics` are used only for command-line parsing, the
750-
// custom `DiagConsumer` might expect a `SourceManager` to be present.
751-
SourceManager SrcMgr(*Diags, *FileMgr);
752-
Diags->setSourceManager(&SrcMgr);
753-
// DisableFree is modified by Tooling for running
754-
// in-process; preserve the original value, which is
755-
// always true for a driver invocation.
756-
bool DisableFree = true;
743+
auto Diags = CompilerInstance::createDiagnostics(*FS, *DiagOpts, &DC,
744+
/*ShouldOwnClient=*/false);
745+
757746
DependencyScanningAction Action(Service, WorkingDirectory, Consumer,
758-
Controller, DepFS, DisableFree, ModuleName);
747+
Controller, DepFS, ModuleName);
759748

760749
bool Success = false;
761750
if (CommandLine[1] == "-cc1") {
762-
Success = createAndRunToolInvocation(CommandLine, Action, *FileMgr,
751+
Success = createAndRunToolInvocation(CommandLine, Action, FS,
763752
PCHContainerOps, *Diags, Consumer);
764753
} else {
765754
Success = forEachDriverJob(
766-
CommandLine, *Diags, *FileMgr, [&](const driver::Command &Cmd) {
755+
CommandLine, *Diags, FS, [&](const driver::Command &Cmd) {
767756
if (StringRef(Cmd.getCreator().getName()) != "clang") {
768757
// Non-clang command. Just pass through to the dependency
769758
// consumer.
@@ -782,7 +771,7 @@ bool DependencyScanningWorker::scanDependencies(
782771
// system to ensure that any file system requests that
783772
// are made by the driver do not go through the
784773
// dependency scanning filesystem.
785-
return createAndRunToolInvocation(std::move(Argv), Action, *FileMgr,
774+
return createAndRunToolInvocation(std::move(Argv), Action, FS,
786775
PCHContainerOps, *Diags, Consumer);
787776
});
788777
}

0 commit comments

Comments
 (0)