[clang] b45888e - [clang][modules] Report module maps affecting `no_undeclared_includes` modules

Jan Svoboda via cfe-commits cfe-commits at lists.llvm.org
Mon Mar 7 01:47:54 PST 2022


Author: Jan Svoboda
Date: 2022-03-07T10:47:46+01:00
New Revision: b45888e959ad2d6562b8d321166e6387facdd412

URL: https://github.com/llvm/llvm-project/commit/b45888e959ad2d6562b8d321166e6387facdd412
DIFF: https://github.com/llvm/llvm-project/commit/b45888e959ad2d6562b8d321166e6387facdd412.diff

LOG: [clang][modules] Report module maps affecting `no_undeclared_includes` modules

Since D106876, PCM files don't report module maps as input files unless they contributed to the compilation.

Reporting only module maps of (transitively) imported modules is not enough, though. For modules marked with `[no_undeclared_includes]`, other module maps affect the compilation by introducing anti-dependencies.

This patch makes sure such module maps are being reported as input files.

Depends on D120463.

Reviewed By: dexonsmith

Differential Revision: https://reviews.llvm.org/D120464

Added: 
    

Modified: 
    clang/include/clang/Basic/Module.h
    clang/lib/Basic/Module.cpp
    clang/lib/Serialization/ASTWriter.cpp
    clang/test/Modules/add-remove-irrelevant-module-map.m

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/Module.h b/clang/include/clang/Basic/Module.h
index 5b97044524553..3d1af45c48f3d 100644
--- a/clang/include/clang/Basic/Module.h
+++ b/clang/include/clang/Basic/Module.h
@@ -371,6 +371,10 @@ class Module {
   /// The set of use declarations that have yet to be resolved.
   SmallVector<ModuleId, 2> UnresolvedDirectUses;
 
+  /// When \c NoUndeclaredIncludes is true, the set of modules this module tried
+  /// to import but didn't because they are not direct uses.
+  llvm::SmallSetVector<const Module *, 2> UndeclaredUses;
+
   /// A library or framework to link against when an entity from this
   /// module is used.
   struct LinkLibrary {
@@ -601,7 +605,7 @@ class Module {
 
   /// Determine whether this module has declared its intention to
   /// directly use another module.
-  bool directlyUses(const Module *Requested) const;
+  bool directlyUses(const Module *Requested);
 
   /// Add the given feature requirement to the list of features
   /// required by this module.

diff  --git a/clang/lib/Basic/Module.cpp b/clang/lib/Basic/Module.cpp
index 09bd3251fea0c..17b83184abb66 100644
--- a/clang/lib/Basic/Module.cpp
+++ b/clang/lib/Basic/Module.cpp
@@ -267,7 +267,7 @@ ArrayRef<const FileEntry *> Module::getTopHeaders(FileManager &FileMgr) {
   return llvm::makeArrayRef(TopHeaders.begin(), TopHeaders.end());
 }
 
-bool Module::directlyUses(const Module *Requested) const {
+bool Module::directlyUses(const Module *Requested) {
   auto *Top = getTopLevelModule();
 
   // A top-level module implicitly uses itself.
@@ -282,6 +282,9 @@ bool Module::directlyUses(const Module *Requested) const {
   if (!Requested->Parent && Requested->Name == "_Builtin_stddef_max_align_t")
     return true;
 
+  if (NoUndeclaredIncludes)
+    UndeclaredUses.insert(Requested);
+
   return false;
 }
 

diff  --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index f0ecfe413c31a..63fcc1eaa5509 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -164,8 +164,8 @@ namespace {
 std::set<const FileEntry *> GetAllModuleMaps(const HeaderSearch &HS,
                                              Module *RootModule) {
   std::set<const FileEntry *> ModuleMaps{};
-  std::set<Module *> ProcessedModules;
-  SmallVector<Module *> ModulesToProcess{RootModule};
+  std::set<const Module *> ProcessedModules;
+  SmallVector<const Module *> ModulesToProcess{RootModule};
 
   SmallVector<const FileEntry *, 16> FilesByUID;
   HS.getFileMgr().GetUniqueIDMapping(FilesByUID);
@@ -209,6 +209,11 @@ std::set<const FileEntry *> GetAllModuleMaps(const HeaderSearch &HS,
       }
       ModulesToProcess.push_back(ImportedModule);
     }
+
+    for (const Module *UndeclaredModule : CurrentModule->UndeclaredUses)
+      if (UndeclaredModule &&
+          ProcessedModules.find(UndeclaredModule) == ProcessedModules.end())
+        ModulesToProcess.push_back(UndeclaredModule);
   }
 
   return ModuleMaps;
@@ -2861,6 +2866,8 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
     // Might be unnecessary as use declarations are only used to build the
     // module itself.
 
+    // TODO: Consider serializing undeclared uses of modules.
+
     // Emit the link libraries.
     for (const auto &LL : Mod->LinkLibraries) {
       RecordData::value_type Record[] = {SUBMODULE_LINK_LIBRARY,

diff  --git a/clang/test/Modules/add-remove-irrelevant-module-map.m b/clang/test/Modules/add-remove-irrelevant-module-map.m
index c7ee07763bbb0..c0b081d8b52d0 100644
--- a/clang/test/Modules/add-remove-irrelevant-module-map.m
+++ b/clang/test/Modules/add-remove-irrelevant-module-map.m
@@ -25,6 +25,34 @@
 
 // Neither PCM file considers 'b.modulemap' an input:
 //
-// RUN: %clang_cc1 -module-file-info %t/cache-without-b/a.pcm | FileCheck %s
-// RUN: %clang_cc1 -module-file-info %t/cache-with-b/a.pcm | FileCheck %s
-// CHECK-NOT: Input file: {{.*}}/b.modulemap
+// RUN: %clang_cc1 -module-file-info %t/cache-without-b/a.pcm | FileCheck %s --check-prefix=CHECK-B
+// RUN: %clang_cc1 -module-file-info %t/cache-with-b/a.pcm | FileCheck %s --check-prefix=CHECK-B
+// CHECK-B-NOT: Input file: {{.*}}/b.modulemap
+
+//--- c.modulemap
+module c [no_undeclared_includes] { header "c.h" }
+
+//--- c.h
+#if __has_include("d.h") // This should use 'd.modulemap' in order to determine that 'd.h'
+                         // doesn't exist for 'c' because of its '[no_undeclared_includes]'.
+#endif
+
+//--- d.modulemap
+module d { header "d.h" }
+
+//--- d.h
+// empty
+
+//--- test-no-undeclared-includes.m
+// expected-no-diagnostics
+ at import c;
+
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t/cache -fdisable-module-hash \
+// RUN:   -fmodule-map-file=%t/c.modulemap -fmodule-map-file=%t/d.modulemap \
+// RUN:   %t/test-no-undeclared-includes.m -verify
+
+// The PCM file considers 'd.modulemap' an input because it affects the compilation,
+// although it doesn't describe the built module or its imports.
+//
+// RUN: %clang_cc1 -module-file-info %t/cache/c.pcm | FileCheck %s --check-prefix=CHECK-D -DDIR=%t
+// CHECK-D: Input file: [[DIR]]/d.modulemap


        


More information about the cfe-commits mailing list