Skip to content

Commit 4de19e1

Browse files
authored
Merge pull request #30819 from brentdax/a-less-ambitious-crossover-event
Ignore transitive ObjC imports when cross-importing
2 parents 2eb460d + 121fa9a commit 4de19e1

File tree

12 files changed

+72
-23
lines changed

12 files changed

+72
-23
lines changed

include/swift/AST/ClangModuleLoader.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,9 @@ class ClangModuleLoader : public ModuleLoader {
128128

129129
/// Retrieves the Swift wrapper for the given Clang module, creating
130130
/// it if necessary.
131-
virtual ModuleDecl *getWrapperForModule(const clang::Module *mod) const = 0;
131+
virtual ModuleDecl *
132+
getWrapperForModule(const clang::Module *mod,
133+
bool returnOverlayIfPossible = false) const = 0;
132134

133135
/// Adds a new search path to the Clang CompilerInstance, as if specified with
134136
/// -I or -F.

include/swift/AST/Module.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,7 @@ class ModuleDecl : public DeclContext, public TypeDecl {
465465
/// Retrieve the top-level module. If this module is already top-level, this
466466
/// returns itself. If this is a submodule such as \c Foo.Bar.Baz, this
467467
/// returns the module \c Foo.
468-
ModuleDecl *getTopLevelModule();
468+
ModuleDecl *getTopLevelModule(bool overlay = false);
469469

470470
bool isResilient() const {
471471
return getResilienceStrategy() != ResilienceStrategy::Default;

include/swift/ClangImporter/ClangImporter.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,9 @@ class ClangImporter final : public ClangModuleLoader {
330330

331331
/// Retrieves the Swift wrapper for the given Clang module, creating
332332
/// it if necessary.
333-
ModuleDecl *getWrapperForModule(const clang::Module *mod) const override;
333+
ModuleDecl *
334+
getWrapperForModule(const clang::Module *mod,
335+
bool returnOverlayIfPossible = false) const override;
334336

335337
std::string getBridgingHeaderContents(StringRef headerPath, off_t &fileSize,
336338
time_t &fileModTime);

lib/AST/Module.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -514,15 +514,16 @@ SourceLookupCache &ModuleDecl::getSourceLookupCache() const {
514514
return *Cache;
515515
}
516516

517-
ModuleDecl *ModuleDecl::getTopLevelModule() {
517+
ModuleDecl *ModuleDecl::getTopLevelModule(bool overlay) {
518518
// If this is a Clang module, ask the Clang importer for the top-level module.
519519
// We need to check isNonSwiftModule() to ensure we don't look through
520520
// overlays.
521521
if (isNonSwiftModule()) {
522522
if (auto *underlying = findUnderlyingClangModule()) {
523523
auto &ctx = getASTContext();
524524
auto *clangLoader = ctx.getClangModuleLoader();
525-
return clangLoader->getWrapperForModule(underlying->getTopLevelModule());
525+
return clangLoader->getWrapperForModule(underlying->getTopLevelModule(),
526+
overlay);
526527
}
527528
}
528529
// Swift modules don't currently support submodules.

lib/ClangImporter/ClangImporter.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1860,8 +1860,13 @@ ModuleDecl *ClangImporter::getImportedHeaderModule() const {
18601860
return Impl.ImportedHeaderUnit->getParentModule();
18611861
}
18621862

1863-
ModuleDecl *ClangImporter::getWrapperForModule(const clang::Module *mod) const {
1864-
return Impl.getWrapperForModule(mod)->getParentModule();
1863+
ModuleDecl *
1864+
ClangImporter::getWrapperForModule(const clang::Module *mod,
1865+
bool returnOverlayIfPossible) const {
1866+
auto clangUnit = Impl.getWrapperForModule(mod);
1867+
if (returnOverlayIfPossible && clangUnit->getOverlayModule())
1868+
return clangUnit->getOverlayModule();
1869+
return clangUnit->getParentModule();
18651870
}
18661871

18671872
PlatformAvailability::PlatformAvailability(LangOptions &langOpts)

lib/Sema/ImportResolution.cpp

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -172,15 +172,13 @@ class ImportResolver final : public DeclVisitor<ImportResolver> {
172172
/// The list of fully bound imports.
173173
SmallVector<ImportedModuleDesc, 16> boundImports;
174174

175-
/// All imported modules, including by re-exports, and including submodules.
176-
llvm::DenseSet<ImportedModuleDesc> visibleModules;
177-
178-
/// \c visibleModules but without the submodules.
175+
/// All imported modules which should be considered when cross-importing.
176+
/// This is basically the transitive import graph, but with only top-level
177+
/// modules and without reexports from Objective-C modules.
179178
///
180179
/// We use a \c SmallSetVector here because this doubles as the worklist for
181180
/// cross-importing, so we want to keep it in order; this is feasible
182-
/// because this set is usually fairly small, while \c visibleModules is
183-
/// often enormous.
181+
/// because this set is usually fairly small.
184182
SmallSetVector<ImportedModuleDesc, 64> crossImportableModules;
185183

186184
/// The subset of \c crossImportableModules which may declare cross-imports.
@@ -223,7 +221,7 @@ class ImportResolver final : public DeclVisitor<ImportResolver> {
223221

224222
/// Adds \p desc and everything it re-exports to \c visibleModules using
225223
/// the settings from \c desc.
226-
void addVisibleModules(ImportedModuleDesc desc);
224+
void addCrossImportableModules(ImportedModuleDesc desc);
227225

228226
/// * If \p I is a cross-import overlay, registers \p M as overlaying
229227
/// \p I.underlyingModule in \c SF.
@@ -341,7 +339,7 @@ void ImportResolver::bindImport(UnboundImport &&I) {
341339

342340
void ImportResolver::addImport(const UnboundImport &I, ModuleDecl *M) {
343341
auto importDesc = I.makeDesc(M);
344-
addVisibleModules(importDesc);
342+
addCrossImportableModules(importDesc);
345343
boundImports.push_back(importDesc);
346344
}
347345

@@ -936,7 +934,7 @@ static bool isSubmodule(ModuleDecl* M) {
936934
return clangMod && clangMod->Parent;
937935
}
938936

939-
void ImportResolver::addVisibleModules(ImportedModuleDesc importDesc) {
937+
void ImportResolver::addCrossImportableModules(ImportedModuleDesc importDesc) {
940938
// FIXME: namelookup::getAllImports() doesn't quite do what we need (mainly
941939
// w.r.t. scoped imports), but it seems like we could extend it to do so, and
942940
// then eliminate most of this.
@@ -953,19 +951,34 @@ void ImportResolver::addVisibleModules(ImportedModuleDesc importDesc) {
953951
nextImport.first))
954952
continue;
955953

954+
// If we are importing a submodule, treat it as though we imported its
955+
// top-level module (or rather, the top-level module's clang overlay if it
956+
// has one).
957+
if (isSubmodule(nextImport.second)) {
958+
nextImport.second =
959+
nextImport.second->getTopLevelModule(/*overlay=*/true);
960+
961+
// If the rewritten import is now for our own parent module, this was an
962+
// import of our own clang submodule in a mixed-language module. We don't
963+
// want to process our own cross-imports.
964+
if (nextImport.second == SF.getParentModule())
965+
continue;
966+
}
967+
956968
// Drop this module into the ImportDesc so we treat it as imported with the
957969
// same options and scope as `I`.
958970
importDesc.module.second = nextImport.second;
959971

960-
// If we've already imported it, we've also already imported its
961-
// imports.
962-
if (!visibleModules.insert(importDesc).second)
972+
// Add it to the list of cross-importable modules. If it's already there,
973+
// we've already done the rest of the work of this loop iteration and can
974+
// skip it.
975+
if (!crossImportableModules.insert(importDesc))
963976
continue;
964977

965-
// We don't cross-import submodules, so we shouldn't add them to the
966-
// visibility set. (However, we do consider their reexports.)
967-
if(!isSubmodule(importDesc.module.second))
968-
crossImportableModules.insert(importDesc);
978+
// We don't consider the re-exports of ObjC modules because ObjC re-exports
979+
// everything, so there isn't enough signal there to work from.
980+
if (nextImport.second->isNonSwiftModule())
981+
continue;
969982

970983
// Add the module's re-exports to worklist.
971984
nextImport.second->getImportedModules(importsWorklist,
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
void fromCoreMI6();
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
%YAML 1.2
2+
---
3+
version: 1
4+
modules:
5+
- name: _NeverImportedOverlay

test/CrossImport/Inputs/lib-templates/include/module.modulemap

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,11 @@ module ClangLibrary {
44
header "clang_library_submodule.h"
55
}
66
}
7+
module core_mi6 {
8+
header "core_mi6.h"
9+
export *
10+
}
11+
module UniversalExports {
12+
header "universal_exports.h"
13+
export *
14+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#import <core_mi6.h>
2+
void fromUniversalExportsClang();

test/CrossImport/Inputs/lib-templates/lib/swift/UniversalExports.swiftinterface

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
// swift-module-flags: -swift-version 5 -enable-library-evolution -module-name UniversalExports
33

44
import Swift
5+
6+
// This is also a clang overlay:
7+
@_exported import UniversalExports
8+
59
@_exported import AlwaysImported
610
import NeverImported
711
import MI6 // @_exported imports NeverImported

test/CrossImport/transitive.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ import UniversalExports
1414
import ThinLibrary
1515
#endif
1616

17+
// We should have loaded the underlying clang module.
18+
fromUniversalExportsClang() // no-error
19+
20+
// We should have loaded core_mi6 too.
21+
fromCoreMI6() // no-error
22+
1723
// We should have loaded _AlwaysImportedOverlay.
1824
fromAlwaysImportedOverlay() // no-error
1925

0 commit comments

Comments
 (0)