]> granicus.if.org Git - clang/commitdiff
Refactor the module map file used for uniquing a module name out of
authorBen Langmuir <blangmuir@apple.com>
Sat, 9 Aug 2014 00:57:23 +0000 (00:57 +0000)
committerBen Langmuir <blangmuir@apple.com>
Sat, 9 Aug 2014 00:57:23 +0000 (00:57 +0000)
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

include/clang/Basic/Module.h
include/clang/Lex/ModuleMap.h
lib/Basic/Module.cpp
lib/Frontend/CompilerInstance.cpp
lib/Frontend/FrontendActions.cpp
lib/Lex/HeaderSearch.cpp
lib/Lex/ModuleMap.cpp
lib/Serialization/ASTReader.cpp
lib/Serialization/ASTWriter.cpp

index 9b66840ba412467c7777bf1af2c8e7e094dab390..e2f5f0efd2ad4cd867b403e0d94a5d4495c49dce 100644 (file)
@@ -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<const DirectoryEntry *, const FileEntry *> Umbrella;
@@ -283,10 +272,8 @@ public:
   std::vector<Conflict> 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();
   
index a86a927499594bc7a5aed74a019d40de1600bdf4..4a583824d7415d5717d333803c470dd05bb0df16 100644 (file)
@@ -146,6 +146,10 @@ private:
   /// framework modules from within those directories.
   llvm::DenseMap<const DirectoryEntry *, InferredDirectory> InferredDirectories;
 
+  /// A mapping from an inferred module to the module map that allowed the
+  /// inference.
+  llvm::DenseMap<const Module *, const FileEntry *> InferredModuleAllowedBy;
+
   /// \brief Describes whether we haved parsed a particular file as a module
   /// map.
   llvm::DenseMap<const FileEntry *, bool> 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<Module *, bool> 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.
index f689c733d9c03738f4c83fceb2bb0118ac29600a..65c8b1b581fba319f606778de4ac6028589875d8 100644 (file)
@@ -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) {
index 4a75058e6afb472f102c70928f040798f824711f..22788aa5fb02de1a68ade4d2185eeba894ad71a5 100644 (file)
@@ -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.
index 6dcaf382c3c4bc065e5ada4251b01721c89676c9..3c2470715077bd59a9c0cf78df4322cd707c8e6f 100644 (file)
@@ -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();
 
index c12d7314ee23d360b45fed191aba3dadc190de47..7be09af38444be2a1a1fa563215bf86bbfd8e41a 100644 (file)
@@ -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,
index 8fae9c933d336ea82e5667fe7eafaf570d571001..92de71d8f37712f3945e3992c1ccbe9a34d4fb70 100644 (file)
@@ -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<Module *, bool> 
-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<Module *>::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;
index 4733c6bdeb004b6ebb6c6d2c3899218730b30d88..f668e28c1af91e99ae951bd288d893fa779dc092 100644 (file)
@@ -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]) {
index baed95ebf84513b0afc0ba0ab2dc5b02aaf8aa11..0a11cf21185af858afd6bbc25c4091b4186f3f3c 100644 (file)
@@ -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);