Skip to content

Commit 31e14f4

Browse files
committed
clang/Modules: Sink CompilerInstance::KnownModules into ModuleMap
Avoid use-after-frees when FrontendAction::BeginSourceFile is called twice on the same CompilerInstance by sinking CompilerInstance::KnownModules into ModuleMap. On the way, rename the map to CachedModuleLoads. I considered (but rejected) merging this with ModuleMap::Modules, since that only has top-level modules and this map includes submodules. This is an alternative to https://reviews.llvm.org/D58497. Thanks to nemanjai for the detailed analysis of the problem!
1 parent 858b15c commit 31e14f4

File tree

3 files changed

+30
-25
lines changed

3 files changed

+30
-25
lines changed

clang/include/clang/Frontend/CompilerInstance.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -126,10 +126,6 @@ class CompilerInstance : public ModuleLoader {
126126

127127
std::vector<std::shared_ptr<DependencyCollector>> DependencyCollectors;
128128

129-
/// The set of top-level modules that has already been loaded,
130-
/// along with the module map
131-
llvm::DenseMap<const IdentifierInfo *, Module *> KnownModules;
132-
133129
/// The set of top-level modules that has already been built on the
134130
/// fly as part of this overall compilation action.
135131
std::map<std::string, std::string> BuiltModules;

clang/include/clang/Lex/ModuleMap.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,18 @@
1414
#ifndef LLVM_CLANG_LEX_MODULEMAP_H
1515
#define LLVM_CLANG_LEX_MODULEMAP_H
1616

17+
#include "clang/Basic/IdentifierTable.h"
1718
#include "clang/Basic/LangOptions.h"
1819
#include "clang/Basic/Module.h"
1920
#include "clang/Basic/SourceLocation.h"
2021
#include "llvm/ADT/ArrayRef.h"
2122
#include "llvm/ADT/DenseMap.h"
2223
#include "llvm/ADT/PointerIntPair.h"
23-
#include "llvm/ADT/StringSet.h"
2424
#include "llvm/ADT/SmallPtrSet.h"
2525
#include "llvm/ADT/SmallVector.h"
2626
#include "llvm/ADT/StringMap.h"
2727
#include "llvm/ADT/StringRef.h"
28+
#include "llvm/ADT/StringSet.h"
2829
#include "llvm/ADT/TinyPtrVector.h"
2930
#include "llvm/ADT/Twine.h"
3031
#include <ctime>
@@ -100,6 +101,10 @@ class ModuleMap {
100101
/// The top-level modules that are known.
101102
llvm::StringMap<Module *> Modules;
102103

104+
/// Module loading cache that includes submodules, indexed by IdentifierInfo.
105+
/// nullptr is stored for modules that are known to fail to load.
106+
llvm::DenseMap<const IdentifierInfo *, Module *> CachedModuleLoads;
107+
103108
/// Shadow modules created while building this module map.
104109
llvm::SmallVector<Module*, 2> ShadowModules;
105110

@@ -684,6 +689,16 @@ class ModuleMap {
684689

685690
module_iterator module_begin() const { return Modules.begin(); }
686691
module_iterator module_end() const { return Modules.end(); }
692+
693+
/// Cache a module load. M might be nullptr.
694+
void cacheModuleLoad(const IdentifierInfo &II, Module *M) {
695+
CachedModuleLoads[&II] = M;
696+
}
697+
698+
/// Return a cached module load.
699+
Module *getCachedModuleLoad(const IdentifierInfo &II) {
700+
return CachedModuleLoads.lookup(&II);
701+
}
687702
};
688703

689704
} // namespace clang

clang/lib/Frontend/CompilerInstance.cpp

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1541,12 +1541,9 @@ bool CompilerInstance::loadModuleFile(StringRef FileName) {
15411541
}
15421542

15431543
void registerAll() {
1544-
for (auto *II : LoadedModules) {
1545-
CI.KnownModules[II] = CI.getPreprocessor()
1546-
.getHeaderSearchInfo()
1547-
.getModuleMap()
1548-
.findModule(II->getName());
1549-
}
1544+
ModuleMap &MM = CI.getPreprocessor().getHeaderSearchInfo().getModuleMap();
1545+
for (auto *II : LoadedModules)
1546+
MM.cacheModuleLoad(*II, MM.findModule(II->getName()));
15501547
LoadedModules.clear();
15511548
}
15521549

@@ -1635,14 +1632,11 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
16351632
return LastModuleImportResult;
16361633
}
16371634

1638-
clang::Module *Module = nullptr;
1639-
16401635
// If we don't already have information on this module, load the module now.
1641-
llvm::DenseMap<const IdentifierInfo *, clang::Module *>::iterator Known
1642-
= KnownModules.find(Path[0].first);
1643-
if (Known != KnownModules.end()) {
1644-
// Retrieve the cached top-level module.
1645-
Module = Known->second;
1636+
ModuleMap &MM = getPreprocessor().getHeaderSearchInfo().getModuleMap();
1637+
clang::Module *Module = MM.getCachedModuleLoad(*Path[0].first);
1638+
if (Module) {
1639+
// Nothing to do here, we found it.
16461640
} else if (ModuleName == getLangOpts().CurrentModule) {
16471641
// This is the module we're building.
16481642
Module = PP->getHeaderSearchInfo().lookupModule(
@@ -1656,7 +1650,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
16561650
// ModuleBuildFailed = true;
16571651
// return ModuleLoadResult();
16581652
//}
1659-
Known = KnownModules.insert(std::make_pair(Path[0].first, Module)).first;
1653+
MM.cacheModuleLoad(*Path[0].first, Module);
16601654
} else {
16611655
// Search for a module with the given name.
16621656
Module = PP->getHeaderSearchInfo().lookupModule(ModuleName, true,
@@ -1750,7 +1744,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
17501744
getDiagnostics().Report(ModuleNameLoc, diag::err_module_prebuilt)
17511745
<< ModuleName;
17521746
ModuleBuildFailed = true;
1753-
KnownModules[Path[0].first] = nullptr;
1747+
MM.cacheModuleLoad(*Path[0].first, nullptr);
17541748
return ModuleLoadResult();
17551749
}
17561750
}
@@ -1764,7 +1758,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
17641758
// necessarily even have a module map. Since ReadAST already produces
17651759
// diagnostics for these two cases, we simply error out here.
17661760
ModuleBuildFailed = true;
1767-
KnownModules[Path[0].first] = nullptr;
1761+
MM.cacheModuleLoad(*Path[0].first, nullptr);
17681762
return ModuleLoadResult();
17691763
}
17701764

@@ -1809,7 +1803,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
18091803
"undiagnosed error in compileAndLoadModule");
18101804
if (getPreprocessorOpts().FailedModules)
18111805
getPreprocessorOpts().FailedModules->addFailed(ModuleName);
1812-
KnownModules[Path[0].first] = nullptr;
1806+
MM.cacheModuleLoad(*Path[0].first, nullptr);
18131807
ModuleBuildFailed = true;
18141808
return ModuleLoadResult();
18151809
}
@@ -1832,19 +1826,19 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
18321826
ModuleLoader::HadFatalFailure = true;
18331827
// FIXME: The ASTReader will already have complained, but can we shoehorn
18341828
// that diagnostic information into a more useful form?
1835-
KnownModules[Path[0].first] = nullptr;
1829+
MM.cacheModuleLoad(*Path[0].first, nullptr);
18361830
return ModuleLoadResult();
18371831

18381832
case ASTReader::Failure:
18391833
ModuleLoader::HadFatalFailure = true;
18401834
// Already complained, but note now that we failed.
1841-
KnownModules[Path[0].first] = nullptr;
1835+
MM.cacheModuleLoad(*Path[0].first, nullptr);
18421836
ModuleBuildFailed = true;
18431837
return ModuleLoadResult();
18441838
}
18451839

18461840
// Cache the result of this top-level module lookup for later.
1847-
Known = KnownModules.insert(std::make_pair(Path[0].first, Module)).first;
1841+
MM.cacheModuleLoad(*Path[0].first, Module);
18481842
}
18491843

18501844
// If we never found the module, fail.

0 commit comments

Comments
 (0)