Author: rsmith Date: Tue Aug 18 18:42:23 2015 New Revision: 245390 URL: http://llvm.org/viewvc/llvm-project?rev=245390&view=rev Log: [modules] Fix HeaderFileInfo serialization to store all the known owning modules for a header, not just the current favourite.
Modified: cfe/trunk/include/clang/Lex/HeaderSearch.h cfe/trunk/include/clang/Lex/ModuleMap.h cfe/trunk/include/clang/Serialization/ASTWriter.h cfe/trunk/lib/Lex/HeaderSearch.cpp cfe/trunk/lib/Lex/ModuleMap.cpp cfe/trunk/lib/Serialization/ASTReader.cpp cfe/trunk/lib/Serialization/ASTWriter.cpp Modified: cfe/trunk/include/clang/Lex/HeaderSearch.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/HeaderSearch.h?rev=245390&r1=245389&r2=245390&view=diff ============================================================================== --- cfe/trunk/include/clang/Lex/HeaderSearch.h (original) +++ cfe/trunk/include/clang/Lex/HeaderSearch.h Tue Aug 18 18:42:23 2015 @@ -49,7 +49,8 @@ struct HeaderFileInfo { /// SrcMgr::CharacteristicKind. unsigned DirInfo : 2; - /// \brief Whether this header file info was supplied by an external source. + /// \brief Whether this header file info was supplied by an external source, + /// and has not changed since. unsigned External : 1; /// \brief Whether this header is part of a module. @@ -58,10 +59,6 @@ struct HeaderFileInfo { /// \brief Whether this header is part of the module that we are building. unsigned isCompilingModuleHeader : 1; - /// \brief Whether this header is part of the module that we are building. - /// This is an instance of ModuleMap::ModuleHeaderRole. - unsigned HeaderRole : 2; - /// \brief Whether this structure is considered to already have been /// "resolved", meaning that it was loaded from the external source. unsigned Resolved : 1; @@ -75,7 +72,7 @@ struct HeaderFileInfo { /// those framework headers. unsigned IndexHeaderMapHeader : 1; - /// \brief Whether this file had been looked up as a header. + /// \brief Whether this file has been looked up as a header. unsigned IsValid : 1; /// \brief The number of times the file has been included already. @@ -105,7 +102,6 @@ struct HeaderFileInfo { HeaderFileInfo() : isImport(false), isPragmaOnce(false), DirInfo(SrcMgr::C_User), External(false), isModuleHeader(false), isCompilingModuleHeader(false), - HeaderRole(ModuleMap::NormalHeader), Resolved(false), IndexHeaderMapHeader(false), IsValid(0), NumIncludes(0), ControllingMacroID(0), ControllingMacro(nullptr) {} @@ -120,16 +116,6 @@ struct HeaderFileInfo { return isImport || isPragmaOnce || NumIncludes || ControllingMacro || ControllingMacroID; } - - /// \brief Get the HeaderRole properly typed. - ModuleMap::ModuleHeaderRole getHeaderRole() const { - return static_cast<ModuleMap::ModuleHeaderRole>(HeaderRole); - } - - /// \brief Set the HeaderRole properly typed. - void setHeaderRole(ModuleMap::ModuleHeaderRole Role) { - HeaderRole = Role; - } }; /// \brief An external source of header file information, which may supply @@ -189,7 +175,7 @@ class HeaderSearch { /// \brief All of the preprocessor-specific data about files that are /// included, indexed by the FileEntry's UID. - std::vector<HeaderFileInfo> FileInfo; + mutable std::vector<HeaderFileInfo> FileInfo; /// Keeps track of each lookup performed by LookupFile. struct LookupFileCacheInfo { @@ -575,20 +561,20 @@ private: /// of the given search directory. void loadSubdirectoryModuleMaps(DirectoryLookup &SearchDir); - /// \brief Return the HeaderFileInfo structure for the specified FileEntry. - const HeaderFileInfo &getFileInfo(const FileEntry *FE) const { - return const_cast<HeaderSearch*>(this)->getFileInfo(FE); - } - public: /// \brief Retrieve the module map. ModuleMap &getModuleMap() { return ModMap; } + /// \brief Retrieve the module map. + const ModuleMap &getModuleMap() const { return ModMap; } + unsigned header_file_size() const { return FileInfo.size(); } - /// \brief Get a \c HeaderFileInfo structure for the specified \c FileEntry, - /// if one exists. - bool tryGetFileInfo(const FileEntry *FE, HeaderFileInfo &Result) const; + /// \brief Return the HeaderFileInfo structure for the specified FileEntry. + HeaderFileInfo &getFileInfo(const FileEntry *FE); + + /// \brief Return the HeaderFileInfo structure for the specified FileEntry. + const HeaderFileInfo *getExistingFileInfo(const FileEntry *FE) const; // Used by external tools typedef std::vector<DirectoryLookup>::const_iterator search_dir_iterator; @@ -665,9 +651,6 @@ private: /// named directory. LoadModuleMapResult loadModuleMapFile(const DirectoryEntry *Dir, bool IsSystem, bool IsFramework); - - /// \brief Return the HeaderFileInfo structure for the specified FileEntry. - HeaderFileInfo &getFileInfo(const FileEntry *FE); }; } // end namespace clang Modified: cfe/trunk/include/clang/Lex/ModuleMap.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/ModuleMap.h?rev=245390&r1=245389&r2=245390&view=diff ============================================================================== --- cfe/trunk/include/clang/Lex/ModuleMap.h (original) +++ cfe/trunk/include/clang/Lex/ModuleMap.h Tue Aug 18 18:42:23 2015 @@ -112,6 +112,13 @@ public: KnownHeader() : Storage(nullptr, NormalHeader) { } KnownHeader(Module *M, ModuleHeaderRole Role) : Storage(M, Role) { } + friend bool operator==(const KnownHeader &A, const KnownHeader &B) { + return A.Storage == B.Storage; + } + friend bool operator!=(const KnownHeader &A, const KnownHeader &B) { + return A.Storage != B.Storage; + } + /// \brief Retrieve the module the header is stored in. Module *getModule() const { return Storage.getPointer(); } @@ -242,6 +249,10 @@ private: KnownHeader findHeaderInUmbrellaDirs(const FileEntry *File, SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs); + /// \brief Given that \p File is not in the Headers map, look it up within + /// umbrella directories and find or create a module for it. + KnownHeader findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File); + /// \brief A convenience method to determine if \p File is (possibly nested) /// in an umbrella directory. bool isHeaderInUmbrellaDirs(const FileEntry *File) { @@ -295,6 +306,14 @@ public: /// that no module owns this header file. KnownHeader findModuleForHeader(const FileEntry *File); + /// \brief Retrieve all the modules that contain the given header file. This + /// may not include umbrella modules, nor information from external sources, + /// if they have not yet been inferred / loaded. + /// + /// Typically, \ref findModuleForHeader should be used instead, as it picks + /// the preferred module for the header. + ArrayRef<KnownHeader> findAllModulesForHeader(const FileEntry *File) const; + /// \brief Reports errors if a module must not include a specific file. /// /// \param RequestingModule The module including a file. Modified: cfe/trunk/include/clang/Serialization/ASTWriter.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTWriter.h?rev=245390&r1=245389&r2=245390&view=diff ============================================================================== --- cfe/trunk/include/clang/Serialization/ASTWriter.h (original) +++ cfe/trunk/include/clang/Serialization/ASTWriter.h Tue Aug 18 18:42:23 2015 @@ -493,7 +493,7 @@ private: /// \brief Retrieve or create a submodule ID for this module. unsigned getSubmoduleID(Module *Mod); - + /// \brief Write the given subexpression to the bitstream. void WriteSubStmt(Stmt *S, llvm::DenseMap<Stmt *, uint64_t> &SubStmtEntries, @@ -767,9 +767,10 @@ public: /// source location. serialization::SubmoduleID inferSubmoduleIDFromLocation(SourceLocation Loc); - /// \brief Retrieve a submodule ID for this module. - /// Returns 0 If no ID has been associated with the module. - unsigned getExistingSubmoduleID(Module *Mod) const; + /// \brief Retrieve or create a submodule ID for this module, or return 0 if + /// the submodule is neither local (a submodle of the currently-written module) + /// nor from an imported module. + unsigned getLocalOrImportedSubmoduleID(Module *Mod); /// \brief Note that the identifier II occurs at the given offset /// within the identifier table. Modified: cfe/trunk/lib/Lex/HeaderSearch.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/HeaderSearch.cpp?rev=245390&r1=245389&r2=245390&view=diff ============================================================================== --- cfe/trunk/lib/Lex/HeaderSearch.cpp (original) +++ cfe/trunk/lib/Lex/HeaderSearch.cpp Tue Aug 18 18:42:23 2015 @@ -975,65 +975,72 @@ static void mergeHeaderFileInfo(HeaderFi if (OtherHFI.External) { HFI.DirInfo = OtherHFI.DirInfo; - HFI.External = OtherHFI.External; + HFI.External = OtherHFI.External && (!HFI.IsValid || HFI.External); HFI.IndexHeaderMapHeader = OtherHFI.IndexHeaderMapHeader; } if (HFI.Framework.empty()) HFI.Framework = OtherHFI.Framework; - - HFI.Resolved = true; } /// getFileInfo - Return the HeaderFileInfo structure for the specified /// FileEntry. HeaderFileInfo &HeaderSearch::getFileInfo(const FileEntry *FE) { if (FE->getUID() >= FileInfo.size()) - FileInfo.resize(FE->getUID()+1); - + FileInfo.resize(FE->getUID() + 1); + HeaderFileInfo &HFI = FileInfo[FE->getUID()]; - if (ExternalSource && !HFI.Resolved) + // FIXME: Use a generation count to check whether this is really up to date. + if (ExternalSource && !HFI.Resolved) { + HFI.Resolved = true; mergeHeaderFileInfo(HFI, ExternalSource->GetHeaderFileInfo(FE)); - HFI.IsValid = 1; + } + + HFI.IsValid = true; + // We have local information about this header file, so it's no longer + // strictly external. + HFI.External = false; return HFI; } -bool HeaderSearch::tryGetFileInfo(const FileEntry *FE, - HeaderFileInfo &Result) const { - if (FE->getUID() >= FileInfo.size()) - return false; - const HeaderFileInfo &HFI = FileInfo[FE->getUID()]; - if (HFI.IsValid) { - Result = HFI; - return true; +const HeaderFileInfo * +HeaderSearch::getExistingFileInfo(const FileEntry *FE) const { + // If we have an external source, ensure we have the latest information. + // FIXME: Use a generation count to check whether this is really up to date. + if (ExternalSource && + (FE->getUID() >= FileInfo.size() || !FileInfo[FE->getUID()].Resolved)) { + auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE); + if (ExternalHFI.External) { + if (FE->getUID() >= FileInfo.size()) + FileInfo.resize(FE->getUID() + 1); + mergeHeaderFileInfo(FileInfo[FE->getUID()], ExternalHFI); + } } - return false; + + if (FE->getUID() >= FileInfo.size()) + return nullptr; + + HeaderFileInfo &HFI = FileInfo[FE->getUID()]; + if (!HFI.IsValid) + return nullptr; + + return &HFI; } bool HeaderSearch::isFileMultipleIncludeGuarded(const FileEntry *File) { // Check if we've ever seen this file as a header. - if (File->getUID() >= FileInfo.size()) - return false; - - // Resolve header file info from the external source, if needed. - HeaderFileInfo &HFI = FileInfo[File->getUID()]; - if (ExternalSource && !HFI.Resolved) - mergeHeaderFileInfo(HFI, ExternalSource->GetHeaderFileInfo(File)); - - return HFI.isPragmaOnce || HFI.isImport || - HFI.ControllingMacro || HFI.ControllingMacroID; + if (auto *HFI = getExistingFileInfo(File)) + return HFI->isPragmaOnce || HFI->isImport || HFI->ControllingMacro || + HFI->ControllingMacroID; + return false; } void HeaderSearch::MarkFileModuleHeader(const FileEntry *FE, ModuleMap::ModuleHeaderRole Role, bool isCompilingModuleHeader) { - if (FE->getUID() >= FileInfo.size()) - FileInfo.resize(FE->getUID()+1); - - HeaderFileInfo &HFI = FileInfo[FE->getUID()]; - HFI.isModuleHeader = true; + auto &HFI = getFileInfo(FE); + HFI.isModuleHeader |= !(Role & ModuleMap::TextualHeader); HFI.isCompilingModuleHeader |= isCompilingModuleHeader; - HFI.setHeaderRole(Role); } bool HeaderSearch::ShouldEnterIncludeFile(Preprocessor &PP, @@ -1143,7 +1150,7 @@ HeaderSearch::findModuleForHeader(const if (ExternalSource) { // Make sure the external source has handled header info about this file, // which includes whether the file is part of a module. - (void)getFileInfo(File); + (void)getExistingFileInfo(File); } return ModMap.findModuleForHeader(File); } Modified: cfe/trunk/lib/Lex/ModuleMap.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/ModuleMap.cpp?rev=245390&r1=245389&r2=245390&view=diff ============================================================================== --- cfe/trunk/lib/Lex/ModuleMap.cpp (original) +++ cfe/trunk/lib/Lex/ModuleMap.cpp Tue Aug 18 18:42:23 2015 @@ -359,6 +359,13 @@ ModuleMap::KnownHeader ModuleMap::findMo return MakeResult(Result); } + return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File)); +} + +ModuleMap::KnownHeader +ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) { + assert(!Headers.count(File) && "already have a module for this header"); + SmallVector<const DirectoryEntry *, 2> SkippedDirs; KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs); if (H) { @@ -419,19 +426,22 @@ ModuleMap::KnownHeader ModuleMap::findMo UmbrellaDirs[SkippedDirs[I]] = Result; } - Headers[File].push_back(KnownHeader(Result, NormalHeader)); - - // If a header corresponds to an unavailable module, don't report - // that it maps to anything. - if (!Result->isAvailable()) - return KnownHeader(); - - return MakeResult(Headers[File].back()); + KnownHeader Header(Result, NormalHeader); + Headers[File].push_back(Header); + return Header; } return KnownHeader(); } +ArrayRef<ModuleMap::KnownHeader> +ModuleMap::findAllModulesForHeader(const FileEntry *File) const { + auto It = Headers.find(File); + if (It == Headers.end()) + return None; + return It->second; +} + bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const { return isHeaderUnavailableInModule(Header, nullptr); } @@ -787,14 +797,21 @@ static Module::HeaderKind headerRoleToKi void ModuleMap::addHeader(Module *Mod, Module::Header Header, ModuleHeaderRole Role) { - if (!(Role & TextualHeader)) { - bool isCompilingModuleHeader = Mod->getTopLevelModule() == CompilingModule; - HeaderInfo.MarkFileModuleHeader(Header.Entry, Role, - isCompilingModuleHeader); - } - Headers[Header.Entry].push_back(KnownHeader(Mod, Role)); + KnownHeader KH(Mod, Role); + // Only add each header to the headers list once. + // FIXME: Should we diagnose if a header is listed twice in the + // same module definition? + auto &HeaderList = Headers[Header.Entry]; + for (auto H : HeaderList) + if (H == KH) + return; + + HeaderList.push_back(KH); Mod->Headers[headerRoleToKind(Role)].push_back(std::move(Header)); + + bool isCompilingModuleHeader = Mod->getTopLevelModule() == CompilingModule; + HeaderInfo.MarkFileModuleHeader(Header.Entry, Role, isCompilingModuleHeader); } void ModuleMap::excludeHeader(Module *Mod, Module::Header Header) { Modified: cfe/trunk/lib/Serialization/ASTReader.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=245390&r1=245389&r2=245390&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTReader.cpp (original) +++ cfe/trunk/lib/Serialization/ASTReader.cpp Tue Aug 18 18:42:23 2015 @@ -1556,14 +1556,15 @@ HeaderFileInfoTrait::ReadData(internal_k using namespace llvm::support; HeaderFileInfo HFI; unsigned Flags = *d++; - HFI.HeaderRole = static_cast<ModuleMap::ModuleHeaderRole> - ((Flags >> 6) & 0x03); - HFI.isImport = (Flags >> 5) & 0x01; - HFI.isPragmaOnce = (Flags >> 4) & 0x01; - HFI.DirInfo = (Flags >> 2) & 0x03; - HFI.Resolved = (Flags >> 1) & 0x01; + // FIXME: Refactor with mergeHeaderFileInfo in HeaderSearch.cpp. + HFI.isImport |= (Flags >> 4) & 0x01; + HFI.isPragmaOnce |= (Flags >> 3) & 0x01; + HFI.DirInfo = (Flags >> 1) & 0x03; HFI.IndexHeaderMapHeader = Flags & 0x01; - HFI.NumIncludes = endian::readNext<uint16_t, little, unaligned>(d); + // FIXME: Find a better way to handle this. Maybe just store a + // "has been included" flag? + HFI.NumIncludes = std::max(endian::readNext<uint16_t, little, unaligned>(d), + HFI.NumIncludes); HFI.ControllingMacroID = Reader.getGlobalIdentifierID( M, endian::readNext<uint32_t, little, unaligned>(d)); if (unsigned FrameworkOffset = @@ -1573,32 +1574,32 @@ HeaderFileInfoTrait::ReadData(internal_k StringRef FrameworkName(FrameworkStrings + FrameworkOffset - 1); HFI.Framework = HS->getUniqueFrameworkName(FrameworkName); } - - if (d != End) { + + assert((End - d) % 4 == 0 && + "Wrong data length in HeaderFileInfo deserialization"); + while (d != End) { uint32_t LocalSMID = endian::readNext<uint32_t, little, unaligned>(d); - if (LocalSMID) { - // This header is part of a module. Associate it with the module to enable - // implicit module import. - SubmoduleID GlobalSMID = Reader.getGlobalSubmoduleID(M, LocalSMID); - Module *Mod = Reader.getSubmodule(GlobalSMID); - HFI.isModuleHeader = true; - FileManager &FileMgr = Reader.getFileManager(); - ModuleMap &ModMap = - Reader.getPreprocessor().getHeaderSearchInfo().getModuleMap(); - // FIXME: This information should be propagated through the - // SUBMODULE_HEADER etc records rather than from here. - // FIXME: We don't ever mark excluded headers. - std::string Filename = key.Filename; - if (key.Imported) - Reader.ResolveImportedPath(M, Filename); - Module::Header H = { key.Filename, FileMgr.getFile(Filename) }; - ModMap.addHeader(Mod, H, HFI.getHeaderRole()); - } + auto HeaderRole = static_cast<ModuleMap::ModuleHeaderRole>(LocalSMID & 3); + LocalSMID >>= 2; + + // This header is part of a module. Associate it with the module to enable + // implicit module import. + SubmoduleID GlobalSMID = Reader.getGlobalSubmoduleID(M, LocalSMID); + Module *Mod = Reader.getSubmodule(GlobalSMID); + FileManager &FileMgr = Reader.getFileManager(); + ModuleMap &ModMap = + Reader.getPreprocessor().getHeaderSearchInfo().getModuleMap(); + + std::string Filename = key.Filename; + if (key.Imported) + Reader.ResolveImportedPath(M, Filename); + // FIXME: This is not always the right filename-as-written, but we're not + // going to use this information to rebuild the module, so it doesn't make + // a lot of difference. + Module::Header H = { key.Filename, FileMgr.getFile(Filename) }; + ModMap.addHeader(Mod, H, HeaderRole); } - assert(End == d && "Wrong data length in HeaderFileInfo deserialization"); - (void)End; - // This HeaderFileInfo was externally loaded. HFI.External = true; return HFI; Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=245390&r1=245389&r2=245390&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTWriter.cpp (original) +++ cfe/trunk/lib/Serialization/ASTWriter.cpp Tue Aug 18 18:42:23 2015 @@ -1637,13 +1637,14 @@ namespace { std::pair<unsigned,unsigned> EmitKeyDataLength(raw_ostream& Out, key_type_ref key, data_type_ref Data) { using namespace llvm::support; - endian::Writer<little> Writer(Out); + endian::Writer<little> LE(Out); unsigned KeyLen = strlen(key.Filename) + 1 + 8 + 8; - Writer.write<uint16_t>(KeyLen); + LE.write<uint16_t>(KeyLen); unsigned DataLen = 1 + 2 + 4 + 4; - if (Data.isModuleHeader) - DataLen += 4; - Writer.write<uint8_t>(DataLen); + for (auto ModInfo : HS.getModuleMap().findAllModulesForHeader(key.FE)) + if (Writer.getLocalOrImportedSubmoduleID(ModInfo.getModule())) + DataLen += 4; + LE.write<uint8_t>(DataLen); return std::make_pair(KeyLen, DataLen); } @@ -1663,11 +1664,9 @@ namespace { endian::Writer<little> LE(Out); uint64_t Start = Out.tell(); (void)Start; - unsigned char Flags = (Data.HeaderRole << 6) - | (Data.isImport << 5) - | (Data.isPragmaOnce << 4) - | (Data.DirInfo << 2) - | (Data.Resolved << 1) + unsigned char Flags = (Data.isImport << 4) + | (Data.isPragmaOnce << 3) + | (Data.DirInfo << 1) | Data.IndexHeaderMapHeader; LE.write<uint8_t>(Flags); LE.write<uint16_t>(Data.NumIncludes); @@ -1694,9 +1693,15 @@ namespace { } LE.write<uint32_t>(Offset); - if (Data.isModuleHeader) { - Module *Mod = HS.findModuleForHeader(key.FE).getModule(); - LE.write<uint32_t>(Writer.getExistingSubmoduleID(Mod)); + // FIXME: If the header is excluded, we should write out some + // record of that fact. + for (auto ModInfo : HS.getModuleMap().findAllModulesForHeader(key.FE)) { + if (uint32_t ModID = + Writer.getLocalOrImportedSubmoduleID(ModInfo.getModule())) { + uint32_t Value = (ModID << 2) | (unsigned)ModInfo.getRole(); + assert((Value >> 2) == ModID && "overflow in header module info"); + LE.write<uint32_t>(Value); + } } assert(Out.tell() - Start == DataLen && "Wrong data length"); @@ -1726,12 +1731,15 @@ void ASTWriter::WriteHeaderSearch(const if (!File) continue; - // Use HeaderSearch's getFileInfo to make sure we get the HeaderFileInfo - // from the external source if it was not provided already. - HeaderFileInfo HFI; - if (!HS.tryGetFileInfo(File, HFI) || - (HFI.External && Chain) || - (HFI.isModuleHeader && !HFI.isCompilingModuleHeader)) + // Get the file info. This will load info from the external source if + // necessary. Skip emitting this file if we have no information on it + // as a header file (in which case HFI will be null) or if it hasn't + // changed since it was loaded. Also skip it if it's for a modular header + // from a different module; in that case, we rely on the module(s) + // containing the header to provide this information. + const HeaderFileInfo *HFI = HS.getExistingFileInfo(File); + if (!HFI || (HFI->External && Chain) || + (HFI->isModuleHeader && !HFI->isCompilingModuleHeader)) continue; // Massage the file path into an appropriate form. @@ -1745,7 +1753,7 @@ void ASTWriter::WriteHeaderSearch(const } HeaderFileInfoTrait::key_type key = { File, Filename }; - Generator.insert(key, HFI, GeneratorTrait); + Generator.insert(key, *HFI, GeneratorTrait); ++NumHeaderSearchEntries; } @@ -2283,27 +2291,28 @@ void ASTWriter::WritePreprocessorDetail( } } -unsigned ASTWriter::getSubmoduleID(Module *Mod) { +unsigned ASTWriter::getLocalOrImportedSubmoduleID(Module *Mod) { if (!Mod) return 0; llvm::DenseMap<Module *, unsigned>::iterator Known = SubmoduleIDs.find(Mod); if (Known != SubmoduleIDs.end()) return Known->second; - - return SubmoduleIDs[Mod] = NextSubmoduleID++; -} -unsigned ASTWriter::getExistingSubmoduleID(Module *Mod) const { - if (!Mod) + if (Mod->getTopLevelModule() != WritingModule) return 0; - llvm::DenseMap<Module *, unsigned>::const_iterator - Known = SubmoduleIDs.find(Mod); - if (Known != SubmoduleIDs.end()) - return Known->second; + return SubmoduleIDs[Mod] = NextSubmoduleID++; +} - return 0; +unsigned ASTWriter::getSubmoduleID(Module *Mod) { + // FIXME: This can easily happen, if we have a reference to a submodule that + // did not result in us loading a module file for that submodule. For + // instance, a cross-top-level-module 'conflict' declaration will hit this. + unsigned ID = getLocalOrImportedSubmoduleID(Mod); + assert((ID || !Mod) && + "asked for module ID for non-local, non-imported module"); + return ID; } /// \brief Compute the number of modules within the given tree (including the @@ -2542,9 +2551,6 @@ void ASTWriter::WriteSubmodules(Module * Stream.ExitBlock(); - // FIXME: This can easily happen, if we have a reference to a submodule that - // did not result in us loading a module file for that submodule. For - // instance, a cross-top-level-module 'conflict' declaration will hit this. assert((NextSubmoduleID - FirstSubmoduleID == getNumberOfModules(WritingModule)) && "Wrong # of submodules; found a reference to a non-local, " _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits