File indexing completed on 2026-05-10 08:36:31
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H
0015 #define LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H
0016
0017 #include "clang/AST/ASTContext.h"
0018 #include "clang/AST/Decl.h"
0019 #include "clang/AST/DeclBase.h"
0020 #include "clang/AST/DeclCXX.h"
0021 #include "clang/AST/DeclarationName.h"
0022 #include "llvm/ADT/DenseMap.h"
0023 #include "llvm/ADT/PointerIntPair.h"
0024 #include "llvm/ADT/PointerUnion.h"
0025 #include <cassert>
0026
0027 namespace clang {
0028
0029 class DependentDiagnostic;
0030
0031
0032
0033 class StoredDeclsList {
0034 using Decls = DeclListNode::Decls;
0035
0036
0037
0038 using DeclsAndHasExternalTy = llvm::PointerIntPair<Decls, 1, bool>;
0039
0040
0041
0042
0043 DeclsAndHasExternalTy Data;
0044
0045 template <typename Fn> DeclListNode::Decls *erase_if(Fn ShouldErase) {
0046 Decls List = Data.getPointer();
0047
0048 if (!List)
0049 return nullptr;
0050
0051 ASTContext &C = getASTContext();
0052 DeclListNode::Decls NewHead = nullptr;
0053 DeclListNode::Decls *NewLast = nullptr;
0054 DeclListNode::Decls *NewTail = &NewHead;
0055 while (true) {
0056 if (!ShouldErase(*DeclListNode::iterator(List))) {
0057 NewLast = NewTail;
0058 *NewTail = List;
0059 if (auto *Node = List.dyn_cast<DeclListNode*>()) {
0060 NewTail = &Node->Rest;
0061 List = Node->Rest;
0062 } else {
0063 break;
0064 }
0065 } else if (DeclListNode *N = List.dyn_cast<DeclListNode*>()) {
0066 List = N->Rest;
0067 C.DeallocateDeclListNode(N);
0068 } else {
0069
0070
0071
0072 if (NewLast) {
0073 DeclListNode *Node = cast<DeclListNode *>(*NewLast);
0074 *NewLast = Node->D;
0075 C.DeallocateDeclListNode(Node);
0076 }
0077 break;
0078 }
0079 }
0080 Data.setPointer(NewHead);
0081
0082 assert(llvm::none_of(getLookupResult(), ShouldErase) && "Still exists!");
0083
0084 if (!Data.getPointer())
0085
0086 return nullptr;
0087 else if (isa<NamedDecl *>(NewHead))
0088
0089 return (DeclListNode::Decls *)&Data;
0090 else {
0091 assert(NewLast && isa<NamedDecl *>(*NewLast) && "Not the tail?");
0092 return NewLast;
0093 }
0094 }
0095
0096 void erase(NamedDecl *ND) {
0097 erase_if([ND](NamedDecl *D) { return D == ND; });
0098 }
0099
0100 public:
0101 StoredDeclsList() = default;
0102
0103 StoredDeclsList(StoredDeclsList &&RHS) : Data(RHS.Data) {
0104 RHS.Data.setPointer(nullptr);
0105 RHS.Data.setInt(false);
0106 }
0107
0108 void MaybeDeallocList() {
0109 if (isNull())
0110 return;
0111
0112 ASTContext &C = getASTContext();
0113 Decls List = Data.getPointer();
0114 while (DeclListNode *ToDealloc = List.dyn_cast<DeclListNode *>()) {
0115 List = ToDealloc->Rest;
0116 C.DeallocateDeclListNode(ToDealloc);
0117 }
0118 }
0119
0120 ~StoredDeclsList() {
0121 MaybeDeallocList();
0122 }
0123
0124 StoredDeclsList &operator=(StoredDeclsList &&RHS) {
0125 MaybeDeallocList();
0126
0127 Data = RHS.Data;
0128 RHS.Data.setPointer(nullptr);
0129 RHS.Data.setInt(false);
0130 return *this;
0131 }
0132
0133 bool isNull() const { return Data.getPointer().isNull(); }
0134
0135 ASTContext &getASTContext() {
0136 assert(!isNull() && "No ASTContext.");
0137 if (NamedDecl *ND = getAsDecl())
0138 return ND->getASTContext();
0139 return getAsList()->D->getASTContext();
0140 }
0141
0142 DeclsAndHasExternalTy getAsListAndHasExternal() const { return Data; }
0143
0144 NamedDecl *getAsDecl() const {
0145 return getAsListAndHasExternal().getPointer().dyn_cast<NamedDecl *>();
0146 }
0147
0148 DeclListNode *getAsList() const {
0149 return getAsListAndHasExternal().getPointer().dyn_cast<DeclListNode*>();
0150 }
0151
0152 bool hasExternalDecls() const {
0153 return getAsListAndHasExternal().getInt();
0154 }
0155
0156 void setHasExternalDecls() {
0157 Data.setInt(true);
0158 }
0159
0160 void remove(NamedDecl *D) {
0161 assert(!isNull() && "removing from empty list");
0162 erase(D);
0163 }
0164
0165
0166 void removeExternalDecls() {
0167 erase_if([](NamedDecl *ND) { return ND->isFromASTFile(); });
0168
0169
0170 Data.setInt(false);
0171 }
0172
0173 void replaceExternalDecls(ArrayRef<NamedDecl*> Decls) {
0174
0175
0176 DeclListNode::Decls *Tail = erase_if([Decls](NamedDecl *ND) {
0177 if (ND->isFromASTFile())
0178 return true;
0179
0180 for (NamedDecl *D : Decls)
0181
0182
0183 if (D->getModuleOwnershipKind() <= ND->getModuleOwnershipKind() &&
0184 D->declarationReplaces(ND, false))
0185 return true;
0186 return false;
0187 });
0188
0189
0190 Data.setInt(false);
0191
0192 if (Decls.empty())
0193 return;
0194
0195
0196 ASTContext &C = Decls.front()->getASTContext();
0197 DeclListNode::Decls DeclsAsList = Decls.back();
0198 for (size_t I = Decls.size() - 1; I != 0; --I) {
0199 DeclListNode *Node = C.AllocateDeclListNode(Decls[I - 1]);
0200 Node->Rest = DeclsAsList;
0201 DeclsAsList = Node;
0202 }
0203
0204 if (!Data.getPointer()) {
0205 Data.setPointer(DeclsAsList);
0206 return;
0207 }
0208
0209
0210 DeclListNode *Node = C.AllocateDeclListNode(cast<NamedDecl *>(*Tail));
0211 Node->Rest = DeclsAsList;
0212 *Tail = Node;
0213 }
0214
0215
0216 DeclContext::lookup_result getLookupResult() const {
0217 return DeclContext::lookup_result(Data.getPointer());
0218 }
0219
0220
0221
0222 void addOrReplaceDecl(NamedDecl *D) {
0223 const bool IsKnownNewer = true;
0224
0225 if (isNull()) {
0226 Data.setPointer(D);
0227 return;
0228 }
0229
0230
0231 if (NamedDecl *OldD = getAsDecl()) {
0232 if (D->declarationReplaces(OldD, IsKnownNewer)) {
0233 Data.setPointer(D);
0234 return;
0235 }
0236
0237
0238 ASTContext &C = D->getASTContext();
0239 DeclListNode *Node = C.AllocateDeclListNode(OldD);
0240 Node->Rest = D;
0241 Data.setPointer(Node);
0242 return;
0243 }
0244
0245
0246
0247 assert(!llvm::is_contained(getLookupResult(), D) && "Already exists!");
0248
0249 for (DeclListNode *N = getAsList(); ;
0250 N = N->Rest.dyn_cast<DeclListNode *>()) {
0251 if (D->declarationReplaces(N->D, IsKnownNewer)) {
0252 N->D = D;
0253 return;
0254 }
0255 if (auto *ND = N->Rest.dyn_cast<NamedDecl *>()) {
0256 if (D->declarationReplaces(ND, IsKnownNewer)) {
0257 N->Rest = D;
0258 return;
0259 }
0260
0261
0262 ASTContext &C = D->getASTContext();
0263 DeclListNode *Node = C.AllocateDeclListNode(ND);
0264 N->Rest = Node;
0265 Node->Rest = D;
0266 return;
0267 }
0268 }
0269 }
0270
0271
0272 void prependDeclNoReplace(NamedDecl *D) {
0273 if (isNull()) {
0274 Data.setPointer(D);
0275 return;
0276 }
0277
0278 ASTContext &C = D->getASTContext();
0279 DeclListNode *Node = C.AllocateDeclListNode(D);
0280 Node->Rest = Data.getPointer();
0281 Data.setPointer(Node);
0282 }
0283
0284 LLVM_DUMP_METHOD void dump() const {
0285 Decls D = Data.getPointer();
0286 if (!D) {
0287 llvm::errs() << "<null>\n";
0288 return;
0289 }
0290
0291 while (true) {
0292 if (auto *Node = D.dyn_cast<DeclListNode*>()) {
0293 llvm::errs() << '[' << Node->D << "] -> ";
0294 D = Node->Rest;
0295 } else {
0296 llvm::errs() << '[' << cast<NamedDecl *>(D) << "]\n";
0297 return;
0298 }
0299 }
0300 }
0301 };
0302
0303 class StoredDeclsMap
0304 : public llvm::SmallDenseMap<DeclarationName, StoredDeclsList, 4> {
0305 friend class ASTContext;
0306 friend class DeclContext;
0307
0308 llvm::PointerIntPair<StoredDeclsMap*, 1> Previous;
0309 public:
0310 static void DestroyAll(StoredDeclsMap *Map, bool Dependent);
0311 };
0312
0313 class DependentStoredDeclsMap : public StoredDeclsMap {
0314 friend class DeclContext;
0315 friend class DependentDiagnostic;
0316
0317 DependentDiagnostic *FirstDiagnostic = nullptr;
0318 public:
0319 DependentStoredDeclsMap() = default;
0320 };
0321
0322 }
0323
0324 #endif