diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-12-05 16:33:54 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-12-05 16:33:54 +0000 |
commit | 55988680ece66b8e505ee136b35e74fcb1173aee (patch) | |
tree | 98b942dc721f88d21eeda306df4a7af70a04db12 | |
parent | 5460ff35ab748860f05aeea4685cd195153dca66 (diff) |
When writing a module file, keep track of the set of (sub)modules that
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
-rw-r--r-- | include/clang/Basic/Module.h | 6 | ||||
-rw-r--r-- | include/clang/Lex/ModuleMap.h | 10 | ||||
-rw-r--r-- | include/clang/Serialization/ASTBitCodes.h | 5 | ||||
-rw-r--r-- | include/clang/Serialization/ASTReader.h | 24 | ||||
-rw-r--r-- | lib/Lex/ModuleMap.cpp | 20 | ||||
-rw-r--r-- | lib/Serialization/ASTReader.cpp | 51 | ||||
-rw-r--r-- | lib/Serialization/ASTWriter.cpp | 48 |
7 files changed, 124 insertions, 40 deletions
diff --git a/include/clang/Basic/Module.h b/include/clang/Basic/Module.h index 43edcfacec..422449b6bb 100644 --- a/include/clang/Basic/Module.h +++ b/include/clang/Basic/Module.h @@ -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; diff --git a/include/clang/Lex/ModuleMap.h b/include/clang/Lex/ModuleMap.h index 40488b29fc..fdd5ddbf5f 100644 --- a/include/clang/Lex/ModuleMap.h +++ b/include/clang/Lex/ModuleMap.h @@ -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. /// diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h index 3d234d9085..17c9992a6c 100644 --- a/include/clang/Serialization/ASTBitCodes.h +++ b/include/clang/Serialization/ASTBitCodes.h @@ -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 diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index 552d1a5bff..5e9da51b97 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -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. /// diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp index 84f7bec919..b20ccd122f 100644 --- a/lib/Lex/ModuleMap.cpp +++ b/lib/Lex/ModuleMap.cpp @@ -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 //----------------------------------------------------------------------------// diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index c7b6b512a5..0742ec6184 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -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 diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index b6198184cc..f2c2f4330a 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -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; |