Store the submodules of a module in source order, as they are stored
authorDouglas Gregor <dgregor@apple.com>
Wed, 4 Jan 2012 23:32:19 +0000 (23:32 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 4 Jan 2012 23:32:19 +0000 (23:32 +0000)
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
clang/lib/Basic/Module.cpp
clang/lib/Frontend/CompilerInstance.cpp
clang/lib/Frontend/FrontendActions.cpp
clang/lib/Lex/ModuleMap.cpp
clang/lib/Sema/Sema.cpp
clang/lib/Serialization/ASTReader.cpp
clang/lib/Serialization/ASTWriter.cpp

index 4e6bba2..1929295 100644 (file)
@@ -22,6 +22,7 @@
 #include "llvm/ADT/StringRef.h"
 #include <string>
 #include <utility>
+#include <vector>
 
 namespace llvm {
   class raw_ostream;
@@ -53,9 +54,15 @@ public:
   /// \brief The umbrella header or directory.
   llvm::PointerUnion<const DirectoryEntry *, const FileEntry *> Umbrella;
   
+private:
   /// \brief The submodules of this module, indexed by name.
-  llvm::StringMap<Module *> SubModules;
+  std::vector<Module *> SubModules;
   
+  /// \brief A mapping from the submodule name to the index into the 
+  /// \c SubModules vector at which that submodule resides.
+  llvm::StringMap<unsigned> SubModuleIndex;
+  
+public:
   /// \brief The headers that are part of this module.
   llvm::SmallVector<const FileEntry *, 2> 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<Module *>::iterator submodule_iterator;
+  typedef std::vector<Module *>::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;
index feec5f0..c5bc86d 100644 (file)
 #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<Module *>::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<Module *>::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<unsigned>::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<Module *>::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);
index 498f6fb..1f0d87c 100644 (file)
@@ -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<clang::Module *>::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<StringRef, 2> Best;
         unsigned BestEditDistance = (std::numeric_limits<unsigned>::max)();
         
-        for (llvm::StringMap<clang::Module *>::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;
     }
   }
   
index dd98fcf..d9a385d 100644 (file)
@@ -186,11 +186,10 @@ static void collectModuleHeaderIncludes(const LangOptions &LangOpts,
   }
   
   // Recurse into submodules.
-  for (llvm::StringMap<clang::Module *>::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, 
index f43abc8..42257f5 100644 (file)
@@ -263,26 +263,20 @@ Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) {
   if (!Context)
     return findModule(Name);
   
-  llvm::StringMap<Module *>::iterator Sub = Context->SubModules.find(Name);
-  if (Sub != Context->SubModules.end())
-    return Sub->getValue();
-
-  return 0;
+  return Context->findSubmodule(Name);
 }
 
 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 *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<Module *> &ModuleSpace
-    = ActiveModule? ActiveModule->SubModules : Map.Modules;
-  llvm::StringMap<Module *>::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 {
index c95cf22..c819904 100644 (file)
@@ -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<Module *>::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);
         }
       }
     }
index 9c9e8b3..c29033e 100644 (file)
@@ -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<Module *>::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.
index 9ed2a6c..1317525 100644 (file)
@@ -1859,10 +1859,10 @@ unsigned ASTWriter::getSubmoduleID(Module *Mod) {
 /// given module).
 static unsigned getNumberOfModules(Module *Mod) {
   unsigned ChildModules = 0;
-  for (llvm::StringMap<Module *>::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<StringRef, 2> SubModules;
-    
-    // Sort the submodules first, so we get a predictable ordering in the AST
-    // file.
-    for (llvm::StringMap<Module *>::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();