From: Ben Langmuir Date: Sat, 9 Aug 2014 00:57:23 +0000 (+0000) Subject: Refactor the module map file used for uniquing a module name out of X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=243f2d734e94504bf5ddbf4c179a235f47866e1b;p=clang Refactor the module map file used for uniquing a module name out of class Module. It's almost always going to be the same as getContainingModule() for top-level modules, so just add a map to cover the remaining cases. This lets us do less bookkeeping to keep the ModuleMap fields up to date. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@215268 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/Module.h b/include/clang/Basic/Module.h index 9b66840ba4..e2f5f0efd2 100644 --- a/include/clang/Basic/Module.h +++ b/include/clang/Basic/Module.h @@ -55,17 +55,6 @@ public: /// \brief The parent of this module. This will be NULL for the top-level /// module. Module *Parent; - - /// \brief The module map file that (along with the module name) uniquely - /// identifies this module. - /// - /// The particular module that \c Name refers to may depend on how the module - /// was found in header search. However, the combination of \c Name and - /// \c ModuleMap will be globally unique for top-level modules. In the case of - /// inferred modules, \c ModuleMap will contain the module map that allowed - /// the inference (e.g. contained 'Module *') rather than the virtual - /// inferred module map file. - const FileEntry *ModuleMap; /// \brief The umbrella header or directory. llvm::PointerUnion Umbrella; @@ -283,10 +272,8 @@ public: std::vector Conflicts; /// \brief Construct a new module or submodule. - /// - /// For an explanation of \p ModuleMap, see Module::ModuleMap. Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent, - const FileEntry *ModuleMap, bool IsFramework, bool IsExplicit); + bool IsFramework, bool IsExplicit); ~Module(); diff --git a/include/clang/Lex/ModuleMap.h b/include/clang/Lex/ModuleMap.h index a86a927499..4a583824d7 100644 --- a/include/clang/Lex/ModuleMap.h +++ b/include/clang/Lex/ModuleMap.h @@ -146,6 +146,10 @@ private: /// framework modules from within those directories. llvm::DenseMap InferredDirectories; + /// A mapping from an inferred module to the module map that allowed the + /// inference. + llvm::DenseMap InferredModuleAllowedBy; + /// \brief Describes whether we haved parsed a particular file as a module /// map. llvm::DenseMap ParsedModuleMap; @@ -316,7 +320,6 @@ public: /// \returns The found or newly-created module, along with a boolean value /// that will be true if the module is newly-created. std::pair findOrCreateModule(StringRef Name, Module *Parent, - const FileEntry *ModuleMap, bool IsFramework, bool IsExplicit); @@ -351,6 +354,19 @@ public: /// module, or NULL if the module definition was inferred. const FileEntry *getContainingModuleMapFile(Module *Module) const; + /// \brief Get the module map file that (along with the module name) uniquely + /// identifies this module. + /// + /// The particular module that \c Name refers to may depend on how the module + /// was found in header search. However, the combination of \c Name and + /// this module map will be globally unique for top-level modules. In the case + /// of inferred modules, returns the module map that allowed the inference + /// (e.g. contained 'module *'). Otherwise, returns + /// getContainingModuleMapFile(). + const FileEntry *getModuleMapFileForUniquing(Module *M) const; + + void setInferredModuleAllowedBy(Module *M, const FileEntry *ModuleMap); + /// \brief Resolve all of the unresolved exports in the given module. /// /// \param Mod The module whose exports should be resolved. diff --git a/lib/Basic/Module.cpp b/lib/Basic/Module.cpp index f689c733d9..65c8b1b581 100644 --- a/lib/Basic/Module.cpp +++ b/lib/Basic/Module.cpp @@ -25,8 +25,8 @@ using namespace clang; Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent, - const FileEntry *File, bool IsFramework, bool IsExplicit) - : Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent), ModuleMap(File), + bool IsFramework, bool IsExplicit) + : Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent), Umbrella(), ASTFile(nullptr), IsMissingRequirement(false), IsAvailable(true), IsFromModuleFile(false), IsFramework(IsFramework), IsExplicit(IsExplicit), IsSystem(false), IsExternC(false), @@ -361,7 +361,11 @@ void Module::print(raw_ostream &OS, unsigned Indent) const { for (submodule_const_iterator MI = submodule_begin(), MIEnd = submodule_end(); MI != MIEnd; ++MI) - if (!(*MI)->IsInferred) + // Print inferred subframework modules so that we don't need to re-infer + // them (requires expensive directory iteration + stat calls) when we build + // the module. Regular inferred submodules are OK, as we need to look at all + // those header files anyway. + if (!(*MI)->IsInferred || (*MI)->IsFramework) (*MI)->print(OS, Indent + 2); for (unsigned I = 0, N = Exports.size(); I != N; ++I) { diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index 4a75058e6a..22788aa5fb 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -958,9 +958,10 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance, SourceMgr.overrideFileContents(ModuleMapFile, ModuleMapBuffer); } - // Construct a module-generating action. Passing through Module->ModuleMap is + // Construct a module-generating action. Passing through the module map is // safe because the FileManager is shared between the compiler instances. - GenerateModuleAction CreateModuleAction(Module->ModuleMap, Module->IsSystem); + GenerateModuleAction CreateModuleAction( + ModMap.getModuleMapFileForUniquing(Module), Module->IsSystem); // Execute the action to actually build the module in-place. Use a separate // thread so that we get a stack large enough. diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp index 6dcaf382c3..3c24707150 100644 --- a/lib/Frontend/FrontendActions.cpp +++ b/lib/Frontend/FrontendActions.cpp @@ -301,10 +301,12 @@ bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI, return false; } - if (!ModuleMapForUniquing) + if (ModuleMapForUniquing && ModuleMapForUniquing != ModuleMap) { + Module->IsInferred = true; + HS.getModuleMap().setInferredModuleAllowedBy(Module, ModuleMapForUniquing); + } else { ModuleMapForUniquing = ModuleMap; - Module->ModuleMap = ModuleMapForUniquing; - assert(Module->ModuleMap && "missing module map file"); + } FileManager &FileMgr = CI.getFileManager(); diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp index c12d7314ee..7be09af384 100644 --- a/lib/Lex/HeaderSearch.cpp +++ b/lib/Lex/HeaderSearch.cpp @@ -114,7 +114,9 @@ const HeaderMap *HeaderSearch::CreateHeaderMap(const FileEntry *FE) { } std::string HeaderSearch::getModuleFileName(Module *Module) { - return getModuleFileName(Module->Name, Module->ModuleMap->getName()); + const FileEntry *ModuleMap = + getModuleMap().getModuleMapFileForUniquing(Module); + return getModuleFileName(Module->Name, ModuleMap->getName()); } std::string HeaderSearch::getModuleFileName(StringRef ModuleName, diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp index 8fae9c933d..92de71d8f3 100644 --- a/lib/Lex/ModuleMap.cpp +++ b/lib/Lex/ModuleMap.cpp @@ -367,6 +367,9 @@ ModuleMap::findModuleForHeader(const FileEntry *File, UmbrellaModule = UmbrellaModule->Parent; if (UmbrellaModule->InferSubmodules) { + const FileEntry *UmbrellaModuleMap = + getModuleMapFileForUniquing(UmbrellaModule); + // Infer submodules for each of the directories we found between // the directory of the umbrella header and the directory where // the actual header is located. @@ -377,8 +380,9 @@ ModuleMap::findModuleForHeader(const FileEntry *File, SmallString<32> NameBuf; StringRef Name = sanitizeFilenameAsIdentifier( llvm::sys::path::stem(SkippedDirs[I-1]->getName()), NameBuf); - Result = findOrCreateModule(Name, Result, UmbrellaModule->ModuleMap, - /*IsFramework=*/false, Explicit).first; + Result = findOrCreateModule(Name, Result, /*IsFramework=*/false, + Explicit).first; + InferredModuleAllowedBy[Result] = UmbrellaModuleMap; Result->IsInferred = true; // Associate the module and the directory. @@ -394,8 +398,9 @@ ModuleMap::findModuleForHeader(const FileEntry *File, SmallString<32> NameBuf; StringRef Name = sanitizeFilenameAsIdentifier( llvm::sys::path::stem(File->getName()), NameBuf); - Result = findOrCreateModule(Name, Result, UmbrellaModule->ModuleMap, - /*IsFramework=*/false, Explicit).first; + Result = findOrCreateModule(Name, Result, /*IsFramework=*/false, + Explicit).first; + InferredModuleAllowedBy[Result] = UmbrellaModuleMap; Result->IsInferred = true; Result->addTopHeader(File); @@ -535,15 +540,14 @@ Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{ } std::pair -ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, - const FileEntry *ModuleMap, bool IsFramework, +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); // Create a new module with this name. - Module *Result = new Module(Name, SourceLocation(), Parent, ModuleMap, + Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework, IsExplicit); if (LangOpts.CurrentModule == Name) { SourceModule = Result; @@ -673,7 +677,7 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName, if (!canInfer) return nullptr; } else - ModuleMapFile = Parent->ModuleMap; + ModuleMapFile = getModuleMapFileForUniquing(Parent); // Look for an umbrella header. @@ -687,8 +691,10 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName, if (!UmbrellaHeader) return nullptr; - Module *Result = new Module(ModuleName, SourceLocation(), Parent, ModuleMapFile, + Module *Result = new Module(ModuleName, SourceLocation(), Parent, /*IsFramework=*/true, /*IsExplicit=*/false); + InferredModuleAllowedBy[Result] = ModuleMapFile; + Result->IsInferred = true; if (LangOpts.CurrentModule == ModuleName) { SourceModule = Result; SourceModuleName = ModuleName; @@ -799,6 +805,19 @@ ModuleMap::getContainingModuleMapFile(Module *Module) const { SourceMgr.getFileID(Module->DefinitionLoc)); } +const FileEntry *ModuleMap::getModuleMapFileForUniquing(Module *M) const { + if (M->IsInferred) { + assert(InferredModuleAllowedBy.count(M) && "missing inferred module map"); + return InferredModuleAllowedBy.find(M)->second; + } + return getContainingModuleMapFile(M); +} + +void ModuleMap::setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap) { + assert(M->IsInferred && "module not inferred"); + InferredModuleAllowedBy[M] = ModMap; +} + void ModuleMap::dump() { llvm::errs() << "Modules:"; for (llvm::StringMap::iterator M = Modules.begin(), @@ -1390,14 +1409,9 @@ void ModuleMapParser::parseModuleDecl() { return; } - // If this is a submodule, use the parent's module map, since we don't want - // the private module map file. - const FileEntry *ModuleMap = ActiveModule ? ActiveModule->ModuleMap - : ModuleMapFile; - // Start defining this module. - ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, ModuleMap, - Framework, Explicit).first; + ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework, + Explicit).first; ActiveModule->DefinitionLoc = ModuleNameLoc; if (Attrs.IsSystem || IsSystem) ActiveModule->IsSystem = true; diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 4733c6bdeb..f668e28c1a 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -2489,15 +2489,18 @@ ASTReader::ReadControlBlock(ModuleFile &F, return Missing; } + HeaderSearch &HS = PP.getHeaderSearchInfo(); const FileEntry *StoredModMap = FileMgr.getFile(F.ModuleMapPath); - if (StoredModMap == nullptr || StoredModMap != M->ModuleMap) { - assert(M->ModuleMap && "found module is missing module map file"); + const FileEntry *ModMap = + HS.getModuleMap().getModuleMapFileForUniquing(M); + if (StoredModMap == nullptr || StoredModMap != ModMap) { + assert(ModMap && "found module is missing module map file"); assert(M->Name == F.ModuleName && "found module with different name"); assert(ImportedBy && "top-level import should be verified"); if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) Diag(diag::err_imported_module_modmap_changed) << F.ModuleName << ImportedBy->FileName - << M->ModuleMap->getName() << F.ModuleMapPath; + << ModMap->getName() << F.ModuleMapPath; return OutOfDate; } } @@ -4281,20 +4284,17 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { bool ConfigMacrosExhaustive = Record[Idx++]; Module *ParentModule = nullptr; - const FileEntry *ModuleMap = nullptr; - if (Parent) { + if (Parent) ParentModule = getSubmodule(Parent); - ModuleMap = ParentModule->ModuleMap; - } - - if (!F.ModuleMapPath.empty()) - ModuleMap = FileMgr.getFile(F.ModuleMapPath); // Retrieve this (sub)module from the module map, creating it if // necessary. - CurrentModule = ModMap.findOrCreateModule(Name, ParentModule, ModuleMap, - IsFramework, + CurrentModule = ModMap.findOrCreateModule(Name, ParentModule, IsFramework, IsExplicit).first; + + // FIXME: set the definition loc for CurrentModule, or call + // ModMap.setInferredModuleAllowedBy() + SubmoduleID GlobalIndex = GlobalID - NUM_PREDEF_SUBMODULE_IDS; if (GlobalIndex >= SubmodulesLoaded.size() || SubmodulesLoaded[GlobalIndex]) { diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index baed95ebf8..0a11cf2118 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -1139,8 +1139,9 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Filename unsigned AbbrevCode = Stream.EmitAbbrev(Abbrev); - assert(WritingModule->ModuleMap && "missing module map"); - SmallString<128> ModuleMap(WritingModule->ModuleMap->getName()); + const FileEntry *ModMapFile = PP.getHeaderSearchInfo().getModuleMap(). + getModuleMapFileForUniquing(WritingModule); + SmallString<128> ModuleMap(ModMapFile->getName()); llvm::sys::fs::make_absolute(ModuleMap); RecordData Record; Record.push_back(MODULE_MAP_FILE);