1 //===- DeclContextInternals.h - DeclContext Representation ------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines the data structures used in the implementation
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H
16 #define LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H
18 #include "clang/AST/Decl.h"
19 #include "clang/AST/DeclBase.h"
20 #include "clang/AST/DeclCXX.h"
21 #include "clang/AST/DeclarationName.h"
22 #include "llvm/ADT/DenseMap.h"
23 #include "llvm/ADT/PointerIntPair.h"
24 #include "llvm/ADT/PointerUnion.h"
25 #include "llvm/ADT/SmallVector.h"
31 class DependentDiagnostic;
33 /// An array of decls optimized for the common case of only containing
35 struct StoredDeclsList {
36 /// When in vector form, this is what the Data pointer points to.
37 using DeclsTy = SmallVector<NamedDecl *, 4>;
39 /// A collection of declarations, with a flag to indicate if we have
40 /// further external declarations.
41 using DeclsAndHasExternalTy = llvm::PointerIntPair<DeclsTy *, 1, bool>;
43 /// The stored data, which will be either a pointer to a NamedDecl,
44 /// or a pointer to a vector with a flag to indicate if there are further
45 /// external declarations.
46 llvm::PointerUnion<NamedDecl *, DeclsAndHasExternalTy> Data;
49 StoredDeclsList() = default;
51 StoredDeclsList(StoredDeclsList &&RHS) : Data(RHS.Data) {
52 RHS.Data = (NamedDecl *)nullptr;
56 // If this is a vector-form, free the vector.
57 if (DeclsTy *Vector = getAsVector())
61 StoredDeclsList &operator=(StoredDeclsList &&RHS) {
62 if (DeclsTy *Vector = getAsVector())
65 RHS.Data = (NamedDecl *)nullptr;
69 bool isNull() const { return Data.isNull(); }
71 NamedDecl *getAsDecl() const {
72 return Data.dyn_cast<NamedDecl *>();
75 DeclsAndHasExternalTy getAsVectorAndHasExternal() const {
76 return Data.dyn_cast<DeclsAndHasExternalTy>();
79 DeclsTy *getAsVector() const {
80 return getAsVectorAndHasExternal().getPointer();
83 bool hasExternalDecls() const {
84 return getAsVectorAndHasExternal().getInt();
87 void setHasExternalDecls() {
88 if (DeclsTy *Vec = getAsVector())
89 Data = DeclsAndHasExternalTy(Vec, true);
91 DeclsTy *VT = new DeclsTy();
92 if (NamedDecl *OldD = getAsDecl())
94 Data = DeclsAndHasExternalTy(VT, true);
98 void setOnlyValue(NamedDecl *ND) {
99 assert(!getAsVector() && "Not inline");
101 // Make sure that Data is a plain NamedDecl* so we can use its address
102 // at getLookupResult.
103 assert(*(NamedDecl **)&Data == ND &&
104 "PointerUnion mangles the NamedDecl pointer!");
107 void remove(NamedDecl *D) {
108 assert(!isNull() && "removing from empty list");
109 if (NamedDecl *Singleton = getAsDecl()) {
110 assert(Singleton == D && "list is different singleton");
112 Data = (NamedDecl *)nullptr;
116 DeclsTy &Vec = *getAsVector();
117 DeclsTy::iterator I = std::find(Vec.begin(), Vec.end(), D);
118 assert(I != Vec.end() && "list does not contain decl");
121 assert(std::find(Vec.begin(), Vec.end(), D)
122 == Vec.end() && "list still contains decl");
125 /// Remove any declarations which were imported from an external
127 void removeExternalDecls() {
130 } else if (NamedDecl *Singleton = getAsDecl()) {
131 if (Singleton->isFromASTFile())
132 *this = StoredDeclsList();
134 DeclsTy &Vec = *getAsVector();
135 Vec.erase(std::remove_if(Vec.begin(), Vec.end(),
136 [](Decl *D) { return D->isFromASTFile(); }),
138 // Don't have any external decls any more.
139 Data = DeclsAndHasExternalTy(&Vec, false);
143 /// getLookupResult - Return an array of all the decls that this list
145 DeclContext::lookup_result getLookupResult() {
147 return DeclContext::lookup_result();
149 // If we have a single NamedDecl, return it.
150 if (NamedDecl *ND = getAsDecl()) {
151 assert(!isNull() && "Empty list isn't allowed");
153 // Data is a raw pointer to a NamedDecl*, return it.
154 return DeclContext::lookup_result(ND);
157 assert(getAsVector() && "Must have a vector at this point");
158 DeclsTy &Vector = *getAsVector();
160 // Otherwise, we have a range result.
161 return DeclContext::lookup_result(Vector);
164 /// HandleRedeclaration - If this is a redeclaration of an existing decl,
165 /// replace the old one with D and return true. Otherwise return false.
166 bool HandleRedeclaration(NamedDecl *D, bool IsKnownNewer) {
167 // Most decls only have one entry in their list, special case it.
168 if (NamedDecl *OldD = getAsDecl()) {
169 if (!D->declarationReplaces(OldD, IsKnownNewer))
175 // Determine if this declaration is actually a redeclaration.
176 DeclsTy &Vec = *getAsVector();
177 for (DeclsTy::iterator OD = Vec.begin(), ODEnd = Vec.end();
179 NamedDecl *OldD = *OD;
180 if (D->declarationReplaces(OldD, IsKnownNewer)) {
189 /// AddSubsequentDecl - This is called on the second and later decl when it is
190 /// not a redeclaration to merge it into the appropriate place in our list.
191 void AddSubsequentDecl(NamedDecl *D) {
192 assert(!isNull() && "don't AddSubsequentDecl when we have no decls");
194 // If this is the second decl added to the list, convert this to vector
196 if (NamedDecl *OldD = getAsDecl()) {
197 DeclsTy *VT = new DeclsTy();
199 Data = DeclsAndHasExternalTy(VT, false);
202 DeclsTy &Vec = *getAsVector();
204 // Using directives end up in a special entry which contains only
205 // other using directives, so all this logic is wasted for them.
206 // But avoiding the logic wastes time in the far-more-common case
207 // that we're *not* adding a new using directive.
209 // Tag declarations always go at the end of the list so that an
210 // iterator which points at the first tag will start a span of
211 // decls that only contains tags.
212 if (D->hasTagIdentifierNamespace())
215 // Resolved using declarations go at the front of the list so that
216 // they won't show up in other lookup results. Unresolved using
217 // declarations (which are always in IDNS_Using | IDNS_Ordinary)
218 // follow that so that the using declarations will be contiguous.
219 else if (D->getIdentifierNamespace() & Decl::IDNS_Using) {
220 DeclsTy::iterator I = Vec.begin();
221 if (D->getIdentifierNamespace() != Decl::IDNS_Using) {
222 while (I != Vec.end() &&
223 (*I)->getIdentifierNamespace() == Decl::IDNS_Using)
228 // All other declarations go at the end of the list, but before any
229 // tag declarations. But we can be clever about tag declarations
230 // because there can only ever be one in a scope.
231 } else if (!Vec.empty() && Vec.back()->hasTagIdentifierNamespace()) {
232 NamedDecl *TagD = Vec.back();
241 : public llvm::SmallDenseMap<DeclarationName, StoredDeclsList, 4> {
243 static void DestroyAll(StoredDeclsMap *Map, bool Dependent);
246 friend class ASTContext; // walks the chain deleting these
247 friend class DeclContext;
249 llvm::PointerIntPair<StoredDeclsMap*, 1> Previous;
252 class DependentStoredDeclsMap : public StoredDeclsMap {
254 DependentStoredDeclsMap() = default;
257 friend class DeclContext; // iterates over diagnostics
258 friend class DependentDiagnostic;
260 DependentDiagnostic *FirstDiagnostic = nullptr;
265 #endif // LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H