bruno created this revision.
bruno added a reviewer: rsmith.

Current generation of dependency files when modules is on take into
account all parsed module maps found while searching for a specific
module.

Add a new cc1 flag that allows changing that behavior: only add module
maps that actually answer for the modules being searched for.


Repository:
  rC Clang

https://reviews.llvm.org/D45012

Files:
  include/clang/Driver/CC1Options.td
  include/clang/Frontend/DependencyOutputOptions.h
  include/clang/Lex/ModuleMap.h
  lib/Frontend/CompilerInvocation.cpp
  lib/Frontend/DependencyFile.cpp
  lib/Lex/ModuleMap.cpp
  test/Modules/Inputs/dependency-skip-unused/module.modulemap
  test/Modules/Inputs/dependency-skip-unused/x/module.modulemap
  test/Modules/Inputs/dependency-skip-unused/y/module.modulemap
  test/Modules/dependency-skip-unused-modulemaps.m

Index: test/Modules/dependency-skip-unused-modulemaps.m
===================================================================
--- /dev/null
+++ test/Modules/dependency-skip-unused-modulemaps.m
@@ -0,0 +1,7 @@
+// RUN: rm -rf %t.cache %t.d
+// RUN: %clang_cc1 -fsyntax-only -fmodules -fimplicit-module-maps -fmodules-cache-path=%t.cache -dependency-file %t.d -MT dependencies -I%S/Inputs/dependency-skip-unused/x -I%S/Inputs/dependency-skip-unused/y -I%S/Inputs/dependency-skip-unused -skip-unused-modulemap-deps %s
+// RUN: FileCheck %s < %t.d
+// CHECK-NOT: dependency-skip-unused{{.}}x{{.}}module.modulemap
+// CHECK-NOT: dependency-skip-unused{{.}}y{{.}}module.modulemap
+
+@import A;
Index: test/Modules/Inputs/dependency-skip-unused/y/module.modulemap
===================================================================
--- /dev/null
+++ test/Modules/Inputs/dependency-skip-unused/y/module.modulemap
@@ -0,0 +1 @@
+module Y {}
Index: test/Modules/Inputs/dependency-skip-unused/x/module.modulemap
===================================================================
--- /dev/null
+++ test/Modules/Inputs/dependency-skip-unused/x/module.modulemap
@@ -0,0 +1 @@
+module X {}
Index: test/Modules/Inputs/dependency-skip-unused/module.modulemap
===================================================================
--- /dev/null
+++ test/Modules/Inputs/dependency-skip-unused/module.modulemap
@@ -0,0 +1 @@
+module A {}
Index: lib/Lex/ModuleMap.cpp
===================================================================
--- lib/Lex/ModuleMap.cpp
+++ lib/Lex/ModuleMap.cpp
@@ -723,8 +723,17 @@
 
 Module *ModuleMap::findModule(StringRef Name) const {
   llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
-  if (Known != Modules.end())
-    return Known->getValue();
+  if (Known != Modules.end()) {
+    Module *M = Known->getValue();
+    // Notify callbacks that we found a module map for the module.
+    if (!M->DefinitionLoc.isInvalid())
+      for (const auto &Cb : Callbacks)
+        Cb->moduleMapFoundForModule(
+            *getContainingModuleMapFile(M), M,
+            SourceMgr.getFileCharacteristic(M->DefinitionLoc) ==
+                SrcMgr::C_System_ModuleMap);
+    return M;
+  }
 
   return nullptr;
 }
Index: lib/Frontend/DependencyFile.cpp
===================================================================
--- lib/Frontend/DependencyFile.cpp
+++ lib/Frontend/DependencyFile.cpp
@@ -161,6 +161,7 @@
   bool AddMissingHeaderDeps;
   bool SeenMissingHeader;
   bool IncludeModuleFiles;
+  bool SkipUnusedModuleMaps;
   DependencyOutputFormat OutputFormat;
 
 private:
@@ -176,6 +177,7 @@
       AddMissingHeaderDeps(Opts.AddMissingHeaderDeps),
       SeenMissingHeader(false),
       IncludeModuleFiles(Opts.IncludeModuleFiles),
+      SkipUnusedModuleMaps(Opts.SkipUnusedModuleMaps),
       OutputFormat(Opts.OutputFormat) {
     for (const auto &ExtraDep : Opts.ExtraDeps) {
       AddFilename(ExtraDep);
@@ -198,17 +200,26 @@
   void AddFilename(StringRef Filename);
   bool includeSystemHeaders() const { return IncludeSystemHeaders; }
   bool includeModuleFiles() const { return IncludeModuleFiles; }
+  bool skipUnusedModuleMaps() const { return SkipUnusedModuleMaps; }
 };
 
 class DFGMMCallback : public ModuleMapCallbacks {
   DFGImpl &Parent;
 public:
   DFGMMCallback(DFGImpl &Parent) : Parent(Parent) {}
   void moduleMapFileRead(SourceLocation Loc, const FileEntry &Entry,
                          bool IsSystem) override {
+    if (Parent.skipUnusedModuleMaps())
+      return;
     if (!IsSystem || Parent.includeSystemHeaders())
       Parent.AddFilename(Entry.getName());
   }
+  void moduleMapFoundForModule(const FileEntry &Entry, const Module *M,
+                               bool IsSystem) override {
+    if (Parent.skipUnusedModuleMaps() &&
+        (!IsSystem || Parent.includeSystemHeaders()))
+      Parent.AddFilename(Entry.getName());
+  }
 };
 
 class DFGASTReaderListener : public ASTReaderListener {
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -1070,6 +1070,7 @@
   Opts.Targets = Args.getAllArgValues(OPT_MT);
   Opts.IncludeSystemHeaders = Args.hasArg(OPT_sys_header_deps);
   Opts.IncludeModuleFiles = Args.hasArg(OPT_module_file_deps);
+  Opts.SkipUnusedModuleMaps = Args.hasArg(OPT_skip_unused_modulemap_file_deps);
   Opts.UsePhonyTargets = Args.hasArg(OPT_MP);
   Opts.ShowHeaderIncludes = Args.hasArg(OPT_H);
   Opts.HeaderIncludeOutputFile = Args.getLastArgValue(OPT_header_include_file);
Index: include/clang/Lex/ModuleMap.h
===================================================================
--- include/clang/Lex/ModuleMap.h
+++ include/clang/Lex/ModuleMap.h
@@ -56,6 +56,14 @@
   virtual void moduleMapFileRead(SourceLocation FileStart,
                                  const FileEntry &File, bool IsSystem) {}
 
+  /// Called when a module map file matches a module lookup
+  ///
+  /// \param File The file itself.
+  /// \param M The module found that matches this module map.
+  /// \param IsSystem Whether this is a module map from a system include path.
+  virtual void moduleMapFoundForModule(const FileEntry &File, const Module *M,
+                                       bool IsSystem) {}
+
   /// \brief Called when a header is added during module map parsing.
   ///
   /// \param Filename The header file itself.
Index: include/clang/Frontend/DependencyOutputOptions.h
===================================================================
--- include/clang/Frontend/DependencyOutputOptions.h
+++ include/clang/Frontend/DependencyOutputOptions.h
@@ -30,6 +30,7 @@
   unsigned AddMissingHeaderDeps : 1; ///< Add missing headers to dependency list
   unsigned PrintShowIncludes : 1; ///< Print cl.exe style /showIncludes info.
   unsigned IncludeModuleFiles : 1; ///< Include module file dependencies.
+  unsigned SkipUnusedModuleMaps : 1; ///< Skip unused module map dependencies.
 
   /// The format for the dependency file.
   DependencyOutputFormat OutputFormat;
@@ -67,6 +68,7 @@
     AddMissingHeaderDeps = 0;
     PrintShowIncludes = 0;
     IncludeModuleFiles = 0;
+    SkipUnusedModuleMaps = 0;
     OutputFormat = DependencyOutputFormat::Make;
   }
 };
Index: include/clang/Driver/CC1Options.td
===================================================================
--- include/clang/Driver/CC1Options.td
+++ include/clang/Driver/CC1Options.td
@@ -362,6 +362,8 @@
 
 def sys_header_deps : Flag<["-"], "sys-header-deps">,
   HelpText<"Include system headers in dependency output">;
+def skip_unused_modulemap_file_deps : Flag<["-"], "skip-unused-modulemap-deps">,
+  HelpText<"Include module map files only for imported modules in dependency output">;
 def module_file_deps : Flag<["-"], "module-file-deps">,
   HelpText<"Include module files in dependency output">;
 def header_include_file : Separate<["-"], "header-include-file">,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to