From eb90e830850eca0c71886ad64ff2a7d0ff492ddb Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 4 Jan 2012 23:32:19 +0000 Subject: [PATCH] Store the submodules of a module in source order, as they are stored in the module map. This provides a bit more predictability for the user, as well as eliminating the need to sort the submodules when serializing them. llvm-svn: 147564 --- clang/include/clang/Basic/Module.h | 33 ++++++++++++------- clang/lib/Basic/Module.cpp | 43 +++++++++++++++++++------ clang/lib/Frontend/CompilerInstance.cpp | 26 ++++++++------- clang/lib/Frontend/FrontendActions.cpp | 7 ++-- clang/lib/Lex/ModuleMap.cpp | 36 +++++++-------------- clang/lib/Sema/Sema.cpp | 6 ++-- clang/lib/Serialization/ASTReader.cpp | 8 ++--- clang/lib/Serialization/ASTWriter.cpp | 21 ++++-------- 8 files changed, 96 insertions(+), 84 deletions(-) diff --git a/clang/include/clang/Basic/Module.h b/clang/include/clang/Basic/Module.h index 4e6bba2ed34d..19292950f585 100644 --- a/clang/include/clang/Basic/Module.h +++ b/clang/include/clang/Basic/Module.h @@ -22,6 +22,7 @@ #include "llvm/ADT/StringRef.h" #include #include +#include namespace llvm { class raw_ostream; @@ -53,9 +54,15 @@ public: /// \brief The umbrella header or directory. llvm::PointerUnion Umbrella; +private: /// \brief The submodules of this module, indexed by name. - llvm::StringMap SubModules; + std::vector SubModules; + /// \brief A mapping from the submodule name to the index into the + /// \c SubModules vector at which that submodule resides. + llvm::StringMap SubModuleIndex; + +public: /// \brief The headers that are part of this module. llvm::SmallVector Headers; @@ -152,16 +159,7 @@ public: /// \brief Construct a new module or submodule. Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent, - bool IsFramework, bool IsExplicit) - : Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent), - Umbrella(), IsAvailable(true), IsFromModuleFile(false), - IsFramework(IsFramework), IsExplicit(IsExplicit), InferSubmodules(false), - InferExplicitSubmodules(false), InferExportWildcard(false), - NameVisibility(Hidden) - { - if (Parent && !Parent->isAvailable()) - IsAvailable = false; - } + bool IsFramework, bool IsExplicit); ~Module(); @@ -245,6 +243,19 @@ public: /// evaluate the availability of this feature. void addRequirement(StringRef Feature, const LangOptions &LangOpts); + /// \brief Find the submodule with the given name. + /// + /// \returns The submodule if found, or NULL otherwise. + Module *findSubmodule(StringRef Name) const; + + typedef std::vector::iterator submodule_iterator; + typedef std::vector::const_iterator submodule_const_iterator; + + submodule_iterator submodule_begin() { return SubModules.begin(); } + submodule_const_iterator submodule_begin() const {return SubModules.begin();} + submodule_iterator submodule_end() { return SubModules.end(); } + submodule_const_iterator submodule_end() const { return SubModules.end(); } + /// \brief Print the module map for this module to the given stream. /// void print(llvm::raw_ostream &OS, unsigned Indent = 0) const; diff --git a/clang/lib/Basic/Module.cpp b/clang/lib/Basic/Module.cpp index feec5f0258c1..c5bc86de81db 100644 --- a/clang/lib/Basic/Module.cpp +++ b/clang/lib/Basic/Module.cpp @@ -20,11 +20,27 @@ #include "llvm/ADT/StringSwitch.h" using namespace clang; +Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent, + bool IsFramework, bool IsExplicit) + : Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent), + Umbrella(), IsAvailable(true), IsFromModuleFile(false), + IsFramework(IsFramework), IsExplicit(IsExplicit), InferSubmodules(false), + InferExplicitSubmodules(false), InferExportWildcard(false), + NameVisibility(Hidden) +{ + if (Parent) { + if (!Parent->isAvailable()) + IsAvailable = false; + + Parent->SubModuleIndex[Name] = Parent->SubModules.size(); + Parent->SubModules.push_back(this); + } +} + Module::~Module() { - for (llvm::StringMap::iterator I = SubModules.begin(), - IEnd = SubModules.end(); + for (submodule_iterator I = submodule_begin(), IEnd = submodule_end(); I != IEnd; ++I) { - delete I->getValue(); + delete *I; } } @@ -126,15 +142,23 @@ void Module::addRequirement(StringRef Feature, const LangOptions &LangOpts) { continue; Current->IsAvailable = false; - for (llvm::StringMap::iterator Sub = Current->SubModules.begin(), - SubEnd = Current->SubModules.end(); + for (submodule_iterator Sub = Current->submodule_begin(), + SubEnd = Current->submodule_end(); Sub != SubEnd; ++Sub) { - if (Sub->second->IsAvailable) - Stack.push_back(Sub->second); + if ((*Sub)->IsAvailable) + Stack.push_back(*Sub); } } } +Module *Module::findSubmodule(StringRef Name) const { + llvm::StringMap::const_iterator Pos = SubModuleIndex.find(Name); + if (Pos == SubModuleIndex.end()) + return 0; + + return SubModules[Pos->getValue()]; +} + static void printModuleId(llvm::raw_ostream &OS, const ModuleId &Id) { for (unsigned I = 0, N = Id.size(); I != N; ++I) { if (I) @@ -181,10 +205,9 @@ void Module::print(llvm::raw_ostream &OS, unsigned Indent) const { OS << "\"\n"; } - for (llvm::StringMap::const_iterator MI = SubModules.begin(), - MIEnd = SubModules.end(); + for (submodule_const_iterator MI = submodule_begin(), MIEnd = submodule_end(); MI != MIEnd; ++MI) - MI->getValue()->print(OS, Indent + 2); + (*MI)->print(OS, Indent + 2); for (unsigned I = 0, N = Exports.size(); I != N; ++I) { OS.indent(Indent + 2); diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index 498f6fbfc097..1f0d87c0626a 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -1222,25 +1222,26 @@ Module *CompilerInstance::loadModule(SourceLocation ImportLoc, if (Path.size() > 1) { for (unsigned I = 1, N = Path.size(); I != N; ++I) { StringRef Name = Path[I].first->getName(); - llvm::StringMap::iterator Pos - = Module->SubModules.find(Name); + clang::Module *Sub = Module->findSubmodule(Name); - if (Pos == Module->SubModules.end()) { + if (!Sub) { // Attempt to perform typo correction to find a module name that works. llvm::SmallVector Best; unsigned BestEditDistance = (std::numeric_limits::max)(); - for (llvm::StringMap::iterator - J = Module->SubModules.begin(), - JEnd = Module->SubModules.end(); + for (clang::Module::submodule_iterator J = Module->submodule_begin(), + JEnd = Module->submodule_end(); J != JEnd; ++J) { - unsigned ED = Name.edit_distance(J->getValue()->Name, + unsigned ED = Name.edit_distance((*J)->Name, /*AllowReplacements=*/true, BestEditDistance); if (ED <= BestEditDistance) { - if (ED < BestEditDistance) + if (ED < BestEditDistance) { Best.clear(); - Best.push_back(J->getValue()->Name); + BestEditDistance = ED; + } + + Best.push_back((*J)->Name); } } @@ -1252,11 +1253,12 @@ Module *CompilerInstance::loadModule(SourceLocation ImportLoc, << SourceRange(Path[0].second, Path[I-1].second) << FixItHint::CreateReplacement(SourceRange(Path[I].second), Best[0]); - Pos = Module->SubModules.find(Best[0]); + + Sub = Module->findSubmodule(Best[0]); } } - if (Pos == Module->SubModules.end()) { + if (!Sub) { // No submodule by this name. Complain, and don't look for further // submodules. getDiagnostics().Report(Path[I].second, diag::err_no_submodule) @@ -1265,7 +1267,7 @@ Module *CompilerInstance::loadModule(SourceLocation ImportLoc, break; } - Module = Pos->getValue(); + Module = Sub; } } diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp index dd98fcf3eb19..d9a385d232e3 100644 --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -186,11 +186,10 @@ static void collectModuleHeaderIncludes(const LangOptions &LangOpts, } // Recurse into submodules. - for (llvm::StringMap::iterator - Sub = Module->SubModules.begin(), - SubEnd = Module->SubModules.end(); + for (clang::Module::submodule_iterator Sub = Module->submodule_begin(), + SubEnd = Module->submodule_end(); Sub != SubEnd; ++Sub) - collectModuleHeaderIncludes(LangOpts, Sub->getValue(), Includes); + collectModuleHeaderIncludes(LangOpts, *Sub, Includes); } bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI, diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp index f43abc86152f..42257f562439 100644 --- a/clang/lib/Lex/ModuleMap.cpp +++ b/clang/lib/Lex/ModuleMap.cpp @@ -263,26 +263,20 @@ Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) { if (!Context) return findModule(Name); - llvm::StringMap::iterator Sub = Context->SubModules.find(Name); - if (Sub != Context->SubModules.end()) - return Sub->getValue(); - - return 0; + return Context->findSubmodule(Name); } std::pair ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework, bool IsExplicit) { // Try to find an existing module with this name. - if (Module *Found = Parent? Parent->SubModules[Name] : Modules[Name]) - return std::make_pair(Found, false); + 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, IsFramework, IsExplicit); - if (Parent) - Parent->SubModules[Name] = Result; - else + if (!Parent) Modules[Name] = Result; return std::make_pair(Result, true); } @@ -311,12 +305,9 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName, Module *Result = new Module(ModuleName, SourceLocation(), Parent, /*IsFramework=*/true, /*IsExplicit=*/false); - - if (Parent) - Parent->SubModules[ModuleName] = Result; - else + if (!Parent) Modules[ModuleName] = Result; - + // umbrella header "umbrella-header-name" Result->Umbrella = UmbrellaHeader; Headers[UmbrellaHeader] = Result; @@ -798,15 +789,10 @@ void ModuleMapParser::parseModuleDecl() { SourceLocation LBraceLoc = consumeToken(); // Determine whether this (sub)module has already been defined. - llvm::StringMap &ModuleSpace - = ActiveModule? ActiveModule->SubModules : Map.Modules; - llvm::StringMap::iterator ExistingModule - = ModuleSpace.find(ModuleName); - if (ExistingModule != ModuleSpace.end()) { + if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) { Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition) << ModuleName; - Diags.Report(ExistingModule->getValue()->DefinitionLoc, - diag::note_mmap_prev_definition); + Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition); // Skip the module definition. skipUntil(MMToken::RBrace); @@ -818,9 +804,9 @@ void ModuleMapParser::parseModuleDecl() { } // Start defining this module. - ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Framework, - Explicit); - ModuleSpace[ModuleName] = ActiveModule; + ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework, + Explicit).first; + ActiveModule->DefinitionLoc = ModuleNameLoc; bool Done = false; do { diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index c95cf224cd4c..c8199042b723 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -503,10 +503,10 @@ void Sema::ActOnEndOfTranslationUnit() { ModMap.resolveExports(Mod, /*Complain=*/false); // Queue the submodules, so their exports will also be resolved. - for (llvm::StringMap::iterator Sub = Mod->SubModules.begin(), - SubEnd = Mod->SubModules.end(); + for (Module::submodule_iterator Sub = Mod->submodule_begin(), + SubEnd = Mod->submodule_end(); Sub != SubEnd; ++Sub) { - Stack.push_back(Sub->getValue()); + Stack.push_back(*Sub); } } } diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 9c9e8b3ca9ee..c29033e833c1 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -2541,11 +2541,11 @@ void ASTReader::makeModuleVisible(Module *Mod, // Push any non-explicit submodules onto the stack to be marked as // visible. - for (llvm::StringMap::iterator Sub = Mod->SubModules.begin(), - SubEnd = Mod->SubModules.end(); + for (Module::submodule_iterator Sub = Mod->submodule_begin(), + SubEnd = Mod->submodule_end(); Sub != SubEnd; ++Sub) { - if (!Sub->getValue()->IsExplicit && Visited.insert(Sub->getValue())) - Stack.push_back(Sub->getValue()); + if (!(*Sub)->IsExplicit && Visited.insert(*Sub)) + Stack.push_back(*Sub); } // Push any exported modules onto the stack to be marked as visible. diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 9ed2a6c6d956..1317525c27d9 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -1859,10 +1859,10 @@ unsigned ASTWriter::getSubmoduleID(Module *Mod) { /// given module). static unsigned getNumberOfModules(Module *Mod) { unsigned ChildModules = 0; - for (llvm::StringMap::iterator Sub = Mod->SubModules.begin(), - SubEnd = Mod->SubModules.end(); + for (Module::submodule_iterator Sub = Mod->submodule_begin(), + SubEnd = Mod->submodule_end(); Sub != SubEnd; ++Sub) - ChildModules += getNumberOfModules(Sub->getValue()); + ChildModules += getNumberOfModules(*Sub); return ChildModules + 1; } @@ -2010,19 +2010,10 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { } // Queue up the submodules of this module. - llvm::SmallVector SubModules; - - // Sort the submodules first, so we get a predictable ordering in the AST - // file. - for (llvm::StringMap::iterator - Sub = Mod->SubModules.begin(), - SubEnd = Mod->SubModules.end(); + for (Module::submodule_iterator Sub = Mod->submodule_begin(), + SubEnd = Mod->submodule_end(); Sub != SubEnd; ++Sub) - SubModules.push_back(Sub->getKey()); - llvm::array_pod_sort(SubModules.begin(), SubModules.end()); - - for (unsigned I = 0, N = SubModules.size(); I != N; ++I) - Q.push(Mod->SubModules[SubModules[I]]); + Q.push(*Sub); } Stream.ExitBlock(); -- GitLab