xref: /llvm-project/clang/include/clang/AST/DeclID.h (revision 9a361684c80a779c28d8315503a423e05f0cc061)
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 
23 namespace 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.
31 enum 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 '__make_integer_seq' template.
75   PREDEF_DECL_MAKE_INTEGER_SEQ_ID,
76 
77   /// The internal '__NSConstantString' typedef.
78   PREDEF_DECL_CF_CONSTANT_STRING_ID,
79 
80   /// The internal '__NSConstantString' tag type.
81   PREDEF_DECL_CF_CONSTANT_STRING_TAG_ID,
82 
83   /// The internal '__type_pack_element' template.
84   PREDEF_DECL_TYPE_PACK_ELEMENT_ID,
85 
86   /// The internal '__builtin_common_type' template.
87   PREDEF_DECL_COMMON_TYPE_ID,
88 
89   /// The number of declaration IDs that are predefined.
90   NUM_PREDEF_DECL_IDS
91 };
92 
93 /// GlobalDeclID means DeclID in the current ASTContext and LocalDeclID means
94 /// DeclID specific to a certain ModuleFile. Specially, in ASTWriter, the
95 /// LocalDeclID to the ModuleFile been writting is equal to the GlobalDeclID.
96 /// Outside the serializer, all the DeclID been used should be GlobalDeclID.
97 /// We can translate a LocalDeclID to the GlobalDeclID by
98 /// `ASTReader::getGlobalDeclID()`.
99 
100 class DeclIDBase {
101 public:
102   /// An ID number that refers to a declaration in an AST file.
103   ///
104   /// The ID numbers of declarations are consecutive (in order of
105   /// discovery), with values below NUM_PREDEF_DECL_IDS being reserved.
106   /// At the start of a chain of precompiled headers, declaration ID 1 is
107   /// used for the translation unit declaration.
108   ///
109   /// DeclID should only be used directly in serialization. All other users
110   /// should use LocalDeclID or GlobalDeclID.
111   using DeclID = uint64_t;
112 
113 protected:
114   DeclIDBase() : ID(PREDEF_DECL_NULL_ID) {}
115   explicit DeclIDBase(DeclID ID) : ID(ID) {}
116 
117 public:
118   DeclID getRawValue() const { return ID; }
119 
120   explicit operator DeclID() const { return ID; }
121 
122   explicit operator PredefinedDeclIDs() const { return (PredefinedDeclIDs)ID; }
123 
124   bool isValid() const { return ID != PREDEF_DECL_NULL_ID; }
125 
126   bool isInvalid() const { return ID == PREDEF_DECL_NULL_ID; }
127 
128   unsigned getModuleFileIndex() const { return ID >> 32; }
129 
130   unsigned getLocalDeclIndex() const;
131 
132   // The DeclID may be compared with predefined decl ID.
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 !operator==(LHS, 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   friend bool operator>(const DeclIDBase &LHS, const DeclID &RHS) {
146     return LHS.ID > RHS;
147   }
148   friend bool operator>=(const DeclIDBase &LHS, const DeclID &RHS) {
149     return LHS.ID >= RHS;
150   }
151 
152   friend bool operator==(const DeclIDBase &LHS, const DeclIDBase &RHS) {
153     return LHS.ID == RHS.ID;
154   }
155   friend bool operator!=(const DeclIDBase &LHS, const DeclIDBase &RHS) {
156     return LHS.ID != RHS.ID;
157   }
158 
159   // We may sort the decl ID.
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   friend bool operator<=(const DeclIDBase &LHS, const DeclIDBase &RHS) {
167     return LHS.ID <= RHS.ID;
168   }
169   friend bool operator>=(const DeclIDBase &LHS, const DeclIDBase &RHS) {
170     return LHS.ID >= RHS.ID;
171   }
172 
173 protected:
174   DeclID ID;
175 };
176 
177 class ASTWriter;
178 class ASTReader;
179 namespace serialization {
180 class ModuleFile;
181 } // namespace serialization
182 
183 class LocalDeclID : public DeclIDBase {
184   using Base = DeclIDBase;
185 
186   LocalDeclID(PredefinedDeclIDs ID) : Base(ID) {}
187   explicit LocalDeclID(DeclID ID) : Base(ID) {}
188 
189   // Every Decl ID is a local decl ID to the module being writing in ASTWriter.
190   friend class ASTWriter;
191   friend class GlobalDeclID;
192   friend struct llvm::DenseMapInfo<clang::LocalDeclID>;
193 
194 public:
195   LocalDeclID() : Base() {}
196 
197   static LocalDeclID get(ASTReader &Reader, serialization::ModuleFile &MF,
198                          DeclID ID);
199   static LocalDeclID get(ASTReader &Reader, serialization::ModuleFile &MF,
200                          unsigned ModuleFileIndex, unsigned LocalDeclID);
201 
202   LocalDeclID &operator++() {
203     ++ID;
204     return *this;
205   }
206 
207   LocalDeclID operator++(int) {
208     LocalDeclID Ret = *this;
209     ++(*this);
210     return Ret;
211   }
212 };
213 
214 class GlobalDeclID : public DeclIDBase {
215   using Base = DeclIDBase;
216 
217 public:
218   GlobalDeclID() : Base() {}
219   explicit GlobalDeclID(DeclID ID) : Base(ID) {}
220 
221   explicit GlobalDeclID(unsigned ModuleFileIndex, unsigned LocalID)
222       : Base((DeclID)ModuleFileIndex << 32 | (DeclID)LocalID) {}
223 
224   // For DeclIDIterator<GlobalDeclID> to be able to convert a GlobalDeclID
225   // to a LocalDeclID.
226   explicit operator LocalDeclID() const { return LocalDeclID(this->ID); }
227 };
228 
229 /// A helper iterator adaptor to convert the iterators to
230 /// `SmallVector<SomeDeclID>` to the iterators to `SmallVector<OtherDeclID>`.
231 template <class FromTy, class ToTy>
232 class DeclIDIterator
233     : public llvm::iterator_adaptor_base<DeclIDIterator<FromTy, ToTy>,
234                                          const FromTy *,
235                                          std::forward_iterator_tag, ToTy> {
236 public:
237   DeclIDIterator() : DeclIDIterator::iterator_adaptor_base(nullptr) {}
238 
239   DeclIDIterator(const FromTy *ID)
240       : DeclIDIterator::iterator_adaptor_base(ID) {}
241 
242   ToTy operator*() const { return ToTy(*this->I); }
243 
244   bool operator==(const DeclIDIterator &RHS) const { return this->I == RHS.I; }
245 };
246 
247 } // namespace clang
248 
249 namespace llvm {
250 template <> struct DenseMapInfo<clang::GlobalDeclID> {
251   using GlobalDeclID = clang::GlobalDeclID;
252   using DeclID = GlobalDeclID::DeclID;
253 
254   static GlobalDeclID getEmptyKey() {
255     return GlobalDeclID(DenseMapInfo<DeclID>::getEmptyKey());
256   }
257 
258   static GlobalDeclID getTombstoneKey() {
259     return GlobalDeclID(DenseMapInfo<DeclID>::getTombstoneKey());
260   }
261 
262   static unsigned getHashValue(const GlobalDeclID &Key) {
263     return DenseMapInfo<DeclID>::getHashValue(Key.getRawValue());
264   }
265 
266   static bool isEqual(const GlobalDeclID &L, const GlobalDeclID &R) {
267     return L == R;
268   }
269 };
270 
271 template <> struct DenseMapInfo<clang::LocalDeclID> {
272   using LocalDeclID = clang::LocalDeclID;
273   using DeclID = LocalDeclID::DeclID;
274 
275   static LocalDeclID getEmptyKey() {
276     return LocalDeclID(DenseMapInfo<DeclID>::getEmptyKey());
277   }
278 
279   static LocalDeclID getTombstoneKey() {
280     return LocalDeclID(DenseMapInfo<DeclID>::getTombstoneKey());
281   }
282 
283   static unsigned getHashValue(const LocalDeclID &Key) {
284     return DenseMapInfo<DeclID>::getHashValue(Key.getRawValue());
285   }
286 
287   static bool isEqual(const LocalDeclID &L, const LocalDeclID &R) {
288     return L == R;
289   }
290 };
291 
292 } // namespace llvm
293 
294 #endif
295