[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