LoadModuleMapResult loadModuleMapFileImpl(const FileEntry *File,
bool IsSystem,
const DirectoryEntry *Dir,
- bool IsExplicitlyProvided,
FileID ID = FileID(),
unsigned *Offset = nullptr);
/// header.
llvm::DenseMap<const DirectoryEntry *, Module *> UmbrellaDirs;
- /// \brief The set of modules provided explicitly (e.g. by -fmodule-map-file),
- /// which are allowed to shadow other implicitly discovered modules.
- llvm::DenseSet<const Module *> ExplicitlyProvidedModules;
+ /// \brief A generation counter that is used to test whether modules of the
+ /// same name may shadow or are illegal redefintions.
+ ///
+ /// Modules from earlier scopes may shadow modules from later ones.
+ /// Modules from the same scope may not have the same name.
+ unsigned CurrentModuleScopeID = 0;
- bool mayShadowModuleBeingParsed(Module *ExistingModule,
- bool IsExplicitlyProvided) {
- assert(!ExistingModule->Parent && "expected top-level module");
- return !IsExplicitlyProvided &&
- ExplicitlyProvidedModules.count(ExistingModule);
- }
+ llvm::DenseMap<Module *, unsigned> ModuleScopeIDs;
/// \brief The set of attributes that can be attached to a module.
struct Attributes {
///
/// \returns The found or newly-created module, along with a boolean value
/// that will be true if the module is newly-created.
- std::pair<Module *, bool>
- findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework,
- bool IsExplicit, bool UsesExplicitModuleMapFile = false);
+ std::pair<Module *, bool> findOrCreateModule(StringRef Name, Module *Parent,
+ bool IsFramework,
+ bool IsExplicit);
/// \brief Create a 'global module' for a C++ Modules TS module interface
/// unit.
Module *createShadowedModule(StringRef Name, bool IsFramework,
Module *ShadowingModule);
+ /// \brief Creates a new declaration scope for module names, allowing
+ /// previously defined modules to shadow definitions from the new scope.
+ ///
+ /// \note Module names from earlier scopes will shadow names from the new
+ /// scope, which is the opposite of how shadowing works for variables.
+ void finishModuleDeclarationScope() { CurrentModuleScopeID += 1; }
+
+ bool mayShadowNewModule(Module *ExistingModule) {
+ assert(!ExistingModule->Parent && "expected top-level module");
+ assert(ModuleScopeIDs.count(ExistingModule) && "unknown module");
+ return ModuleScopeIDs[ExistingModule] < CurrentModuleScopeID;
+ }
+
/// \brief Retrieve the module map file containing the definition of the given
/// module.
///
/// \brief Marks this header as being excluded from the given module.
void excludeHeader(Module *Mod, Module::Header Header);
- void setExplicitlyProvided(Module *Mod);
-
/// \brief Parse the given module map file, and record any modules we
/// encounter.
///
/// \returns true if an error occurred, false otherwise.
bool parseModuleMapFile(const FileEntry *File, bool IsSystem,
const DirectoryEntry *HomeDir,
- bool IsExplicitlyProvided = false,
FileID ID = FileID(), unsigned *Offset = nullptr,
SourceLocation ExternModuleLoc = SourceLocation());
CI.getDiagnostics().Report(diag::err_module_map_not_found) << Filename;
}
+ // Add a module declaration scope so that modules from -fmodule-map-file
+ // arguments may shadow modules found implicitly in search paths.
+ CI.getPreprocessor()
+ .getHeaderSearchInfo()
+ .getModuleMap()
+ .finishModuleDeclarationScope();
+
// If we were asked to load any module files, do so now.
for (const auto &ModuleFile : CI.getFrontendOpts().ModuleFiles)
if (!CI.loadModuleFile(ModuleFile))
}
}
- switch (loadModuleMapFileImpl(File, IsSystem, Dir,
- /*IsExplictlyProvided=*/true, ID, Offset)) {
+ switch (loadModuleMapFileImpl(File, IsSystem, Dir, ID, Offset)) {
case LMM_AlreadyLoaded:
case LMM_NewlyLoaded:
return false;
llvm_unreachable("Unknown load module map result");
}
-HeaderSearch::LoadModuleMapResult HeaderSearch::loadModuleMapFileImpl(
- const FileEntry *File, bool IsSystem, const DirectoryEntry *Dir,
- bool IsExplicitlyProvided, FileID ID, unsigned *Offset) {
+HeaderSearch::LoadModuleMapResult
+HeaderSearch::loadModuleMapFileImpl(const FileEntry *File, bool IsSystem,
+ const DirectoryEntry *Dir, FileID ID,
+ unsigned *Offset) {
assert(File && "expected FileEntry");
// Check whether we've already loaded this module map, and mark it as being
if (!AddResult.second)
return AddResult.first->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap;
- if (ModMap.parseModuleMapFile(File, IsSystem, Dir, IsExplicitlyProvided, ID,
- Offset)) {
+ if (ModMap.parseModuleMapFile(File, IsSystem, Dir, ID, Offset)) {
LoadedModuleMaps[File] = false;
return LMM_InvalidModuleMap;
}
// Try to load a corresponding private module map.
if (const FileEntry *PMMFile = getPrivateModuleMap(File, FileMgr)) {
- if (ModMap.parseModuleMapFile(PMMFile, IsSystem, Dir,
- IsExplicitlyProvided)) {
+ if (ModMap.parseModuleMapFile(PMMFile, IsSystem, Dir)) {
LoadedModuleMaps[File] = false;
return LMM_InvalidModuleMap;
}
return KnownDir->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap;
if (const FileEntry *ModuleMapFile = lookupModuleMapFile(Dir, IsFramework)) {
- LoadModuleMapResult Result = loadModuleMapFileImpl(
- ModuleMapFile, IsSystem, Dir, /*IsExplicitlyProvided=*/false);
+ LoadModuleMapResult Result =
+ loadModuleMapFileImpl(ModuleMapFile, IsSystem, Dir);
// Add Dir explicitly in case ModuleMapFile is in a subdirectory.
// E.g. Foo.framework/Modules/module.modulemap
// ^Dir ^ModuleMapFile
return Context->findSubmodule(Name);
}
-std::pair<Module *, bool>
-ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework,
- bool IsExplicit, bool UsesExplicitModuleMapFile) {
+std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
+ Module *Parent,
+ bool IsFramework,
+ bool IsExplicit) {
// Try to find an existing module with this name.
if (Module *Sub = lookupModuleQualified(Name, Parent))
return std::make_pair(Sub, false);
if (LangOpts.CurrentModule == Name)
SourceModule = Result;
Modules[Name] = Result;
- if (UsesExplicitModuleMapFile)
- ExplicitlyProvidedModules.insert(Result);
+ ModuleScopeIDs[Result] = CurrentModuleScopeID;
}
return std::make_pair(Result, true);
}
if (LangOpts.CurrentModule == ModuleName)
SourceModule = Result;
Modules[ModuleName] = Result;
+ ModuleScopeIDs[Result] = CurrentModuleScopeID;
}
Result->IsSystem |= Attrs.IsSystem;
/*IsExplicit=*/false, NumCreatedModules++);
Result->ShadowingModule = ShadowingModule;
Result->IsAvailable = false;
+ ModuleScopeIDs[Result] = CurrentModuleScopeID;
ShadowModules.push_back(Result);
return Result;
Mod->Headers[Module::HK_Excluded].push_back(std::move(Header));
}
-void ModuleMap::setExplicitlyProvided(Module *Mod) {
- assert(Modules[Mod->Name] == Mod && "explicitly provided module is shadowed");
- ExplicitlyProvidedModules.insert(Mod);
-}
-
const FileEntry *
ModuleMap::getContainingModuleMapFile(const Module *Module) const {
if (Module->DefinitionLoc.isInvalid())
/// \brief Consume the current token and return its location.
SourceLocation consumeToken();
- bool UsesExplicitModuleMapFile = false;
-
/// \brief Skip tokens until we reach the a token with the given kind
/// (or the end of the file).
void skipUntil(MMToken::TokenKind K);
explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
const TargetInfo *Target, DiagnosticsEngine &Diags,
ModuleMap &Map, const FileEntry *ModuleMapFile,
- const DirectoryEntry *Directory, bool IsSystem,
- bool UsesExplicitModuleMapFile)
+ const DirectoryEntry *Directory, bool IsSystem)
: L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
ModuleMapFile(ModuleMapFile), Directory(Directory),
- IsSystem(IsSystem),
- UsesExplicitModuleMapFile(UsesExplicitModuleMapFile) {
+ IsSystem(IsSystem) {
Tok.clear();
consumeToken();
}
return;
}
- if (!Existing->Parent &&
- Map.mayShadowModuleBeingParsed(Existing, UsesExplicitModuleMapFile)) {
+ if (!Existing->Parent && Map.mayShadowNewModule(Existing)) {
ShadowingModule = Existing;
} else {
// This is not a shawdowed module decl, it is an illegal redefinition.
ActiveModule =
Map.createShadowedModule(ModuleName, Framework, ShadowingModule);
} else {
- ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework,
- Explicit, UsesExplicitModuleMapFile)
- .first;
+ ActiveModule =
+ Map.findOrCreateModule(ModuleName, ActiveModule, Framework, Explicit)
+ .first;
}
ActiveModule->DefinitionLoc = ModuleNameLoc;
Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd
? Directory
: File->getDir(),
- false /*IsExplicitlyProvided*/, FileID(), nullptr, ExternLoc);
+ FileID(), nullptr, ExternLoc);
}
/// Whether to add the requirement \p Feature to the module \p M.
}
bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem,
- const DirectoryEntry *Dir,
- bool IsExplicitlyProvided, FileID ID,
+ const DirectoryEntry *Dir, FileID ID,
unsigned *Offset,
SourceLocation ExternModuleLoc) {
assert(Target && "Missing target information");
Buffer->getBufferEnd());
SourceLocation Start = L.getSourceLocation();
ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir,
- IsSystem, IsExplicitlyProvided);
+ IsSystem);
bool Result = Parser.parseModuleMapFile();
ParsedModuleMap[File] = Result;