[clang] 0a92e09 - [clang][deps] Generate the full command-line for modules
Jan Svoboda via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 19 05:32:56 PDT 2021
Author: Jan Svoboda
Date: 2021-04-19T14:32:49+02:00
New Revision: 0a92e09c078527b46e37e31dc8c2615a207c7639
URL: https://github.com/llvm/llvm-project/commit/0a92e09c078527b46e37e31dc8c2615a207c7639
DIFF: https://github.com/llvm/llvm-project/commit/0a92e09c078527b46e37e31dc8c2615a207c7639.diff
LOG: [clang][deps] Generate the full command-line for modules
This patch uses the new `CompilerInvocation::generateCC1CommandLine` to generate the full canonical command line for modular dependencies, instead of only appending additional arguments.
Reviewed By: dexonsmith
Differential Revision: https://reviews.llvm.org/D100534
Added:
Modified:
clang/include/clang/Frontend/CompilerInstance.h
clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h
clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
clang/test/ClangScanDeps/modules-full.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h
index e5d0790f9e10..54d57019fa54 100644
--- a/clang/include/clang/Frontend/CompilerInstance.h
+++ b/clang/include/clang/Frontend/CompilerInstance.h
@@ -225,9 +225,11 @@ class CompilerInstance : public ModuleLoader {
bool hasInvocation() const { return Invocation != nullptr; }
- CompilerInvocation &getInvocation() {
+ CompilerInvocation &getInvocation() { return *getInvocationPtr(); }
+
+ std::shared_ptr<CompilerInvocation> getInvocationPtr() {
assert(Invocation && "Compiler instance has no invocation!");
- return *Invocation;
+ return Invocation;
}
/// setInvocation - Replace the current invocation.
diff --git a/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h b/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h
index c85aed8af2c7..5e90fb2f7b09 100644
--- a/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h
+++ b/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h
@@ -12,6 +12,7 @@
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/Utils.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/PPCallbacks.h"
@@ -47,6 +48,9 @@ struct ModuleDeps {
/// The identifier of the module.
ModuleID ID;
+ /// Whether this is a "system" module.
+ bool IsSystem;
+
/// The path to the modulemap file which defines this module.
///
/// This can be used to explicitly build this module. This file will
@@ -71,6 +75,10 @@ struct ModuleDeps {
// the primary TU.
bool ImportedByMainFile = false;
+ /// The compiler invocation associated with the translation unit that imports
+ /// this module.
+ std::shared_ptr<CompilerInvocation> Invocation;
+
/// Gets the full command line suitable for passing to clang.
///
/// \param LookupPCMPath This function is called to fill in `-fmodule-file=`
diff --git a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
index e85ac63843a5..68a03291e7bb 100644
--- a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
+++ b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
@@ -12,32 +12,61 @@
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Tooling/DependencyScanning/DependencyScanningWorker.h"
+#include "llvm/Support/StringSaver.h"
using namespace clang;
using namespace tooling;
using namespace dependencies;
+static CompilerInvocation
+makeInvocationForModuleBuildWithoutPaths(const ModuleDeps &Deps) {
+ // Make a deep copy of the invocation.
+ CompilerInvocation CI(*Deps.Invocation);
+
+ // Remove options incompatible with explicit module build.
+ CI.getFrontendOpts().Inputs.clear();
+ CI.getFrontendOpts().OutputFile.clear();
+
+ CI.getFrontendOpts().ProgramAction = frontend::GenerateModule;
+ CI.getLangOpts()->ModuleName = Deps.ID.ModuleName;
+ CI.getFrontendOpts().IsSystemModule = Deps.IsSystem;
+
+ CI.getLangOpts()->ImplicitModules = false;
+ CI.getHeaderSearchOpts().ImplicitModuleMaps = false;
+
+ return CI;
+}
+
+static std::vector<std::string>
+serializeCompilerInvocation(CompilerInvocation &CI) {
+ // Set up string allocator.
+ llvm::BumpPtrAllocator Alloc;
+ llvm::StringSaver Strings(Alloc);
+ auto SA = [&Strings](const Twine &Arg) { return Strings.save(Arg).data(); };
+ SmallVector<const char *, 32> Args;
+
+ // Synthesize full command line from the CompilerInvocation.
+ CI.generateCC1CommandLine(Args, SA);
+
+ // Convert arguments to the return type.
+ std::vector<std::string> Ret;
+ Ret.reserve(Args.size());
+ for (const char *Arg : Args)
+ Ret.emplace_back(Arg);
+
+ return Ret;
+}
+
std::vector<std::string> ModuleDeps::getFullCommandLine(
std::function<StringRef(ModuleID)> LookupPCMPath,
std::function<const ModuleDeps &(ModuleID)> LookupModuleDeps) const {
- // TODO: Build full command line. That also means capturing the original
- // command line into NonPathCommandLine.
-
- std::vector<std::string> Ret{
- "-fno-implicit-modules",
- "-fno-implicit-module-maps",
- };
+ CompilerInvocation CI(makeInvocationForModuleBuildWithoutPaths(*this));
- std::vector<std::string> PCMPaths;
- std::vector<std::string> ModMapPaths;
dependencies::detail::collectPCMAndModuleMapPaths(
- ClangModuleDeps, LookupPCMPath, LookupModuleDeps, PCMPaths, ModMapPaths);
- for (const std::string &PCMPath : PCMPaths)
- Ret.push_back("-fmodule-file=" + PCMPath);
- for (const std::string &ModMapPath : ModMapPaths)
- Ret.push_back("-fmodule-map-file=" + ModMapPath);
+ ClangModuleDeps, LookupPCMPath, LookupModuleDeps,
+ CI.getFrontendOpts().ModuleFiles, CI.getFrontendOpts().ModuleMapFiles);
- return Ret;
+ return serializeCompilerInvocation(CI);
}
void dependencies::detail::collectPCMAndModuleMapPaths(
@@ -149,10 +178,12 @@ void ModuleDepCollectorPP::handleTopLevelModule(const Module *M) {
.getModuleMap()
.getContainingModuleMapFile(M);
+ MD.Invocation = Instance.getInvocationPtr();
MD.ClangModuleMapFile = std::string(ModuleMap ? ModuleMap->getName() : "");
MD.ID.ModuleName = M->getFullModuleName();
MD.ImplicitModulePCMPath = std::string(M->getASTFile()->getName());
MD.ID.ContextHash = MDC.ContextHash;
+ MD.IsSystem = M->IsSystem;
serialization::ModuleFile *MF =
MDC.Instance.getASTReader()->getModuleManager().lookup(M->getASTFile());
MDC.Instance.getASTReader()->visitInputFiles(
diff --git a/clang/test/ClangScanDeps/modules-full.cpp b/clang/test/ClangScanDeps/modules-full.cpp
index 14c08b25996b..4337ae9642a5 100644
--- a/clang/test/ClangScanDeps/modules-full.cpp
+++ b/clang/test/ClangScanDeps/modules-full.cpp
@@ -37,11 +37,11 @@
// CHECK-NEXT: ],
// CHECK-NEXT: "clang-modulemap-file": "[[PREFIX]]/Inputs/module.modulemap",
// CHECK-NEXT: "command-line": [
-// CHECK-NEXT: "-fno-implicit-modules",
-// CHECK-NEXT: "-fno-implicit-module-maps",
-// CHECK-NEXT: "-fmodule-file=[[PREFIX]]/module-cache{{(_clangcl)?}}/[[CONTEXT_HASH_H1]]/header2-{{[A-Z0-9]+}}.pcm",
-// CHECK-NEXT: "-fmodule-map-file=[[PREFIX]]/Inputs/module.modulemap"
-// CHECK-NEXT: ],
+// CHECK: "-fmodule-map-file=[[PREFIX]]/Inputs/module.modulemap",
+// CHECK: "-fmodule-file=[[PREFIX]]/module-cache{{(_clangcl)?}}/[[CONTEXT_HASH_H1]]/header2-{{[A-Z0-9]+}}.pcm",
+// CHECK-NOT: "-fimplicit-module-maps",
+// CHECK: "-fno-implicit-modules",
+// CHECK: ],
// CHECK-NEXT: "context-hash": "[[CONTEXT_HASH_H1]]",
// CHECK-NEXT: "file-deps": [
// CHECK-NEXT: "[[PREFIX]]/Inputs/header.h",
@@ -53,9 +53,9 @@
// CHECK-NEXT: "clang-module-deps": [],
// CHECK-NEXT: "clang-modulemap-file": "[[PREFIX]]/Inputs/module.modulemap",
// CHECK-NEXT: "command-line": [
-// CHECK-NEXT: "-fno-implicit-modules",
-// CHECK-NEXT: "-fno-implicit-module-maps"
-// CHECK-NEXT: ],
+// CHECK-NOT: "-fimplicit-module-maps",
+// CHECK: "-fno-implicit-modules",
+// CHECK: ],
// CHECK-NEXT: "context-hash": "[[CONTEXT_HASH_H2:[A-Z0-9]+]]",
// CHECK-NEXT: "file-deps": [
// CHECK-NEXT: "[[PREFIX]]/Inputs/header.h",
@@ -67,9 +67,9 @@
// CHECK-NEXT: "clang-module-deps": [],
// CHECK-NEXT: "clang-modulemap-file": "[[PREFIX]]/Inputs/module.modulemap",
// CHECK-NEXT: "command-line": [
-// CHECK-NEXT: "-fno-implicit-modules",
-// CHECK-NEXT: "-fno-implicit-module-maps"
-// CHECK-NEXT: ],
+// CHECK-NOT: "-fimplicit-module-maps",
+// CHECK: "-fno-implicit-modules",
+// CHECK: ],
// CHECK-NEXT: "context-hash": "[[CONTEXT_HASH_H1]]",
// CHECK-NEXT: "file-deps": [
// CHECK-NEXT: "[[PREFIX]]/Inputs/header2.h",
More information about the cfe-commits
mailing list