Skip to content

Commit 5880e7d

Browse files
authored
Merge pull request #14487 from jrose-apple/bridge-over-troubled-modules
[ClangImporter] Handle submodule imports in bridging headers
2 parents a8a3c72 + 6754cc6 commit 5880e7d

File tree

5 files changed

+75
-62
lines changed

5 files changed

+75
-62
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 {
@@ -3015,45 +3015,44 @@ void ClangModuleUnit::getImportedModules(
30153015
if (filter != ModuleDecl::ImportFilter::Public)
30163016
imports.push_back({ModuleDecl::AccessPathTy(), owner.getStdlibModule()});
30173017

3018+
SmallVector<clang::Module *, 8> imported;
30183019
if (!clangModule) {
30193020
// This is the special "imported headers" module.
30203021
if (filter != ModuleDecl::ImportFilter::Private) {
3021-
imports.append(owner.ImportedHeaderExports.begin(),
3022-
owner.ImportedHeaderExports.end());
3022+
imported.append(owner.ImportedHeaderExports.begin(),
3023+
owner.ImportedHeaderExports.end());
30233024
}
3024-
return;
3025-
}
30263025

3027-
auto topLevelAdapter = getAdapterModule();
3026+
} else {
3027+
clangModule->getExportedModules(imported);
3028+
if (filter != ModuleDecl::ImportFilter::Public) {
3029+
if (filter == ModuleDecl::ImportFilter::All) {
3030+
llvm::SmallPtrSet<clang::Module *, 8> knownModules;
3031+
imported.append(clangModule->Imports.begin(), clangModule->Imports.end());
3032+
imported.erase(std::remove_if(imported.begin(), imported.end(),
3033+
[&](clang::Module *mod) -> bool {
3034+
return !knownModules.insert(mod).second;
3035+
}),
3036+
imported.end());
3037+
} else {
3038+
llvm::SmallPtrSet<clang::Module *, 8> knownModules(imported.begin(),
3039+
imported.end());
3040+
SmallVector<clang::Module *, 8> privateImports;
3041+
std::copy_if(clangModule->Imports.begin(), clangModule->Imports.end(),
3042+
std::back_inserter(privateImports), [&](clang::Module *mod) {
3043+
return knownModules.count(mod) == 0;
3044+
});
3045+
imported.swap(privateImports);
3046+
}
30283047

3029-
SmallVector<clang::Module *, 8> imported;
3030-
clangModule->getExportedModules(imported);
3031-
if (filter != ModuleDecl::ImportFilter::Public) {
3032-
if (filter == ModuleDecl::ImportFilter::All) {
3033-
llvm::SmallPtrSet<clang::Module *, 8> knownModules;
3034-
imported.append(clangModule->Imports.begin(), clangModule->Imports.end());
3035-
imported.erase(std::remove_if(imported.begin(), imported.end(),
3036-
[&](clang::Module *mod) -> bool {
3037-
return !knownModules.insert(mod).second;
3038-
}),
3039-
imported.end());
3040-
} else {
3041-
llvm::SmallPtrSet<clang::Module *, 8> knownModules(imported.begin(),
3042-
imported.end());
3043-
SmallVector<clang::Module *, 8> privateImports;
3044-
std::copy_if(clangModule->Imports.begin(), clangModule->Imports.end(),
3045-
std::back_inserter(privateImports), [&](clang::Module *mod) {
3046-
return knownModules.count(mod) == 0;
3047-
});
3048-
imported.swap(privateImports);
3048+
// FIXME: The parent module isn't exactly a private import, but it is
3049+
// needed for link dependencies.
3050+
if (clangModule->Parent)
3051+
imported.push_back(clangModule->Parent);
30493052
}
3050-
3051-
// FIXME: The parent module isn't exactly a private import, but it is
3052-
// needed for link dependencies.
3053-
if (clangModule->Parent)
3054-
imported.push_back(clangModule->Parent);
30553053
}
30563054

3055+
auto topLevelAdapter = getAdapterModule();
30573056
for (auto importMod : imported) {
30583057
auto wrapper = owner.getWrapperForModule(importMod);
30593058

@@ -3062,11 +3061,12 @@ void ClangModuleUnit::getImportedModules(
30623061
// HACK: Deal with imports of submodules by importing the top-level module
30633062
// as well.
30643063
auto importTopLevel = importMod->getTopLevelModule();
3065-
if (importTopLevel != importMod &&
3066-
importTopLevel != clangModule->getTopLevelModule()) {
3067-
auto topLevelWrapper = owner.getWrapperForModule(importTopLevel);
3068-
imports.push_back({ ModuleDecl::AccessPathTy(),
3069-
topLevelWrapper->getParentModule() });
3064+
if (importTopLevel != importMod) {
3065+
if (!clangModule || importTopLevel != clangModule->getTopLevelModule()){
3066+
auto topLevelWrapper = owner.getWrapperForModule(importTopLevel);
3067+
imports.push_back({ ModuleDecl::AccessPathTy(),
3068+
topLevelWrapper->getParentModule() });
3069+
}
30703070
}
30713071
actualMod = wrapper->getParentModule();
30723072
} else if (actualMod == topLevelAdapter) {
@@ -3081,13 +3081,6 @@ void ClangModuleUnit::getImportedModules(
30813081
void ClangModuleUnit::getImportedModulesForLookup(
30823082
SmallVectorImpl<ModuleDecl::ImportedModule> &imports) const {
30833083

3084-
if (!clangModule) {
3085-
// This is the special "imported headers" module.
3086-
imports.append(owner.ImportedHeaderExports.begin(),
3087-
owner.ImportedHeaderExports.end());
3088-
return;
3089-
}
3090-
30913084
// Reuse our cached list of imports if we have one.
30923085
if (!importedModulesForLookup.empty()) {
30933086
imports.append(importedModulesForLookup.begin(),
@@ -3096,11 +3089,20 @@ void ClangModuleUnit::getImportedModulesForLookup(
30963089
}
30973090

30983091
size_t firstImport = imports.size();
3099-
auto topLevel = clangModule->getTopLevelModule();
3100-
auto topLevelAdapter = getAdapterModule();
31013092

31023093
SmallVector<clang::Module *, 8> imported;
3103-
clangModule->getExportedModules(imported);
3094+
const clang::Module *topLevel;
3095+
ModuleDecl *topLevelAdapter = getAdapterModule();
3096+
if (!clangModule) {
3097+
// This is the special "imported headers" module.
3098+
imported.append(owner.ImportedHeaderExports.begin(),
3099+
owner.ImportedHeaderExports.end());
3100+
topLevel = nullptr;
3101+
} else {
3102+
clangModule->getExportedModules(imported);
3103+
topLevel = clangModule->getTopLevelModule();
3104+
}
3105+
31043106
if (imported.empty())
31053107
return;
31063108

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>

test/ClangImporter/pch-bridging-header.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,30 @@
44

55
// First test the explicit frontend-based bridging PCH generation and use works
66
// RUN: %target-swift-frontend -emit-pch -o %t/sdk-bridging-header.pch %S/Inputs/sdk-bridging-header.h
7-
// RUN: %target-swift-frontend -parse -verify %s -import-objc-header %t/sdk-bridging-header.pch
7+
// RUN: %target-swift-frontend -typecheck -verify %s -import-objc-header %t/sdk-bridging-header.pch
88

99
// Now test the driver-automated version is inert when disabled
10-
// RUN: env TMPDIR=%t/tmp/ %target-swiftc_driver -parse -disable-bridging-pch -save-temps %s -import-objc-header %S/Inputs/sdk-bridging-header.h
10+
// RUN: env TMPDIR=%t/tmp/ %target-swiftc_driver -typecheck -disable-bridging-pch -save-temps %s -import-objc-header %S/Inputs/sdk-bridging-header.h
1111
// RUN: not ls %t/tmp/*.pch >/dev/null 2>&1
1212

1313
// Test the driver-automated version works by default
14-
// RUN: env TMPDIR=%t/tmp/ %target-swiftc_driver -parse -save-temps %s -import-objc-header %S/Inputs/sdk-bridging-header.h
14+
// RUN: env TMPDIR=%t/tmp/ %target-swiftc_driver -typecheck -save-temps %s -import-objc-header %S/Inputs/sdk-bridging-header.h
1515
// RUN: ls %t/tmp/*.pch >/dev/null 2>&1
1616
// RUN: llvm-objdump -raw-clang-ast %t/tmp/*.pch | llvm-bcanalyzer -dump | %FileCheck %s
1717
// CHECK: ORIGINAL_FILE{{.*}}Inputs/sdk-bridging-header.h
1818

1919
// Test the driver-automated version deletes its PCH file when done
2020
// RUN: rm %t/tmp/*.pch
21-
// RUN: env TMPDIR=%t/tmp/ %target-swiftc_driver -parse %s -import-objc-header %S/Inputs/sdk-bridging-header.h
21+
// RUN: env TMPDIR=%t/tmp/ %target-swiftc_driver -typecheck %s -import-objc-header %S/Inputs/sdk-bridging-header.h
2222
// RUN: not ls %t/tmp/*.pch >/dev/null 2>&1
2323

2424
// Test -emit-pch invocation but with a persistent PCH
2525
// RUN: %target-swift-frontend -emit-pch -pch-output-dir %t/pch %S/Inputs/sdk-bridging-header.h
26-
// RUN: %target-swift-frontend -parse -verify %s -import-objc-header %S/Inputs/sdk-bridging-header.h -pch-output-dir %t/pch -pch-disable-validation
26+
// RUN: %target-swift-frontend -typecheck -verify %s -import-objc-header %S/Inputs/sdk-bridging-header.h -pch-output-dir %t/pch -pch-disable-validation
2727
// RUN: ls %t/pch/*.pch >/dev/null 2>&1
2828

2929
// Test implicit use of persistent PCH
30-
// RUN: %target-swift-frontend -parse -verify %s -import-objc-header %S/Inputs/sdk-bridging-header.h -pch-output-dir %t/pch2
30+
// RUN: %target-swift-frontend -typecheck -verify %s -import-objc-header %S/Inputs/sdk-bridging-header.h -pch-output-dir %t/pch2
3131
// RUN: ls %t/pch2/*.pch >/dev/null 2>&1
3232

3333
// RUN: touch %t/header.with.dot.h
@@ -37,7 +37,7 @@
3737
// RUN: ls %t/pch_with_dot/*swift*clang*.pch | count 2
3838

3939
// Test the driver-automated version using persistent PCH
40-
// RUN: %target-swiftc_driver -parse -save-temps %s -import-objc-header %S/Inputs/sdk-bridging-header.h -pch-output-dir %t/pch3
40+
// RUN: %target-swiftc_driver -typecheck -save-temps %s -import-objc-header %S/Inputs/sdk-bridging-header.h -pch-output-dir %t/pch3
4141
// RUN: ls %t/pch3/*.pch >/dev/null 2>&1
4242
// RUN: llvm-objdump -raw-clang-ast %t/pch3/*.pch | llvm-bcanalyzer -dump | %FileCheck %s -check-prefix=PERSISTENT
4343
// PERSISTENT: ORIGINAL_FILE{{.*}}Inputs/sdk-bridging-header.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)