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 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H
15 #define LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H
17 #include "clang/AST/Decl.h"
18 #include "clang/AST/DeclCXX.h"
19 #include "clang/AST/DeclarationName.h"
20 #include "llvm/ADT/DenseMap.h"
21 #include "llvm/ADT/PointerIntPair.h"
22 #include "llvm/ADT/PointerUnion.h"
23 #include "llvm/ADT/SmallVector.h"
28 class DependentDiagnostic;
30 /// \brief An array of decls optimized for the common case of only containing
32 struct StoredDeclsList {
34 /// \brief When in vector form, this is what the Data pointer points to.
35 typedef SmallVector<NamedDecl *, 4> DeclsTy;
37 /// \brief A collection of declarations, with a flag to indicate if we have
38 /// further external declarations.
39 typedef llvm::PointerIntPair<DeclsTy *, 1, bool> DeclsAndHasExternalTy;
41 /// \brief The stored data, which will be either a pointer to a NamedDecl,
42 /// or a pointer to a vector with a flag to indicate if there are further
43 /// external declarations.
44 llvm::PointerUnion<NamedDecl*, DeclsAndHasExternalTy> Data;
49 StoredDeclsList(const StoredDeclsList &RHS) : Data(RHS.Data) {
50 if (DeclsTy *RHSVec = RHS.getAsVector())
51 Data = DeclsAndHasExternalTy(new DeclsTy(*RHSVec),
52 RHS.hasExternalDecls());
56 // If this is a vector-form, free the vector.
57 if (DeclsTy *Vector = getAsVector())
61 StoredDeclsList &operator=(const StoredDeclsList &RHS) {
62 if (DeclsTy *Vector = getAsVector())
65 if (DeclsTy *RHSVec = RHS.getAsVector())
66 Data = DeclsAndHasExternalTy(new DeclsTy(*RHSVec), hasExternalDecls());
70 bool isNull() const { return Data.isNull(); }
72 NamedDecl *getAsDecl() const {
73 return Data.dyn_cast<NamedDecl *>();
76 DeclsAndHasExternalTy getAsVectorAndHasExternal() const {
77 return Data.dyn_cast<DeclsAndHasExternalTy>();
80 DeclsTy *getAsVector() const {
81 return getAsVectorAndHasExternal().getPointer();
84 bool hasExternalDecls() const {
85 return getAsVectorAndHasExternal().getInt();
88 void setHasExternalDecls() {
89 if (DeclsTy *Vec = getAsVector())
90 Data = DeclsAndHasExternalTy(Vec, true);
92 DeclsTy *VT = new DeclsTy();
93 if (NamedDecl *OldD = getAsDecl())
95 Data = DeclsAndHasExternalTy(VT, true);
99 void setOnlyValue(NamedDecl *ND) {
100 assert(!getAsVector() && "Not inline");
102 // Make sure that Data is a plain NamedDecl* so we can use its address
103 // at getLookupResult.
104 assert(*(NamedDecl **)&Data == ND &&
105 "PointerUnion mangles the NamedDecl pointer!");
108 void remove(NamedDecl *D) {
109 assert(!isNull() && "removing from empty list");
110 if (NamedDecl *Singleton = getAsDecl()) {
111 assert(Singleton == D && "list is different singleton");
113 Data = (NamedDecl *)0;
117 DeclsTy &Vec = *getAsVector();
118 DeclsTy::iterator I = std::find(Vec.begin(), Vec.end(), D);
119 assert(I != Vec.end() && "list does not contain decl");
122 assert(std::find(Vec.begin(), Vec.end(), D)
123 == Vec.end() && "list still contains decl");
126 /// \brief Remove any declarations which were imported from an external
128 void removeExternalDecls() {
131 } else if (NamedDecl *Singleton = getAsDecl()) {
132 if (Singleton->isFromASTFile())
133 *this = StoredDeclsList();
135 DeclsTy &Vec = *getAsVector();
136 Vec.erase(std::remove_if(Vec.begin(), Vec.end(),
137 std::mem_fun(&Decl::isFromASTFile)),
139 // Don't have any external decls any more.
140 Data = DeclsAndHasExternalTy(&Vec, false);
144 /// getLookupResult - Return an array of all the decls that this list
146 DeclContext::lookup_result getLookupResult() {
148 return DeclContext::lookup_result(DeclContext::lookup_iterator(0),
149 DeclContext::lookup_iterator(0));
151 // If we have a single NamedDecl, return it.
153 assert(!isNull() && "Empty list isn't allowed");
155 // Data is a raw pointer to a NamedDecl*, return it.
157 return DeclContext::lookup_result((NamedDecl**)Ptr, (NamedDecl**)Ptr+1);
160 assert(getAsVector() && "Must have a vector at this point");
161 DeclsTy &Vector = *getAsVector();
163 // Otherwise, we have a range result.
164 return DeclContext::lookup_result(Vector.begin(), Vector.end());
167 /// HandleRedeclaration - If this is a redeclaration of an existing decl,
168 /// replace the old one with D and return true. Otherwise return false.
169 bool HandleRedeclaration(NamedDecl *D) {
170 // Most decls only have one entry in their list, special case it.
171 if (NamedDecl *OldD = getAsDecl()) {
172 if (!D->declarationReplaces(OldD))
178 // Determine if this declaration is actually a redeclaration.
179 DeclsTy &Vec = *getAsVector();
180 for (DeclsTy::iterator OD = Vec.begin(), ODEnd = Vec.end();
182 NamedDecl *OldD = *OD;
183 if (D->declarationReplaces(OldD)) {
192 /// AddSubsequentDecl - This is called on the second and later decl when it is
193 /// not a redeclaration to merge it into the appropriate place in our list.
195 void AddSubsequentDecl(NamedDecl *D) {
196 assert(!isNull() && "don't AddSubsequentDecl when we have no decls");
198 // If this is the second decl added to the list, convert this to vector
200 if (NamedDecl *OldD = getAsDecl()) {
201 DeclsTy *VT = new DeclsTy();
203 Data = DeclsAndHasExternalTy(VT, false);
206 DeclsTy &Vec = *getAsVector();
208 // Using directives end up in a special entry which contains only
209 // other using directives, so all this logic is wasted for them.
210 // But avoiding the logic wastes time in the far-more-common case
211 // that we're *not* adding a new using directive.
213 // Tag declarations always go at the end of the list so that an
214 // iterator which points at the first tag will start a span of
215 // decls that only contains tags.
216 if (D->hasTagIdentifierNamespace())
219 // Resolved using declarations go at the front of the list so that
220 // they won't show up in other lookup results. Unresolved using
221 // declarations (which are always in IDNS_Using | IDNS_Ordinary)
222 // follow that so that the using declarations will be contiguous.
223 else if (D->getIdentifierNamespace() & Decl::IDNS_Using) {
224 DeclsTy::iterator I = Vec.begin();
225 if (D->getIdentifierNamespace() != Decl::IDNS_Using) {
226 while (I != Vec.end() &&
227 (*I)->getIdentifierNamespace() == Decl::IDNS_Using)
232 // All other declarations go at the end of the list, but before any
233 // tag declarations. But we can be clever about tag declarations
234 // because there can only ever be one in a scope.
235 } else if (!Vec.empty() && Vec.back()->hasTagIdentifierNamespace()) {
236 NamedDecl *TagD = Vec.back();
245 : public llvm::SmallDenseMap<DeclarationName, StoredDeclsList, 4> {
248 static void DestroyAll(StoredDeclsMap *Map, bool Dependent);
251 friend class ASTContext; // walks the chain deleting these
252 friend class DeclContext;
253 llvm::PointerIntPair<StoredDeclsMap*, 1> Previous;
256 class DependentStoredDeclsMap : public StoredDeclsMap {
258 DependentStoredDeclsMap() : FirstDiagnostic(0) {}
261 friend class DependentDiagnostic;
262 friend class DeclContext; // iterates over diagnostics
264 DependentDiagnostic *FirstDiagnostic;
267 } // end namespace clang