1//===--- DeclID.h - ID number for deserialized declarations ----*- C++ -*-===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines DeclID class family to describe the deserialized
10// declarations. The DeclID is widely used in AST via LazyDeclPtr, or calls to
11// `ExternalASTSource::getExternalDecl`. It will be helpful for type safety to
12// require the use of `DeclID` to explicit.
13//
14//===----------------------------------------------------------------------===//
15
16#ifndef LLVM_CLANG_AST_DECLID_H
17#define LLVM_CLANG_AST_DECLID_H
18
19#include "llvm/ADT/DenseMapInfo.h"
20#include "llvm/ADT/Hashing.h"
21#include "llvm/ADT/iterator.h"
22
23namespace clang {
24
25/// Predefined declaration IDs.
26///
27/// These declaration IDs correspond to predefined declarations in the AST
28/// context, such as the NULL declaration ID. Such declarations are never
29/// actually serialized, since they will be built by the AST context when
30/// it is created.
31enum PredefinedDeclIDs {
32 /// The NULL declaration.
33 PREDEF_DECL_NULL_ID,
34
35 /// The translation unit.
36 PREDEF_DECL_TRANSLATION_UNIT_ID,
37
38 /// The Objective-C 'id' type.
39 PREDEF_DECL_OBJC_ID_ID,
40
41 /// The Objective-C 'SEL' type.
42 PREDEF_DECL_OBJC_SEL_ID,
43
44 /// The Objective-C 'Class' type.
45 PREDEF_DECL_OBJC_CLASS_ID,
46
47 /// The Objective-C 'Protocol' type.
48 PREDEF_DECL_OBJC_PROTOCOL_ID,
49
50 /// The signed 128-bit integer type.
51 PREDEF_DECL_INT_128_ID,
52
53 /// The unsigned 128-bit integer type.
54 PREDEF_DECL_UNSIGNED_INT_128_ID,
55
56 /// The internal 'instancetype' typedef.
57 PREDEF_DECL_OBJC_INSTANCETYPE_ID,
58
59 /// The internal '__builtin_va_list' typedef.
60 PREDEF_DECL_BUILTIN_VA_LIST_ID,
61
62 /// The internal '__va_list_tag' struct, if any.
63 PREDEF_DECL_VA_LIST_TAG,
64
65 /// The internal '__builtin_ms_va_list' typedef.
66 PREDEF_DECL_BUILTIN_MS_VA_LIST_ID,
67
68 /// The predeclared '_GUID' struct.
69 PREDEF_DECL_BUILTIN_MS_GUID_ID,
70
71 /// The extern "C" context.
72 PREDEF_DECL_EXTERN_C_CONTEXT_ID,
73
74 /// The internal '__NSConstantString' typedef.
75 PREDEF_DECL_CF_CONSTANT_STRING_ID,
76
77 /// The internal '__NSConstantString' tag type.
78 PREDEF_DECL_CF_CONSTANT_STRING_TAG_ID,
79
80#define BuiltinTemplate(BTName) PREDEF_DECL##BTName##_ID,
81#include "clang/Basic/BuiltinTemplates.inc"
82
83 /// The number of declaration IDs that are predefined.
84 NUM_PREDEF_DECL_IDS
85};
86
87/// GlobalDeclID means DeclID in the current ASTContext and LocalDeclID means
88/// DeclID specific to a certain ModuleFile. Specially, in ASTWriter, the
89/// LocalDeclID to the ModuleFile been writting is equal to the GlobalDeclID.
90/// Outside the serializer, all the DeclID been used should be GlobalDeclID.
91/// We can translate a LocalDeclID to the GlobalDeclID by
92/// `ASTReader::getGlobalDeclID()`.
93
94class DeclIDBase {
95public:
96 /// An ID number that refers to a declaration in an AST file.
97 ///
98 /// The ID numbers of declarations are consecutive (in order of
99 /// discovery), with values below NUM_PREDEF_DECL_IDS being reserved.
100 /// At the start of a chain of precompiled headers, declaration ID 1 is
101 /// used for the translation unit declaration.
102 ///
103 /// DeclID should only be used directly in serialization. All other users
104 /// should use LocalDeclID or GlobalDeclID.
105 using DeclID = uint64_t;
106
107protected:
108 DeclIDBase() : ID(PREDEF_DECL_NULL_ID) {}
109 explicit DeclIDBase(DeclID ID) : ID(ID) {}
110
111public:
112 DeclID getRawValue() const { return ID; }
113
114 explicit operator DeclID() const { return ID; }
115
116 explicit operator PredefinedDeclIDs() const { return (PredefinedDeclIDs)ID; }
117
118 bool isValid() const { return ID != PREDEF_DECL_NULL_ID; }
119
120 bool isInvalid() const { return ID == PREDEF_DECL_NULL_ID; }
121
122 unsigned getModuleFileIndex() const { return ID >> 32; }
123
124 unsigned getLocalDeclIndex() const;
125
126 // The DeclID may be compared with predefined decl ID.
127 friend bool operator==(const DeclIDBase &LHS, const DeclID &RHS) {
128 return LHS.ID == RHS;
129 }
130 friend bool operator!=(const DeclIDBase &LHS, const DeclID &RHS) {
131 return !operator==(LHS, RHS);
132 }
133 friend bool operator<(const DeclIDBase &LHS, const DeclID &RHS) {
134 return LHS.ID < RHS;
135 }
136 friend bool operator<=(const DeclIDBase &LHS, const DeclID &RHS) {
137 return LHS.ID <= RHS;
138 }
139 friend bool operator>(const DeclIDBase &LHS, const DeclID &RHS) {
140 return LHS.ID > RHS;
141 }
142 friend bool operator>=(const DeclIDBase &LHS, const DeclID &RHS) {
143 return LHS.ID >= RHS;
144 }
145
146 friend bool operator==(const DeclIDBase &LHS, const DeclIDBase &RHS) {
147 return LHS.ID == RHS.ID;
148 }
149 friend bool operator!=(const DeclIDBase &LHS, const DeclIDBase &RHS) {
150 return LHS.ID != RHS.ID;
151 }
152
153 // We may sort the decl ID.
154 friend bool operator<(const DeclIDBase &LHS, const DeclIDBase &RHS) {
155 return LHS.ID < RHS.ID;
156 }
157 friend bool operator>(const DeclIDBase &LHS, const DeclIDBase &RHS) {
158 return LHS.ID > RHS.ID;
159 }
160 friend bool operator<=(const DeclIDBase &LHS, const DeclIDBase &RHS) {
161 return LHS.ID <= RHS.ID;
162 }
163 friend bool operator>=(const DeclIDBase &LHS, const DeclIDBase &RHS) {
164 return LHS.ID >= RHS.ID;
165 }
166
167protected:
168 DeclID ID;
169};
170
171class ASTWriter;
172class ASTReader;
173namespace serialization {
174class ModuleFile;
175} // namespace serialization
176
177class LocalDeclID : public DeclIDBase {
178 using Base = DeclIDBase;
179
180 LocalDeclID(PredefinedDeclIDs ID) : Base(ID) {}
181 explicit LocalDeclID(DeclID ID) : Base(ID) {}
182
183 // Every Decl ID is a local decl ID to the module being writing in ASTWriter.
184 friend class ASTWriter;
185 friend class GlobalDeclID;
186 friend struct llvm::DenseMapInfo<clang::LocalDeclID>;
187
188public:
189 LocalDeclID() : Base() {}
190
191 static LocalDeclID get(ASTReader &Reader, serialization::ModuleFile &MF,
192 DeclID ID);
193 static LocalDeclID get(ASTReader &Reader, serialization::ModuleFile &MF,
194 unsigned ModuleFileIndex, unsigned LocalDeclID);
195
196 LocalDeclID &operator++() {
197 ++ID;
198 return *this;
199 }
200
201 LocalDeclID operator++(int) {
202 LocalDeclID Ret = *this;
203 ++(*this);
204 return Ret;
205 }
206};
207
208class GlobalDeclID : public DeclIDBase {
209 using Base = DeclIDBase;
210
211public:
212 GlobalDeclID() : Base() {}
213 explicit GlobalDeclID(DeclID ID) : Base(ID) {}
214
215 explicit GlobalDeclID(unsigned ModuleFileIndex, unsigned LocalID)
216 : Base((DeclID)ModuleFileIndex << 32 | (DeclID)LocalID) {}
217
218 // For DeclIDIterator<GlobalDeclID> to be able to convert a GlobalDeclID
219 // to a LocalDeclID.
220 explicit operator LocalDeclID() const { return LocalDeclID(this->ID); }
221};
222
223/// A helper iterator adaptor to convert the iterators to
224/// `SmallVector<SomeDeclID>` to the iterators to `SmallVector<OtherDeclID>`.
225template <class FromTy, class ToTy>
226class DeclIDIterator
227 : public llvm::iterator_adaptor_base<DeclIDIterator<FromTy, ToTy>,
228 const FromTy *,
229 std::forward_iterator_tag, ToTy> {
230public:
231 DeclIDIterator() : DeclIDIterator::iterator_adaptor_base(nullptr) {}
232
233 DeclIDIterator(const FromTy *ID)
234 : DeclIDIterator::iterator_adaptor_base(ID) {}
235
236 ToTy operator*() const { return ToTy(*this->I); }
237
238 bool operator==(const DeclIDIterator &RHS) const { return this->I == RHS.I; }
239};
240
241} // namespace clang
242
243namespace llvm {
244template <> struct DenseMapInfo<clang::GlobalDeclID> {
245 using GlobalDeclID = clang::GlobalDeclID;
246 using DeclID = GlobalDeclID::DeclID;
247
248 static GlobalDeclID getEmptyKey() {
249 return GlobalDeclID(DenseMapInfo<DeclID>::getEmptyKey());
250 }
251
252 static GlobalDeclID getTombstoneKey() {
253 return GlobalDeclID(DenseMapInfo<DeclID>::getTombstoneKey());
254 }
255
256 static unsigned getHashValue(const GlobalDeclID &Key) {
257 return DenseMapInfo<DeclID>::getHashValue(Val: Key.getRawValue());
258 }
259
260 static bool isEqual(const GlobalDeclID &L, const GlobalDeclID &R) {
261 return L == R;
262 }
263};
264
265template <> struct DenseMapInfo<clang::LocalDeclID> {
266 using LocalDeclID = clang::LocalDeclID;
267 using DeclID = LocalDeclID::DeclID;
268
269 static LocalDeclID getEmptyKey() {
270 return LocalDeclID(DenseMapInfo<DeclID>::getEmptyKey());
271 }
272
273 static LocalDeclID getTombstoneKey() {
274 return LocalDeclID(DenseMapInfo<DeclID>::getTombstoneKey());
275 }
276
277 static unsigned getHashValue(const LocalDeclID &Key) {
278 return DenseMapInfo<DeclID>::getHashValue(Val: Key.getRawValue());
279 }
280
281 static bool isEqual(const LocalDeclID &L, const LocalDeclID &R) {
282 return L == R;
283 }
284};
285
286} // namespace llvm
287
288#endif
289