Skip to content

Commit 057097a

Browse files
committed
[NFC] Hide LoadedModules From Clients of ASTContext
There's no reason clients need to be able to access this data directly. It obscures where module loading is actually happening, and makes it too easy to accidentally register a module with the wrong identifier in the context. Hide the registration operations behind opaque accessors.
1 parent 15c8c26 commit 057097a

File tree

10 files changed

+58
-25
lines changed

10 files changed

+58
-25
lines changed

include/swift/AST/ASTContext.h

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -254,11 +254,6 @@ class ASTContext final {
254254
/// The request-evaluator that is used to process various requests.
255255
Evaluator evaluator;
256256

257-
/// The set of top-level modules we have loaded.
258-
/// This map is used for iteration, therefore it's a MapVector and not a
259-
/// DenseMap.
260-
llvm::MapVector<Identifier, ModuleDecl*> LoadedModules;
261-
262257
/// The builtin module.
263258
ModuleDecl * const TheBuiltinModule;
264259

@@ -787,8 +782,24 @@ class ASTContext final {
787782
/// The loader is owned by the AST context.
788783
ClangModuleLoader *getDWARFModuleLoader() const;
789784

785+
public:
790786
namelookup::ImportCache &getImportCache() const;
791787

788+
/// Returns an iterator over the modules that are known by this context
789+
/// to be loaded.
790+
///
791+
/// Iteration order is guaranteed to match the order in which
792+
/// \c addLoadedModule was called to register the loaded module
793+
/// with this context.
794+
iterator_range<llvm::MapVector<Identifier, ModuleDecl *>::const_iterator>
795+
getLoadedModules() const;
796+
797+
/// Returns the number of loaded modules known by this context to be loaded.
798+
unsigned getNumLoadedModules() const {
799+
auto eltRange = getLoadedModules();
800+
return std::distance(eltRange.begin(), eltRange.end());
801+
}
802+
792803
/// Asks every module loader to verify the ASTs it has loaded.
793804
///
794805
/// Does nothing in non-asserts (NDEBUG) builds.
@@ -828,6 +839,11 @@ class ASTContext final {
828839
return const_cast<ASTContext *>(this)->getStdlibModule(false);
829840
}
830841

842+
/// Insert an externally-sourced module into the set of known loaded modules
843+
/// in this context.
844+
void addLoadedModule(ModuleDecl *M);
845+
846+
public:
831847
/// Retrieve the current generation number, which reflects the
832848
/// number of times a module import has caused mass invalidation of
833849
/// lookup tables.

lib/AST/ASTContext.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,11 @@ struct ASTContext::Implementation {
156156
/// The set of cleanups to be called when the ASTContext is destroyed.
157157
std::vector<std::function<void(void)>> Cleanups;
158158

159+
/// The set of top-level modules we have loaded.
160+
/// This map is used for iteration, therefore it's a MapVector and not a
161+
/// DenseMap.
162+
llvm::MapVector<Identifier, ModuleDecl *> LoadedModules;
163+
159164
// FIXME: This is a StringMap rather than a StringSet because StringSet
160165
// doesn't allow passing in a pre-existing allocator.
161166
llvm::StringMap<Identifier::Aligner, llvm::BumpPtrAllocator&>
@@ -1538,8 +1543,18 @@ ModuleDecl *ASTContext::getLoadedModule(
15381543
return nullptr;
15391544
}
15401545

1546+
iterator_range<llvm::MapVector<Identifier, ModuleDecl *>::const_iterator>
1547+
ASTContext::getLoadedModules() const {
1548+
return {getImpl().LoadedModules.begin(), getImpl().LoadedModules.end()};
1549+
}
1550+
15411551
ModuleDecl *ASTContext::getLoadedModule(Identifier ModuleName) const {
1542-
return LoadedModules.lookup(ModuleName);
1552+
return getImpl().LoadedModules.lookup(ModuleName);
1553+
}
1554+
1555+
void ASTContext::addLoadedModule(ModuleDecl *M) {
1556+
assert(M);
1557+
getImpl().LoadedModules[M->getName()] = M;
15431558
}
15441559

15451560
static AllocationArena getArena(GenericSignature genericSig) {

lib/ClangImporter/ClangImporter.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1825,9 +1825,9 @@ ModuleDecl *ClangImporter::Implementation::finishLoadingClangModule(
18251825
if (clangModule->isSubModule()) {
18261826
finishLoadingClangModule(clangModule->getTopLevelModule(), importLoc);
18271827
} else {
1828-
ModuleDecl *&loaded = SwiftContext.LoadedModules[result->getName()];
1829-
if (!loaded)
1830-
loaded = result;
1828+
1829+
if (!SwiftContext.getLoadedModule(result->getName()))
1830+
SwiftContext.addLoadedModule(result);
18311831
}
18321832

18331833
return result;
@@ -3368,10 +3368,12 @@ ModuleDecl *ClangModuleUnit::getOverlayModule() const {
33683368
if (overlay == M) {
33693369
overlay = nullptr;
33703370
} else {
3371-
auto &sharedModuleRef = Ctx.LoadedModules[M->getName()];
3371+
// FIXME: This bizarre and twisty invariant is due to nested
3372+
// re-entrancy in both clang module loading and overlay module loading.
3373+
auto *sharedModuleRef = Ctx.getLoadedModule(M->getName());
33723374
assert(!sharedModuleRef || sharedModuleRef == overlay ||
33733375
sharedModuleRef == M);
3374-
sharedModuleRef = overlay;
3376+
Ctx.addLoadedModule(overlay);
33753377
}
33763378

33773379
auto mutableThis = const_cast<ClangModuleUnit *>(this);

lib/ClangImporter/DWARFImporter.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,8 @@ ModuleDecl *ClangImporter::Implementation::loadModuleDWARF(
121121
(void) namelookup::getAllImports(decl);
122122

123123
// Register the module with the ASTContext so it is available for lookups.
124-
ModuleDecl *&loaded = SwiftContext.LoadedModules[name];
125-
if (!loaded)
126-
loaded = decl;
124+
if (!SwiftContext.getLoadedModule(name))
125+
SwiftContext.addLoadedModule(decl);
127126

128127
return decl;
129128
}

lib/Frontend/Frontend.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -751,7 +751,8 @@ ModuleDecl *CompilerInstance::getMainModule() const {
751751
if (Invocation.getFrontendOptions().EnableLibraryEvolution)
752752
MainModule->setResilienceStrategy(ResilienceStrategy::Resilient);
753753

754-
Context->LoadedModules[MainModule->getName()] = MainModule;
754+
// Register the main module with the AST context.
755+
Context->addLoadedModule(MainModule);
755756

756757
// Create and add the module's files.
757758
SmallVector<FileUnit *, 16> files;
@@ -773,7 +774,7 @@ ModuleDecl *CompilerInstance::getMainModule() const {
773774
void CompilerInstance::setMainModule(ModuleDecl *newMod) {
774775
assert(newMod->isMainModule());
775776
MainModule = newMod;
776-
Context->LoadedModules[newMod->getName()] = newMod;
777+
Context->addLoadedModule(newMod);
777778
}
778779

779780
void CompilerInstance::performParseAndResolveImportsOnly() {

lib/FrontendTool/FrontendTool.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,7 @@ static bool emitLoadedModuleTraceIfNeeded(ModuleDecl *mainModule,
436436
importedModules.insert(import.importedModule);
437437

438438
llvm::DenseMap<StringRef, ModuleDecl *> pathToModuleDecl;
439-
for (auto &module : ctxt.LoadedModules) {
439+
for (const auto &module : ctxt.getLoadedModules()) {
440440
ModuleDecl *loadedDecl = module.second;
441441
if (!loadedDecl)
442442
llvm::report_fatal_error("Expected loaded modules to be non-null.");
@@ -690,7 +690,7 @@ static void countStatsPostSema(UnifiedStatsReporter &Stats,
690690
C.NumLinkLibraries = Instance.getLinkLibraries().size();
691691

692692
auto const &AST = Instance.getASTContext();
693-
C.NumLoadedModules = AST.LoadedModules.size();
693+
C.NumLoadedModules = AST.getNumLoadedModules();
694694

695695
if (auto *D = Instance.getDependencyTracker()) {
696696
C.NumDependencies = D->getDependencies().size();
@@ -1229,9 +1229,9 @@ static void performEndOfPipelineActions(CompilerInstance &Instance) {
12291229
auto action = Instance.getInvocation().getFrontendOptions().RequestedAction;
12301230
if (FrontendOptions::shouldActionOnlyParse(action) &&
12311231
action != FrontendOptions::ActionType::EmitImportedModules) {
1232-
assert(ctx.LoadedModules.size() == 1 &&
1232+
assert(ctx.getNumLoadedModules() == 1 &&
12331233
"Loaded a module during parse-only");
1234-
assert(ctx.LoadedModules.front().second == Instance.getMainModule());
1234+
assert(ctx.getLoadedModules().begin()->second == Instance.getMainModule());
12351235
}
12361236

12371237
// Verify the AST for all the modules we've loaded.

lib/Sema/SourceLoader.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ ModuleDecl *SourceLoader::loadModule(SourceLoc importLoc,
118118
auto *importMod = ModuleDecl::create(moduleID.Item, Ctx, importInfo);
119119
if (EnableLibraryEvolution)
120120
importMod->setResilienceStrategy(ResilienceStrategy::Resilient);
121-
Ctx.LoadedModules[moduleID.Item] = importMod;
121+
Ctx.addLoadedModule(importMod);
122122

123123
auto *importFile =
124124
new (Ctx) SourceFile(*importMod, SourceFileKind::Library, bufferID,

lib/Serialization/SerializedModuleLoader.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -959,7 +959,7 @@ SerializedModuleLoaderBase::loadModule(SourceLoc importLoc,
959959

960960
auto M = ModuleDecl::create(moduleID.Item, Ctx);
961961
M->setIsSystemModule(isSystemModule);
962-
Ctx.LoadedModules[moduleID.Item] = M;
962+
Ctx.addLoadedModule(M);
963963
SWIFT_DEFER { M->setHasResolvedImports(); };
964964

965965
StringRef moduleInterfacePathStr =
@@ -1010,7 +1010,7 @@ MemoryBufferSerializedModuleLoader::loadModule(SourceLoc importLoc,
10101010
return nullptr;
10111011

10121012
M->addFile(*file);
1013-
Ctx.LoadedModules[moduleID.Item] = M;
1013+
Ctx.addLoadedModule(M);
10141014
return M;
10151015
}
10161016

lib/Serialization/SerializedSILLoader.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ SerializedSILLoader::SerializedSILLoader(
2727

2828
// Get a list of SerializedModules from ASTContext.
2929
// FIXME: Iterating over LoadedModules is not a good way to do this.
30-
for (auto &Entry : Ctx.LoadedModules) {
30+
for (const auto &Entry : Ctx.getLoadedModules()) {
3131
for (auto File : Entry.second->getFiles()) {
3232
if (auto LoadedAST = dyn_cast<SerializedASTFile>(File)) {
3333
auto Des = new SILDeserializer(&LoadedAST->File, *SILMod, callbacks);

unittests/AST/TestContext.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ TestContext::TestContext(ShouldDeclareOptionalTypes optionals)
4040
registerTypeCheckerRequestFunctions(Ctx.evaluator);
4141
auto stdlibID = Ctx.getIdentifier(STDLIB_NAME);
4242
auto *module = ModuleDecl::create(stdlibID, Ctx);
43-
Ctx.LoadedModules[stdlibID] = module;
43+
Ctx.addLoadedModule(module);
4444

4545
FileForLookups = new (Ctx) SourceFile(*module, SourceFileKind::Library,
4646
/*buffer*/ None);

0 commit comments

Comments
 (0)