jansvoboda11 updated this revision to Diff 454975.
jansvoboda11 added a comment.

Add `-fmodule-file=` assertions


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D132430/new/

https://reviews.llvm.org/D132430

Files:
  clang/include/clang/Basic/Module.h
  clang/include/clang/Lex/ModuleLoader.h
  clang/include/clang/Lex/Preprocessor.h
  clang/include/clang/Serialization/ASTBitCodes.h
  clang/include/clang/Serialization/ASTReader.h
  clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h
  clang/lib/Frontend/CompilerInstance.cpp
  clang/lib/Lex/HeaderSearch.cpp
  clang/lib/Lex/PPDirectives.cpp
  clang/lib/Serialization/ASTReader.cpp
  clang/lib/Serialization/ASTWriter.cpp
  clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
  clang/test/ClangScanDeps/modules-incomplete-umbrella.c

Index: clang/test/ClangScanDeps/modules-incomplete-umbrella.c
===================================================================
--- /dev/null
+++ clang/test/ClangScanDeps/modules-incomplete-umbrella.c
@@ -0,0 +1,202 @@
+// This test checks that modules loaded during compilation (but not imported)
+// are still reported as dependencies.
+
+// RUN: rm -rf %t && mkdir %t
+// RUN: split-file %s %t
+
+//--- frameworks/FW.framework/Modules/module.modulemap
+framework module FW {
+  umbrella header "FW.h"
+  module * { export * }
+}
+//--- frameworks/FW.framework/Headers/FW.h
+//--- frameworks/FW.framework/Modules/module.private.modulemap
+framework module FW_Private {
+  umbrella header "FW_Private.h"
+  module * { export * }
+}
+//--- frameworks/FW.framework/PrivateHeaders/FW_Private.h
+#include "One.h"
+//--- frameworks/FW.framework/PrivateHeaders/One.h
+//--- frameworks/FW.framework/PrivateHeaders/Two.h
+
+// Let's check we report the non-imported modular dependencies for a translation unit.
+
+//--- from_tu.cdb.json.template
+[{
+  "file": "DIR/from_tu.m",
+  "directory": "DIR",
+  "command": "clang -fmodules -fmodules-cache-path=DIR/cache -iframework DIR/frameworks -c DIR/from_tu.m -o DIR/from_tu.o"
+}]
+//--- from_tu.m
+#include "FW/FW.h"
+#include "FW/Two.h"
+
+// RUN: sed -e "s|DIR|%/t|g" %t/from_tu.cdb.json.template > %t/from_tu.cdb.json
+// RUN: clang-scan-deps -compilation-database %t/from_tu.cdb.json -format experimental-full > %t/from_tu_result.json
+// RUN: FileCheck %s --input-file=%t/from_tu_result.json -DPREFIX=%t --check-prefixes=CHECK_TU
+// CHECK_TU:      {
+// CHECK_TU-NEXT:   "modules": [
+// CHECK_TU-NEXT:     {
+// CHECK_TU-NEXT:       "clang-module-deps": [],
+// CHECK_TU-NEXT:       "clang-modulemap-file": "[[PREFIX]]/frameworks/FW.framework/Modules/module.modulemap",
+// CHECK_TU-NEXT:       "command-line": [
+// CHECK_TU:            ],
+// CHECK_TU-NEXT:       "context-hash": "{{.*}}",
+// CHECK_TU-NEXT:       "file-deps": [
+// CHECK_TU-NEXT:         "[[PREFIX]]/frameworks/FW.framework/Headers/FW.h",
+// CHECK_TU-NEXT:         "[[PREFIX]]/frameworks/FW.framework/Modules/module.modulemap",
+// CHECK_TU-NEXT:         "[[PREFIX]]/frameworks/FW.framework/Modules/module.private.modulemap"
+// CHECK_TU-NEXT:       ],
+// CHECK_TU-NEXT:       "name": "FW"
+// CHECK_TU-NEXT:     },
+// CHECK_TU-NEXT:     {
+// CHECK_TU-NEXT:       "clang-module-deps": [],
+// CHECK_TU-NEXT:       "clang-modulemap-file": "[[PREFIX]]/frameworks/FW.framework/Modules/module.private.modulemap",
+// CHECK_TU-NEXT:       "command-line": [
+// CHECK_TU:            ],
+// CHECK_TU-NEXT:       "context-hash": "{{.*}}",
+// CHECK_TU-NEXT:       "file-deps": [
+// CHECK_TU-NEXT:         "[[PREFIX]]/frameworks/FW.framework/Modules/module.modulemap",
+// CHECK_TU-NEXT:         "[[PREFIX]]/frameworks/FW.framework/Modules/module.private.modulemap",
+// CHECK_TU-NEXT:         "[[PREFIX]]/frameworks/FW.framework/PrivateHeaders/FW_Private.h",
+// CHECK_TU-NEXT:         "[[PREFIX]]/frameworks/FW.framework/PrivateHeaders/One.h"
+// CHECK_TU-NEXT:       ],
+// CHECK_TU-NEXT:       "name": "FW_Private"
+// CHECK_TU-NEXT:     }
+// CHECK_TU-NEXT:   ],
+// CHECK_TU-NEXT:   "translation-units": [
+// CHECK_TU-NEXT:     {
+// CHECK_TU-NEXT:       "clang-context-hash": "{{.*}}",
+// CHECK_TU-NEXT:       "clang-module-deps": [
+// CHECK_TU-NEXT:         {
+// CHECK_TU-NEXT:           "context-hash": "{{.*}}",
+// CHECK_TU-NEXT:           "module-name": "FW"
+// CHECK_TU-NEXT:         },
+// CHECK_TU-NEXT:         {
+// CHECK_TU-NEXT:           "context-hash": "{{.*}}",
+// CHECK_TU-NEXT:           "module-name": "FW_Private"
+// CHECK_TU-NEXT:         }
+// CHECK_TU-NEXT:       ],
+// CHECK_TU-NEXT:       "command-line": [
+// CHECK_TU:              "-fmodule-file={{.*}}/FW-{{.*}}.pcm"
+// CHECK_TU:              "-fmodule-file={{.*}}/FW_Private-{{.*}}.pcm"
+// CHECK_TU:            ],
+// CHECK_TU-NEXT:       "file-deps": [
+// CHECK_TU-NEXT:         "[[PREFIX]]/from_tu.m",
+// CHECK_TU-NEXT:         "[[PREFIX]]/frameworks/FW.framework/PrivateHeaders/Two.h"
+// CHECK_TU-NEXT:       ],
+// CHECK_TU-NEXT:       "input-file": "[[PREFIX]]/from_tu.m"
+// CHECK_TU-NEXT:     }
+// CHECK_TU-NEXT:   ]
+// CHECK_TU-NEXT: }
+
+// RUN: %deps-to-rsp %t/from_tu_result.json --module-name=FW > %t/FW.cc1.rsp
+// RUN: %deps-to-rsp %t/from_tu_result.json --module-name=FW_Private > %t/FW_Private.cc1.rsp
+// RUN: %deps-to-rsp %t/from_tu_result.json --tu-index=0 > %t/tu.rsp
+// RUN: %clang @%t/FW.cc1.rsp
+// RUN: %clang @%t/FW_Private.cc1.rsp
+// RUN: %clang @%t/tu.rsp
+
+// Now let's check we report the dependencies for modules as well.
+
+//--- from_module.cdb.json.template
+[{
+  "file": "DIR/from_module.m",
+  "directory": "DIR",
+  "command": "clang -fmodules -fmodules-cache-path=DIR/cache -iframework DIR/frameworks -c DIR/from_module.m -o DIR/from_module.o"
+}]
+//--- module.modulemap
+module Mod { header "Mod.h" }
+//--- Mod.h
+#include "FW/FW.h"
+#include "FW/Two.h"
+//--- from_module.m
+#include "Mod.h"
+
+// RUN: sed -e "s|DIR|%/t|g" %t/from_module.cdb.json.template > %t/from_module.cdb.json
+// RUN: clang-scan-deps -compilation-database %t/from_module.cdb.json -format experimental-full > %t/from_module_result.json
+// RUN: FileCheck %s --input-file=%t/from_module_result.json -DPREFIX=%t --check-prefixes=CHECK_MODULE
+// CHECK_MODULE:      {
+// CHECK_MODULE-NEXT:   "modules": [
+// CHECK_MODULE-NEXT:     {
+// CHECK_MODULE-NEXT:       "clang-module-deps": [],
+// CHECK_MODULE-NEXT:       "clang-modulemap-file": "[[PREFIX]]/frameworks/FW.framework/Modules/module.modulemap",
+// CHECK_MODULE-NEXT:       "command-line": [
+// CHECK_MODULE:            ],
+// CHECK_MODULE-NEXT:       "context-hash": "{{.*}}",
+// CHECK_MODULE-NEXT:       "file-deps": [
+// CHECK_MODULE-NEXT:         "[[PREFIX]]/frameworks/FW.framework/Headers/FW.h",
+// CHECK_MODULE-NEXT:         "[[PREFIX]]/frameworks/FW.framework/Modules/module.modulemap",
+// CHECK_MODULE-NEXT:         "[[PREFIX]]/frameworks/FW.framework/Modules/module.private.modulemap"
+// CHECK_MODULE-NEXT:       ],
+// CHECK_MODULE-NEXT:       "name": "FW"
+// CHECK_MODULE-NEXT:     },
+// CHECK_MODULE-NEXT:     {
+// CHECK_MODULE-NEXT:       "clang-module-deps": [],
+// CHECK_MODULE-NEXT:       "clang-modulemap-file": "[[PREFIX]]/frameworks/FW.framework/Modules/module.private.modulemap",
+// CHECK_MODULE-NEXT:       "command-line": [
+// CHECK_MODULE:            ],
+// CHECK_MODULE-NEXT:       "context-hash": "{{.*}}",
+// CHECK_MODULE-NEXT:       "file-deps": [
+// CHECK_MODULE-NEXT:         "[[PREFIX]]/frameworks/FW.framework/Modules/module.modulemap",
+// CHECK_MODULE-NEXT:         "[[PREFIX]]/frameworks/FW.framework/Modules/module.private.modulemap",
+// CHECK_MODULE-NEXT:         "[[PREFIX]]/frameworks/FW.framework/PrivateHeaders/FW_Private.h",
+// CHECK_MODULE-NEXT:         "[[PREFIX]]/frameworks/FW.framework/PrivateHeaders/One.h"
+// CHECK_MODULE-NEXT:       ],
+// CHECK_MODULE-NEXT:       "name": "FW_Private"
+// CHECK_MODULE-NEXT:     },
+// CHECK_MODULE-NEXT:     {
+// CHECK_MODULE-NEXT:       "clang-module-deps": [
+// CHECK_MODULE-NEXT:         {
+// CHECK_MODULE-NEXT:           "context-hash": "{{.*}}",
+// CHECK_MODULE-NEXT:           "module-name": "FW"
+// CHECK_MODULE-NEXT:         },
+// CHECK_MODULE-NEXT:         {
+// CHECK_MODULE-NEXT:           "context-hash": "{{.*}}",
+// CHECK_MODULE-NEXT:           "module-name": "FW_Private"
+// CHECK_MODULE-NEXT:         }
+// CHECK_MODULE-NEXT:       ],
+// CHECK_MODULE-NEXT:       "clang-modulemap-file": "[[PREFIX]]/module.modulemap",
+// CHECK_MODULE-NEXT:       "command-line": [
+// CHECK_MODULE:              "-fmodule-file={{.*}}/FW-{{.*}}.pcm"
+// CHECK_MODULE:              "-fmodule-file={{.*}}/FW_Private-{{.*}}.pcm"
+// CHECK_MODULE:            ],
+// CHECK_MODULE-NEXT:       "context-hash": "{{.*}}",
+// CHECK_MODULE-NEXT:       "file-deps": [
+// CHECK_MODULE-NEXT:         "[[PREFIX]]/Mod.h"
+// CHECK_MODULE-NEXT:         "[[PREFIX]]/frameworks/FW.framework/Modules/module.modulemap",
+// CHECK_MODULE-NEXT:         "[[PREFIX]]/frameworks/FW.framework/Modules/module.private.modulemap",
+// CHECK_MODULE-NEXT:         "[[PREFIX]]/frameworks/FW.framework/PrivateHeaders/Two.h",
+// CHECK_MODULE-NEXT:         "[[PREFIX]]/module.modulemap"
+// CHECK_MODULE-NEXT:       ],
+// CHECK_MODULE-NEXT:       "name": "Mod"
+// CHECK_MODULE-NEXT:     }
+// CHECK_MODULE-NEXT:   ],
+// CHECK_MODULE-NEXT:   "translation-units": [
+// CHECK_MODULE-NEXT:     {
+// CHECK_MODULE-NEXT:       "clang-context-hash": "{{.*}}",
+// CHECK_MODULE-NEXT:       "clang-module-deps": [
+// CHECK_MODULE-NEXT:         {
+// CHECK_MODULE-NEXT:           "context-hash": "{{.*}}",
+// CHECK_MODULE-NEXT:           "module-name": "Mod"
+// CHECK_MODULE-NEXT:         }
+// CHECK_MODULE-NEXT:       ],
+// CHECK_MODULE-NEXT:       "command-line": [
+// CHECK_MODULE:            ],
+// CHECK_MODULE-NEXT:       "file-deps": [
+// CHECK_MODULE-NEXT:         "[[PREFIX]]/from_module.m"
+// CHECK_MODULE-NEXT:       ],
+// CHECK_MODULE-NEXT:       "input-file": "[[PREFIX]]/from_module.m"
+// CHECK_MODULE-NEXT:     }
+// CHECK_MODULE-NEXT:   ]
+// CHECK_MODULE-NEXT: }
+
+// RUN: %deps-to-rsp %t/from_module_result.json --module-name=FW > %t/FW.cc1.rsp
+// RUN: %deps-to-rsp %t/from_module_result.json --module-name=FW_Private > %t/FW_Private.cc1.rsp
+// RUN: %deps-to-rsp %t/from_module_result.json --module-name=Mod > %t/Mod.cc1.rsp
+// RUN: %deps-to-rsp %t/from_module_result.json --tu-index=0 > %t/tu.rsp
+// RUN: %clang @%t/FW.cc1.rsp
+// RUN: %clang @%t/FW_Private.cc1.rsp
+// RUN: %clang @%t/Mod.cc1.rsp
+// RUN: %clang @%t/tu.rsp
Index: clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
===================================================================
--- clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
+++ clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
@@ -305,6 +305,11 @@
   if (!MDC.ScanInstance.getPreprocessorOpts().ImplicitPCHInclude.empty())
     MDC.addFileDep(MDC.ScanInstance.getPreprocessorOpts().ImplicitPCHInclude);
 
+  for (const Module *M :
+       MDC.ScanInstance.getPreprocessor().getAffectingModules())
+    if (!MDC.isPrebuiltModule(M))
+      DirectModularDeps.insert(M);
+
   for (const Module *M : DirectModularDeps) {
     // A top-level module might not be actually imported as a module when
     // -fmodule-name is used to compile a translation unit that imports this
@@ -416,6 +421,8 @@
   addAllSubmodulePrebuiltDeps(M, MD, SeenModules);
   llvm::DenseSet<const Module *> AddedModules;
   addAllSubmoduleDeps(M, MD, AddedModules);
+  llvm::DenseSet<const Module *> ProcessedModules;
+  addAllAffectingModules(M, MD, ProcessedModules);
 
   MD.BuildInvocation = MDC.makeInvocationForModuleBuildWithoutOutputs(
       MD, [&](CompilerInvocation &BuildInvocation) {
@@ -488,6 +495,30 @@
   }
 }
 
+void ModuleDepCollectorPP::addAllAffectingModules(
+    const Module *M, ModuleDeps &MD,
+    llvm::DenseSet<const Module *> &AddedModules) {
+  addAffectingModule(M, MD, AddedModules);
+
+  for (const Module *SubM : M->submodules())
+    addAllAffectingModules(SubM, MD, AddedModules);
+}
+
+void ModuleDepCollectorPP::addAffectingModule(
+    const Module *M, ModuleDeps &MD,
+    llvm::DenseSet<const Module *> &AddedModules) {
+  for (const Module *Affecting : M->AffectingModules) {
+    assert(Affecting == Affecting->getTopLevelModule() &&
+           "Not quite import not top-level module");
+    if (Affecting != M->getTopLevelModule() &&
+        !MDC.isPrebuiltModule(Affecting)) {
+      ModuleID ImportID = handleTopLevelModule(Affecting);
+      if (AddedModules.insert(Affecting).second)
+        MD.ClangModuleDeps.push_back(ImportID);
+    }
+  }
+}
+
 ModuleDepCollector::ModuleDepCollector(
     std::unique_ptr<DependencyOutputOptions> Opts,
     CompilerInstance &ScanInstance, DependencyConsumer &C,
Index: clang/lib/Serialization/ASTWriter.cpp
===================================================================
--- clang/lib/Serialization/ASTWriter.cpp
+++ clang/lib/Serialization/ASTWriter.cpp
@@ -883,6 +883,7 @@
   RECORD(SUBMODULE_TOPHEADER);
   RECORD(SUBMODULE_UMBRELLA_DIR);
   RECORD(SUBMODULE_IMPORTS);
+  RECORD(SUBMODULE_AFFECTING_MODULES);
   RECORD(SUBMODULE_EXPORTS);
   RECORD(SUBMODULE_REQUIRES);
   RECORD(SUBMODULE_EXCLUDED_HEADER);
@@ -2865,6 +2866,14 @@
       Stream.EmitRecord(SUBMODULE_IMPORTS, Record);
     }
 
+    // Emit the modules affecting compilation that were not imported.
+    if (!Mod->AffectingModules.empty()) {
+      RecordData Record;
+      for (auto *I : Mod->AffectingModules)
+        Record.push_back(getSubmoduleID(I));
+      Stream.EmitRecord(SUBMODULE_AFFECTING_MODULES, Record);
+    }
+
     // Emit the exports.
     if (!Mod->Exports.empty()) {
       RecordData Record;
Index: clang/lib/Serialization/ASTReader.cpp
===================================================================
--- clang/lib/Serialization/ASTReader.cpp
+++ clang/lib/Serialization/ASTReader.cpp
@@ -4376,6 +4376,11 @@
         Unresolved.Mod->Imports.insert(ResolvedMod);
       continue;
 
+    case UnresolvedModuleRef::Affecting:
+      if (ResolvedMod)
+        Unresolved.Mod->AffectingModules.insert(ResolvedMod);
+      continue;
+
     case UnresolvedModuleRef::Export:
       if (ResolvedMod || Unresolved.IsWildcard)
         Unresolved.Mod->Exports.push_back(
@@ -5674,6 +5679,18 @@
       }
       break;
 
+    case SUBMODULE_AFFECTING_MODULES:
+      for (unsigned Idx = 0; Idx != Record.size(); ++Idx) {
+        UnresolvedModuleRef Unresolved;
+        Unresolved.File = &F;
+        Unresolved.Mod = CurrentModule;
+        Unresolved.ID = Record[Idx];
+        Unresolved.Kind = UnresolvedModuleRef::Affecting;
+        Unresolved.IsWildcard = false;
+        UnresolvedModuleRefs.push_back(Unresolved);
+      }
+      break;
+
     case SUBMODULE_EXPORTS:
       for (unsigned Idx = 0; Idx + 1 < Record.size(); Idx += 2) {
         UnresolvedModuleRef Unresolved;
Index: clang/lib/Lex/PPDirectives.cpp
===================================================================
--- clang/lib/Lex/PPDirectives.cpp
+++ clang/lib/Lex/PPDirectives.cpp
@@ -2281,6 +2281,13 @@
     if (Imported) {
       Action = Import;
     } else if (Imported.isMissingExpected()) {
+      Module *M = static_cast<Module *>(Imported)->getTopLevelModule();
+      if (!BuildingSubmoduleStack.empty()) {
+        if (Imported != BuildingSubmoduleStack.back().M)
+          BuildingSubmoduleStack.back().M->AffectingModules.insert(M);
+      } else {
+        AffectingModules.insert(M);
+      }
       // We failed to find a submodule that we assumed would exist (because it
       // was in the directory of an umbrella header, for instance), but no
       // actual module containing it exists (because the umbrella header is
Index: clang/lib/Lex/HeaderSearch.cpp
===================================================================
--- clang/lib/Lex/HeaderSearch.cpp
+++ clang/lib/Lex/HeaderSearch.cpp
@@ -1563,6 +1563,8 @@
           *SuggestedModule = ModuleMap::KnownHeader();
         return true;
       }
+      // TODO: Add this module (or just its module map file) into something like
+      // `RequestingModule->AffectingModules`.
       return false;
     }
   }
Index: clang/lib/Frontend/CompilerInstance.cpp
===================================================================
--- clang/lib/Frontend/CompilerInstance.cpp
+++ clang/lib/Frontend/CompilerInstance.cpp
@@ -2100,7 +2100,7 @@
         << Module->getFullModuleName()
         << SourceRange(Path.front().second, Path.back().second);
 
-      return ModuleLoadResult::MissingExpected;
+      return ModuleLoadResult(Module, ModuleLoadResult::MissingExpected);
     }
 
     // Check whether this module is available.
Index: clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h
===================================================================
--- clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h
+++ clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h
@@ -176,6 +176,13 @@
                            llvm::DenseSet<const Module *> &AddedModules);
   void addModuleDep(const Module *M, ModuleDeps &MD,
                     llvm::DenseSet<const Module *> &AddedModules);
+
+  /// Traverses the affecting modules and updates \c MD with references to the
+  /// parent \c ModuleDepCollector info.
+  void addAllAffectingModules(const Module *M, ModuleDeps &MD,
+                              llvm::DenseSet<const Module *> &AddedModules);
+  void addAffectingModule(const Module *M, ModuleDeps &MD,
+                          llvm::DenseSet<const Module *> &AddedModules);
 };
 
 /// Collects modular and non-modular dependencies of the main file by attaching
Index: clang/include/clang/Serialization/ASTReader.h
===================================================================
--- clang/include/clang/Serialization/ASTReader.h
+++ clang/include/clang/Serialization/ASTReader.h
@@ -689,7 +689,7 @@
     Module *Mod;
 
     /// The kind of module reference.
-    enum { Import, Export, Conflict } Kind;
+    enum { Import, Export, Conflict, Affecting } Kind;
 
     /// The local ID of the module that is being exported.
     unsigned ID;
Index: clang/include/clang/Serialization/ASTBitCodes.h
===================================================================
--- clang/include/clang/Serialization/ASTBitCodes.h
+++ clang/include/clang/Serialization/ASTBitCodes.h
@@ -829,6 +829,9 @@
   /// Specifies the name of the module that will eventually
   /// re-export the entities in this module.
   SUBMODULE_EXPORT_AS = 17,
+
+  /// Specifies affecting modules that were not imported.
+  SUBMODULE_AFFECTING_MODULES = 18,
 };
 
 /// Record types used within a comments block.
Index: clang/include/clang/Lex/Preprocessor.h
===================================================================
--- clang/include/clang/Lex/Preprocessor.h
+++ clang/include/clang/Lex/Preprocessor.h
@@ -860,6 +860,10 @@
   /// The files that have been included.
   IncludedFilesSet IncludedFiles;
 
+  /// The set of top-level modules that affected preprocessing, but were not
+  /// imported.
+  llvm::SmallSetVector<Module *, 2> AffectingModules;
+
   /// The set of known macros exported from modules.
   llvm::FoldingSet<ModuleMacro> ModuleMacros;
 
@@ -1331,6 +1335,12 @@
 
   /// \}
 
+  /// Get the set of top-level modules that affected preprocessing, but were not
+  /// imported.
+  const llvm::SmallSetVector<Module *, 2> &getAffectingModules() const {
+    return AffectingModules;
+  }
+
   /// Mark the file as included.
   /// Returns true if this is the first time the file was included.
   bool markIncluded(const FileEntry *File) {
Index: clang/include/clang/Lex/ModuleLoader.h
===================================================================
--- clang/include/clang/Lex/ModuleLoader.h
+++ clang/include/clang/Lex/ModuleLoader.h
@@ -51,6 +51,11 @@
   ModuleLoadResult() = default;
   ModuleLoadResult(Module *M) : Storage(M, Normal) {}
   ModuleLoadResult(LoadResultKind Kind) : Storage(nullptr, Kind) {}
+  ModuleLoadResult(Module *M, LoadResultKind Kind) : Storage(M, Kind) {}
+
+  operator bool() const {
+    return Storage.getInt() == Normal && Storage.getPointer();
+  }
 
   operator Module *() const { return Storage.getPointer(); }
 
Index: clang/include/clang/Basic/Module.h
===================================================================
--- clang/include/clang/Basic/Module.h
+++ clang/include/clang/Basic/Module.h
@@ -345,6 +345,10 @@
   /// module depends.
   llvm::SmallSetVector<Module *, 2> Imports;
 
+  /// The set of top-level modules that affected the compilation of this module,
+  /// but were not imported.
+  llvm::SmallSetVector<Module *, 2> AffectingModules;
+
   /// Describes an exported module.
   ///
   /// The pointer is the module being re-exported, while the bit will be true
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to