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