@@ -2834,6 +2834,74 @@ ClangModuleUnit *ClangImporter::Implementation::getWrapperForModule(
28342834 if (auto mainModule = SwiftContext.MainModule ) {
28352835 implicitImportInfo = mainModule->getImplicitImportInfo ();
28362836 }
2837+
2838+ if (!underlying->isSubModule ()) {
2839+ // Make sure that synthesized Swift code in the clang module wrapper
2840+ // (e.g. _SwiftifyImport macro expansions) can access the same symbols
2841+ // as if it were actually in the clang module, by copying the imports.
2842+ // Because this top-level module wrapper contains all the imported decls
2843+ // of the clang submodules, we need to add the imports of all the
2844+ // transitive submodules, since we don't know at this point of the
2845+ // compilation which submodules will contain relevant macros.
2846+ // We also need to add (transitive) explicit submodules as imports,
2847+ // to make sure that they are marked as imported *somewhere* (clang modules
2848+ // including them don't count) - otherwise their decls won't be found after
2849+ // non-visible clang decls are filtered out.
2850+ llvm::SmallVector<const clang::Module *, 32 > SubmoduleWorklist;
2851+ llvm::DenseSet<ImportPath> Imported;
2852+ SubmoduleWorklist.push_back (underlying);
2853+ ImportPath::Builder underlyingSwiftModulePath =
2854+ getSwiftModulePath (underlying);
2855+ Imported.insert (underlyingSwiftModulePath.get ());
2856+ for (auto UI : implicitImportInfo.AdditionalUnloadedImports )
2857+ Imported.insert (UI.module .getImportPath ());
2858+ assert (implicitImportInfo.AdditionalImports .empty ());
2859+
2860+ auto addImplicitImport = [&implicitImportInfo, &Imported,
2861+ this ](const clang::Module *M,
2862+ bool guaranteedUnique) {
2863+ ImportPath::Builder builder = getSwiftModulePath (M);
2864+ if (!guaranteedUnique && Imported.count (builder.get ()))
2865+ return ;
2866+
2867+ // Don't perform this clone for modules already added to the list
2868+ ImportPath importedModulePath = builder.copyTo (SwiftContext);
2869+
2870+ #ifndef NDEBUG
2871+ const bool performSanityCheck = true ;
2872+ #else
2873+ const bool performSanityCheck = false ;
2874+ #endif
2875+ if (!guaranteedUnique || performSanityCheck) {
2876+ bool WasInserted = Imported.insert (importedModulePath).second ;
2877+ assert (WasInserted);
2878+ }
2879+
2880+ UnloadedImportedModule importedModule (importedModulePath,
2881+ ImportKind::Module);
2882+ implicitImportInfo.AdditionalUnloadedImports .push_back (
2883+ std::move (importedModule));
2884+ };
2885+
2886+ while (!SubmoduleWorklist.empty ()) {
2887+ const clang::Module *CurrModule = SubmoduleWorklist.pop_back_val ();
2888+ if (CurrModule->IsExplicit ) {
2889+ // We don't add imports under the same TLM, and submodules form
2890+ // a tree, so these don't require deduplication.
2891+ addImplicitImport (CurrModule, /* guaranteedUnique=*/ true );
2892+ }
2893+ for (auto *I : CurrModule->Imports ) {
2894+ // `underlying` is the current TLM. Only explicit submodules need to
2895+ // be imported under the same TLM, which is handled above.
2896+ if (I->getTopLevelModule () == underlying)
2897+ continue ;
2898+ addImplicitImport (I, /* guaranteedUnique=*/ false );
2899+ }
2900+ for (auto *Submodule : CurrModule->submodules ())
2901+ SubmoduleWorklist.push_back (Submodule);
2902+ }
2903+ }
2904+
28372905 ClangModuleUnit *file = nullptr ;
28382906 auto wrapper = ModuleDecl::create (name, SwiftContext, implicitImportInfo,
28392907 [&](ModuleDecl *wrapper, auto addFile) {
@@ -3742,7 +3810,11 @@ ImportDecl *swift::createImportDecl(ASTContext &Ctx,
37423810 while (TmpMod) {
37433811 // If this is a C++ stdlib module, print its name as `CxxStdlib` instead of
37443812 // `std`. `CxxStdlib` is the only accepted spelling of the C++ stdlib module
3745- // name in Swift.
3813+ // name in Swift. In libc++ versions 17-19 there are multiple TLMs, named
3814+ // std_vector, std_array etc. We don't support importing those modules, but
3815+ // when printing the module interface it'd be weird to print "import
3816+ // CxxStdlib" over and over, so those are still printed as "import
3817+ // std_vector". This only affects the module interface for CxxStdlib.
37463818 Identifier moduleName = !TmpMod->isSubModule () && TmpMod->Name == " std"
37473819 ? Ctx.Id_CxxStdlib
37483820 : Ctx.getIdentifier (TmpMod->Name );
@@ -4597,8 +4669,8 @@ void ClangModuleUnit::getImportedModulesForLookup(
45974669 if (owner.SwiftContext .LangOpts .EnableCXXInterop && topLevel &&
45984670 isCxxStdModule (topLevel) && wrapper->clangModule &&
45994671 isCxxStdModule (wrapper->clangModule )) {
4600- // The CxxStdlib overlay re-exports the clang module std, which in recent
4601- // libc++ versions re-exports top-level modules for different std headers
4672+ // The CxxStdlib overlay re-exports the clang module std, which in libc++
4673+ // versions 17-19 re-exports top-level modules for different std headers
46024674 // (std_string, std_vector, etc). The overlay module for each of the std
46034675 // modules is the CxxStdlib module itself. Make sure we return the actual
46044676 // clang modules (std_xyz) as transitive dependencies instead of just
@@ -8663,7 +8735,7 @@ bool importer::isCxxStdModule(const clang::Module *module) {
86638735bool importer::isCxxStdModule (StringRef moduleName, bool IsSystem) {
86648736 if (moduleName == " std" )
86658737 return true ;
8666- // In recent libc++ versions the module is split into multiple top-level
8738+ // In libc++ versions 17-19 the module is split into multiple top-level
86678739 // modules (std_vector, std_utility, etc).
86688740 if (IsSystem && moduleName.starts_with (" std_" )) {
86698741 if (moduleName == " std_errno_h" )
@@ -8673,6 +8745,19 @@ bool importer::isCxxStdModule(StringRef moduleName, bool IsSystem) {
86738745 return false ;
86748746}
86758747
8748+ ImportPath::Builder ClangImporter::Implementation::getSwiftModulePath (const clang::Module *M) {
8749+ ImportPath::Builder builder;
8750+ while (M) {
8751+ if (!M->isSubModule () && isCxxStdModule (M))
8752+ builder.push_back (SwiftContext.Id_CxxStdlib );
8753+ else
8754+ builder.push_back (SwiftContext.getIdentifier (M->Name ));
8755+ M = M->Parent ;
8756+ }
8757+ std::reverse (builder.begin (), builder.end ());
8758+ return builder;
8759+ }
8760+
86768761std::optional<clang::QualType>
86778762importer::getCxxReferencePointeeTypeOrNone (const clang::Type *type) {
86788763 if (type->isReferenceType ())
0 commit comments