 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
69.7% |
53 / 76 |
| Generated: |
2010-02-10 01:31 |
|
Branches Executed: |
94.7% |
72 / 76 |
| |
|
Line Coverage: |
91.9% |
91 / 99 |
| |
 |
|
 |
1 : //===-- DeclContextInternals.h - DeclContext Representation -----*- C++ -*-===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 : //
10 : // This file defines the data structures used in the implementation
11 : // of DeclContext.
12 : //
13 : //===----------------------------------------------------------------------===//
14 : #ifndef LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H
15 : #define LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H
16 :
17 : #include "clang/AST/Decl.h"
18 : #include "clang/AST/DeclarationName.h"
19 : #include "clang/AST/DeclCXX.h"
20 : #include "llvm/ADT/DenseMap.h"
21 : #include "llvm/ADT/PointerUnion.h"
22 : #include "llvm/ADT/SmallVector.h"
23 : #include <algorithm>
24 :
25 : namespace clang {
26 :
27 : /// StoredDeclsList - This is an array of decls optimized a common case of only
28 : /// containing one entry.
29 : struct StoredDeclsList {
30 : /// The kind of data encoded in this list.
31 : enum DataKind {
32 : /// \brief The data is a NamedDecl*.
33 : DK_Decl = 0,
34 : /// \brief The data is a declaration ID (an unsigned value),
35 : /// shifted left by 2 bits.
36 : DK_DeclID = 1,
37 : /// \brief The data is a pointer to a vector (of type VectorTy)
38 : /// that contains declarations.
39 : DK_Decl_Vector = 2,
40 : /// \brief The data is a pointer to a vector (of type VectorTy)
41 : /// that contains declaration ID.
42 : DK_ID_Vector = 3
43 : };
44 :
45 : /// VectorTy - When in vector form, this is what the Data pointer points to.
46 : typedef llvm::SmallVector<uintptr_t, 4> VectorTy;
47 :
48 : /// \brief The stored data, which will be either a declaration ID, a
49 : /// pointer to a NamedDecl, or a pointer to a vector.
50 : uintptr_t Data;
51 :
52 : public:
53 39687: StoredDeclsList() : Data(0) {}
54 :
55 43634: StoredDeclsList(const StoredDeclsList &RHS) : Data(RHS.Data) {
177: branch 1 taken
43457: branch 2 taken
56 43634: if (VectorTy *RHSVec = RHS.getAsVector()) {
57 177: VectorTy *New = new VectorTy(*RHSVec);
58 177: Data = reinterpret_cast<uintptr_t>(New) | (Data & 0x03);
59 : }
60 43634: }
61 :
62 43634: ~StoredDeclsList() {
63 : // If this is a vector-form, free the vector.
177: branch 1 taken
43457: branch 2 taken
64 43634: if (VectorTy *Vector = getAsVector())
177: branch 0 taken
0: branch 1 not taken
65 177: delete Vector;
66 43634: }
67 :
68 : StoredDeclsList &operator=(const StoredDeclsList &RHS) {
69 : if (VectorTy *Vector = getAsVector())
70 : delete Vector;
71 : Data = RHS.Data;
72 : if (VectorTy *RHSVec = RHS.getAsVector()) {
73 : VectorTy *New = new VectorTy(*RHSVec);
74 : Data = reinterpret_cast<uintptr_t>(New) | (Data & 0x03);
75 : }
76 : return *this;
77 : }
78 :
79 112221: bool isNull() const { return (Data & ~0x03) == 0; }
80 :
81 46449: NamedDecl *getAsDecl() const {
6763: branch 0 taken
39686: branch 1 taken
82 46449: if ((Data & 0x03) != DK_Decl)
83 6763: return 0;
84 :
85 39686: return reinterpret_cast<NamedDecl *>(Data & ~0x03);
86 : }
87 :
88 144706: VectorTy *getAsVector() const {
144706: branch 0 taken
0: branch 1 not taken
127311: branch 2 taken
17395: branch 3 taken
89 144706: if ((Data & 0x03) != DK_ID_Vector && (Data & 0x03) != DK_Decl_Vector)
90 127311: return 0;
91 :
92 17395: return reinterpret_cast<VectorTy *>(Data & ~0x03);
93 : }
94 :
95 40378: void setOnlyValue(NamedDecl *ND) {
40378: branch 1 taken
0: branch 2 not taken
96 40378: assert(!getAsVector() && "Not inline");
97 40378: Data = reinterpret_cast<uintptr_t>(ND);
98 40378: }
99 :
100 19: void setFromDeclIDs(const llvm::SmallVectorImpl<unsigned> &Vec) {
2: branch 1 taken
17: branch 2 taken
101 19: if (Vec.size() > 1) {
102 2: VectorTy *Vector = getAsVector();
2: branch 0 taken
0: branch 1 not taken
103 2: if (!Vector) {
104 2: Vector = new VectorTy;
105 2: Data = reinterpret_cast<uintptr_t>(Vector) | DK_ID_Vector;
106 : }
107 :
108 2: Vector->resize(Vec.size());
109 2: std::copy(Vec.begin(), Vec.end(), Vector->begin());
110 2: return;
111 : }
112 :
0: branch 1 not taken
17: branch 2 taken
113 17: if (VectorTy *Vector = getAsVector())
0: branch 0 not taken
0: branch 1 not taken
114 0: delete Vector;
115 :
0: branch 1 not taken
17: branch 2 taken
116 17: if (Vec.empty())
117 0: Data = 0;
118 : else
119 17: Data = (Vec[0] << 2) | DK_DeclID;
120 : }
121 :
122 : /// \brief Force the stored declarations list to contain actual
123 : /// declarations.
124 : ///
125 : /// This routine will resolve any declaration IDs for declarations
126 : /// that may not yet have been loaded from external storage.
127 : void materializeDecls(ASTContext &Context);
128 :
129 46446: bool hasDeclarationIDs() const {
130 46446: DataKind DK = (DataKind)(Data & 0x03);
46436: branch 0 taken
10: branch 1 taken
0: branch 2 not taken
46436: branch 3 taken
131 46446: return DK == DK_DeclID || DK == DK_ID_Vector;
132 : }
133 :
134 3: void remove(NamedDecl *D) {
3: branch 1 taken
0: branch 2 not taken
135 3: assert(!isNull() && "removing from empty list");
0: branch 1 not taken
3: branch 2 taken
136 3: if (NamedDecl *Singleton = getAsDecl()) {
0: branch 0 not taken
0: branch 1 not taken
137 0: assert(Singleton == D && "list is different singleton");
138 : (void)Singleton;
139 0: Data = 0;
140 0: return;
141 : }
142 :
143 3: VectorTy &Vec = *getAsVector();
144 : VectorTy::iterator I = std::find(Vec.begin(), Vec.end(),
145 3: reinterpret_cast<uintptr_t>(D));
3: branch 1 taken
0: branch 2 not taken
146 3: assert(I != Vec.end() && "list does not contain decl");
147 3: Vec.erase(I);
148 :
149 : assert(std::find(Vec.begin(), Vec.end(), reinterpret_cast<uintptr_t>(D))
3: branch 4 taken
0: branch 5 not taken
150 6: == Vec.end() && "list still contains decl");
151 : }
152 :
153 : /// getLookupResult - Return an array of all the decls that this list
154 : /// represents.
155 36645: DeclContext::lookup_result getLookupResult(ASTContext &Context) {
0: branch 1 not taken
36645: branch 2 taken
156 36645: if (isNull())
157 0: return DeclContext::lookup_result(0, 0);
158 :
10: branch 1 taken
36635: branch 2 taken
159 36645: if (hasDeclarationIDs())
160 10: materializeDecls(Context);
161 :
162 : // If we have a single NamedDecl, return it.
30570: branch 1 taken
6075: branch 2 taken
163 36645: if (getAsDecl()) {
30570: branch 1 taken
0: branch 2 not taken
164 30570: assert(!isNull() && "Empty list isn't allowed");
165 :
166 : // Data is a raw pointer to a NamedDecl*, return it.
167 30570: void *Ptr = &Data;
168 30570: return DeclContext::lookup_result((NamedDecl**)Ptr, (NamedDecl**)Ptr+1);
169 : }
170 :
6075: branch 1 taken
0: branch 2 not taken
171 6075: assert(getAsVector() && "Must have a vector at this point");
172 6075: VectorTy &Vector = *getAsVector();
173 :
174 : // Otherwise, we have a range result.
175 : return DeclContext::lookup_result((NamedDecl **)&Vector[0],
176 6075: (NamedDecl **)&Vector[0]+Vector.size());
177 : }
178 :
179 : /// HandleRedeclaration - If this is a redeclaration of an existing decl,
180 : /// replace the old one with D and return true. Otherwise return false.
181 5325: bool HandleRedeclaration(ASTContext &Context, NamedDecl *D) {
0: branch 1 not taken
5325: branch 2 taken
182 5325: if (hasDeclarationIDs())
183 0: materializeDecls(Context);
184 :
185 : // Most decls only have one entry in their list, special case it.
4913: branch 1 taken
412: branch 2 taken
186 5325: if (NamedDecl *OldD = getAsDecl()) {
4203: branch 1 taken
710: branch 2 taken
187 4913: if (!D->declarationReplaces(OldD))
188 4203: return false;
189 710: setOnlyValue(D);
190 710: return true;
191 : }
192 :
193 : // Determine if this declaration is actually a redeclaration.
194 412: VectorTy &Vec = *getAsVector();
1033: branch 2 taken
273: branch 3 taken
195 1306: for (VectorTy::iterator OD = Vec.begin(), ODEnd = Vec.end();
196 : OD != ODEnd; ++OD) {
197 1033: NamedDecl *OldD = reinterpret_cast<NamedDecl *>(*OD);
139: branch 1 taken
894: branch 2 taken
198 1033: if (D->declarationReplaces(OldD)) {
199 139: *OD = reinterpret_cast<uintptr_t>(D);
200 139: return true;
201 : }
202 : }
203 :
204 273: return false;
205 : }
206 :
207 : /// AddSubsequentDecl - This is called on the second and later decl when it is
208 : /// not a redeclaration to merge it into the appropriate place in our list.
209 : ///
210 4476: void AddSubsequentDecl(NamedDecl *D) {
4476: branch 1 taken
0: branch 2 not taken
211 4476: assert(!hasDeclarationIDs() && "Must materialize before adding decls");
212 :
213 : // If this is the second decl added to the list, convert this to vector
214 : // form.
4203: branch 1 taken
273: branch 2 taken
215 4476: if (NamedDecl *OldD = getAsDecl()) {
216 4203: VectorTy *VT = new VectorTy();
217 4203: VT->push_back(reinterpret_cast<uintptr_t>(OldD));
218 4203: Data = reinterpret_cast<uintptr_t>(VT) | DK_Decl_Vector;
219 : }
220 :
221 4476: VectorTy &Vec = *getAsVector();
222 :
223 : // Using directives end up in a special entry which contains only
224 : // other using directives, so all this logic is wasted for them.
225 : // But avoiding the logic wastes time in the far-more-common case
226 : // that we're *not* adding a new using directive.
227 :
228 : // Tag declarations always go at the end of the list so that an
229 : // iterator which points at the first tag will start a span of
230 : // decls that only contains tags.
18: branch 1 taken
4458: branch 2 taken
231 4476: if (D->getIdentifierNamespace() == Decl::IDNS_Tag)
232 18: Vec.push_back(reinterpret_cast<uintptr_t>(D));
233 :
234 : // Resolved using declarations go at the front of the list so that
235 : // they won't show up in other lookup results. Unresolved using
236 : // declarations (which are always in IDNS_Using | IDNS_Ordinary)
237 : // follow that so that the using declarations will be contiguous.
17: branch 1 taken
4441: branch 2 taken
238 4458: else if (D->getIdentifierNamespace() & Decl::IDNS_Using) {
239 17: VectorTy::iterator I = Vec.begin();
1: branch 1 taken
16: branch 2 taken
240 17: if (D->getIdentifierNamespace() != Decl::IDNS_Using) {
1: branch 1 taken
0: branch 2 not taken
0: branch 4 not taken
1: branch 5 taken
0: branch 6 not taken
1: branch 7 taken
241 2: while (I != Vec.end() &&
242 : reinterpret_cast<NamedDecl *>(*I)
243 : ->getIdentifierNamespace() == Decl::IDNS_Using)
244 0: ++I;
245 : }
246 17: Vec.insert(I, reinterpret_cast<uintptr_t>(D));
247 :
248 : // All other declarations go at the end of the list, but before any
249 : // tag declarations. But we can be clever about tag declarations
250 : // because there can only ever be one in a scope.
120: branch 2 taken
4321: branch 3 taken
251 4441: } else if (reinterpret_cast<NamedDecl *>(Vec.back())
252 : ->getIdentifierNamespace() == Decl::IDNS_Tag) {
253 120: uintptr_t TagD = Vec.back();
254 120: Vec.back() = reinterpret_cast<uintptr_t>(D);
255 120: Vec.push_back(TagD);
256 : } else
257 4321: Vec.push_back(reinterpret_cast<uintptr_t>(D));
258 4476: }
259 : };
260 :
261 : typedef llvm::DenseMap<DeclarationName, StoredDeclsList> StoredDeclsMap;
262 :
263 :
264 : } // end namespace clang
265 :
266 : #endif
Generated: 2010-02-10 01:31 by zcov