aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp')
-rw-r--r--clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp189
1 files changed, 38 insertions, 151 deletions
diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
index 796e587..9515421 100644
--- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
+++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
@@ -8,29 +8,9 @@
#include "clang/Tooling/DependencyScanning/DependencyScanningWorker.h"
#include "DependencyScannerImpl.h"
-#include "clang/Basic/DiagnosticDriver.h"
#include "clang/Basic/DiagnosticFrontend.h"
-#include "clang/Basic/DiagnosticSerialization.h"
-#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
-#include "clang/Driver/Job.h"
#include "clang/Driver/Tool.h"
-#include "clang/Frontend/CompilerInstance.h"
-#include "clang/Frontend/CompilerInvocation.h"
-#include "clang/Frontend/FrontendActions.h"
-#include "clang/Frontend/TextDiagnosticPrinter.h"
-#include "clang/Frontend/Utils.h"
-#include "clang/Lex/PreprocessorOptions.h"
-#include "clang/Serialization/ObjectFilePCHContainerReader.h"
-#include "clang/Tooling/DependencyScanning/DependencyScanningService.h"
-#include "clang/Tooling/DependencyScanning/InProcessModuleCache.h"
-#include "clang/Tooling/DependencyScanning/ModuleDepCollector.h"
-#include "llvm/ADT/IntrusiveRefCntPtr.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/TargetParser/Host.h"
-#include <optional>
using namespace clang;
using namespace tooling;
@@ -63,32 +43,19 @@ DependencyScanningWorker::DependencyScanningWorker(
}
}
-static std::unique_ptr<DiagnosticOptions>
-createDiagOptions(const std::vector<std::string> &CommandLine) {
- std::vector<const char *> CLI;
- for (const std::string &Arg : CommandLine)
- CLI.push_back(Arg.c_str());
- auto DiagOpts = CreateAndPopulateDiagOpts(CLI);
- sanitizeDiagOpts(*DiagOpts);
- return DiagOpts;
-}
-
llvm::Error DependencyScanningWorker::computeDependencies(
StringRef WorkingDirectory, const std::vector<std::string> &CommandLine,
DependencyConsumer &Consumer, DependencyActionController &Controller,
std::optional<llvm::MemoryBufferRef> TUBuffer) {
// Capture the emitted diagnostics and report them to the client
// in the case of a failure.
- std::string DiagnosticOutput;
- llvm::raw_string_ostream DiagnosticsOS(DiagnosticOutput);
- auto DiagOpts = createDiagOptions(CommandLine);
- TextDiagnosticPrinter DiagPrinter(DiagnosticsOS, *DiagOpts);
+ TextDiagnosticsPrinterWithOutput DiagPrinterWithOS(CommandLine);
if (computeDependencies(WorkingDirectory, CommandLine, Consumer, Controller,
- DiagPrinter, TUBuffer))
+ DiagPrinterWithOS.DiagPrinter, TUBuffer))
return llvm::Error::success();
- return llvm::make_error<llvm::StringError>(DiagnosticsOS.str(),
- llvm::inconvertibleErrorCode());
+ return llvm::make_error<llvm::StringError>(
+ DiagPrinterWithOS.DiagnosticsOS.str(), llvm::inconvertibleErrorCode());
}
llvm::Error DependencyScanningWorker::computeDependencies(
@@ -97,51 +64,24 @@ llvm::Error DependencyScanningWorker::computeDependencies(
StringRef ModuleName) {
// Capture the emitted diagnostics and report them to the client
// in the case of a failure.
- std::string DiagnosticOutput;
- llvm::raw_string_ostream DiagnosticsOS(DiagnosticOutput);
- auto DiagOpts = createDiagOptions(CommandLine);
- TextDiagnosticPrinter DiagPrinter(DiagnosticsOS, *DiagOpts);
+ TextDiagnosticsPrinterWithOutput DiagPrinterWithOS(CommandLine);
if (computeDependencies(WorkingDirectory, CommandLine, Consumer, Controller,
- DiagPrinter, ModuleName))
+ DiagPrinterWithOS.DiagPrinter, ModuleName))
return llvm::Error::success();
- return llvm::make_error<llvm::StringError>(DiagnosticsOS.str(),
- llvm::inconvertibleErrorCode());
+ return llvm::make_error<llvm::StringError>(
+ DiagPrinterWithOS.DiagnosticsOS.str(), llvm::inconvertibleErrorCode());
}
static bool forEachDriverJob(
ArrayRef<std::string> ArgStrs, DiagnosticsEngine &Diags,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
llvm::function_ref<bool(const driver::Command &Cmd)> Callback) {
- SmallVector<const char *, 256> Argv;
- Argv.reserve(ArgStrs.size());
- for (const std::string &Arg : ArgStrs)
- Argv.push_back(Arg.c_str());
-
- std::unique_ptr<driver::Driver> Driver = std::make_unique<driver::Driver>(
- Argv[0], llvm::sys::getDefaultTargetTriple(), Diags,
- "clang LLVM compiler", FS);
- Driver->setTitle("clang_based_tool");
-
- llvm::BumpPtrAllocator Alloc;
- bool CLMode = driver::IsClangCL(
- driver::getDriverMode(Argv[0], ArrayRef(Argv).slice(1)));
-
- if (llvm::Error E =
- driver::expandResponseFiles(Argv, CLMode, Alloc, FS.get())) {
- Diags.Report(diag::err_drv_expand_response_file)
- << llvm::toString(std::move(E));
- return false;
- }
-
- const std::unique_ptr<driver::Compilation> Compilation(
- Driver->BuildCompilation(llvm::ArrayRef(Argv)));
+ // Compilation holds a non-owning a reference to the Driver, hence we need to
+ // keep the Driver alive when we use Compilation.
+ auto [Driver, Compilation] = buildCompilation(ArgStrs, Diags, FS);
if (!Compilation)
return false;
-
- if (Compilation->containsError())
- return false;
-
for (const driver::Command &Job : Compilation->getJobs()) {
if (!Callback(Job))
return false;
@@ -150,30 +90,21 @@ static bool forEachDriverJob(
}
static bool createAndRunToolInvocation(
- std::vector<std::string> CommandLine, DependencyScanningAction &Action,
+ const std::vector<std::string> &CommandLine,
+ DependencyScanningAction &Action,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
std::shared_ptr<clang::PCHContainerOperations> &PCHContainerOps,
DiagnosticsEngine &Diags, DependencyConsumer &Consumer) {
-
- // Save executable path before providing CommandLine to ToolInvocation
- std::string Executable = CommandLine[0];
-
- llvm::opt::ArgStringList Argv;
- for (const std::string &Str : ArrayRef(CommandLine).drop_front())
- Argv.push_back(Str.c_str());
-
- auto Invocation = std::make_shared<CompilerInvocation>();
- if (!CompilerInvocation::CreateFromArgs(*Invocation, Argv, Diags)) {
- // FIXME: Should we just go on like cc1_main does?
+ auto Invocation = createCompilerInvocation(CommandLine, Diags);
+ if (!Invocation)
return false;
- }
if (!Action.runInvocation(std::move(Invocation), std::move(FS),
PCHContainerOps, Diags.getClient()))
return false;
std::vector<std::string> Args = Action.takeLastCC1Arguments();
- Consumer.handleBuildCommand({std::move(Executable), std::move(Args)});
+ Consumer.handleBuildCommand({CommandLine[0], std::move(Args)});
return true;
}
@@ -182,24 +113,19 @@ bool DependencyScanningWorker::scanDependencies(
DependencyConsumer &Consumer, DependencyActionController &Controller,
DiagnosticConsumer &DC, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
std::optional<StringRef> ModuleName) {
- std::vector<const char *> CCommandLine(CommandLine.size(), nullptr);
- llvm::transform(CommandLine, CCommandLine.begin(),
- [](const std::string &Str) { return Str.c_str(); });
- auto DiagOpts = CreateAndPopulateDiagOpts(CCommandLine);
- sanitizeDiagOpts(*DiagOpts);
- auto Diags = CompilerInstance::createDiagnostics(*FS, *DiagOpts, &DC,
- /*ShouldOwnClient=*/false);
-
+ DignosticsEngineWithDiagOpts DiagEngineWithCmdAndOpts(CommandLine, FS, DC);
DependencyScanningAction Action(Service, WorkingDirectory, Consumer,
Controller, DepFS, ModuleName);
bool Success = false;
if (CommandLine[1] == "-cc1") {
- Success = createAndRunToolInvocation(CommandLine, Action, FS,
- PCHContainerOps, *Diags, Consumer);
+ Success = createAndRunToolInvocation(
+ CommandLine, Action, FS, PCHContainerOps,
+ *DiagEngineWithCmdAndOpts.DiagEngine, Consumer);
} else {
Success = forEachDriverJob(
- CommandLine, *Diags, FS, [&](const driver::Command &Cmd) {
+ CommandLine, *DiagEngineWithCmdAndOpts.DiagEngine, FS,
+ [&](const driver::Command &Cmd) {
if (StringRef(Cmd.getCreator().getName()) != "clang") {
// Non-clang command. Just pass through to the dependency
// consumer.
@@ -218,13 +144,15 @@ bool DependencyScanningWorker::scanDependencies(
// system to ensure that any file system requests that
// are made by the driver do not go through the
// dependency scanning filesystem.
- return createAndRunToolInvocation(std::move(Argv), Action, FS,
- PCHContainerOps, *Diags, Consumer);
+ return createAndRunToolInvocation(
+ std::move(Argv), Action, FS, PCHContainerOps,
+ *DiagEngineWithCmdAndOpts.DiagEngine, Consumer);
});
}
if (Success && !Action.hasScanned())
- Diags->Report(diag::err_fe_expected_compiler_job)
+ DiagEngineWithCmdAndOpts.DiagEngine->Report(
+ diag::err_fe_expected_compiler_job)
<< llvm::join(CommandLine, " ");
// Ensure finish() is called even if we never reached ExecuteAction().
@@ -238,66 +166,25 @@ bool DependencyScanningWorker::computeDependencies(
StringRef WorkingDirectory, const std::vector<std::string> &CommandLine,
DependencyConsumer &Consumer, DependencyActionController &Controller,
DiagnosticConsumer &DC, std::optional<llvm::MemoryBufferRef> TUBuffer) {
- // Reset what might have been modified in the previous worker invocation.
- BaseFS->setCurrentWorkingDirectory(WorkingDirectory);
-
- std::optional<std::vector<std::string>> ModifiedCommandLine;
- llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> ModifiedFS;
-
- // If we're scanning based on a module name alone, we don't expect the client
- // to provide us with an input file. However, the driver really wants to have
- // one. Let's just make it up to make the driver happy.
if (TUBuffer) {
- auto OverlayFS =
- llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>(BaseFS);
- auto InMemoryFS =
- llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
- InMemoryFS->setCurrentWorkingDirectory(WorkingDirectory);
- auto InputPath = TUBuffer->getBufferIdentifier();
- InMemoryFS->addFile(
- InputPath, 0,
- llvm::MemoryBuffer::getMemBufferCopy(TUBuffer->getBuffer()));
- llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> InMemoryOverlay =
- InMemoryFS;
-
- OverlayFS->pushOverlay(InMemoryOverlay);
- ModifiedFS = OverlayFS;
- ModifiedCommandLine = CommandLine;
- ModifiedCommandLine->emplace_back(InputPath);
+ auto [FinalFS, FinalCommandLine] = initVFSForTUBuferScanning(
+ BaseFS, CommandLine, WorkingDirectory, *TUBuffer);
+ return scanDependencies(WorkingDirectory, FinalCommandLine, Consumer,
+ Controller, DC, FinalFS,
+ /*ModuleName=*/std::nullopt);
+ } else {
+ BaseFS->setCurrentWorkingDirectory(WorkingDirectory);
+ return scanDependencies(WorkingDirectory, CommandLine, Consumer, Controller,
+ DC, BaseFS, /*ModuleName=*/std::nullopt);
}
-
- const std::vector<std::string> &FinalCommandLine =
- ModifiedCommandLine ? *ModifiedCommandLine : CommandLine;
- auto &FinalFS = ModifiedFS ? ModifiedFS : BaseFS;
-
- return scanDependencies(WorkingDirectory, FinalCommandLine, Consumer,
- Controller, DC, FinalFS, /*ModuleName=*/std::nullopt);
}
bool DependencyScanningWorker::computeDependencies(
StringRef WorkingDirectory, const std::vector<std::string> &CommandLine,
DependencyConsumer &Consumer, DependencyActionController &Controller,
DiagnosticConsumer &DC, StringRef ModuleName) {
- // Reset what might have been modified in the previous worker invocation.
- BaseFS->setCurrentWorkingDirectory(WorkingDirectory);
-
- // If we're scanning based on a module name alone, we don't expect the client
- // to provide us with an input file. However, the driver really wants to have
- // one. Let's just make it up to make the driver happy.
- auto OverlayFS =
- llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>(BaseFS);
- auto InMemoryFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
- InMemoryFS->setCurrentWorkingDirectory(WorkingDirectory);
- SmallString<128> FakeInputPath;
- // TODO: We should retry the creation if the path already exists.
- llvm::sys::fs::createUniquePath(ModuleName + "-%%%%%%%%.input", FakeInputPath,
- /*MakeAbsolute=*/false);
- InMemoryFS->addFile(FakeInputPath, 0, llvm::MemoryBuffer::getMemBuffer(""));
- llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> InMemoryOverlay = InMemoryFS;
-
- OverlayFS->pushOverlay(InMemoryOverlay);
- auto ModifiedCommandLine = CommandLine;
- ModifiedCommandLine.emplace_back(FakeInputPath);
+ auto [OverlayFS, ModifiedCommandLine] = initVFSForByNameScanning(
+ BaseFS, CommandLine, WorkingDirectory, ModuleName);
return scanDependencies(WorkingDirectory, ModifiedCommandLine, Consumer,
Controller, DC, OverlayFS, ModuleName);