Skip to content

Commit ef59c7b

Browse files
authored
[ClangImporter] Handle submodule imports in bridging headers (#14500)
If a bridging header imported a submodule but /not/ the top-level module, the top-level module would never be made visible. This is a problem since the Clang importer makes all top-level decls available through their enclosing top-level modules, not the individual submodules. To fix this, stop special-casing the way we handle bridging header imports; we can translate them from Clang Modules to Swift ModuleDecls the same way we do for regular imports. rdar://problem/37355259 (cherry picked from commit 6754cc6)
1 parent 9564de7 commit ef59c7b

File tree

4 files changed

+68
-55
lines changed

4 files changed

+68
-55
lines changed

lib/ClangImporter/ClangImporter.cpp

Lines changed: 55 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,8 @@ namespace {
8383
void handleImport(const clang::Module *imported) {
8484
if (!imported)
8585
return;
86-
Impl.DeferredHeaderImports.push_back(imported);
86+
Impl.ImportedHeaderExports.push_back(
87+
const_cast<clang::Module *>(imported));
8788
}
8889

8990
void InclusionDirective(clang::SourceLocation HashLoc,
@@ -1584,16 +1585,15 @@ ModuleDecl *ClangImporter::Implementation::finishLoadingClangModule(
15841585
void ClangImporter::Implementation::handleDeferredImports()
15851586
{
15861587
clang::ASTReader &R = *Instance->getModuleManager();
1588+
llvm::SmallSet<clang::serialization::SubmoduleID, 32> seenSubmodules;
15871589
for (clang::serialization::SubmoduleID ID : PCHImportedSubmodules) {
1588-
DeferredHeaderImports.push_back(R.getSubmodule(ID));
1590+
if (!seenSubmodules.insert(ID).second)
1591+
continue;
1592+
ImportedHeaderExports.push_back(R.getSubmodule(ID));
15891593
}
15901594
PCHImportedSubmodules.clear();
1591-
for (const clang::Module *M : DeferredHeaderImports) {
1592-
ModuleDecl *nativeImported =
1593-
finishLoadingClangModule(M, /*preferAdapter=*/true);
1594-
ImportedHeaderExports.push_back({ /*filter=*/{}, nativeImported });
1595-
}
1596-
DeferredHeaderImports.clear();
1595+
for (const clang::Module *M : ImportedHeaderExports)
1596+
(void)finishLoadingClangModule(M, /*preferAdapter=*/true);
15971597
}
15981598

15991599
ModuleDecl *ClangImporter::getImportedHeaderModule() const {
@@ -2936,45 +2936,44 @@ void ClangModuleUnit::getImportedModules(
29362936
if (filter != ModuleDecl::ImportFilter::Public)
29372937
imports.push_back({ModuleDecl::AccessPathTy(), owner.getStdlibModule()});
29382938

2939+
SmallVector<clang::Module *, 8> imported;
29392940
if (!clangModule) {
29402941
// This is the special "imported headers" module.
29412942
if (filter != ModuleDecl::ImportFilter::Private) {
2942-
imports.append(owner.ImportedHeaderExports.begin(),
2943-
owner.ImportedHeaderExports.end());
2943+
imported.append(owner.ImportedHeaderExports.begin(),
2944+
owner.ImportedHeaderExports.end());
29442945
}
2945-
return;
2946-
}
29472946

2948-
auto topLevelAdapter = getAdapterModule();
2947+
} else {
2948+
clangModule->getExportedModules(imported);
2949+
if (filter != ModuleDecl::ImportFilter::Public) {
2950+
if (filter == ModuleDecl::ImportFilter::All) {
2951+
llvm::SmallPtrSet<clang::Module *, 8> knownModules;
2952+
imported.append(clangModule->Imports.begin(), clangModule->Imports.end());
2953+
imported.erase(std::remove_if(imported.begin(), imported.end(),
2954+
[&](clang::Module *mod) -> bool {
2955+
return !knownModules.insert(mod).second;
2956+
}),
2957+
imported.end());
2958+
} else {
2959+
llvm::SmallPtrSet<clang::Module *, 8> knownModules(imported.begin(),
2960+
imported.end());
2961+
SmallVector<clang::Module *, 8> privateImports;
2962+
std::copy_if(clangModule->Imports.begin(), clangModule->Imports.end(),
2963+
std::back_inserter(privateImports), [&](clang::Module *mod) {
2964+
return knownModules.count(mod) == 0;
2965+
});
2966+
imported.swap(privateImports);
2967+
}
29492968

2950-
SmallVector<clang::Module *, 8> imported;
2951-
clangModule->getExportedModules(imported);
2952-
if (filter != ModuleDecl::ImportFilter::Public) {
2953-
if (filter == ModuleDecl::ImportFilter::All) {
2954-
llvm::SmallPtrSet<clang::Module *, 8> knownModules;
2955-
imported.append(clangModule->Imports.begin(), clangModule->Imports.end());
2956-
imported.erase(std::remove_if(imported.begin(), imported.end(),
2957-
[&](clang::Module *mod) -> bool {
2958-
return !knownModules.insert(mod).second;
2959-
}),
2960-
imported.end());
2961-
} else {
2962-
llvm::SmallPtrSet<clang::Module *, 8> knownModules(imported.begin(),
2963-
imported.end());
2964-
SmallVector<clang::Module *, 8> privateImports;
2965-
std::copy_if(clangModule->Imports.begin(), clangModule->Imports.end(),
2966-
std::back_inserter(privateImports), [&](clang::Module *mod) {
2967-
return knownModules.count(mod) == 0;
2968-
});
2969-
imported.swap(privateImports);
2969+
// FIXME: The parent module isn't exactly a private import, but it is
2970+
// needed for link dependencies.
2971+
if (clangModule->Parent)
2972+
imported.push_back(clangModule->Parent);
29702973
}
2971-
2972-
// FIXME: The parent module isn't exactly a private import, but it is
2973-
// needed for link dependencies.
2974-
if (clangModule->Parent)
2975-
imported.push_back(clangModule->Parent);
29762974
}
29772975

2976+
auto topLevelAdapter = getAdapterModule();
29782977
for (auto importMod : imported) {
29792978
auto wrapper = owner.getWrapperForModule(importMod);
29802979

@@ -2983,11 +2982,12 @@ void ClangModuleUnit::getImportedModules(
29832982
// HACK: Deal with imports of submodules by importing the top-level module
29842983
// as well.
29852984
auto importTopLevel = importMod->getTopLevelModule();
2986-
if (importTopLevel != importMod &&
2987-
importTopLevel != clangModule->getTopLevelModule()) {
2988-
auto topLevelWrapper = owner.getWrapperForModule(importTopLevel);
2989-
imports.push_back({ ModuleDecl::AccessPathTy(),
2990-
topLevelWrapper->getParentModule() });
2985+
if (importTopLevel != importMod) {
2986+
if (!clangModule || importTopLevel != clangModule->getTopLevelModule()){
2987+
auto topLevelWrapper = owner.getWrapperForModule(importTopLevel);
2988+
imports.push_back({ ModuleDecl::AccessPathTy(),
2989+
topLevelWrapper->getParentModule() });
2990+
}
29912991
}
29922992
actualMod = wrapper->getParentModule();
29932993
} else if (actualMod == topLevelAdapter) {
@@ -3002,13 +3002,6 @@ void ClangModuleUnit::getImportedModules(
30023002
void ClangModuleUnit::getImportedModulesForLookup(
30033003
SmallVectorImpl<ModuleDecl::ImportedModule> &imports) const {
30043004

3005-
if (!clangModule) {
3006-
// This is the special "imported headers" module.
3007-
imports.append(owner.ImportedHeaderExports.begin(),
3008-
owner.ImportedHeaderExports.end());
3009-
return;
3010-
}
3011-
30123005
// Reuse our cached list of imports if we have one.
30133006
if (!importedModulesForLookup.empty()) {
30143007
imports.append(importedModulesForLookup.begin(),
@@ -3017,11 +3010,20 @@ void ClangModuleUnit::getImportedModulesForLookup(
30173010
}
30183011

30193012
size_t firstImport = imports.size();
3020-
auto topLevel = clangModule->getTopLevelModule();
3021-
auto topLevelAdapter = getAdapterModule();
30223013

30233014
SmallVector<clang::Module *, 8> imported;
3024-
clangModule->getExportedModules(imported);
3015+
const clang::Module *topLevel;
3016+
ModuleDecl *topLevelAdapter = getAdapterModule();
3017+
if (!clangModule) {
3018+
// This is the special "imported headers" module.
3019+
imported.append(owner.ImportedHeaderExports.begin(),
3020+
owner.ImportedHeaderExports.end());
3021+
topLevel = nullptr;
3022+
} else {
3023+
clangModule->getExportedModules(imported);
3024+
topLevel = clangModule->getTopLevelModule();
3025+
}
3026+
30253027
if (imported.empty())
30263028
return;
30273029

lib/ClangImporter/ImporterImpl.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,6 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
298298

299299
bool IsReadingBridgingPCH;
300300
llvm::SmallVector<clang::serialization::SubmoduleID, 2> PCHImportedSubmodules;
301-
llvm::SmallVector<const clang::Module*, 2> DeferredHeaderImports;
302301

303302
const Version CurrentVersion;
304303

@@ -491,7 +490,7 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
491490
ClangModuleUnit *ImportedHeaderUnit = nullptr;
492491

493492
/// The modules re-exported by imported headers.
494-
llvm::SmallVector<ModuleDecl::ImportedModule, 8> ImportedHeaderExports;
493+
llvm::SmallVector<clang::Module *, 8> ImportedHeaderExports;
495494

496495
/// The modules that requested imported headers.
497496
///
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#include <ctypes/bits.h>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -verify -I %S/Inputs/custom-modules/ -import-objc-header %S/Inputs/submodules-bridging-header.h %s
3+
4+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-pch -o %t/submodules-bridging-header.pch %S/Inputs/submodules-bridging-header.h
5+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -verify -I %S/Inputs/custom-modules/ -import-objc-header %t/submodules-bridging-header.pch %s
6+
7+
// From ctypes.bits submodule
8+
public var x : DWORD = MY_INT
9+
public var y : CInt = x
10+
public var z : DWORD = "" // expected-error {{cannot convert value}}
11+

0 commit comments

Comments
 (0)