Skip to content

Commit cfa0ab3

Browse files
committed
AST: Introduce ModuleDecl::ImportFilter::ForLinking
ModuleDecl::forAllVisibleModules() now has a includeLinkOnlyModules parameter. This is intended to be used when computing the set of libraries to autolink.
1 parent 7539674 commit cfa0ab3

File tree

5 files changed

+77
-12
lines changed

5 files changed

+77
-12
lines changed

include/swift/AST/Module.h

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -345,9 +345,17 @@ class ModuleDecl : public DeclContext, public TypeDecl {
345345

346346
/// \sa getImportedModules
347347
enum class ImportFilter {
348+
// Everything.
348349
All,
350+
351+
// @_exported only.
349352
Public,
350-
Private
353+
354+
// Not @_exported only. Also includes @_usableFromInline.
355+
Private,
356+
357+
// @_usableFromInline and @_exported only.
358+
ForLinking
351359
};
352360

353361
/// Looks up which modules are imported by this module.
@@ -360,11 +368,16 @@ class ModuleDecl : public DeclContext, public TypeDecl {
360368
/// Looks up which modules are imported by this module, ignoring any that
361369
/// won't contain top-level decls.
362370
///
363-
/// This is a performance hack. Do not use for anything but name lookup.
364-
/// May go away in the future.
371+
/// This is a performance hack for the ClangImporter. Do not use for
372+
/// anything but name lookup. May go away in the future.
365373
void
366374
getImportedModulesForLookup(SmallVectorImpl<ImportedModule> &imports) const;
367375

376+
/// Extension of the above hack. Identical to getImportedModulesForLookup()
377+
/// for imported modules, otherwise also includes @usableFromInline imports.
378+
void
379+
getImportedModulesForLinking(SmallVectorImpl<ImportedModule> &imports) const;
380+
368381
/// Finds all top-level decls of this module.
369382
///
370383
/// This does a simple local lookup, not recursively looking through imports.
@@ -402,11 +415,16 @@ class ModuleDecl : public DeclContext, public TypeDecl {
402415
/// results, with the given access path.
403416
/// \param fn A callback of type bool(ImportedModule) or void(ImportedModule).
404417
/// Return \c false to abort iteration.
418+
/// \param includeLinkOnlyModules Include modules that are not visible to
419+
/// name lookup but must be linked in because inlinable code can
420+
/// reference their symbols.
405421
///
406422
/// \return True if the traversal ran to completion, false if it ended early
407423
/// due to the callback.
408424
bool forAllVisibleModules(AccessPathTy topLevelAccessPath,
409-
llvm::function_ref<bool(ImportedModule)> fn);
425+
llvm::function_ref<bool(ImportedModule)> fn,
426+
bool includeLinkOnlyModules = false);
427+
410428

411429
/// @}
412430

@@ -638,6 +656,12 @@ class FileUnit : public DeclContext {
638656
return getImportedModules(imports, ModuleDecl::ImportFilter::Public);
639657
}
640658

659+
/// \see ModuleDecl::getImportedModulesForLinking
660+
virtual void getImportedModulesForLinking(
661+
SmallVectorImpl<ModuleDecl::ImportedModule> &imports) const {
662+
return getImportedModules(imports, ModuleDecl::ImportFilter::ForLinking);
663+
}
664+
641665
/// Generates the list of libraries needed to link this file, based on its
642666
/// imports.
643667
virtual void
@@ -649,11 +673,15 @@ class FileUnit : public DeclContext {
649673
///
650674
/// \param fn A callback of type bool(ImportedModule) or void(ImportedModule).
651675
/// Return \c false to abort iteration.
676+
/// \param includeLinkOnlyModules Include modules that are not visible to
677+
/// name lookup but must be linked in because inlinable code can
678+
/// reference their symbols.
652679
///
653680
/// \return True if the traversal ran to completion, false if it ended early
654681
/// due to the callback.
655682
bool
656-
forAllVisibleModules(llvm::function_ref<bool(ModuleDecl::ImportedModule)> fn);
683+
forAllVisibleModules(llvm::function_ref<bool(ModuleDecl::ImportedModule)> fn,
684+
bool includeLinkOnlyModules = false);
657685

658686
/// @}
659687

include/swift/ClangImporter/ClangModule.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,12 @@ class ClangModuleUnit final : public LoadedFile {
9797
virtual void getImportedModulesForLookup(
9898
SmallVectorImpl<ModuleDecl::ImportedModule> &imports) const override;
9999

100+
virtual void getImportedModulesForLinking(
101+
SmallVectorImpl<ModuleDecl::ImportedModule> &imports) const override {
102+
// In C, anything that's linkable is visible to the source language.
103+
return getImportedModulesForLookup(imports);
104+
}
105+
100106
virtual void
101107
collectLinkLibraries(ModuleDecl::LinkLibraryCallback callback) const override;
102108

lib/AST/Module.cpp

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -974,6 +974,11 @@ SourceFile::getImportedModules(SmallVectorImpl<ModuleDecl::ImportedModule> &modu
974974
if (importPair.second.contains(ImportFlags::Exported))
975975
continue;
976976
break;
977+
case ModuleDecl::ImportFilter::ForLinking:
978+
if (!importPair.second.contains(ImportFlags::UsableFromInline) &&
979+
!importPair.second.contains(ImportFlags::Exported))
980+
continue;
981+
break;
977982
}
978983

979984
modules.push_back(importPair.first);
@@ -985,6 +990,11 @@ void ModuleDecl::getImportedModulesForLookup(
985990
FORWARD(getImportedModulesForLookup, (modules));
986991
}
987992

993+
void ModuleDecl::getImportedModulesForLinking(
994+
SmallVectorImpl<ImportedModule> &modules) const {
995+
FORWARD(getImportedModulesForLinking, (modules));
996+
}
997+
988998
bool ModuleDecl::isSameAccessPath(AccessPathTy lhs, AccessPathTy rhs) {
989999
using AccessPathElem = std::pair<Identifier, SourceLoc>;
9901000
if (lhs.size() != rhs.size())
@@ -1128,11 +1138,15 @@ bool ModuleDecl::isSystemModule() const {
11281138
}
11291139

11301140
bool ModuleDecl::forAllVisibleModules(AccessPathTy thisPath,
1131-
llvm::function_ref<bool(ImportedModule)> fn) {
1141+
llvm::function_ref<bool(ImportedModule)> fn,
1142+
bool includeLinkOnlyModules) {
11321143
llvm::SmallSet<ImportedModule, 32, ModuleDecl::OrderImportedModules> visited;
11331144
SmallVector<ImportedModule, 32> stack;
11341145

1135-
getImportedModules(stack, ModuleDecl::ImportFilter::Public);
1146+
if (includeLinkOnlyModules)
1147+
getImportedModules(stack, ModuleDecl::ImportFilter::ForLinking);
1148+
else
1149+
getImportedModules(stack, ModuleDecl::ImportFilter::Public);
11361150

11371151
// Make sure the top-level module is first; we want pre-order-ish traversal.
11381152
stack.push_back(ImportedModule(thisPath, this));
@@ -1158,15 +1172,20 @@ bool ModuleDecl::forAllVisibleModules(AccessPathTy thisPath,
11581172
if (!fn(next))
11591173
return false;
11601174

1161-
next.second->getImportedModulesForLookup(stack);
1175+
if (includeLinkOnlyModules)
1176+
next.second->getImportedModulesForLinking(stack);
1177+
else
1178+
next.second->getImportedModulesForLookup(stack);
11621179
}
11631180

11641181
return true;
11651182
}
11661183

11671184
bool FileUnit::forAllVisibleModules(
1168-
llvm::function_ref<bool(ModuleDecl::ImportedModule)> fn) {
1169-
if (!getParentModule()->forAllVisibleModules(ModuleDecl::AccessPathTy(), fn))
1185+
llvm::function_ref<bool(ModuleDecl::ImportedModule)> fn,
1186+
bool includeLinkOnlyModules) {
1187+
if (!getParentModule()->forAllVisibleModules(ModuleDecl::AccessPathTy(), fn,
1188+
includeLinkOnlyModules))
11701189
return false;
11711190

11721191
if (auto SF = dyn_cast<SourceFile>(this)) {
@@ -1175,7 +1194,8 @@ bool FileUnit::forAllVisibleModules(
11751194
SmallVector<ModuleDecl::ImportedModule, 4> imports;
11761195
SF->getImportedModules(imports, ModuleDecl::ImportFilter::Private);
11771196
for (auto importPair : imports)
1178-
if (!importPair.second->forAllVisibleModules(importPair.first, fn))
1197+
if (!importPair.second->forAllVisibleModules(importPair.first, fn,
1198+
includeLinkOnlyModules))
11791199
return false;
11801200
}
11811201

@@ -1198,7 +1218,8 @@ SourceFile::collectLinkLibraries(ModuleDecl::LinkLibraryCallback callback) const
11981218

11991219
next->collectLinkLibraries(callback);
12001220
return true;
1201-
});
1221+
},
1222+
/*includeLinkOnlyModules=*/true);
12021223
}
12031224

12041225
bool ModuleDecl::walk(ASTWalker &Walker) {

lib/ClangImporter/ClangImporter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3049,6 +3049,7 @@ void ClangModuleUnit::getImportedModules(
30493049
imports.push_back({ModuleDecl::AccessPathTy(), owner.getStdlibModule()});
30503050
break;
30513051
case ModuleDecl::ImportFilter::Public:
3052+
case ModuleDecl::ImportFilter::ForLinking:
30523053
break;
30533054
}
30543055

@@ -3058,6 +3059,7 @@ void ClangModuleUnit::getImportedModules(
30583059
switch (filter) {
30593060
case ModuleDecl::ImportFilter::All:
30603061
case ModuleDecl::ImportFilter::Public:
3062+
case ModuleDecl::ImportFilter::ForLinking:
30613063
imported.append(owner.ImportedHeaderExports.begin(),
30623064
owner.ImportedHeaderExports.end());
30633065
break;
@@ -3106,6 +3108,7 @@ void ClangModuleUnit::getImportedModules(
31063108
}
31073109

31083110
case ModuleDecl::ImportFilter::Public:
3111+
case ModuleDecl::ImportFilter::ForLinking:
31093112
break;
31103113
}
31113114
}

lib/Serialization/ModuleFile.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1598,6 +1598,13 @@ void ModuleFile::getImportedModules(
15981598
continue;
15991599

16001600
break;
1601+
1602+
case ModuleDecl::ImportFilter::ForLinking:
1603+
// FIXME
1604+
if (!dep.isExported())
1605+
continue;
1606+
1607+
break;
16011608
}
16021609

16031610
assert(dep.isLoaded());

0 commit comments

Comments
 (0)