Skip to content

Commit 0ea5677

Browse files
committed
[ImportResolution] Deduplicate top-level clang modules from import list
Importing clang submodules results in an implicit import of the top-level module as well. This can result in the same TLM being imported many different times, if multiple submodules are imported from the same module. This deduplicates these imports. Other imports are not expected to be duplicated, so care is taken to only deduplicate clang TLM imports.
1 parent 369fc18 commit 0ea5677

File tree

3 files changed

+14
-30
lines changed

3 files changed

+14
-30
lines changed

lib/Sema/ImportResolution.cpp

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,11 @@ class ImportResolver final : public DeclVisitor<ImportResolver> {
163163
/// The list of fully bound imports.
164164
SmallVector<AttributedImport<ImportedModule>, 16> boundImports;
165165

166+
/// Set of imported top-level clang modules. We normally don't expect
167+
/// duplicated imports, but importing multiple submodules of the same clang
168+
/// TLM would cause the same TLM to be imported once per submodule.
169+
SmallPtrSet<const ModuleDecl*, 16> seenClangTLMs;
170+
166171
/// All imported modules which should be considered when cross-importing.
167172
/// This is basically the transitive import graph, but with only top-level
168173
/// modules and without reexports from Objective-C modules.
@@ -388,14 +393,16 @@ void ImportResolver::bindImport(UnboundImport &&I) {
388393

389394
I.validateOptions(topLevelModule, SF);
390395

391-
if (topLevelModule && topLevelModule != M) {
392-
// If we have distinct submodule and top-level module, add both.
393-
addImport(I, M);
394-
addImport(I, topLevelModule.get());
395-
}
396-
else {
397-
// Add only the import itself.
396+
if (!M->isNonSwiftModule() || topLevelModule != M ||
397+
seenClangTLMs.insert(M).second) {
398398
addImport(I, M);
399+
if (topLevelModule && topLevelModule != M &&
400+
seenClangTLMs.insert(topLevelModule.get()).second) {
401+
// If we have distinct submodule and top-level module, add both.
402+
// Importing the submodule ensures that it gets loaded, but the decls
403+
// are imported to the TLM, so import that for visibility.
404+
addImport(I, topLevelModule.get());
405+
}
399406
}
400407

401408
crossImport(M, I);

test/Interop/C/swiftify-import/clang-includes-indirect-explicit-modules.swift

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -156,9 +156,7 @@ d1_t b2d(void * _Nonnull __sized_by(size), int size);
156156
// DUMP-NEXT: D1
157157
// DUMP-NEXT: A1
158158
// DUMP-NEXT: C1
159-
// DUMP-NEXT: A1
160159
// DUMP-NEXT: B1
161-
// DUMP-NEXT: A1
162160
// DUMP-NEXT: B2
163161
// DUMP-CXX-NEXT: CxxShim
164162
// DUMP-CXX-NEXT: Cxx
@@ -174,9 +172,7 @@ d1_t b2d(void * _Nonnull __sized_by(size), int size);
174172
// DUMP-NEXT: D1
175173
// DUMP-NEXT: A1
176174
// DUMP-NEXT: C1
177-
// DUMP-NEXT: A1
178175
// DUMP-NEXT: B1
179-
// DUMP-NEXT: A1
180176
// DUMP-NEXT: B2
181177
// DUMP-CXX-NEXT: CxxShim
182178
// DUMP-CXX-NEXT: Cxx
@@ -192,9 +188,7 @@ d1_t b2d(void * _Nonnull __sized_by(size), int size);
192188
// DUMP-NEXT: D1
193189
// DUMP-NEXT: A1
194190
// DUMP-NEXT: C1
195-
// DUMP-NEXT: A1
196191
// DUMP-NEXT: B1
197-
// DUMP-NEXT: A1
198192
// DUMP-NEXT: B2
199193
// DUMP-CXX-NEXT: CxxShim
200194
// DUMP-CXX-NEXT: Cxx

test/Interop/C/swiftify-import/clang-includes-redundant-imports.swift

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,12 @@ import A2.B2.C2
3838
// DUMP-NEXT: SwiftOnoneSupport
3939
// DUMP-NEXT: A1
4040
// DUMP-NEXT: B1
41-
// DUMP-NEXT: A1
4241
// DUMP-NEXT: C1
43-
// DUMP-NEXT: A1
4442
// DUMP-NEXT: D1
45-
// DUMP-NEXT: A1
4643
// DUMP-NEXT: E1
47-
// DUMP-NEXT: A1
4844
// DUMP-NEXT: B2
4945
// DUMP-NEXT: A2
5046
// DUMP-NEXT: C2
51-
// DUMP-NEXT: A2
5247

5348
public func callUnsafe(_ p: UnsafeMutableRawPointer) {
5449
let _ = a1(p, 13)
@@ -301,10 +296,7 @@ c2_t b2_2(void * _Nonnull __sized_by(size), int size);
301296
// DUMP-NEXT: D1
302297
// DUMP-NEXT: A1
303298
// DUMP-NEXT: C1
304-
// DUMP-NEXT: A1
305299
// DUMP-NEXT: B1
306-
// DUMP-NEXT: A1
307-
// DUMP-NEXT: A1
308300
// DUMP-CXX-NEXT: CxxShim
309301
// DUMP-CXX-NEXT: Cxx
310302
// DUMP-NEXT: _StringProcessing
@@ -320,10 +312,7 @@ c2_t b2_2(void * _Nonnull __sized_by(size), int size);
320312
// DUMP-NEXT: D1
321313
// DUMP-NEXT: A1
322314
// DUMP-NEXT: C1
323-
// DUMP-NEXT: A1
324315
// DUMP-NEXT: B1
325-
// DUMP-NEXT: A1
326-
// DUMP-NEXT: A1
327316
// DUMP-CXX-NEXT: CxxShim
328317
// DUMP-CXX-NEXT: Cxx
329318
// DUMP-NEXT: _StringProcessing
@@ -352,10 +341,7 @@ e2_t c2(void * _Nonnull __sized_by(size), int size);
352341
// DUMP-NEXT: D1
353342
// DUMP-NEXT: A1
354343
// DUMP-NEXT: C1
355-
// DUMP-NEXT: A1
356344
// DUMP-NEXT: B1
357-
// DUMP-NEXT: A1
358-
// DUMP-NEXT: A1
359345
// DUMP-CXX-NEXT: CxxShim
360346
// DUMP-CXX-NEXT: Cxx
361347
// DUMP-NEXT: _StringProcessing
@@ -380,10 +366,7 @@ e2_t d2(void * _Nonnull __sized_by(size), int size);
380366
// DUMP-NEXT: D1
381367
// DUMP-NEXT: A1
382368
// DUMP-NEXT: C1
383-
// DUMP-NEXT: A1
384369
// DUMP-NEXT: B1
385-
// DUMP-NEXT: A1
386-
// DUMP-NEXT: A1
387370
// DUMP-CXX-NEXT: CxxShim
388371
// DUMP-CXX-NEXT: Cxx
389372
// DUMP-NEXT: _StringProcessing

0 commit comments

Comments
 (0)