File indexing completed on 2026-05-10 08:36:41
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef LLVM_CLANG_AST_REDECLARABLE_H
0014 #define LLVM_CLANG_AST_REDECLARABLE_H
0015
0016 #include "clang/AST/ExternalASTSource.h"
0017 #include "llvm/ADT/DenseMapInfo.h"
0018 #include "llvm/ADT/PointerUnion.h"
0019 #include "llvm/ADT/iterator_range.h"
0020 #include "llvm/Support/Casting.h"
0021 #include <cassert>
0022 #include <cstddef>
0023 #include <iterator>
0024
0025 namespace clang {
0026
0027 class ASTContext;
0028 class Decl;
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083 template<typename decl_type>
0084 class Redeclarable {
0085 protected:
0086 class DeclLink {
0087
0088
0089 using KnownLatest =
0090 LazyGenerationalUpdatePtr<const Decl *, Decl *,
0091 &ExternalASTSource::CompleteRedeclChain>;
0092
0093
0094
0095
0096 using UninitializedLatest = const void *;
0097
0098 using Previous = Decl *;
0099
0100
0101
0102
0103 using NotKnownLatest = llvm::PointerUnion<Previous, UninitializedLatest>;
0104
0105 mutable llvm::PointerUnion<NotKnownLatest, KnownLatest> Link;
0106
0107 public:
0108 enum PreviousTag { PreviousLink };
0109 enum LatestTag { LatestLink };
0110
0111 DeclLink(LatestTag, const ASTContext &Ctx)
0112 : Link(NotKnownLatest(reinterpret_cast<UninitializedLatest>(&Ctx))) {}
0113 DeclLink(PreviousTag, decl_type *D) : Link(NotKnownLatest(Previous(D))) {}
0114
0115 bool isFirst() const {
0116 return isa<KnownLatest>(Link) ||
0117
0118
0119 isa<UninitializedLatest>(cast<NotKnownLatest>(Link));
0120 }
0121
0122 decl_type *getPrevious(const decl_type *D) const {
0123 if (NotKnownLatest NKL = dyn_cast<NotKnownLatest>(Link)) {
0124 if (auto *Prev = dyn_cast<Previous>(NKL))
0125 return static_cast<decl_type *>(Prev);
0126
0127
0128 Link = KnownLatest(*reinterpret_cast<const ASTContext *>(
0129 cast<UninitializedLatest>(NKL)),
0130 const_cast<decl_type *>(D));
0131 }
0132
0133 return static_cast<decl_type *>(cast<KnownLatest>(Link).get(D));
0134 }
0135
0136 void setPrevious(decl_type *D) {
0137 assert(!isFirst() && "decl became non-canonical unexpectedly");
0138 Link = Previous(D);
0139 }
0140
0141 void setLatest(decl_type *D) {
0142 assert(isFirst() && "decl became canonical unexpectedly");
0143 if (NotKnownLatest NKL = dyn_cast<NotKnownLatest>(Link)) {
0144 Link = KnownLatest(*reinterpret_cast<const ASTContext *>(
0145 cast<UninitializedLatest>(NKL)),
0146 D);
0147 } else {
0148 auto Latest = cast<KnownLatest>(Link);
0149 Latest.set(D);
0150 Link = Latest;
0151 }
0152 }
0153
0154 void markIncomplete() { cast<KnownLatest>(Link).markIncomplete(); }
0155
0156 Decl *getLatestNotUpdated() const {
0157 assert(isFirst() && "expected a canonical decl");
0158 if (isa<NotKnownLatest>(Link))
0159 return nullptr;
0160 return cast<KnownLatest>(Link).getNotUpdated();
0161 }
0162 };
0163
0164 static DeclLink PreviousDeclLink(decl_type *D) {
0165 return DeclLink(DeclLink::PreviousLink, D);
0166 }
0167
0168 static DeclLink LatestDeclLink(const ASTContext &Ctx) {
0169 return DeclLink(DeclLink::LatestLink, Ctx);
0170 }
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183 DeclLink RedeclLink;
0184
0185 decl_type *First;
0186
0187 decl_type *getNextRedeclaration() const {
0188 return RedeclLink.getPrevious(static_cast<const decl_type *>(this));
0189 }
0190
0191 public:
0192 friend class ASTDeclMerger;
0193 friend class ASTDeclReader;
0194 friend class ASTDeclWriter;
0195 friend class IncrementalParser;
0196
0197 Redeclarable(const ASTContext &Ctx)
0198 : RedeclLink(LatestDeclLink(Ctx)),
0199 First(static_cast<decl_type *>(this)) {}
0200
0201
0202
0203 decl_type *getPreviousDecl() {
0204 if (!RedeclLink.isFirst())
0205 return getNextRedeclaration();
0206 return nullptr;
0207 }
0208 const decl_type *getPreviousDecl() const {
0209 return const_cast<decl_type *>(
0210 static_cast<const decl_type*>(this))->getPreviousDecl();
0211 }
0212
0213
0214
0215 decl_type *getFirstDecl() { return First; }
0216
0217
0218
0219 const decl_type *getFirstDecl() const { return First; }
0220
0221
0222 bool isFirstDecl() const { return RedeclLink.isFirst(); }
0223
0224
0225 decl_type *getMostRecentDecl() {
0226 return getFirstDecl()->getNextRedeclaration();
0227 }
0228
0229
0230 const decl_type *getMostRecentDecl() const {
0231 return getFirstDecl()->getNextRedeclaration();
0232 }
0233
0234
0235
0236 void setPreviousDecl(decl_type *PrevDecl);
0237
0238
0239 class redecl_iterator {
0240
0241 decl_type *Current = nullptr;
0242 decl_type *Starter = nullptr;
0243 bool PassedFirst = false;
0244
0245 public:
0246 using value_type = decl_type *;
0247 using reference = decl_type *;
0248 using pointer = decl_type *;
0249 using iterator_category = std::forward_iterator_tag;
0250 using difference_type = std::ptrdiff_t;
0251
0252 redecl_iterator() = default;
0253 explicit redecl_iterator(decl_type *C) : Current(C), Starter(C) {}
0254
0255 reference operator*() const { return Current; }
0256 pointer operator->() const { return Current; }
0257
0258 redecl_iterator& operator++() {
0259 assert(Current && "Advancing while iterator has reached end");
0260
0261
0262 if (Current->isFirstDecl()) {
0263 if (PassedFirst) {
0264 assert(0 && "Passed first decl twice, invalid redecl chain!");
0265 Current = nullptr;
0266 return *this;
0267 }
0268 PassedFirst = true;
0269 }
0270
0271
0272 decl_type *Next = Current->getNextRedeclaration();
0273 Current = (Next != Starter) ? Next : nullptr;
0274 return *this;
0275 }
0276
0277 redecl_iterator operator++(int) {
0278 redecl_iterator tmp(*this);
0279 ++(*this);
0280 return tmp;
0281 }
0282
0283 friend bool operator==(const redecl_iterator &x, const redecl_iterator &y) {
0284 return x.Current == y.Current;
0285 }
0286 friend bool operator!=(const redecl_iterator &x, const redecl_iterator &y) {
0287 return x.Current != y.Current;
0288 }
0289 };
0290
0291 using redecl_range = llvm::iterator_range<redecl_iterator>;
0292
0293
0294
0295 redecl_range redecls() const {
0296 return redecl_range(redecl_iterator(const_cast<decl_type *>(
0297 static_cast<const decl_type *>(this))),
0298 redecl_iterator());
0299 }
0300
0301 redecl_iterator redecls_begin() const { return redecls().begin(); }
0302 redecl_iterator redecls_end() const { return redecls().end(); }
0303 };
0304
0305
0306
0307 Decl *getPrimaryMergedDecl(Decl *D);
0308
0309
0310
0311
0312 template<typename decl_type>
0313 class Mergeable {
0314 public:
0315 Mergeable() = default;
0316
0317
0318
0319 decl_type *getFirstDecl() {
0320 auto *D = static_cast<decl_type *>(this);
0321 if (!D->isFromASTFile())
0322 return D;
0323 return cast<decl_type>(getPrimaryMergedDecl(const_cast<decl_type*>(D)));
0324 }
0325
0326
0327
0328 const decl_type *getFirstDecl() const {
0329 const auto *D = static_cast<const decl_type *>(this);
0330 if (!D->isFromASTFile())
0331 return D;
0332 return cast<decl_type>(getPrimaryMergedDecl(const_cast<decl_type*>(D)));
0333 }
0334
0335
0336 bool isFirstDecl() const { return getFirstDecl() == this; }
0337 };
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348 template <typename decl_type> class CanonicalDeclPtr {
0349 public:
0350 CanonicalDeclPtr() = default;
0351 CanonicalDeclPtr(decl_type *Ptr)
0352 : Ptr(Ptr ? Ptr->getCanonicalDecl() : nullptr) {}
0353 CanonicalDeclPtr(const CanonicalDeclPtr &) = default;
0354 CanonicalDeclPtr &operator=(const CanonicalDeclPtr &) = default;
0355
0356 operator decl_type *() { return Ptr; }
0357 operator const decl_type *() const { return Ptr; }
0358
0359 decl_type *operator->() { return Ptr; }
0360 const decl_type *operator->() const { return Ptr; }
0361
0362 decl_type &operator*() { return *Ptr; }
0363 const decl_type &operator*() const { return *Ptr; }
0364
0365 friend bool operator==(CanonicalDeclPtr LHS, CanonicalDeclPtr RHS) {
0366 return LHS.Ptr == RHS.Ptr;
0367 }
0368 friend bool operator!=(CanonicalDeclPtr LHS, CanonicalDeclPtr RHS) {
0369 return LHS.Ptr != RHS.Ptr;
0370 }
0371
0372 private:
0373 friend struct llvm::DenseMapInfo<CanonicalDeclPtr<decl_type>>;
0374 friend struct llvm::PointerLikeTypeTraits<CanonicalDeclPtr<decl_type>>;
0375
0376 decl_type *Ptr = nullptr;
0377 };
0378
0379 }
0380
0381 namespace llvm {
0382
0383 template <typename decl_type>
0384 struct DenseMapInfo<clang::CanonicalDeclPtr<decl_type>> {
0385 using CanonicalDeclPtr = clang::CanonicalDeclPtr<decl_type>;
0386 using BaseInfo = DenseMapInfo<decl_type *>;
0387
0388 static CanonicalDeclPtr getEmptyKey() {
0389
0390
0391 CanonicalDeclPtr P;
0392 P.Ptr = BaseInfo::getEmptyKey();
0393 return P;
0394 }
0395
0396 static CanonicalDeclPtr getTombstoneKey() {
0397 CanonicalDeclPtr P;
0398 P.Ptr = BaseInfo::getTombstoneKey();
0399 return P;
0400 }
0401
0402 static unsigned getHashValue(const CanonicalDeclPtr &P) {
0403 return BaseInfo::getHashValue(P);
0404 }
0405
0406 static bool isEqual(const CanonicalDeclPtr &LHS,
0407 const CanonicalDeclPtr &RHS) {
0408 return BaseInfo::isEqual(LHS, RHS);
0409 }
0410 };
0411
0412 template <typename decl_type>
0413 struct PointerLikeTypeTraits<clang::CanonicalDeclPtr<decl_type>> {
0414 static inline void *getAsVoidPointer(clang::CanonicalDeclPtr<decl_type> P) {
0415 return P.Ptr;
0416 }
0417 static inline clang::CanonicalDeclPtr<decl_type> getFromVoidPointer(void *P) {
0418 clang::CanonicalDeclPtr<decl_type> C;
0419 C.Ptr = PointerLikeTypeTraits<decl_type *>::getFromVoidPtr(P);
0420 return C;
0421 }
0422 static constexpr int NumLowBitsAvailable =
0423 PointerLikeTypeTraits<decl_type *>::NumLowBitsAvailable;
0424 };
0425
0426 }
0427
0428 #endif