]> granicus.if.org Git - clang/commitdiff
When writing a module file, keep track of the set of (sub)modules that
authorDouglas Gregor <dgregor@apple.com>
Mon, 5 Dec 2011 16:33:54 +0000 (16:33 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 5 Dec 2011 16:33:54 +0000 (16:33 +0000)
it imports, establishing dependencies at the (sub)module
granularity. This is not a user-visible change (yet).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@145808 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/Module.h
include/clang/Lex/ModuleMap.h
include/clang/Serialization/ASTBitCodes.h
include/clang/Serialization/ASTReader.h
lib/Lex/ModuleMap.cpp
lib/Serialization/ASTReader.cpp
lib/Serialization/ASTWriter.cpp

index 43edcfaceceddbd74ca28b04d9d7125c5120cd0b..422449b6bb9ea6bdfe1ef500bedaa1bcbc46b332 100644 (file)
@@ -78,6 +78,10 @@ public:
   
   ///\ brief The visibility of names within this particular module.
   NameVisibilityKind NameVisibility;
+
+  /// \brief The set of modules imported by this module, and on which this
+  /// module depends.
+  llvm::SmallVector<Module *, 2> Imports;
   
   /// \brief Describes an exported module.
   ///
@@ -89,7 +93,7 @@ public:
   llvm::SmallVector<ExportDecl, 2> Exports;
   
   /// \brief Describes an exported module that has not yet been resolved
-  /// (perhaps because the module it refers to has not yet been loaded).
+  /// (perhaps because tASThe module it refers to has not yet been loaded).
   struct UnresolvedExportDecl {
     /// \brief The location of the 'export' keyword in the module map file.
     SourceLocation ExportLoc;
index 40488b29fc29d4a05746e1447873c8140110e9bc..fdd5ddbf5fecc799a1377c810a53da6249c9db28 100644 (file)
@@ -167,6 +167,16 @@ public:
   /// false otherwise.
   bool resolveExports(Module *Mod, bool Complain);
 
+  /// \brief Infers the (sub)module based on the given source location and 
+  /// source manager.
+  ///
+  /// \param Loc The location within the source that we are querying, along
+  /// with its source manager.
+  ///
+  /// \returns The module that owns this source location, or null if no
+  /// module owns this source location.
+  Module *inferModuleFromLocation(FullSourceLoc Loc);
+  
   /// \brief Parse the given module map file, and record any modules we 
   /// encounter.
   ///
index 3d234d9085950b11009e13ffe88cc5271ffa6043..17c9992a6c73745cd243850b73310fd0cf9cd311 100644 (file)
@@ -517,9 +517,12 @@ namespace clang {
       SUBMODULE_HEADER = 2,
       /// \brief Metadata for submodules as a whole.
       SUBMODULE_METADATA = 3,
+      /// \brief Specifies the submodules that are imported by this 
+      /// submodule.
+      SUBMODULE_IMPORTS = 4,
       /// \brief Specifies the submodules that are re-exported from this 
       /// submodule.
-      SUBMODULE_EXPORTS = 4
+      SUBMODULE_EXPORTS = 5
     };
     
     /// \defgroup ASTAST AST file AST constants
index 552d1a5bffd5b8cceeb7c3edaba83cbf3f79b4b2..5e9da51b97b196e63a1ce73ab079f7a389d55bfb 100644 (file)
@@ -393,21 +393,29 @@ private:
   /// declarations in that submodule that could be made visible.
   HiddenNamesMapType HiddenNamesMap;
   
-  /// \brief A module export that hasn't yet been resolved.
-  struct UnresolvedModuleExport {
+  
+  /// \brief A module import or export that hasn't yet been resolved.
+  struct UnresolvedModuleImportExport {
     /// \brief The file in which this module resides.
     ModuleFile *File;
     
-    /// \brief The module that is exporting, along with a bit that specifies
-    /// whether this is a wildcard export.
-    llvm::PointerIntPair<Module *, 1, bool> ModuleAndWildcard;
+    /// \brief The module that is importing or exporting.
+    Module *Mod;
     
     /// \brief The local ID of the module that is being exported.
-    unsigned ExportedID;
+    unsigned ID;
+    
+    /// \brief Whether this is an import (vs. an export).
+    unsigned IsImport : 1;
+    
+    /// \brief Whether this is a wildcard export.
+    unsigned IsWildcard : 1;
   };
   
-  /// \brief The set of module exports that still need to be resolved.
-  llvm::SmallVector<UnresolvedModuleExport, 2> UnresolvedModuleExports;
+  /// \brief The set of module imports and exports that still need to be 
+  /// resolved.
+  llvm::SmallVector<UnresolvedModuleImportExport, 2> 
+    UnresolvedModuleImportExports;
   
   /// \brief A vector containing selectors that have already been loaded.
   ///
index 84f7bec91924729d866f8399604c43fc795a84b7..b20ccd122f541d70157460f3c055b5542f0fa900 100644 (file)
@@ -238,6 +238,26 @@ bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
   return HadError;
 }
 
+Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) {
+  if (Loc.isInvalid())
+    return 0;
+  
+  // Use the expansion location to determine which module we're in.
+  FullSourceLoc ExpansionLoc = Loc.getExpansionLoc();
+  if (!ExpansionLoc.isFileID())
+    return 0;  
+  
+  
+  const SourceManager &SrcMgr = Loc.getManager();
+  FileID ExpansionFileID = ExpansionLoc.getFileID();
+  const FileEntry *ExpansionFile = SrcMgr.getFileEntryForID(ExpansionFileID);
+  if (!ExpansionFile)
+    return 0;
+  
+  // Find the module that owns this header.
+  return findModuleForHeader(ExpansionFile);
+}
+
 //----------------------------------------------------------------------------//
 // Module map file parser
 //----------------------------------------------------------------------------//
index c7b6b512a5d47c4178836e7e7d01f947d52fb694..0742ec61842778eab0fd6aa19d9b7f7fce688de9 100644 (file)
@@ -2560,17 +2560,18 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName,
     Id->second->setOutOfDate(true);
 
   // Resolve any unresolved module exports.
-  for (unsigned I = 0, N = UnresolvedModuleExports.size(); I != N; ++I) {
-    UnresolvedModuleExport &Unresolved = UnresolvedModuleExports[I];
-    SubmoduleID GlobalID = getGlobalSubmoduleID(*Unresolved.File,
-                                                Unresolved.ExportedID);
-    if (Module *Exported = getSubmodule(GlobalID)) {
-      Module *Exportee = Unresolved.ModuleAndWildcard.getPointer();
-      bool Wildcard = Unresolved.ModuleAndWildcard.getInt();
-      Exportee->Exports.push_back(Module::ExportDecl(Exported, Wildcard));
+  for (unsigned I = 0, N = UnresolvedModuleImportExports.size(); I != N; ++I) {
+    UnresolvedModuleImportExport &Unresolved = UnresolvedModuleImportExports[I];
+    SubmoduleID GlobalID = getGlobalSubmoduleID(*Unresolved.File,Unresolved.ID);
+    if (Module *ResolvedMod = getSubmodule(GlobalID)) {
+      if (Unresolved.IsImport)
+        Unresolved.Mod->Imports.push_back(ResolvedMod);
+      else
+        Unresolved.Mod->Exports.push_back(
+          Module::ExportDecl(ResolvedMod, Unresolved.IsWildcard));
     }
   }
-  UnresolvedModuleExports.clear();
+  UnresolvedModuleImportExports.clear();
   
   InitializeContext();
 
@@ -3097,6 +3098,27 @@ ASTReader::ASTReadResult ASTReader::ReadSubmoduleBlock(ModuleFile &F) {
       break;
     }
         
+    case SUBMODULE_IMPORTS: {
+      if (First) {
+        Error("missing submodule metadata record at beginning of block");
+        return Failure;
+      }
+      
+      if (!CurrentModule)
+        break;
+      
+      for (unsigned Idx = 0; Idx != Record.size(); ++Idx) {
+        UnresolvedModuleImportExport Unresolved;
+        Unresolved.File = &F;
+        Unresolved.Mod = CurrentModule;
+        Unresolved.ID = Record[Idx];
+        Unresolved.IsImport = true;
+        Unresolved.IsWildcard = false;
+        UnresolvedModuleImportExports.push_back(Unresolved);
+      }
+      break;
+    }
+
     case SUBMODULE_EXPORTS: {
       if (First) {
         Error("missing submodule metadata record at beginning of block");
@@ -3107,12 +3129,13 @@ ASTReader::ASTReadResult ASTReader::ReadSubmoduleBlock(ModuleFile &F) {
         break;
       
       for (unsigned Idx = 0; Idx + 1 < Record.size(); Idx += 2) {
-        UnresolvedModuleExport Unresolved;
+        UnresolvedModuleImportExport Unresolved;
         Unresolved.File = &F;
-        Unresolved.ModuleAndWildcard.setPointer(CurrentModule);
-        Unresolved.ModuleAndWildcard.setInt(Record[Idx + 1]);
-        Unresolved.ExportedID = Record[Idx];
-        UnresolvedModuleExports.push_back(Unresolved);
+        Unresolved.Mod = CurrentModule;
+        Unresolved.ID = Record[Idx];
+        Unresolved.IsImport = false;
+        Unresolved.IsWildcard = Record[Idx + 1];
+        UnresolvedModuleImportExports.push_back(Unresolved);
       }
       
       // Once we've loaded the set of exports, there's no reason to keep 
index b6198184cca92f0c770904d4c1a26d3d161d46ec..f2c2f4330adcc1963893e1bf2a292dc2ea70cd99 100644 (file)
@@ -1858,6 +1858,22 @@ static unsigned getNumberOfModules(Module *Mod) {
 }
 
 void ASTWriter::WriteSubmodules(Module *WritingModule) {
+  // 
+  // FIXME: This feels like it belongs somewhere else, but there are no
+  // other consumers of this information.
+  SourceManager &SrcMgr = PP->getSourceManager();
+  ModuleMap &ModMap = PP->getHeaderSearchInfo().getModuleMap();
+  for (ASTContext::import_iterator I = Context->local_import_begin(),
+                                IEnd = Context->local_import_end();
+       I != IEnd; ++I) {
+    assert(SubmoduleIDs.find(I->getImportedModule()) != SubmoduleIDs.end());
+    if (Module *ImportedFrom
+          = ModMap.inferModuleFromLocation(FullSourceLoc(I->getLocation(), 
+                                                         SrcMgr))) {
+      ImportedFrom->Imports.push_back(I->getImportedModule());
+    }
+  }
+  
   // Enter the submodule description block.
   Stream.EnterSubblock(SUBMODULE_BLOCK_ID, NUM_ALLOWED_ABBREVS_SIZE);
   
@@ -1924,7 +1940,18 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
       Stream.EmitRecordWithBlob(HeaderAbbrev, Record, 
                                 Mod->Headers[I]->getName());
     }
-    
+
+    // Emit the imports. 
+    if (!Mod->Imports.empty()) {
+      Record.clear();
+      for (unsigned I = 0, N = Mod->Imports.size(); I != N; ++I) {
+        unsigned ImportedID = SubmoduleIDs[Mod->Imports[I]];
+        assert(ImportedID && "Unknown submodule!");                                           
+        Record.push_back(ImportedID);
+      }
+      Stream.EmitRecord(SUBMODULE_IMPORTS, Record);
+    }
+
     // Emit the exports. 
     if (!Mod->Exports.empty()) {
       Record.clear();
@@ -1960,22 +1987,11 @@ serialization::SubmoduleID
 ASTWriter::inferSubmoduleIDFromLocation(SourceLocation Loc) {
   if (Loc.isInvalid() || SubmoduleIDs.empty())
     return 0; // No submodule
-  
-  // Use the expansion location to determine which module we're in.
-  SourceManager &SrcMgr = PP->getSourceManager();
-  SourceLocation ExpansionLoc = SrcMgr.getExpansionLoc(Loc);
-  if (!ExpansionLoc.isFileID())
-    return 0;  
-
-  
-  FileID ExpansionFileID = SrcMgr.getFileID(ExpansionLoc);
-  const FileEntry *ExpansionFile = SrcMgr.getFileEntryForID(ExpansionFileID);
-  if (!ExpansionFile)
-    return 0;
-  
-  // Find the module that owns this header.
+    
+  // Find the module that owns this location.
   ModuleMap &ModMap = PP->getHeaderSearchInfo().getModuleMap();
-  Module *OwningMod = ModMap.findModuleForHeader(ExpansionFile);
+  Module *OwningMod 
+    = ModMap.inferModuleFromLocation(FullSourceLoc(Loc,PP->getSourceManager()));
   if (!OwningMod)
     return 0;