@@ -2834,6 +2834,74 @@ ClangModuleUnit *ClangImporter::Implementation::getWrapperForModule(
2834
2834
if (auto mainModule = SwiftContext.MainModule ) {
2835
2835
implicitImportInfo = mainModule->getImplicitImportInfo ();
2836
2836
}
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
+
2837
2905
ClangModuleUnit *file = nullptr ;
2838
2906
auto wrapper = ModuleDecl::create (name, SwiftContext, implicitImportInfo,
2839
2907
[&](ModuleDecl *wrapper, auto addFile) {
@@ -3742,7 +3810,11 @@ ImportDecl *swift::createImportDecl(ASTContext &Ctx,
3742
3810
while (TmpMod) {
3743
3811
// If this is a C++ stdlib module, print its name as `CxxStdlib` instead of
3744
3812
// `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.
3746
3818
Identifier moduleName = !TmpMod->isSubModule () && TmpMod->Name == " std"
3747
3819
? Ctx.Id_CxxStdlib
3748
3820
: Ctx.getIdentifier (TmpMod->Name );
@@ -4597,8 +4669,8 @@ void ClangModuleUnit::getImportedModulesForLookup(
4597
4669
if (owner.SwiftContext .LangOpts .EnableCXXInterop && topLevel &&
4598
4670
isCxxStdModule (topLevel) && wrapper->clangModule &&
4599
4671
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
4602
4674
// (std_string, std_vector, etc). The overlay module for each of the std
4603
4675
// modules is the CxxStdlib module itself. Make sure we return the actual
4604
4676
// clang modules (std_xyz) as transitive dependencies instead of just
@@ -8663,7 +8735,7 @@ bool importer::isCxxStdModule(const clang::Module *module) {
8663
8735
bool importer::isCxxStdModule (StringRef moduleName, bool IsSystem) {
8664
8736
if (moduleName == " std" )
8665
8737
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
8667
8739
// modules (std_vector, std_utility, etc).
8668
8740
if (IsSystem && moduleName.starts_with (" std_" )) {
8669
8741
if (moduleName == " std_errno_h" )
@@ -8673,6 +8745,19 @@ bool importer::isCxxStdModule(StringRef moduleName, bool IsSystem) {
8673
8745
return false ;
8674
8746
}
8675
8747
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
+
8676
8761
std::optional<clang::QualType>
8677
8762
importer::getCxxReferencePointeeTypeOrNone (const clang::Type *type) {
8678
8763
if (type->isReferenceType ())
0 commit comments