Skip to content

Commit 6dcda93

Browse files
committed
[Serialization] Always list the bridging header before any imports
This mirrors how a bridging header is processed when compiling source files: before any of the imports. This is important for LLDB to recreate the source environment as closely as possible to how the compiler does it; in the test case being added involving a non-modular header file, failure to do so resulted in a deserialization cross-reference crash. Note that Serialization still sorts imports, which normal resolution of imports in source does not do. So we're still not consistent. But this is less important than handling textual includes (bridging headers) before modular imports. rdar://problem/40471329
1 parent 07b2001 commit 6dcda93

File tree

7 files changed

+69
-18
lines changed

7 files changed

+69
-18
lines changed

lib/Serialization/Serialization.cpp

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,28 +1081,38 @@ void Serializer::writeInputBlock(const SerializationOptions &options) {
10811081
publicImportSet.insert(publicImports.begin(), publicImports.end());
10821082

10831083
removeDuplicateImports(allImports);
1084+
10841085
auto clangImporter =
10851086
static_cast<ClangImporter *>(M->getASTContext().getClangModuleLoader());
1086-
ModuleDecl *importedHeaderModule = clangImporter->getImportedHeaderModule();
1087+
ModuleDecl *bridgingHeaderModule = clangImporter->getImportedHeaderModule();
1088+
ModuleDecl::ImportedModule bridgingHeaderImport{{}, bridgingHeaderModule};
1089+
1090+
// Make sure the bridging header module is always at the top of the import
1091+
// list, mimicking how it is processed before any module imports when
1092+
// compiling source files.
1093+
if (llvm::is_contained(allImports, bridgingHeaderImport)) {
1094+
off_t importedHeaderSize = 0;
1095+
time_t importedHeaderModTime = 0;
1096+
std::string contents;
1097+
if (!options.ImportedHeader.empty()) {
1098+
contents = clangImporter->getBridgingHeaderContents(
1099+
options.ImportedHeader, importedHeaderSize, importedHeaderModTime);
1100+
}
1101+
assert(publicImportSet.count(bridgingHeaderImport));
1102+
ImportedHeader.emit(ScratchRecord,
1103+
publicImportSet.count(bridgingHeaderImport),
1104+
importedHeaderSize, importedHeaderModTime,
1105+
options.ImportedHeader);
1106+
if (!contents.empty()) {
1107+
contents.push_back('\0');
1108+
ImportedHeaderContents.emit(ScratchRecord, contents);
1109+
}
1110+
}
1111+
10871112
ModuleDecl *theBuiltinModule = M->getASTContext().TheBuiltinModule;
10881113
for (auto import : allImports) {
1089-
if (import.second == theBuiltinModule)
1090-
continue;
1091-
1092-
if (import.second == importedHeaderModule) {
1093-
off_t importedHeaderSize = 0;
1094-
time_t importedHeaderModTime = 0;
1095-
std::string contents;
1096-
if (!options.ImportedHeader.empty())
1097-
contents = clangImporter->getBridgingHeaderContents(
1098-
options.ImportedHeader, importedHeaderSize, importedHeaderModTime);
1099-
ImportedHeader.emit(ScratchRecord, publicImportSet.count(import),
1100-
importedHeaderSize, importedHeaderModTime,
1101-
options.ImportedHeader);
1102-
if (!contents.empty()) {
1103-
contents.push_back('\0');
1104-
ImportedHeaderContents.emit(ScratchRecord, contents);
1105-
}
1114+
if (import.second == theBuiltinModule ||
1115+
import.second == bridgingHeaderModule) {
11061116
continue;
11071117
}
11081118

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
@protocol AmbivalentProtocol
2+
@end
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#import <AmbivalentProtocol.h>
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module Module {
2+
umbrella header "modular.h"
3+
module * { export * }
4+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#import "AmbivalentProtocol.h"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
$S4main1CCACycfc
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// RUN: %empty-directory(%t)
2+
3+
// RUN: %target-build-swift -emit-module -emit-executable %s -g -I %S/Inputs/bridging-header-first/ -import-objc-header %S/Inputs/bridging-header-first/bridging.h -o %t/main
4+
// RUN: llvm-bcanalyzer -dump %t/main.swiftmodule | %FileCheck -check-prefix CHECK-DUMP %s
5+
// RUN: %lldb-moduleimport-test %t/main -type-from-mangled %S/Inputs/bridging-header-first/mangled.txt 2>&1 | %FileCheck -check-prefix CHECK-RESOLVED-TYPE %s
6+
7+
// RUN: %target-build-swift -emit-module -emit-executable %s -g -I %S/Inputs/bridging-header-first/ -import-objc-header %S/Inputs/bridging-header-first/bridging.h -o %t/main -whole-module-optimization
8+
// RUN: llvm-bcanalyzer -dump %t/main.swiftmodule | %FileCheck -check-prefix CHECK-DUMP %s
9+
// RUN: %lldb-moduleimport-test %t/main -type-from-mangled %S/Inputs/bridging-header-first/mangled.txt 2>&1 | %FileCheck -check-prefix CHECK-RESOLVED-TYPE %s
10+
11+
// REQUIRES: objc_interop
12+
13+
// CHECK-DUMP-LABEL: CONTROL_BLOCK
14+
// CHECK-DUMP: MODULE_NAME
15+
// CHECK-DUMP-SAME: 'main'
16+
17+
// CHECK-DUMP-LABEL: INPUT_BLOCK
18+
// CHECK-DUMP: IMPORTED_HEADER
19+
// CHECK-DUMP-SAME: '{{.+}}/bridging.h'
20+
// CHECK-DUMP: IMPORTED_MODULE
21+
// CHECK-DUMP-SAME: 'Module'
22+
// CHECK-DUMP: IMPORTED_MODULE
23+
// CHECK-DUMP-SAME: 'Swift'
24+
25+
26+
// CHECK-RESOLVED-TYPE: @convention(method) (C.Type) -> () -> C
27+
28+
import Module
29+
class C {}
30+
extension C: AmbivalentProtocol {
31+
func f() {}
32+
}

0 commit comments

Comments
 (0)