diff --git a/clang/include/clang/Serialization/ModuleFile.h b/clang/include/clang/Serialization/ModuleFile.h --- a/clang/include/clang/Serialization/ModuleFile.h +++ b/clang/include/clang/Serialization/ModuleFile.h @@ -503,6 +503,9 @@ Kind == MK_PrebuiltModule; } + /// Collect all transitive imports of this module file. + void collectTransitiveImports(std::vector &Files); + /// Dump debugging output for this module. void dump(); }; diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -1626,13 +1626,6 @@ CI.getPreprocessor().getIdentifierInfo(ModuleName)); } - void registerAll() { - ModuleMap &MM = CI.getPreprocessor().getHeaderSearchInfo().getModuleMap(); - for (auto *II : LoadedModules) - MM.cacheModuleLoad(*II, MM.findModule(II->getName())); - LoadedModules.clear(); - } - void markAllUnavailable() { for (auto *II : LoadedModules) { if (Module *M = CI.getPreprocessor() @@ -1658,6 +1651,16 @@ } }; + auto RegisterAll = [&](serialization::ModuleFile *TopMF) { + std::vector AllMFs{TopMF}; + TopMF->collectTransitiveImports(AllMFs); + for (serialization::ModuleFile *MF : AllMFs) { + ModuleMap &MM = getPreprocessor().getHeaderSearchInfo().getModuleMap(); + MM.cacheModuleLoad(*getPreprocessor().getIdentifierInfo(MF->ModuleName), + MM.findModule(MF->ModuleName)); + } + }; + // If we don't already have an ASTReader, create one now. if (!TheASTReader) createASTReader(); @@ -1681,7 +1684,7 @@ case ASTReader::Success: // We successfully loaded the module file; remember the set of provided // modules so that we don't try to load implicit modules for them. - ListenerRef.registerAll(); + RegisterAll(TheASTReader->getModuleManager().lookupByFileName(FileName)); return true; case ASTReader::ConfigurationMismatch: diff --git a/clang/lib/Serialization/ModuleFile.cpp b/clang/lib/Serialization/ModuleFile.cpp --- a/clang/lib/Serialization/ModuleFile.cpp +++ b/clang/lib/Serialization/ModuleFile.cpp @@ -28,6 +28,15 @@ delete static_cast(SelectorLookupTable); } +void ModuleFile::collectTransitiveImports(std::vector &Files) { + SmallVector Stack{this}; + while (!Stack.empty()) { + serialization::ModuleFile *MF = Stack.pop_back_val(); + Stack.insert(Stack.end(), MF->Imports.begin(), MF->Imports.end()); + Files.push_back(MF); + } +} + template static void dumpLocalRemap(StringRef Name, diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp @@ -38,7 +38,7 @@ }; for (const PrebuiltModuleDep &PMD : PrebuiltModuleDeps) { - Args.push_back("-fmodule-file=" + PMD.ModuleName + "=" + PMD.PCMFile); + Args.push_back("-fmodule-file=" + PMD.PCMFile); Args.push_back("-fmodule-map-file=" + PMD.ModuleMapFile); } diff --git a/clang/test/ClangScanDeps/modules-pch.c b/clang/test/ClangScanDeps/modules-pch.c --- a/clang/test/ClangScanDeps/modules-pch.c +++ b/clang/test/ClangScanDeps/modules-pch.c @@ -229,8 +229,7 @@ // CHECK-TU-WITH-COMMON-NEXT: "command-line": [ // CHECK-TU-WITH-COMMON-NEXT: "-fno-implicit-modules", // CHECK-TU-WITH-COMMON-NEXT: "-fno-implicit-module-maps", -// FIXME: Figure out why we need `=ModCommon2` here for Clang to pick up the PCM. -// CHECK-TU-WITH-COMMON-NEXT: "-fmodule-file=ModCommon2=[[PREFIX]]/build/{{.*}}/ModCommon2-{{.*}}.pcm", +// CHECK-TU-WITH-COMMON-NEXT: "-fmodule-file=[[PREFIX]]/build/{{.*}}/ModCommon2-{{.*}}.pcm", // CHECK-TU-WITH-COMMON-NEXT: "-fmodule-map-file=[[PREFIX]]/module.modulemap" // CHECK-TU-WITH-COMMON-NEXT: "-fmodule-file=[[PREFIX]]/build/[[HASH_MOD_TU_WITH_COMMON]]/ModTUWithCommon-{{.*}}.pcm", // CHECK-TU-WITH-COMMON-NEXT: "-fmodule-map-file=[[PREFIX]]/module.modulemap" diff --git a/clang/test/Modules/Inputs/pch-shared-module/mod.h b/clang/test/Modules/Inputs/pch-shared-module/mod.h new file mode 100644 diff --git a/clang/test/Modules/Inputs/pch-shared-module/module.modulemap b/clang/test/Modules/Inputs/pch-shared-module/module.modulemap new file mode 100644 --- /dev/null +++ b/clang/test/Modules/Inputs/pch-shared-module/module.modulemap @@ -0,0 +1 @@ +module mod { header "mod.h" } diff --git a/clang/test/Modules/Inputs/pch-shared-module/pch.h b/clang/test/Modules/Inputs/pch-shared-module/pch.h new file mode 100644 --- /dev/null +++ b/clang/test/Modules/Inputs/pch-shared-module/pch.h @@ -0,0 +1 @@ +#include "mod.h" diff --git a/clang/test/Modules/pch-shared-module.c b/clang/test/Modules/pch-shared-module.c new file mode 100644 --- /dev/null +++ b/clang/test/Modules/pch-shared-module.c @@ -0,0 +1,14 @@ +// rm -rf %t && mkdir %t + +// RUN: %clang_cc1 -fmodules -emit-module -fmodule-name=mod %S/Inputs/pch-shared-module/module.modulemap -o %t/mod.pcm + +// RUN: %clang_cc1 -fmodules -emit-pch %S/Inputs/pch-shared-module/pch.h -o %t/pch.h.gch \ +// RUN: -fmodule-file=%t/mod.pcm -fmodule-map-file=%S/Inputs/pch-shared-module/module.modulemap + +// Check that `mod.pcm` is loaded correctly, even though it's imported by the PCH as well. +// RUN: %clang_cc1 -fmodules -fsyntax-only %s -include-pch %t/pch.h.gch -I %S/Inputs/pch-shared-module \ +// RUN: -fmodule-file=%t/mod.pcm -fmodule-map-file=%S/Inputs/pch-shared-module/module.modulemap -verify + +#include "mod.h" + +// expected-no-diagnostics