Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit ef1b5dc

Browse files
committed
Allow multiple modules with the same name to coexist in the module cache
To differentiate between two modules with the same name, we will consider the path the module map file that they are defined by* part of the ‘key’ for looking up the precompiled module (pcm file). Specifically, this patch renames the precompiled module (pcm) files from cache-path/<module hash>/Foo.pcm to cache-path/<module hash>/Foo-<hash of module map path>.pcm In addition, I’ve taught the ASTReader to re-resolve the names of imported modules during module loading so that if the header search context changes between when a module was originally built and when it is loaded we can rebuild it if necessary. For example, if module A imports module B first time: clang -I /path/to/A -I /path/to/B ... second time: clang -I /path/to/A -I /different/path/to/B ... will now rebuild A as expected. * in the case of inferred modules, we use the module map file that allowed the inference, not the __inferred_module.map file, since the inferred file path is the same for every inferred module. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@206201 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 0fc2a68 commit ef1b5dc

35 files changed

+328
-100
lines changed

Diff for: include/clang/Basic/DiagnosticSerializationKinds.td

+6-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,12 @@ def err_pch_different_branch : Error<
4848
"PCH file built from a different branch (%0) than the compiler (%1)">;
4949
def err_pch_with_compiler_errors : Error<
5050
"PCH file contains compiler errors">;
51-
51+
52+
def err_imported_module_not_found : Error<
53+
"module '%0' imported by AST file '%1' not found">, DefaultFatal;
54+
def err_imported_module_modmap_changed : Error<
55+
"module '%0' imported by AST file '%1' found in a different module map file"
56+
" (%2) than when the importing AST file was built (%3)">, DefaultFatal;
5257
def warn_module_conflict : Warning<
5358
"module '%0' conflicts with already-imported module '%1': %2">,
5459
InGroup<ModuleConflict>;

Diff for: include/clang/Basic/Module.h

+16-3
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,21 @@ class Module {
5151

5252
/// \brief The location of the module definition.
5353
SourceLocation DefinitionLoc;
54-
54+
5555
/// \brief The parent of this module. This will be NULL for the top-level
5656
/// module.
5757
Module *Parent;
58+
59+
/// \brief The module map file that (along with the module name) uniquely
60+
/// identifies this module.
61+
///
62+
/// The particular module that \c Name refers to may depend on how the module
63+
/// was found in header search. However, the combination of \c Name and
64+
/// \c ModuleMap will be globally unique for top-level modules. In the case of
65+
/// inferred modules, \c ModuleMap will contain the module map that allowed
66+
/// the inference (e.g. contained 'Module *') rather than the virtual
67+
/// inferred module map file.
68+
const FileEntry *ModuleMap;
5869

5970
/// \brief The umbrella header or directory.
6071
llvm::PointerUnion<const DirectoryEntry *, const FileEntry *> Umbrella;
@@ -264,8 +275,10 @@ class Module {
264275
std::vector<Conflict> Conflicts;
265276

266277
/// \brief Construct a new module or submodule.
267-
Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
268-
bool IsFramework, bool IsExplicit);
278+
///
279+
/// For an explanation of \p ModuleMap, see Module::ModuleMap.
280+
Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
281+
const FileEntry *ModuleMap, bool IsFramework, bool IsExplicit);
269282

270283
~Module();
271284

Diff for: include/clang/Frontend/FrontendActions.h

+12-8
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
namespace clang {
1818

1919
class Module;
20+
class FileEntry;
2021

2122
//===----------------------------------------------------------------------===//
2223
// Custom Consumer Actions
@@ -92,7 +93,8 @@ class GeneratePCHAction : public ASTFrontendAction {
9293
};
9394

9495
class GenerateModuleAction : public ASTFrontendAction {
95-
clang::Module *Module;
96+
Module *Module;
97+
const FileEntry *ModuleMapForUniquing;
9698
bool IsSystem;
9799

98100
protected:
@@ -106,20 +108,22 @@ class GenerateModuleAction : public ASTFrontendAction {
106108
bool hasASTFileSupport() const override { return false; }
107109

108110
public:
109-
explicit GenerateModuleAction(bool IsSystem = false)
110-
: ASTFrontendAction(), IsSystem(IsSystem) { }
111+
GenerateModuleAction(const FileEntry *ModuleMap = nullptr,
112+
bool IsSystem = false)
113+
: ASTFrontendAction(), ModuleMapForUniquing(ModuleMap), IsSystem(IsSystem)
114+
{ }
111115

112116
bool BeginSourceFileAction(CompilerInstance &CI, StringRef Filename) override;
113117

114118
/// \brief Compute the AST consumer arguments that will be used to
115119
/// create the PCHGenerator instance returned by CreateASTConsumer.
116120
///
117121
/// \returns true if an error occurred, false otherwise.
118-
static bool ComputeASTConsumerArguments(CompilerInstance &CI,
119-
StringRef InFile,
120-
std::string &Sysroot,
121-
std::string &OutputFile,
122-
raw_ostream *&OS);
122+
bool ComputeASTConsumerArguments(CompilerInstance &CI,
123+
StringRef InFile,
124+
std::string &Sysroot,
125+
std::string &OutputFile,
126+
raw_ostream *&OS);
123127
};
124128

125129
class SyntaxOnlyAction : public ASTFrontendAction {

Diff for: include/clang/Lex/HeaderSearch.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -493,9 +493,12 @@ class HeaderSearch {
493493
///
494494
/// \param ModuleName The module whose module file name will be returned.
495495
///
496+
/// \param ModuleMapPath A path that when combined with \c ModuleName
497+
/// uniquely identifies this module. See Module::ModuleMap.
498+
///
496499
/// \returns The name of the module file that corresponds to this module,
497500
/// or an empty string if this module does not correspond to any module file.
498-
std::string getModuleFileName(StringRef ModuleName);
501+
std::string getModuleFileName(StringRef ModuleName, StringRef ModuleMapPath);
499502

500503
/// \brief Lookup a module Search for a module with the given name.
501504
///

Diff for: include/clang/Lex/ModuleMap.h

+9-1
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,10 @@ class ModuleMap {
131131
/// \brief Whether the modules we infer are [system] modules.
132132
unsigned InferSystemModules : 1;
133133

134+
/// \brief If \c InferModules is non-zero, the module map file that allowed
135+
/// inferred modules. Otherwise, nullptr.
136+
const FileEntry *ModuleMapFile;
137+
134138
/// \brief The names of modules that cannot be inferred within this
135139
/// directory.
136140
SmallVector<std::string, 2> ExcludedModules;
@@ -293,13 +297,17 @@ class ModuleMap {
293297
/// \param Parent The module that will act as the parent of this submodule,
294298
/// or NULL to indicate that this is a top-level module.
295299
///
300+
/// \param ModuleMap The module map that defines or allows the inference of
301+
/// this module.
302+
///
296303
/// \param IsFramework Whether this is a framework module.
297304
///
298305
/// \param IsExplicit Whether this is an explicit submodule.
299306
///
300307
/// \returns The found or newly-created module, along with a boolean value
301308
/// that will be true if the module is newly-created.
302-
std::pair<Module *, bool> findOrCreateModule(StringRef Name, Module *Parent,
309+
std::pair<Module *, bool> findOrCreateModule(StringRef Name, Module *Parent,
310+
const FileEntry *ModuleMap,
303311
bool IsFramework,
304312
bool IsExplicit);
305313

Diff for: include/clang/Serialization/ASTBitCodes.h

+8-1
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,14 @@ namespace clang {
281281
HEADER_SEARCH_OPTIONS = 11,
282282

283283
/// \brief Record code for the preprocessor options table.
284-
PREPROCESSOR_OPTIONS = 12
284+
PREPROCESSOR_OPTIONS = 12,
285+
286+
/// \brief Record code for the module name.
287+
MODULE_NAME = 13,
288+
289+
/// \brief Record code for the module map file that was used to build this
290+
/// AST file.
291+
MODULE_MAP_FILE = 14
285292
};
286293

287294
/// \brief Record types that occur within the input-files block

Diff for: include/clang/Serialization/ASTReader.h

+1
Original file line numberDiff line numberDiff line change
@@ -1079,6 +1079,7 @@ class ASTReader
10791079
unsigned ClientLoadCapabilities);
10801080
ASTReadResult ReadControlBlock(ModuleFile &F,
10811081
SmallVectorImpl<ImportedModule> &Loaded,
1082+
const ModuleFile *ImportedBy,
10821083
unsigned ClientLoadCapabilities);
10831084
ASTReadResult ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities);
10841085
bool ParseLineTable(ModuleFile &F, SmallVectorImpl<uint64_t> &Record);

Diff for: include/clang/Serialization/Module.h

+5
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,9 @@ class ModuleFile {
116116
/// \brief The file name of the module file.
117117
std::string FileName;
118118

119+
/// \brief The name of the module.
120+
std::string ModuleName;
121+
119122
std::string getTimestampFilename() const {
120123
return FileName + ".timestamp";
121124
}
@@ -137,6 +140,8 @@ class ModuleFile {
137140
/// allow resolving headers even after headers+PCH was moved to a new path.
138141
std::string OriginalDir;
139142

143+
std::string ModuleMapPath;
144+
140145
/// \brief Whether this precompiled header is a relocatable PCH file.
141146
bool RelocatablePCH;
142147

Diff for: lib/Basic/Module.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@
2525
using namespace clang;
2626

2727
Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
28-
bool IsFramework, bool IsExplicit)
29-
: Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent),
28+
const FileEntry *File, bool IsFramework, bool IsExplicit)
29+
: Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent), ModuleMap(File),
3030
Umbrella(), ASTFile(0), IsAvailable(true), IsFromModuleFile(false),
3131
IsFramework(IsFramework), IsExplicit(IsExplicit), IsSystem(false),
3232
IsExternC(false), InferSubmodules(false), InferExplicitSubmodules(false),

Diff for: lib/Frontend/CompilerInstance.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -870,8 +870,9 @@ static void compileModuleImpl(CompilerInstance &ImportingInstance,
870870
SourceMgr.overrideFileContents(ModuleMapFile, ModuleMapBuffer);
871871
}
872872

873-
// Construct a module-generating action.
874-
GenerateModuleAction CreateModuleAction(Module->IsSystem);
873+
// Construct a module-generating action. Passing through Module->ModuleMap is
874+
// safe because the FileManager is shared between the compiler instances.
875+
GenerateModuleAction CreateModuleAction(Module->ModuleMap, Module->IsSystem);
875876

876877
// Execute the action to actually build the module in-place. Use a separate
877878
// thread so that we get a stack large enough.

Diff for: lib/Frontend/FrontendAction.cpp

+9-7
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,10 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
256256
if (!BeginSourceFileAction(CI, InputFile))
257257
goto failure;
258258

259+
// Initialize the main file entry.
260+
if (!CI.InitializeSourceManager(CurrentInput))
261+
goto failure;
262+
259263
return true;
260264
}
261265

@@ -302,6 +306,11 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
302306
if (!BeginSourceFileAction(CI, InputFile))
303307
goto failure;
304308

309+
// Initialize the main file entry. It is important that this occurs after
310+
// BeginSourceFileAction, which may change CurrentInput during module builds.
311+
if (!CI.InitializeSourceManager(CurrentInput))
312+
goto failure;
313+
305314
// Create the AST context and consumer unless this is a preprocessor only
306315
// action.
307316
if (!usesPreprocessorOnly()) {
@@ -389,13 +398,6 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
389398
bool FrontendAction::Execute() {
390399
CompilerInstance &CI = getCompilerInstance();
391400

392-
// Initialize the main file entry. This needs to be delayed until after PCH
393-
// has loaded.
394-
if (!isCurrentFileAST()) {
395-
if (!CI.InitializeSourceManager(getCurrentInput()))
396-
return false;
397-
}
398-
399401
if (CI.hasFrontendTimer()) {
400402
llvm::TimeRegion Timer(CI.getFrontendTimer());
401403
ExecuteAction();

Diff for: lib/Frontend/FrontendActions.cpp

+8-4
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,11 @@ bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI,
299299
return false;
300300
}
301301

302+
if (!ModuleMapForUniquing)
303+
ModuleMapForUniquing = ModuleMap;
304+
Module->ModuleMap = ModuleMapForUniquing;
305+
assert(Module->ModuleMap && "missing module map file");
306+
302307
FileManager &FileMgr = CI.getFileManager();
303308

304309
// Collect the set of #includes we need to build the module.
@@ -337,10 +342,9 @@ bool GenerateModuleAction::ComputeASTConsumerArguments(CompilerInstance &CI,
337342
// in the module cache.
338343
if (CI.getFrontendOpts().OutputFile.empty()) {
339344
HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();
340-
SmallString<256> ModuleFileName(HS.getModuleCachePath());
341-
llvm::sys::path::append(ModuleFileName,
342-
CI.getLangOpts().CurrentModule + ".pcm");
343-
CI.getFrontendOpts().OutputFile = ModuleFileName.str();
345+
CI.getFrontendOpts().OutputFile =
346+
HS.getModuleFileName(CI.getLangOpts().CurrentModule,
347+
ModuleMapForUniquing->getName());
344348
}
345349

346350
// We use createOutputFile here because this is exposed via libclang, and we

Diff for: lib/Lex/HeaderSearch.cpp

+23-12
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#include "clang/Lex/HeaderSearchOptions.h"
1919
#include "clang/Lex/LexDiagnostic.h"
2020
#include "clang/Lex/Lexer.h"
21+
#include "llvm/ADT/APInt.h"
22+
#include "llvm/ADT/Hashing.h"
2123
#include "llvm/ADT/SmallString.h"
2224
#include "llvm/Support/Capacity.h"
2325
#include "llvm/Support/FileSystem.h"
@@ -112,24 +114,33 @@ const HeaderMap *HeaderSearch::CreateHeaderMap(const FileEntry *FE) {
112114
}
113115

114116
std::string HeaderSearch::getModuleFileName(Module *Module) {
115-
// If we don't have a module cache path, we can't do anything.
116-
if (ModuleCachePath.empty())
117-
return std::string();
118-
119-
120-
SmallString<256> Result(ModuleCachePath);
121-
llvm::sys::path::append(Result, Module->getTopLevelModule()->Name + ".pcm");
122-
return Result.str().str();
117+
return getModuleFileName(Module->Name, Module->ModuleMap->getName());
123118
}
124119

125-
std::string HeaderSearch::getModuleFileName(StringRef ModuleName) {
120+
std::string HeaderSearch::getModuleFileName(StringRef ModuleName,
121+
StringRef ModuleMapPath) {
126122
// If we don't have a module cache path, we can't do anything.
127123
if (ModuleCachePath.empty())
128124
return std::string();
129-
130-
125+
131126
SmallString<256> Result(ModuleCachePath);
132-
llvm::sys::path::append(Result, ModuleName + ".pcm");
127+
llvm::sys::fs::make_absolute(Result);
128+
129+
if (HSOpts->DisableModuleHash) {
130+
llvm::sys::path::append(Result, ModuleName + ".pcm");
131+
} else {
132+
// Construct the name <ModuleName>-<hash of ModuleMapPath>.pcm which should
133+
// be globally unique to this particular module. To avoid false-negatives
134+
// on case-insensitive filesystems, we use lower-case, which is safe because
135+
// to cause a collision the modules must have the same name, which is an
136+
// error if they are imported in the same translation.
137+
SmallString<256> AbsModuleMapPath(ModuleMapPath);
138+
llvm::sys::fs::make_absolute(AbsModuleMapPath);
139+
llvm::APInt Code(64, llvm::hash_value(AbsModuleMapPath.str().lower()));
140+
SmallString<128> HashStr;
141+
Code.toStringUnsigned(HashStr, /*Radix*/36);
142+
llvm::sys::path::append(Result, ModuleName + "-" + HashStr.str() + ".pcm");
143+
}
133144
return Result.str().str();
134145
}
135146

0 commit comments

Comments
 (0)