Skip to content

Commit 546c26c

Browse files
authored
[ClangImporter] Handle submodule imports in bridging headers (#14501)
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 8243a7f commit 546c26c

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,
@@ -1596,16 +1597,15 @@ ModuleDecl *ClangImporter::Implementation::finishLoadingClangModule(
15961597
void ClangImporter::Implementation::handleDeferredImports()
15971598
{
15981599
clang::ASTReader &R = *Instance->getModuleManager();
1600+
llvm::SmallSet<clang::serialization::SubmoduleID, 32> seenSubmodules;
15991601
for (clang::serialization::SubmoduleID ID : PCHImportedSubmodules) {
1600-
DeferredHeaderImports.push_back(R.getSubmodule(ID));
1602+
if (!seenSubmodules.insert(ID).second)
1603+
continue;
1604+
ImportedHeaderExports.push_back(R.getSubmodule(ID));
16011605
}
16021606
PCHImportedSubmodules.clear();
1603-
for (const clang::Module *M : DeferredHeaderImports) {
1604-
ModuleDecl *nativeImported =
1605-
finishLoadingClangModule(M, /*preferAdapter=*/true);
1606-
ImportedHeaderExports.push_back({ /*filter=*/{}, nativeImported });
1607-
}
1608-
DeferredHeaderImports.clear();
1607+
for (const clang::Module *M : ImportedHeaderExports)
1608+
(void)finishLoadingClangModule(M, /*preferAdapter=*/true);
16091609
}
16101610

16111611
ModuleDecl *ClangImporter::getImportedHeaderModule() const {
@@ -2948,45 +2948,44 @@ void ClangModuleUnit::getImportedModules(
29482948
if (filter != ModuleDecl::ImportFilter::Public)
29492949
imports.push_back({ModuleDecl::AccessPathTy(), owner.getStdlibModule()});
29502950

2951+
SmallVector<clang::Module *, 8> imported;
29512952
if (!clangModule) {
29522953
// This is the special "imported headers" module.
29532954
if (filter != ModuleDecl::ImportFilter::Private) {
2954-
imports.append(owner.ImportedHeaderExports.begin(),
2955-
owner.ImportedHeaderExports.end());
2955+
imported.append(owner.ImportedHeaderExports.begin(),
2956+
owner.ImportedHeaderExports.end());
29562957
}
2957-
return;
2958-
}
29592958

2960-
auto topLevelAdapter = getAdapterModule();
2959+
} else {
2960+
clangModule->getExportedModules(imported);
2961+
if (filter != ModuleDecl::ImportFilter::Public) {
2962+
if (filter == ModuleDecl::ImportFilter::All) {
2963+
llvm::SmallPtrSet<clang::Module *, 8> knownModules;
2964+
imported.append(clangModule->Imports.begin(), clangModule->Imports.end());
2965+
imported.erase(std::remove_if(imported.begin(), imported.end(),
2966+
[&](clang::Module *mod) -> bool {
2967+
return !knownModules.insert(mod).second;
2968+
}),
2969+
imported.end());
2970+
} else {
2971+
llvm::SmallPtrSet<clang::Module *, 8> knownModules(imported.begin(),
2972+
imported.end());
2973+
SmallVector<clang::Module *, 8> privateImports;
2974+
std::copy_if(clangModule->Imports.begin(), clangModule->Imports.end(),
2975+
std::back_inserter(privateImports), [&](clang::Module *mod) {
2976+
return knownModules.count(mod) == 0;
2977+
});
2978+
imported.swap(privateImports);
2979+
}
29612980

2962-
SmallVector<clang::Module *, 8> imported;
2963-
clangModule->getExportedModules(imported);
2964-
if (filter != ModuleDecl::ImportFilter::Public) {
2965-
if (filter == ModuleDecl::ImportFilter::All) {
2966-
llvm::SmallPtrSet<clang::Module *, 8> knownModules;
2967-
imported.append(clangModule->Imports.begin(), clangModule->Imports.end());
2968-
imported.erase(std::remove_if(imported.begin(), imported.end(),
2969-
[&](clang::Module *mod) -> bool {
2970-
return !knownModules.insert(mod).second;
2971-
}),
2972-
imported.end());
2973-
} else {
2974-
llvm::SmallPtrSet<clang::Module *, 8> knownModules(imported.begin(),
2975-
imported.end());
2976-
SmallVector<clang::Module *, 8> privateImports;
2977-
std::copy_if(clangModule->Imports.begin(), clangModule->Imports.end(),
2978-
std::back_inserter(privateImports), [&](clang::Module *mod) {
2979-
return knownModules.count(mod) == 0;
2980-
});
2981-
imported.swap(privateImports);
2981+
// FIXME: The parent module isn't exactly a private import, but it is
2982+
// needed for link dependencies.
2983+
if (clangModule->Parent)
2984+
imported.push_back(clangModule->Parent);
29822985
}
2983-
2984-
// FIXME: The parent module isn't exactly a private import, but it is
2985-
// needed for link dependencies.
2986-
if (clangModule->Parent)
2987-
imported.push_back(clangModule->Parent);
29882986
}
29892987

2988+
auto topLevelAdapter = getAdapterModule();
29902989
for (auto importMod : imported) {
29912990
auto wrapper = owner.getWrapperForModule(importMod);
29922991

@@ -2995,11 +2994,12 @@ void ClangModuleUnit::getImportedModules(
29952994
// HACK: Deal with imports of submodules by importing the top-level module
29962995
// as well.
29972996
auto importTopLevel = importMod->getTopLevelModule();
2998-
if (importTopLevel != importMod &&
2999-
importTopLevel != clangModule->getTopLevelModule()) {
3000-
auto topLevelWrapper = owner.getWrapperForModule(importTopLevel);
3001-
imports.push_back({ ModuleDecl::AccessPathTy(),
3002-
topLevelWrapper->getParentModule() });
2997+
if (importTopLevel != importMod) {
2998+
if (!clangModule || importTopLevel != clangModule->getTopLevelModule()){
2999+
auto topLevelWrapper = owner.getWrapperForModule(importTopLevel);
3000+
imports.push_back({ ModuleDecl::AccessPathTy(),
3001+
topLevelWrapper->getParentModule() });
3002+
}
30033003
}
30043004
actualMod = wrapper->getParentModule();
30053005
} else if (actualMod == topLevelAdapter) {
@@ -3014,13 +3014,6 @@ void ClangModuleUnit::getImportedModules(
30143014
void ClangModuleUnit::getImportedModulesForLookup(
30153015
SmallVectorImpl<ModuleDecl::ImportedModule> &imports) const {
30163016

3017-
if (!clangModule) {
3018-
// This is the special "imported headers" module.
3019-
imports.append(owner.ImportedHeaderExports.begin(),
3020-
owner.ImportedHeaderExports.end());
3021-
return;
3022-
}
3023-
30243017
// Reuse our cached list of imports if we have one.
30253018
if (!importedModulesForLookup.empty()) {
30263019
imports.append(importedModulesForLookup.begin(),
@@ -3029,11 +3022,20 @@ void ClangModuleUnit::getImportedModulesForLookup(
30293022
}
30303023

30313024
size_t firstImport = imports.size();
3032-
auto topLevel = clangModule->getTopLevelModule();
3033-
auto topLevelAdapter = getAdapterModule();
30343025

30353026
SmallVector<clang::Module *, 8> imported;
3036-
clangModule->getExportedModules(imported);
3027+
const clang::Module *topLevel;
3028+
ModuleDecl *topLevelAdapter = getAdapterModule();
3029+
if (!clangModule) {
3030+
// This is the special "imported headers" module.
3031+
imported.append(owner.ImportedHeaderExports.begin(),
3032+
owner.ImportedHeaderExports.end());
3033+
topLevel = nullptr;
3034+
} else {
3035+
clangModule->getExportedModules(imported);
3036+
topLevel = clangModule->getTopLevelModule();
3037+
}
3038+
30373039
if (imported.empty())
30383040
return;
30393041

lib/ClangImporter/ImporterImpl.h

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

337337
bool IsReadingBridgingPCH;
338338
llvm::SmallVector<clang::serialization::SubmoduleID, 2> PCHImportedSubmodules;
339-
llvm::SmallVector<const clang::Module*, 2> DeferredHeaderImports;
340339

341340
const Version CurrentVersion;
342341

@@ -529,7 +528,7 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
529528
ClangModuleUnit *ImportedHeaderUnit = nullptr;
530529

531530
/// The modules re-exported by imported headers.
532-
llvm::SmallVector<ModuleDecl::ImportedModule, 8> ImportedHeaderExports;
531+
llvm::SmallVector<clang::Module *, 8> ImportedHeaderExports;
533532

534533
/// The modules that requested imported headers.
535534
///
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)