diff --git a/clang/include/clang/Serialization/ModuleManager.h b/clang/include/clang/Serialization/ModuleManager.h --- a/clang/include/clang/Serialization/ModuleManager.h +++ b/clang/include/clang/Serialization/ModuleManager.h @@ -59,8 +59,36 @@ // to implement short-circuiting logic when running DFS over the dependencies. SmallVector Roots; + struct EntryKey { + const FileEntry *Entry; + + struct Info { + static inline EntryKey getEmptyKey() { + return EntryKey{llvm::DenseMapInfo::getEmptyKey()}; + } + static inline EntryKey getTombstoneKey() { + return EntryKey{ + llvm::DenseMapInfo::getTombstoneKey()}; + } + static unsigned getHashValue(const EntryKey &Val) { + return llvm::hash_combine(Val.Entry, Val.Entry->getSize(), + Val.Entry->getModificationTime()); + } + static bool isEqual(const EntryKey &LHS, const EntryKey &RHS) { + if (RHS.Entry == getEmptyKey().Entry) + return LHS.Entry == getEmptyKey().Entry; + if (RHS.Entry == getTombstoneKey().Entry) + return LHS.Entry == getTombstoneKey().Entry; + return LHS.Entry == RHS.Entry && + LHS.Entry->getSize() == RHS.Entry->getSize() && + LHS.Entry->getModificationTime() == + RHS.Entry->getModificationTime(); + } + }; + }; + /// All loaded modules, indexed by name. - llvm::DenseMap Modules; + llvm::DenseMap Modules; /// FileManager that handles translating between filenames and /// FileEntry *. @@ -76,7 +104,7 @@ const HeaderSearch &HeaderSearchInfo; /// A lookup of in-memory (virtual file) buffers - llvm::DenseMap> + llvm::DenseMap, EntryKey::Info> InMemoryBuffers; /// The visitation order. diff --git a/clang/lib/Serialization/ModuleManager.cpp b/clang/lib/Serialization/ModuleManager.cpp --- a/clang/lib/Serialization/ModuleManager.cpp +++ b/clang/lib/Serialization/ModuleManager.cpp @@ -59,7 +59,7 @@ } ModuleFile *ModuleManager::lookup(const FileEntry *File) const { - auto Known = Modules.find(File); + auto Known = Modules.find(EntryKey{File}); if (Known == Modules.end()) return nullptr; @@ -72,7 +72,7 @@ /*CacheFailure=*/false); if (!Entry) return nullptr; - return std::move(InMemoryBuffers[*Entry]); + return std::move(InMemoryBuffers[EntryKey{*Entry}]); } static bool checkSignature(ASTFileSignature Signature, @@ -133,7 +133,7 @@ } // Check whether we already loaded this module, before - if (ModuleFile *ModuleEntry = Modules.lookup(Entry)) { + if (ModuleFile *ModuleEntry = Modules.lookup(EntryKey{Entry})) { // Check the stored signature. if (checkSignature(ModuleEntry->Signature, ExpectedSignature, ErrorStr)) return OutOfDate; @@ -208,7 +208,7 @@ return OutOfDate; // We're keeping this module. Store it everywhere. - Module = Modules[Entry] = NewModule.get(); + Module = Modules[EntryKey{Entry}] = NewModule.get(); updateModuleImports(*NewModule, ImportedBy, ImportLoc); @@ -255,7 +255,7 @@ // Delete the modules and erase them from the various structures. for (ModuleIterator victim = First; victim != Last; ++victim) { - Modules.erase(victim->File); + Modules.erase(EntryKey{victim->File}); if (modMap) { StringRef ModuleName = victim->ModuleName; @@ -274,7 +274,7 @@ std::unique_ptr Buffer) { const FileEntry *Entry = FileMgr.getVirtualFile(FileName, Buffer->getBufferSize(), 0); - InMemoryBuffers[Entry] = std::move(Buffer); + InMemoryBuffers[EntryKey{Entry}] = std::move(Buffer); } ModuleManager::VisitState *ModuleManager::allocateVisitState() {