diff --git a/clang/include/clang/Basic/FileManager.h b/clang/include/clang/Basic/FileManager.h --- a/clang/include/clang/Basic/FileManager.h +++ b/clang/include/clang/Basic/FileManager.h @@ -310,10 +310,11 @@ /// \returns true if \c Path changed to absolute. bool makeAbsolutePath(SmallVectorImpl &Path) const; - /// Produce an array mapping from the unique IDs assigned to each - /// file to the corresponding FileEntry pointer. - void GetUniqueIDMapping( - SmallVectorImpl &UIDToFiles) const; + /// Produce an array of seen FileEntryRef. The entries will be sorted + /// by UID and Name. + void getSeenFileEntries( + SmallVectorImpl &Entries) + const; /// Retrieve the canonical name for a given directory. /// diff --git a/clang/lib/Basic/FileManager.cpp b/clang/lib/Basic/FileManager.cpp --- a/clang/lib/Basic/FileManager.cpp +++ b/clang/lib/Basic/FileManager.cpp @@ -17,6 +17,7 @@ //===----------------------------------------------------------------------===// #include "clang/Basic/FileManager.h" +#include "clang/Basic/FileEntry.h" #include "clang/Basic/FileSystemStatCache.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" @@ -611,25 +612,28 @@ return std::error_code(); } -void FileManager::GetUniqueIDMapping( - SmallVectorImpl &UIDToFiles) const { - UIDToFiles.clear(); - UIDToFiles.resize(NextFileUID); - - // Map file entries - for (llvm::StringMap, - llvm::BumpPtrAllocator>::const_iterator - FE = SeenFileEntries.begin(), - FEEnd = SeenFileEntries.end(); - FE != FEEnd; ++FE) - if (llvm::ErrorOr Entry = FE->getValue()) { - if (const auto *FE = Entry->V.dyn_cast()) - UIDToFiles[FE->getUID()] = FE; - } +void FileManager::getSeenFileEntries( + SmallVectorImpl &Entries) + const { + Entries.reserve(SeenFileEntries.size()); + + for (const auto &Entry : SeenFileEntries) { + if (auto Value = Entry.getValue()) + // Ignore VFS-mapped entries, they will have a separate on-disk + // file entry. + if (Value->V.dyn_cast()) + Entries.push_back(FileEntryRef(Entry)); + } + + // We want the file entries in deterministic order for + // module serialization. + llvm::sort(Entries, [](OptionalFileEntryRefDegradesToFileEntryPtr &A, + OptionalFileEntryRefDegradesToFileEntryPtr &B) { + if (A->getUID() != B->getUID()) + return A->getUID() < B->getUID(); - // Map virtual file entries - for (const auto &VFE : VirtualFileEntries) - UIDToFiles[VFE->getUID()] = VFE; + return A->getName() < B->getName(); + }); } StringRef FileManager::getCanonicalName(const DirectoryEntry *Dir) { diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -36,6 +36,7 @@ #include "clang/AST/TypeLocVisitor.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/DiagnosticOptions.h" +#include "clang/Basic/FileEntry.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/FileSystemOptions.h" #include "clang/Basic/IdentifierTable.h" @@ -169,17 +170,10 @@ const HeaderSearch &HS = PP.getHeaderSearchInfo(); - SmallVector FilesByUID; - HS.getFileMgr().GetUniqueIDMapping(FilesByUID); - - if (FilesByUID.size() > HS.header_file_size()) - FilesByUID.resize(HS.header_file_size()); - - for (unsigned UID = 0, LastUID = FilesByUID.size(); UID != LastUID; ++UID) { - const FileEntry *File = FilesByUID[UID]; - if (!File) - continue; + SmallVector FileEntries; + HS.getFileMgr().getSeenFileEntries(FileEntries); + for (auto File : FileEntries) { const HeaderFileInfo *HFI = HS.getExistingFileInfo(File, /*WantExternal*/ false); if (!HFI || (HFI->isModuleHeader && !HFI->isCompilingModuleHeader)) @@ -1918,16 +1912,10 @@ } } - SmallVector FilesByUID; - HS.getFileMgr().GetUniqueIDMapping(FilesByUID); + SmallVector FileEntries; + HS.getFileMgr().getSeenFileEntries(FileEntries); - if (FilesByUID.size() > HS.header_file_size()) - FilesByUID.resize(HS.header_file_size()); - - for (unsigned UID = 0, LastUID = FilesByUID.size(); UID != LastUID; ++UID) { - const FileEntry *File = FilesByUID[UID]; - if (!File) - continue; + for (auto File : FileEntries) { // 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