diff --git a/clang-tools-extra/clangd/Headers.h b/clang-tools-extra/clangd/Headers.h --- a/clang-tools-extra/clangd/Headers.h +++ b/clang-tools-extra/clangd/Headers.h @@ -14,6 +14,7 @@ #include "index/Symbol.h" #include "support/Logger.h" #include "support/Path.h" +#include "clang/Basic/FileEntry.h" #include "clang/Basic/TokenKinds.h" #include "clang/Format/Format.h" #include "clang/Lex/HeaderSearch.h" @@ -119,6 +120,12 @@ RealPathNames.emplace_back(); } + void setMainFileEntry(const FileEntry *Entry) { + assert(Entry && Entry->isValid()); + assert(!RealPathNames.empty()); + this->MainFileEntry = Entry; + } + // HeaderID identifies file in the include graph. It corresponds to a // FileEntry rather than a FileID, but stays stable across preamble & main // file builds. @@ -126,8 +133,7 @@ llvm::Optional getID(const FileEntry *Entry, const SourceManager &SM) const; - HeaderID getOrCreateID(const FileEntry *Entry, - const SourceManager &SM); + HeaderID getOrCreateID(const FileEntry *Entry, const SourceManager &SM); StringRef getRealPath(HeaderID ID) const { assert(static_cast(ID) <= RealPathNames.size()); @@ -141,8 +147,8 @@ // All transitive includes (absolute paths), with their minimum include depth. // Root --> 0, #included file --> 1, etc. // Root is the ID of the header being visited first. - // Usually it is getID(SM.getFileEntryForID(SM.getMainFileID()), SM). - llvm::DenseMap includeDepth(HeaderID Root) const; + llvm::DenseMap + includeDepth(HeaderID Root = static_cast(0u)) const; // Maps HeaderID to the ids of the files included from it. llvm::DenseMap> IncludeChildren; @@ -150,16 +156,18 @@ std::vector MainFileIncludes; private: + const FileEntry *MainFileEntry; + std::vector RealPathNames; // In HeaderID order. - // HeaderID maps the FileEntry::UniqueID to the internal representation. + // FileEntry::UniqueID is mapped to the internal representation (HeaderID). // Identifying files in a way that persists from preamble build to subsequent - // builds is surprisingly hard. FileID is unavailable in - // InclusionDirective(), and RealPathName and UniqueID are not preserved in + // builds is surprisingly hard. FileID is unavailable in InclusionDirective(), + // and RealPathName and UniqueID are not preserved in // the preamble. // - // We reserve 0 to the main file and will manually check for that in getID - // and getOrCreateID because llvm::sys::fs::UniqueID is not stable when their - // content of the main file changes. + // We reserve HeaderID(0) for the main file and will manually check for that + // in getID and getOrCreateID because llvm::sys::fs::UniqueID is not stable + // when their content of the main file changes. llvm::DenseMap UIDToIndex; }; @@ -228,7 +236,7 @@ namespace llvm { -// Support Tokens as DenseMap keys. +// Support HeaderIDs as DenseMap keys. template <> struct DenseMapInfo { static inline clang::clangd::IncludeStructure::HeaderID getEmptyKey() { return static_cast( @@ -251,30 +259,6 @@ } }; -// Support Tokens as DenseMap keys. -template <> struct DenseMapInfo { - static inline llvm::sys::fs::UniqueID getEmptyKey() { - auto EmptyKey = DenseMapInfo>::getEmptyKey(); - return {EmptyKey.first, EmptyKey.second}; - } - - static inline llvm::sys::fs::UniqueID getTombstoneKey() { - auto TombstoneKey = - DenseMapInfo>::getTombstoneKey(); - return {TombstoneKey.first, TombstoneKey.second}; - } - - static unsigned getHashValue(const llvm::sys::fs::UniqueID &Tag) { - return hash_value( - std::pair(Tag.getDevice(), Tag.getFile())); - } - - static bool isEqual(const llvm::sys::fs::UniqueID &LHS, - const llvm::sys::fs::UniqueID &RHS) { - return LHS == RHS; - } -}; - } // namespace llvm #endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_HEADERS_H diff --git a/clang-tools-extra/clangd/Headers.cpp b/clang-tools-extra/clangd/Headers.cpp --- a/clang-tools-extra/clangd/Headers.cpp +++ b/clang-tools-extra/clangd/Headers.cpp @@ -152,14 +152,14 @@ std::unique_ptr collectIncludeStructureCallback(const SourceManager &SM, IncludeStructure *Out) { + Out->setMainFileEntry(SM.getFileEntryForID(SM.getMainFileID())); return std::make_unique(SM, Out); } llvm::Optional -IncludeStructure::getID(const FileEntry *Entry, - const SourceManager &SM) const { +IncludeStructure::getID(const FileEntry *Entry, const SourceManager &SM) const { // HeaderID of the main file is always 0; - if (SM.getMainFileID() == SM.translateFile(Entry)) { + if (Entry == MainFileEntry) { return static_cast(0u); } auto It = UIDToIndex.find(Entry->getUniqueID()); @@ -171,10 +171,10 @@ IncludeStructure::HeaderID IncludeStructure::getOrCreateID(const FileEntry *Entry, const SourceManager &SM) { - // Main file's FileID was not known at IncludeStructure creation time. - if (SM.getMainFileID() == SM.translateFile(Entry)) { - UIDToIndex[Entry->getUniqueID()] = - static_cast(0u); + // Main file's FileEntry was not known at IncludeStructure creation time. + if (Entry == MainFileEntry) { + RealPathNames[0] = MainFileEntry->tryGetRealPathName().str(); + return static_cast(0u); } auto R = UIDToIndex.try_emplace( Entry->getUniqueID(), diff --git a/llvm/include/llvm/Support/FileSystem/UniqueID.h b/llvm/include/llvm/Support/FileSystem/UniqueID.h --- a/llvm/include/llvm/Support/FileSystem/UniqueID.h +++ b/llvm/include/llvm/Support/FileSystem/UniqueID.h @@ -14,7 +14,9 @@ #ifndef LLVM_SUPPORT_FILESYSTEM_UNIQUEID_H #define LLVM_SUPPORT_FILESYSTEM_UNIQUEID_H +#include "llvm/ADT/DenseMap.h" #include +#include namespace llvm { namespace sys { @@ -47,6 +49,31 @@ } // end namespace fs } // end namespace sys + +// Support UniqueIDs as DenseMap keys. +template <> struct DenseMapInfo { + static inline llvm::sys::fs::UniqueID getEmptyKey() { + auto EmptyKey = DenseMapInfo>::getEmptyKey(); + return {EmptyKey.first, EmptyKey.second}; + } + + static inline llvm::sys::fs::UniqueID getTombstoneKey() { + auto TombstoneKey = + DenseMapInfo>::getTombstoneKey(); + return {TombstoneKey.first, TombstoneKey.second}; + } + + static unsigned getHashValue(const llvm::sys::fs::UniqueID &Tag) { + return hash_value( + std::pair(Tag.getDevice(), Tag.getFile())); + } + + static bool isEqual(const llvm::sys::fs::UniqueID &LHS, + const llvm::sys::fs::UniqueID &RHS) { + return LHS == RHS; + } +}; + } // end namespace llvm #endif // LLVM_SUPPORT_FILESYSTEM_UNIQUEID_H