Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 36 additions & 47 deletions clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
#include "clang/Tooling/DependencyScanning/DependencyScanningService.h"
#include "clang/Tooling/DependencyScanning/InProcessModuleCache.h"
#include "clang/Tooling/DependencyScanning/ModuleDepCollector.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Error.h"
Expand Down Expand Up @@ -376,25 +375,23 @@ class ScanningDependencyDirectivesGetter : public DependencyDirectivesGetter {

/// A clang tool that runs the preprocessor in a mode that's optimized for
/// dependency scanning for the given compiler invocation.
class DependencyScanningAction : public tooling::ToolAction {
class DependencyScanningAction {
public:
DependencyScanningAction(
DependencyScanningService &Service, StringRef WorkingDirectory,
DependencyConsumer &Consumer, DependencyActionController &Controller,
llvm::IntrusiveRefCntPtr<DependencyScanningWorkerFilesystem> DepFS,
bool DisableFree, std::optional<StringRef> ModuleName = std::nullopt)
std::optional<StringRef> ModuleName = std::nullopt)
: Service(Service), WorkingDirectory(WorkingDirectory),
Consumer(Consumer), Controller(Controller), DepFS(std::move(DepFS)),
DisableFree(DisableFree), ModuleName(ModuleName) {}
ModuleName(ModuleName) {}

bool runInvocation(std::shared_ptr<CompilerInvocation> Invocation,
FileManager *DriverFileMgr,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
DiagnosticConsumer *DiagConsumer) override {
DiagnosticConsumer *DiagConsumer) {
// Make a deep copy of the original Clang invocation.
CompilerInvocation OriginalInvocation(*Invocation);
// Restore the value of DisableFree, which may be modified by Tooling.
OriginalInvocation.getFrontendOpts().DisableFree = DisableFree;
if (any(Service.getOptimizeArgs() & ScanningOptimizations::Macros))
canonicalizeDefines(OriginalInvocation.getPreprocessorOpts());

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

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

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

// Support for virtual file system overlays.
auto FS = createVFSFromCompilerInvocation(
ScanInstance.getInvocation(), ScanInstance.getDiagnostics(),
DriverFileMgr->getVirtualFileSystemPtr());
FS = createVFSFromCompilerInvocation(ScanInstance.getInvocation(),
ScanInstance.getDiagnostics(),
std::move(FS));

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

// Propagate the statistics to the parent FileManager.
DriverFileMgr->AddStats(ScanInstance.getFileManager());

return Result;
}

Expand Down Expand Up @@ -584,7 +579,6 @@ class DependencyScanningAction : public tooling::ToolAction {
DependencyConsumer &Consumer;
DependencyActionController &Controller;
llvm::IntrusiveRefCntPtr<DependencyScanningWorkerFilesystem> DepFS;
bool DisableFree;
std::optional<StringRef> ModuleName;
std::optional<CompilerInstance> ScanInstanceStorage;
std::shared_ptr<ModuleDepCollector> MDC;
Expand Down Expand Up @@ -669,15 +663,14 @@ llvm::Error DependencyScanningWorker::computeDependencies(
}

static bool forEachDriverJob(
ArrayRef<std::string> ArgStrs, DiagnosticsEngine &Diags, FileManager &FM,
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());

llvm::vfs::FileSystem *FS = &FM.getVirtualFileSystem();

std::unique_ptr<driver::Driver> Driver = std::make_unique<driver::Driver>(
Argv[0], llvm::sys::getDefaultTargetTriple(), Diags,
"clang LLVM compiler", FS);
Expand All @@ -687,7 +680,8 @@ static bool forEachDriverJob(
bool CLMode = driver::IsClangCL(
driver::getDriverMode(Argv[0], ArrayRef(Argv).slice(1)));

if (llvm::Error E = driver::expandResponseFiles(Argv, CLMode, Alloc, FS)) {
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;
Expand All @@ -710,17 +704,25 @@ static bool forEachDriverJob(

static bool createAndRunToolInvocation(
std::vector<std::string> CommandLine, DependencyScanningAction &Action,
FileManager &FM,
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];
ToolInvocation Invocation(std::move(CommandLine), &Action, &FM,
PCHContainerOps);
Invocation.setDiagnosticConsumer(Diags.getClient());
Invocation.setDiagnosticOptions(&Diags.getDiagnosticOptions());
if (!Invocation.run())

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?
return false;
}

if (!Action.runInvocation(std::move(Invocation), std::move(FS),
PCHContainerOps, Diags.getClient()))
return false;

std::vector<std::string> Args = Action.takeLastCC1Arguments();
Expand All @@ -733,37 +735,24 @@ bool DependencyScanningWorker::scanDependencies(
DependencyConsumer &Consumer, DependencyActionController &Controller,
DiagnosticConsumer &DC, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
std::optional<StringRef> ModuleName) {
auto FileMgr =
llvm::makeIntrusiveRefCnt<FileManager>(FileSystemOptions{}, FS);

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);
IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
CompilerInstance::createDiagnostics(FileMgr->getVirtualFileSystem(),
*DiagOpts, &DC,
/*ShouldOwnClient=*/false);

// Although `Diagnostics` are used only for command-line parsing, the
// custom `DiagConsumer` might expect a `SourceManager` to be present.
SourceManager SrcMgr(*Diags, *FileMgr);
Diags->setSourceManager(&SrcMgr);
// DisableFree is modified by Tooling for running
// in-process; preserve the original value, which is
// always true for a driver invocation.
bool DisableFree = true;
auto Diags = CompilerInstance::createDiagnostics(*FS, *DiagOpts, &DC,
/*ShouldOwnClient=*/false);

DependencyScanningAction Action(Service, WorkingDirectory, Consumer,
Controller, DepFS, DisableFree, ModuleName);
Controller, DepFS, ModuleName);

bool Success = false;
if (CommandLine[1] == "-cc1") {
Success = createAndRunToolInvocation(CommandLine, Action, *FileMgr,
Success = createAndRunToolInvocation(CommandLine, Action, FS,
PCHContainerOps, *Diags, Consumer);
} else {
Success = forEachDriverJob(
CommandLine, *Diags, *FileMgr, [&](const driver::Command &Cmd) {
CommandLine, *Diags, FS, [&](const driver::Command &Cmd) {
if (StringRef(Cmd.getCreator().getName()) != "clang") {
// Non-clang command. Just pass through to the dependency
// consumer.
Expand All @@ -782,7 +771,7 @@ 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, *FileMgr,
return createAndRunToolInvocation(std::move(Argv), Action, FS,
PCHContainerOps, *Diags, Consumer);
});
}
Expand Down
Loading