[clang] [Dependency Scanning] Teach `DependencyScanningTool::getModuleDependencies` to Process a List of Module Names (PR #129915)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Mar 5 11:22:20 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Qiongsi Wu (qiongsiwu)
<details>
<summary>Changes</summary>
Currently `DependencyScanningTool::getModuleDependencies` takes a single `ModuleName` and if we have a list of module names to process for the same compilation, we invoke `getModuleDependencies` multiple times and sets up the identical `CompilerInvocation` multiple times (in `DependencyScanningAction::runInvocation`).
This PR revises `getModuleDependencies` so it can take a list of module names.
rdar://136303612
---
Full diff: https://github.com/llvm/llvm-project/pull/129915.diff
7 Files Affected:
- (modified) clang/include/clang/Frontend/FrontendActions.h (+3-3)
- (modified) clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h (+8-6)
- (modified) clang/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h (+3-3)
- (modified) clang/lib/Frontend/FrontendActions.cpp (+13-7)
- (modified) clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp (+6-3)
- (modified) clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp (+21-14)
- (modified) clang/tools/clang-scan-deps/ClangScanDeps.cpp (+2-2)
``````````diff
diff --git a/clang/include/clang/Frontend/FrontendActions.h b/clang/include/clang/Frontend/FrontendActions.h
index a620ddfc40447..c80422e97462d 100644
--- a/clang/include/clang/Frontend/FrontendActions.h
+++ b/clang/include/clang/Frontend/FrontendActions.h
@@ -320,12 +320,12 @@ class PrintPreprocessedAction : public PreprocessorFrontendAction {
};
class GetDependenciesByModuleNameAction : public PreprocessOnlyAction {
- StringRef ModuleName;
+ ArrayRef<StringRef> ModuleNames;
void ExecuteAction() override;
public:
- GetDependenciesByModuleNameAction(StringRef ModuleName)
- : ModuleName(ModuleName) {}
+ GetDependenciesByModuleNameAction(ArrayRef<StringRef> ModuleNames)
+ : ModuleNames(ModuleNames) {}
};
} // end namespace clang
diff --git a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h
index d13c3ee76d74f..25473b5c2500f 100644
--- a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h
+++ b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h
@@ -144,12 +144,14 @@ class DependencyScanningTool {
std::optional<llvm::MemoryBufferRef> TUBuffer = std::nullopt);
/// Given a compilation context specified via the Clang driver command-line,
- /// gather modular dependencies of module with the given name, and return the
- /// information needed for explicit build.
- llvm::Expected<ModuleDepsGraph> getModuleDependencies(
- StringRef ModuleName, const std::vector<std::string> &CommandLine,
- StringRef CWD, const llvm::DenseSet<ModuleID> &AlreadySeen,
- LookupModuleOutputCallback LookupModuleOutput);
+ /// gather modular dependencies of modules specified by the the given list of
+ /// names, and return the information needed for explicit build.
+ llvm::Expected<ModuleDepsGraph>
+ getModuleDependencies(ArrayRef<StringRef> ModuleNames,
+ const std::vector<std::string> &CommandLine,
+ StringRef CWD,
+ const llvm::DenseSet<ModuleID> &AlreadySeen,
+ LookupModuleOutputCallback LookupModuleOutput);
llvm::vfs::FileSystem &getWorkerVFS() const { return Worker.getVFS(); }
diff --git a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h
index 5f0b983ebb58f..901f42715e6e6 100644
--- a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h
+++ b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h
@@ -111,7 +111,7 @@ class DependencyScanningWorker {
DependencyConsumer &DepConsumer,
DependencyActionController &Controller,
DiagnosticConsumer &DiagConsumer,
- StringRef ModuleName);
+ ArrayRef<StringRef> ModuleNames);
/// Run the dependency scanning tool for a given clang driver command-line
/// for a specific translation unit via file system or memory buffer.
@@ -132,7 +132,7 @@ class DependencyScanningWorker {
const std::vector<std::string> &CommandLine,
DependencyConsumer &Consumer,
DependencyActionController &Controller,
- StringRef ModuleName);
+ ArrayRef<StringRef> ModuleNames);
llvm::vfs::FileSystem &getVFS() const { return *BaseFS; }
@@ -156,7 +156,7 @@ class DependencyScanningWorker {
DependencyActionController &Controller,
DiagnosticConsumer &DC,
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
- std::optional<StringRef> ModuleName);
+ std::optional<ArrayRef<StringRef>> ModuleNames);
};
} // end namespace dependencies
diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp
index 1ea4a2e9e88cf..5c6419bd4e677 100644
--- a/clang/lib/Frontend/FrontendActions.cpp
+++ b/clang/lib/Frontend/FrontendActions.cpp
@@ -1213,11 +1213,17 @@ void GetDependenciesByModuleNameAction::ExecuteAction() {
Preprocessor &PP = CI.getPreprocessor();
SourceManager &SM = PP.getSourceManager();
FileID MainFileID = SM.getMainFileID();
- SourceLocation FileStart = SM.getLocForStartOfFile(MainFileID);
- SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> Path;
- IdentifierInfo *ModuleID = PP.getIdentifierInfo(ModuleName);
- Path.push_back(std::make_pair(ModuleID, FileStart));
- auto ModResult = CI.loadModule(FileStart, Path, Module::Hidden, false);
- PPCallbacks *CB = PP.getPPCallbacks();
- CB->moduleImport(SourceLocation(), Path, ModResult);
+ SourceLocation SLoc = SM.getLocForStartOfFile(MainFileID);
+ for (auto ModuleName : ModuleNames) {
+ SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> Path;
+ IdentifierInfo *ModuleID = PP.getIdentifierInfo(ModuleName);
+ Path.push_back(std::make_pair(ModuleID, SLoc));
+ auto ModResult = CI.loadModule(SLoc, Path, Module::Hidden, false);
+ PPCallbacks *CB = PP.getPPCallbacks();
+ CB->moduleImport(SourceLocation(), Path, ModResult);
+ // FIXME: how do you know that this offset is correct?
+ SLoc = SLoc.getLocWithOffset(1);
+ assert(SLoc <= SM.getLocForEndOfFile(MainFileID) &&
+ "Import location extends past file");
+ }
}
diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp
index 2b4c2bb76434a..e7b6f87e2db11 100644
--- a/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp
+++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp
@@ -155,13 +155,16 @@ DependencyScanningTool::getTranslationUnitDependencies(
}
llvm::Expected<ModuleDepsGraph> DependencyScanningTool::getModuleDependencies(
- StringRef ModuleName, const std::vector<std::string> &CommandLine,
- StringRef CWD, const llvm::DenseSet<ModuleID> &AlreadySeen,
+ ArrayRef<StringRef> ModuleNames,
+ const std::vector<std::string> &CommandLine, StringRef CWD,
+ const llvm::DenseSet<ModuleID> &AlreadySeen,
LookupModuleOutputCallback LookupModuleOutput) {
FullDependencyConsumer Consumer(AlreadySeen);
CallbackActionController Controller(LookupModuleOutput);
+
+ assert(ModuleNames.size() && "GettingModuleDependencies for an empty list!");
llvm::Error Result = Worker.computeDependencies(CWD, CommandLine, Consumer,
- Controller, ModuleName);
+ Controller, ModuleNames);
if (Result)
return std::move(Result);
return Consumer.takeModuleGraphDeps();
diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
index 697f26ee5d12f..f2c5a0716126a 100644
--- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
+++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
@@ -287,10 +287,11 @@ class DependencyScanningAction : public tooling::ToolAction {
DependencyScanningService &Service, StringRef WorkingDirectory,
DependencyConsumer &Consumer, DependencyActionController &Controller,
llvm::IntrusiveRefCntPtr<DependencyScanningWorkerFilesystem> DepFS,
- bool DisableFree, std::optional<StringRef> ModuleName = std::nullopt)
+ bool DisableFree,
+ std::optional<ArrayRef<StringRef>> ModuleNames = std::nullopt)
: Service(Service), WorkingDirectory(WorkingDirectory),
Consumer(Consumer), Controller(Controller), DepFS(std::move(DepFS)),
- DisableFree(DisableFree), ModuleName(ModuleName) {}
+ DisableFree(DisableFree), ModuleNames(ModuleNames) {}
bool runInvocation(std::shared_ptr<CompilerInvocation> Invocation,
FileManager *DriverFileMgr,
@@ -431,8 +432,9 @@ class DependencyScanningAction : public tooling::ToolAction {
if (Service.getFormat() == ScanningOutputFormat::P1689)
Action = std::make_unique<PreprocessOnlyAction>();
- else if (ModuleName)
- Action = std::make_unique<GetDependenciesByModuleNameAction>(*ModuleName);
+ else if (ModuleNames)
+ Action =
+ std::make_unique<GetDependenciesByModuleNameAction>(*ModuleNames);
else
Action = std::make_unique<ReadPCHAndPreprocessAction>();
@@ -478,7 +480,7 @@ class DependencyScanningAction : public tooling::ToolAction {
DependencyActionController &Controller;
llvm::IntrusiveRefCntPtr<DependencyScanningWorkerFilesystem> DepFS;
bool DisableFree;
- std::optional<StringRef> ModuleName;
+ std::optional<ArrayRef<StringRef>> ModuleNames;
std::optional<CompilerInstance> ScanInstanceStorage;
std::shared_ptr<ModuleDepCollector> MDC;
std::vector<std::string> LastCC1Arguments;
@@ -546,7 +548,7 @@ llvm::Error DependencyScanningWorker::computeDependencies(
llvm::Error DependencyScanningWorker::computeDependencies(
StringRef WorkingDirectory, const std::vector<std::string> &CommandLine,
DependencyConsumer &Consumer, DependencyActionController &Controller,
- StringRef ModuleName) {
+ ArrayRef<StringRef> ModuleNames) {
// Capture the emitted diagnostics and report them to the client
// in the case of a failure.
std::string DiagnosticOutput;
@@ -555,7 +557,7 @@ llvm::Error DependencyScanningWorker::computeDependencies(
TextDiagnosticPrinter DiagPrinter(DiagnosticsOS, DiagOpts.release());
if (computeDependencies(WorkingDirectory, CommandLine, Consumer, Controller,
- DiagPrinter, ModuleName))
+ DiagPrinter, ModuleNames))
return llvm::Error::success();
return llvm::make_error<llvm::StringError>(DiagnosticsOS.str(),
llvm::inconvertibleErrorCode());
@@ -625,7 +627,7 @@ bool DependencyScanningWorker::scanDependencies(
StringRef WorkingDirectory, const std::vector<std::string> &CommandLine,
DependencyConsumer &Consumer, DependencyActionController &Controller,
DiagnosticConsumer &DC, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
- std::optional<StringRef> ModuleName) {
+ std::optional<ArrayRef<StringRef>> ModuleNames) {
auto FileMgr =
llvm::makeIntrusiveRefCnt<FileManager>(FileSystemOptions{}, FS);
@@ -648,7 +650,7 @@ bool DependencyScanningWorker::scanDependencies(
// always true for a driver invocation.
bool DisableFree = true;
DependencyScanningAction Action(Service, WorkingDirectory, Consumer,
- Controller, DepFS, DisableFree, ModuleName);
+ Controller, DepFS, DisableFree, ModuleNames);
bool Success = false;
if (CommandLine[1] == "-cc1") {
@@ -729,13 +731,14 @@ bool DependencyScanningWorker::computeDependencies(
auto &FinalFS = ModifiedFS ? ModifiedFS : BaseFS;
return scanDependencies(WorkingDirectory, FinalCommandLine, Consumer,
- Controller, DC, FinalFS, /*ModuleName=*/std::nullopt);
+ Controller, DC, FinalFS,
+ /*ModuleNames=*/std::nullopt);
}
bool DependencyScanningWorker::computeDependencies(
StringRef WorkingDirectory, const std::vector<std::string> &CommandLine,
DependencyConsumer &Consumer, DependencyActionController &Controller,
- DiagnosticConsumer &DC, StringRef ModuleName) {
+ DiagnosticConsumer &DC, ArrayRef<StringRef> ModuleNames) {
// Reset what might have been modified in the previous worker invocation.
BaseFS->setCurrentWorkingDirectory(WorkingDirectory);
@@ -748,9 +751,13 @@ bool DependencyScanningWorker::computeDependencies(
InMemoryFS->setCurrentWorkingDirectory(WorkingDirectory);
SmallString<128> FakeInputPath;
// TODO: We should retry the creation if the path already exists.
- llvm::sys::fs::createUniquePath(ModuleName + "-%%%%%%%%.input", FakeInputPath,
+ // FIXME: should we create files for multiple modules? I think so?
+ llvm::sys::fs::createUniquePath(ModuleNames[0] + "-%%%%%%%%.input",
+ FakeInputPath,
/*MakeAbsolute=*/false);
- InMemoryFS->addFile(FakeInputPath, 0, llvm::MemoryBuffer::getMemBuffer(""));
+ std::string FakeString(ModuleNames.size(), ' ');
+ InMemoryFS->addFile(FakeInputPath, 0,
+ llvm::MemoryBuffer::getMemBuffer(FakeString));
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> InMemoryOverlay = InMemoryFS;
OverlayFS->pushOverlay(InMemoryOverlay);
@@ -758,7 +765,7 @@ bool DependencyScanningWorker::computeDependencies(
ModifiedCommandLine.emplace_back(FakeInputPath);
return scanDependencies(WorkingDirectory, ModifiedCommandLine, Consumer,
- Controller, DC, OverlayFS, ModuleName);
+ Controller, DC, OverlayFS, ModuleNames);
}
DependencyActionController::~DependencyActionController() {}
diff --git a/clang/tools/clang-scan-deps/ClangScanDeps.cpp b/clang/tools/clang-scan-deps/ClangScanDeps.cpp
index 3bdeb461e4bfa..8c857418b26ea 100644
--- a/clang/tools/clang-scan-deps/ClangScanDeps.cpp
+++ b/clang/tools/clang-scan-deps/ClangScanDeps.cpp
@@ -1025,8 +1025,8 @@ int clang_scan_deps_main(int argc, char **argv, const llvm::ToolContext &) {
}
} else if (ModuleName) {
auto MaybeModuleDepsGraph = WorkerTool.getModuleDependencies(
- *ModuleName, Input->CommandLine, CWD, AlreadySeenModules,
- LookupOutput);
+ ArrayRef<StringRef>({*ModuleName}), Input->CommandLine, CWD,
+ AlreadySeenModules, LookupOutput);
if (handleModuleResult(*ModuleName, MaybeModuleDepsGraph, *FD,
LocalIndex, DependencyOS, Errs))
HadErrors = true;
``````````
</details>
https://github.com/llvm/llvm-project/pull/129915
More information about the cfe-commits
mailing list