1 //===--- SymbolID.h ----------------------------------------------*- C++-*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_SYMBOLID_H
10 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_SYMBOLID_H
12 #include "llvm/ADT/Hashing.h"
13 #include "llvm/ADT/StringRef.h"
14 #include "llvm/Support/Error.h"
15 #include "llvm/Support/raw_ostream.h"
24 // The class identifies a particular C++ symbol (class, function, method, etc).
26 // As USRs (Unified Symbol Resolution) could be large, especially for functions
27 // with long type arguments, SymbolID is using truncated SHA1(USR) values to
28 // guarantee the uniqueness of symbols while using a relatively small amount of
29 // memory (vs storing USRs directly).
31 // SymbolID can be used as key in the symbol indexes to lookup the symbol.
35 explicit SymbolID(llvm::StringRef USR
);
37 bool operator==(const SymbolID
&Sym
) const {
38 return HashValue
== Sym
.HashValue
;
40 bool operator!=(const SymbolID
&Sym
) const { return !(*this == Sym
); }
41 bool operator<(const SymbolID
&Sym
) const {
42 // Avoid lexicographic compare which requires swapping bytes or even memcmp!
43 return llvm::bit_cast
<IntTy
>(HashValue
) <
44 llvm::bit_cast
<IntTy
>(Sym
.HashValue
);
47 // The stored hash is truncated to RawSize bytes.
48 // This trades off memory against the number of symbols we can handle.
49 constexpr static size_t RawSize
= 8;
50 llvm::StringRef
raw() const;
51 static SymbolID
fromRaw(llvm::StringRef
);
53 // Returns a hex encoded string.
54 std::string
str() const;
55 static llvm::Expected
<SymbolID
> fromStr(llvm::StringRef
);
57 bool isNull() const { return *this == SymbolID(); }
58 explicit operator bool() const { return !isNull(); }
61 using IntTy
= uint64_t;
62 static_assert(sizeof(IntTy
) == RawSize
);
63 std::array
<uint8_t, RawSize
> HashValue
{};
66 inline llvm::hash_code
hash_value(const SymbolID
&ID
) {
67 // We already have a good hash, just return the first bytes.
68 static_assert(sizeof(size_t) <= SymbolID::RawSize
,
69 "size_t longer than SHA1!");
71 memcpy(&Result
, ID
.raw().data(), sizeof(size_t));
72 return llvm::hash_code(Result
);
75 // Write SymbolID into the given stream. SymbolID is encoded as ID.str().
76 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&OS
, const SymbolID
&ID
);
82 // Support SymbolIDs as DenseMap keys.
83 template <> struct DenseMapInfo
<clang::clangd::SymbolID
> {
84 static inline clang::clangd::SymbolID
getEmptyKey() {
85 static clang::clangd::SymbolID
EmptyKey("EMPTYKEY");
88 static inline clang::clangd::SymbolID
getTombstoneKey() {
89 static clang::clangd::SymbolID
TombstoneKey("TOMBSTONEKEY");
92 static unsigned getHashValue(const clang::clangd::SymbolID
&Sym
) {
93 return hash_value(Sym
);
95 static bool isEqual(const clang::clangd::SymbolID
&LHS
,
96 const clang::clangd::SymbolID
&RHS
) {
102 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_SYMBOLID_H