blob: 21e1e0ce10c5041e944dd23608f3da3b3117f1be [file] [log] [blame]
Eli Friedman56d29372008-06-07 16:52:53 +00001//===--- DeclBase.cpp - Declaration AST Node Implementation ---------------===//
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 implements the Decl and DeclContext classes.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/AST/DeclBase.h"
Douglas Gregor64650af2009-02-02 23:39:07 +000015#include "clang/AST/Decl.h"
Daniel Dunbare91593e2008-08-11 04:54:23 +000016#include "clang/AST/DeclObjC.h"
Argyrios Kyrtzidisd3bb44f2008-06-09 21:05:31 +000017#include "clang/AST/DeclCXX.h"
Eli Friedman56d29372008-06-07 16:52:53 +000018#include "clang/AST/ASTContext.h"
Douglas Gregor44b43212008-12-11 16:49:14 +000019#include "clang/AST/Type.h"
Eli Friedman56d29372008-06-07 16:52:53 +000020#include "llvm/ADT/DenseMap.h"
Douglas Gregor6ed40e32008-12-23 21:05:05 +000021#include <algorithm>
22#include <functional>
Douglas Gregor3fc749d2008-12-23 00:26:44 +000023#include <vector>
Eli Friedman56d29372008-06-07 16:52:53 +000024using namespace clang;
25
26//===----------------------------------------------------------------------===//
27// Statistics
28//===----------------------------------------------------------------------===//
29
Douglas Gregor64650af2009-02-02 23:39:07 +000030#define DECL(Derived, Base) static int n##Derived##s = 0;
31#include "clang/AST/DeclNodes.def"
Eli Friedman56d29372008-06-07 16:52:53 +000032
33static bool StatSwitch = false;
34
35// This keeps track of all decl attributes. Since so few decls have attrs, we
36// keep them in a hash map instead of wasting space in the Decl class.
37typedef llvm::DenseMap<const Decl*, Attr*> DeclAttrMapTy;
38
39static DeclAttrMapTy *DeclAttrs = 0;
40
41const char *Decl::getDeclKindName() const {
42 switch (DeclKind) {
Douglas Gregor64650af2009-02-02 23:39:07 +000043 default: assert(0 && "Declaration not in DeclNodes.def!");
44#define DECL(Derived, Base) case Derived: return #Derived;
45#include "clang/AST/DeclNodes.def"
Eli Friedman56d29372008-06-07 16:52:53 +000046 }
47}
48
Steve Naroff0a473932009-01-20 19:53:53 +000049const char *DeclContext::getDeclKindName() const {
50 switch (DeclKind) {
Douglas Gregor64650af2009-02-02 23:39:07 +000051 default: assert(0 && "Declaration context not in DeclNodes.def!");
52#define DECL_CONTEXT(Node) case Decl::Node: return #Node;
53#include "clang/AST/DeclNodes.def"
Steve Naroff0a473932009-01-20 19:53:53 +000054 }
55}
56
Eli Friedman56d29372008-06-07 16:52:53 +000057bool Decl::CollectingStats(bool Enable) {
58 if (Enable)
59 StatSwitch = true;
60 return StatSwitch;
61}
62
63void Decl::PrintStats() {
64 fprintf(stderr, "*** Decl Stats:\n");
Eli Friedman56d29372008-06-07 16:52:53 +000065
Douglas Gregor64650af2009-02-02 23:39:07 +000066 int totalDecls = 0;
67#define DECL(Derived, Base) totalDecls += n##Derived##s;
68#include "clang/AST/DeclNodes.def"
69 fprintf(stderr, " %d decls total.\n", totalDecls);
70
71 int totalBytes = 0;
72#define DECL(Derived, Base) \
73 if (n##Derived##s > 0) { \
74 totalBytes += (int)(n##Derived##s * sizeof(Derived##Decl)); \
75 fprintf(stderr, " %d " #Derived " decls, %d each (%d bytes)\n", \
76 n##Derived##s, (int)sizeof(Derived##Decl), \
77 (int)(n##Derived##s * sizeof(Derived##Decl))); \
78 }
79#include "clang/AST/DeclNodes.def"
Eli Friedman56d29372008-06-07 16:52:53 +000080
Douglas Gregor64650af2009-02-02 23:39:07 +000081 fprintf(stderr, "Total bytes = %d\n", totalBytes);
Eli Friedman56d29372008-06-07 16:52:53 +000082}
83
84void Decl::addDeclKind(Kind k) {
85 switch (k) {
Douglas Gregor64650af2009-02-02 23:39:07 +000086 default: assert(0 && "Declaration not in DeclNodes.def!");
87#define DECL(Derived, Base) case Derived: ++n##Derived##s; break;
88#include "clang/AST/DeclNodes.def"
Eli Friedman56d29372008-06-07 16:52:53 +000089 }
90}
91
92//===----------------------------------------------------------------------===//
93// Decl Implementation
94//===----------------------------------------------------------------------===//
95
Douglas Gregor4afa39d2009-01-20 01:17:11 +000096void Decl::setDeclContext(DeclContext *DC) {
97 if (isOutOfSemaDC())
98 delete getMultipleDC();
99
100 DeclCtx = reinterpret_cast<uintptr_t>(DC);
101}
102
103void Decl::setLexicalDeclContext(DeclContext *DC) {
104 if (DC == getLexicalDeclContext())
105 return;
106
107 if (isInSemaDC()) {
108 MultipleDC *MDC = new MultipleDC();
109 MDC->SemanticDC = getDeclContext();
110 MDC->LexicalDC = DC;
111 DeclCtx = reinterpret_cast<uintptr_t>(MDC) | 0x1;
112 } else {
113 getMultipleDC()->LexicalDC = DC;
114 }
115}
116
Eli Friedman56d29372008-06-07 16:52:53 +0000117// Out-of-line virtual method providing a home for Decl.
118Decl::~Decl() {
Douglas Gregor4afa39d2009-01-20 01:17:11 +0000119 if (isOutOfSemaDC())
120 delete getMultipleDC();
121
Eli Friedman56d29372008-06-07 16:52:53 +0000122 if (!HasAttrs)
123 return;
124
125 DeclAttrMapTy::iterator it = DeclAttrs->find(this);
126 assert(it != DeclAttrs->end() && "No attrs found but HasAttrs is true!");
127
128 // release attributes.
129 delete it->second;
130 invalidateAttrs();
131}
132
133void Decl::addAttr(Attr *NewAttr) {
134 if (!DeclAttrs)
135 DeclAttrs = new DeclAttrMapTy();
136
137 Attr *&ExistingAttr = (*DeclAttrs)[this];
138
139 NewAttr->setNext(ExistingAttr);
140 ExistingAttr = NewAttr;
141
142 HasAttrs = true;
143}
144
145void Decl::invalidateAttrs() {
146 if (!HasAttrs) return;
147
148 HasAttrs = false;
149 (*DeclAttrs)[this] = 0;
150 DeclAttrs->erase(this);
151
152 if (DeclAttrs->empty()) {
153 delete DeclAttrs;
154 DeclAttrs = 0;
155 }
156}
157
158const Attr *Decl::getAttrs() const {
159 if (!HasAttrs)
160 return 0;
161
162 return (*DeclAttrs)[this];
163}
164
165void Decl::swapAttrs(Decl *RHS) {
166 bool HasLHSAttr = this->HasAttrs;
167 bool HasRHSAttr = RHS->HasAttrs;
168
169 // Usually, neither decl has attrs, nothing to do.
170 if (!HasLHSAttr && !HasRHSAttr) return;
171
172 // If 'this' has no attrs, swap the other way.
173 if (!HasLHSAttr)
174 return RHS->swapAttrs(this);
175
176 // Handle the case when both decls have attrs.
177 if (HasRHSAttr) {
178 std::swap((*DeclAttrs)[this], (*DeclAttrs)[RHS]);
179 return;
180 }
181
182 // Otherwise, LHS has an attr and RHS doesn't.
183 (*DeclAttrs)[RHS] = (*DeclAttrs)[this];
184 (*DeclAttrs).erase(this);
185 this->HasAttrs = false;
186 RHS->HasAttrs = true;
187}
188
189
190void Decl::Destroy(ASTContext& C) {
Douglas Gregora0fc55f2009-01-13 19:47:12 +0000191#if 0
Douglas Gregor00ad0ef2009-01-20 04:25:11 +0000192 // FIXME: Once ownership is fully understood, we can enable this code
193 if (DeclContext *DC = dyn_cast<DeclContext>(this))
194 DC->decls_begin()->Destroy(C);
Eli Friedman56d29372008-06-07 16:52:53 +0000195
Douglas Gregor00ad0ef2009-01-20 04:25:11 +0000196 // Observe the unrolled recursion. By setting N->NextDeclInScope = 0x0
Douglas Gregor4afa39d2009-01-20 01:17:11 +0000197 // within the loop, only the Destroy method for the first Decl
198 // will deallocate all of the Decls in a chain.
199
Douglas Gregor00ad0ef2009-01-20 04:25:11 +0000200 Decl* N = NextDeclInScope;
Douglas Gregor4afa39d2009-01-20 01:17:11 +0000201
202 while (N) {
Douglas Gregor00ad0ef2009-01-20 04:25:11 +0000203 Decl* Tmp = N->NextDeclInScope;
204 N->NextDeclInScope = 0;
Douglas Gregor4afa39d2009-01-20 01:17:11 +0000205 N->Destroy(C);
206 N = Tmp;
Eli Friedman56d29372008-06-07 16:52:53 +0000207 }
Douglas Gregora0fc55f2009-01-13 19:47:12 +0000208
Eli Friedman56d29372008-06-07 16:52:53 +0000209 this->~Decl();
Steve Naroff3e970492009-01-27 21:25:57 +0000210 C.Deallocate((void *)this);
Douglas Gregor00ad0ef2009-01-20 04:25:11 +0000211#endif
Eli Friedman56d29372008-06-07 16:52:53 +0000212}
213
Argyrios Kyrtzidis42220c52008-10-12 16:14:48 +0000214Decl *Decl::castFromDeclContext (const DeclContext *D) {
215 return DeclContext::CastTo<Decl>(D);
216}
217
218DeclContext *Decl::castToDeclContext(const Decl *D) {
219 return DeclContext::CastTo<DeclContext>(D);
220}
221
Eli Friedman56d29372008-06-07 16:52:53 +0000222//===----------------------------------------------------------------------===//
223// DeclContext Implementation
224//===----------------------------------------------------------------------===//
225
Argyrios Kyrtzidis20bc6762008-11-19 17:36:39 +0000226const DeclContext *DeclContext::getParent() const {
Douglas Gregor4afa39d2009-01-20 01:17:11 +0000227 if (const Decl *D = dyn_cast<Decl>(this))
228 return D->getDeclContext();
229
230 return NULL;
Eli Friedman56d29372008-06-07 16:52:53 +0000231}
Argyrios Kyrtzidis77407b82008-11-19 18:01:13 +0000232
233const DeclContext *DeclContext::getLexicalParent() const {
Douglas Gregor4afa39d2009-01-20 01:17:11 +0000234 if (const Decl *D = dyn_cast<Decl>(this))
235 return D->getLexicalDeclContext();
236
Argyrios Kyrtzidis051c13a2008-11-19 18:07:24 +0000237 return getParent();
Argyrios Kyrtzidis77407b82008-11-19 18:01:13 +0000238}
Douglas Gregor44b43212008-12-11 16:49:14 +0000239
Douglas Gregor44b43212008-12-11 16:49:14 +0000240// FIXME: We really want to use a DenseSet here to eliminate the
241// redundant storage of the declaration names, but (1) it doesn't give
242// us the ability to search based on DeclarationName, (2) we really
243// need something more like a DenseMultiSet, and (3) it's
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000244// implemented in terms of DenseMap anyway. However, this data
245// structure is really space-inefficient, so we'll have to do
246// something.
Douglas Gregor4afa39d2009-01-20 01:17:11 +0000247typedef llvm::DenseMap<DeclarationName, std::vector<NamedDecl*> >
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000248 StoredDeclsMap;
Douglas Gregor44b43212008-12-11 16:49:14 +0000249
250DeclContext::~DeclContext() {
251 unsigned Size = LookupPtr.getInt();
252 if (Size == LookupIsMap) {
253 StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(LookupPtr.getPointer());
254 delete Map;
255 } else {
Douglas Gregor4afa39d2009-01-20 01:17:11 +0000256 NamedDecl **Array = static_cast<NamedDecl**>(LookupPtr.getPointer());
Douglas Gregor44b43212008-12-11 16:49:14 +0000257 delete [] Array;
258 }
259}
260
261void DeclContext::DestroyDecls(ASTContext &C) {
Douglas Gregor00ad0ef2009-01-20 04:25:11 +0000262 for (decl_iterator D = decls_begin(); D != decls_end(); )
263 (*D++)->Destroy(C);
Douglas Gregor44b43212008-12-11 16:49:14 +0000264}
265
Douglas Gregor074149e2009-01-05 19:45:36 +0000266bool DeclContext::isTransparentContext() const {
267 if (DeclKind == Decl::Enum)
268 return true; // FIXME: Check for C++0x scoped enums
269 else if (DeclKind == Decl::LinkageSpec)
270 return true;
271 else if (DeclKind == Decl::Record || DeclKind == Decl::CXXRecord)
Douglas Gregorbcbffc42009-01-07 00:43:41 +0000272 return cast<RecordDecl>(this)->isAnonymousStructOrUnion();
Douglas Gregor074149e2009-01-05 19:45:36 +0000273 else if (DeclKind == Decl::Namespace)
274 return false; // FIXME: Check for C++0x inline namespaces
275
276 return false;
277}
278
Steve Naroff0701bbb2009-01-08 17:28:14 +0000279DeclContext *DeclContext::getPrimaryContext() {
Douglas Gregor44b43212008-12-11 16:49:14 +0000280 switch (DeclKind) {
Douglas Gregor44b43212008-12-11 16:49:14 +0000281 case Decl::TranslationUnit:
Douglas Gregor074149e2009-01-05 19:45:36 +0000282 case Decl::LinkageSpec:
283 case Decl::Block:
Douglas Gregor44b43212008-12-11 16:49:14 +0000284 // There is only one DeclContext for these entities.
285 return this;
286
287 case Decl::Namespace:
288 // The original namespace is our primary context.
289 return static_cast<NamespaceDecl*>(this)->getOriginalNamespace();
290
291 case Decl::Enum:
Douglas Gregor44b43212008-12-11 16:49:14 +0000292 case Decl::Record:
Douglas Gregor0b7a1582009-01-17 00:42:38 +0000293 case Decl::CXXRecord:
294 // If this is a tag type that has a definition or is currently
295 // being defined, that definition is our primary context.
296 if (TagType *TagT = cast_or_null<TagType>(cast<TagDecl>(this)->TypeForDecl))
297 if (TagT->isBeingDefined() ||
298 (TagT->getDecl() && TagT->getDecl()->isDefinition()))
299 return TagT->getDecl();
Douglas Gregor44b43212008-12-11 16:49:14 +0000300 return this;
Douglas Gregor44b43212008-12-11 16:49:14 +0000301
302 case Decl::ObjCMethod:
303 return this;
304
305 case Decl::ObjCInterface:
Steve Naroff0701bbb2009-01-08 17:28:14 +0000306 case Decl::ObjCProtocol:
307 case Decl::ObjCCategory:
Douglas Gregor44b43212008-12-11 16:49:14 +0000308 // FIXME: Can Objective-C interfaces be forward-declared?
309 return this;
310
Steve Naroff0701bbb2009-01-08 17:28:14 +0000311 case Decl::ObjCImplementation:
312 case Decl::ObjCCategoryImpl:
313 return this;
314
Douglas Gregor44b43212008-12-11 16:49:14 +0000315 default:
316 assert(DeclKind >= Decl::FunctionFirst && DeclKind <= Decl::FunctionLast &&
317 "Unknown DeclContext kind");
318 return this;
319 }
320}
321
322DeclContext *DeclContext::getNextContext() {
323 switch (DeclKind) {
Douglas Gregor44b43212008-12-11 16:49:14 +0000324 case Decl::TranslationUnit:
325 case Decl::Enum:
326 case Decl::Record:
327 case Decl::CXXRecord:
328 case Decl::ObjCMethod:
329 case Decl::ObjCInterface:
Steve Naroff0701bbb2009-01-08 17:28:14 +0000330 case Decl::ObjCCategory:
331 case Decl::ObjCProtocol:
332 case Decl::ObjCImplementation:
333 case Decl::ObjCCategoryImpl:
Douglas Gregor074149e2009-01-05 19:45:36 +0000334 case Decl::LinkageSpec:
335 case Decl::Block:
Douglas Gregor44b43212008-12-11 16:49:14 +0000336 // There is only one DeclContext for these entities.
337 return 0;
338
339 case Decl::Namespace:
340 // Return the next namespace
341 return static_cast<NamespaceDecl*>(this)->getNextNamespace();
342
343 default:
344 assert(DeclKind >= Decl::FunctionFirst && DeclKind <= Decl::FunctionLast &&
345 "Unknown DeclContext kind");
346 return 0;
347 }
348}
349
Douglas Gregor4afa39d2009-01-20 01:17:11 +0000350void DeclContext::addDecl(Decl *D) {
Douglas Gregora8cc8ce2009-01-09 18:51:29 +0000351 assert(D->getLexicalDeclContext() == this && "Decl inserted into wrong lexical context");
Douglas Gregor6037fcb2009-01-09 19:42:16 +0000352 assert(!D->NextDeclInScope && D != LastDecl &&
353 "Decl already inserted into a DeclContext");
354
355 if (FirstDecl) {
356 LastDecl->NextDeclInScope = D;
357 LastDecl = D;
358 } else {
359 FirstDecl = LastDecl = D;
360 }
Douglas Gregor4afa39d2009-01-20 01:17:11 +0000361
362 if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
Douglas Gregor40f4e692009-01-20 16:54:50 +0000363 ND->getDeclContext()->makeDeclVisibleInContext(ND);
Douglas Gregor44b43212008-12-11 16:49:14 +0000364}
365
Douglas Gregor074149e2009-01-05 19:45:36 +0000366/// buildLookup - Build the lookup data structure with all of the
367/// declarations in DCtx (and any other contexts linked to it or
368/// transparent contexts nested within it).
Steve Naroff0701bbb2009-01-08 17:28:14 +0000369void DeclContext::buildLookup(DeclContext *DCtx) {
Douglas Gregor074149e2009-01-05 19:45:36 +0000370 for (; DCtx; DCtx = DCtx->getNextContext()) {
Douglas Gregor4f3b8f82009-01-06 07:17:58 +0000371 for (decl_iterator D = DCtx->decls_begin(), DEnd = DCtx->decls_end();
372 D != DEnd; ++D) {
Douglas Gregor074149e2009-01-05 19:45:36 +0000373 // Insert this declaration into the lookup structure
Douglas Gregor4afa39d2009-01-20 01:17:11 +0000374 if (NamedDecl *ND = dyn_cast<NamedDecl>(*D))
Douglas Gregor40f4e692009-01-20 16:54:50 +0000375 makeDeclVisibleInContextImpl(ND);
Douglas Gregor074149e2009-01-05 19:45:36 +0000376
377 // If this declaration is itself a transparent declaration context,
378 // add its members (recursively).
379 if (DeclContext *InnerCtx = dyn_cast<DeclContext>(*D))
380 if (InnerCtx->isTransparentContext())
Steve Naroff0701bbb2009-01-08 17:28:14 +0000381 buildLookup(InnerCtx->getPrimaryContext());
Douglas Gregor074149e2009-01-05 19:45:36 +0000382 }
383 }
384}
385
Douglas Gregor44b43212008-12-11 16:49:14 +0000386DeclContext::lookup_result
Steve Naroff0701bbb2009-01-08 17:28:14 +0000387DeclContext::lookup(DeclarationName Name) {
388 DeclContext *PrimaryContext = getPrimaryContext();
Douglas Gregor44b43212008-12-11 16:49:14 +0000389 if (PrimaryContext != this)
Steve Naroff0701bbb2009-01-08 17:28:14 +0000390 return PrimaryContext->lookup(Name);
Douglas Gregor44b43212008-12-11 16:49:14 +0000391
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000392 /// If there is no lookup data structure, build one now by walking
Douglas Gregor44b43212008-12-11 16:49:14 +0000393 /// all of the linked DeclContexts (in declaration order!) and
394 /// inserting their values.
Douglas Gregor074149e2009-01-05 19:45:36 +0000395 if (LookupPtr.getPointer() == 0)
Steve Naroff0701bbb2009-01-08 17:28:14 +0000396 buildLookup(this);
Douglas Gregor44b43212008-12-11 16:49:14 +0000397
Douglas Gregor44b43212008-12-11 16:49:14 +0000398 if (isLookupMap()) {
399 StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(LookupPtr.getPointer());
400 StoredDeclsMap::iterator Pos = Map->find(Name);
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000401 if (Pos != Map->end())
402 return lookup_result(&Pos->second.front(),
403 &Pos->second.front() + Pos->second.size());
404 return lookup_result(0, 0);
Douglas Gregor44b43212008-12-11 16:49:14 +0000405 }
406
407 // We have a small array. Look into it.
408 unsigned Size = LookupPtr.getInt();
Douglas Gregor4afa39d2009-01-20 01:17:11 +0000409 NamedDecl **Array = static_cast<NamedDecl**>(LookupPtr.getPointer());
Douglas Gregore267ff32008-12-11 20:41:00 +0000410 for (unsigned Idx = 0; Idx != Size; ++Idx)
Douglas Gregor44b43212008-12-11 16:49:14 +0000411 if (Array[Idx]->getDeclName() == Name) {
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000412 unsigned Last = Idx + 1;
413 while (Last != Size && Array[Last]->getDeclName() == Name)
414 ++Last;
415 return lookup_result(&Array[Idx], &Array[Last]);
Douglas Gregor44b43212008-12-11 16:49:14 +0000416 }
417
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000418 return lookup_result(0, 0);
Douglas Gregor44b43212008-12-11 16:49:14 +0000419}
420
421DeclContext::lookup_const_result
Steve Naroff0701bbb2009-01-08 17:28:14 +0000422DeclContext::lookup(DeclarationName Name) const {
423 return const_cast<DeclContext*>(this)->lookup(Name);
Douglas Gregor44b43212008-12-11 16:49:14 +0000424}
425
Douglas Gregor17a9b9e2009-01-07 02:48:43 +0000426const DeclContext *DeclContext::getLookupContext() const {
427 const DeclContext *Ctx = this;
Douglas Gregor72de6672009-01-08 20:45:30 +0000428 // Skip through transparent contexts.
Douglas Gregorce356072009-01-06 23:51:29 +0000429 while (Ctx->isTransparentContext())
430 Ctx = Ctx->getParent();
431 return Ctx;
432}
433
Douglas Gregor40f4e692009-01-20 16:54:50 +0000434void DeclContext::makeDeclVisibleInContext(NamedDecl *D) {
Steve Naroff0701bbb2009-01-08 17:28:14 +0000435 DeclContext *PrimaryContext = getPrimaryContext();
Douglas Gregor44b43212008-12-11 16:49:14 +0000436 if (PrimaryContext != this) {
Douglas Gregor40f4e692009-01-20 16:54:50 +0000437 PrimaryContext->makeDeclVisibleInContext(D);
Douglas Gregor44b43212008-12-11 16:49:14 +0000438 return;
439 }
440
441 // If we already have a lookup data structure, perform the insertion
442 // into it. Otherwise, be lazy and don't build that structure until
443 // someone asks for it.
444 if (LookupPtr.getPointer())
Douglas Gregor40f4e692009-01-20 16:54:50 +0000445 makeDeclVisibleInContextImpl(D);
Douglas Gregor074149e2009-01-05 19:45:36 +0000446
Douglas Gregor074149e2009-01-05 19:45:36 +0000447 // If we are a transparent context, insert into our parent context,
448 // too. This operation is recursive.
449 if (isTransparentContext())
Douglas Gregor40f4e692009-01-20 16:54:50 +0000450 getParent()->makeDeclVisibleInContext(D);
Douglas Gregor44b43212008-12-11 16:49:14 +0000451}
452
Douglas Gregor40f4e692009-01-20 16:54:50 +0000453void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D) {
Douglas Gregor074149e2009-01-05 19:45:36 +0000454 // Skip unnamed declarations.
455 if (!D->getDeclName())
456 return;
457
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000458 bool MayBeRedeclaration = true;
459
Douglas Gregor44b43212008-12-11 16:49:14 +0000460 if (!isLookupMap()) {
461 unsigned Size = LookupPtr.getInt();
462
463 // The lookup data is stored as an array. Search through the array
464 // to find the insertion location.
Douglas Gregor4afa39d2009-01-20 01:17:11 +0000465 NamedDecl **Array;
Douglas Gregor44b43212008-12-11 16:49:14 +0000466 if (Size == 0) {
Douglas Gregor4afa39d2009-01-20 01:17:11 +0000467 Array = new NamedDecl*[LookupIsMap - 1];
Douglas Gregor44b43212008-12-11 16:49:14 +0000468 LookupPtr.setPointer(Array);
469 } else {
Douglas Gregor4afa39d2009-01-20 01:17:11 +0000470 Array = static_cast<NamedDecl **>(LookupPtr.getPointer());
Douglas Gregor44b43212008-12-11 16:49:14 +0000471 }
472
473 // We always keep declarations of the same name next to each other
474 // in the array, so that it is easy to return multiple results
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000475 // from lookup().
476 unsigned FirstMatch;
477 for (FirstMatch = 0; FirstMatch != Size; ++FirstMatch)
478 if (Array[FirstMatch]->getDeclName() == D->getDeclName())
Douglas Gregore267ff32008-12-11 20:41:00 +0000479 break;
Douglas Gregor44b43212008-12-11 16:49:14 +0000480
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000481 unsigned InsertPos = FirstMatch;
482 if (FirstMatch != Size) {
483 // We found another declaration with the same name. First
484 // determine whether this is a redeclaration of an existing
485 // declaration in this scope, in which case we will replace the
486 // existing declaration.
487 unsigned LastMatch = FirstMatch;
488 for (; LastMatch != Size; ++LastMatch) {
489 if (Array[LastMatch]->getDeclName() != D->getDeclName())
490 break;
491
Douglas Gregor6ed40e32008-12-23 21:05:05 +0000492 if (D->declarationReplaces(Array[LastMatch])) {
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000493 // D is a redeclaration of an existing element in the
494 // array. Replace that element with D.
495 Array[LastMatch] = D;
496 return;
497 }
Douglas Gregor44b43212008-12-11 16:49:14 +0000498 }
499
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000500 // [FirstMatch, LastMatch) contains the set of declarations that
501 // have the same name as this declaration. Determine where the
Douglas Gregor2a3009a2009-02-03 19:21:40 +0000502 // declaration D will be inserted into this range.
503 if (D->getKind() == Decl::UsingDirective ||
504 D->getIdentifierNamespace() == Decl::IDNS_Tag)
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000505 InsertPos = LastMatch;
506 else if (Array[LastMatch-1]->getIdentifierNamespace() == Decl::IDNS_Tag)
507 InsertPos = LastMatch - 1;
508 else
509 InsertPos = LastMatch;
Douglas Gregor44b43212008-12-11 16:49:14 +0000510 }
511
512 if (Size < LookupIsMap - 1) {
513 // The new declaration will fit in the array. Insert the new
514 // declaration at the position Match in the array.
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000515 for (unsigned Idx = Size; Idx > InsertPos; --Idx)
Douglas Gregor44b43212008-12-11 16:49:14 +0000516 Array[Idx] = Array[Idx-1];
517
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000518 Array[InsertPos] = D;
Douglas Gregor44b43212008-12-11 16:49:14 +0000519 LookupPtr.setInt(Size + 1);
520 return;
521 }
522
523 // We've reached capacity in this array. Create a map and copy in
524 // all of the declarations that were stored in the array.
525 StoredDeclsMap *Map = new StoredDeclsMap(16);
526 LookupPtr.setPointer(Map);
527 LookupPtr.setInt(LookupIsMap);
Douglas Gregore267ff32008-12-11 20:41:00 +0000528 for (unsigned Idx = 0; Idx != LookupIsMap - 1; ++Idx)
Douglas Gregor40f4e692009-01-20 16:54:50 +0000529 makeDeclVisibleInContextImpl(Array[Idx]);
Douglas Gregor44b43212008-12-11 16:49:14 +0000530 delete [] Array;
531
532 // Fall through to perform insertion into the map.
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000533 MayBeRedeclaration = false;
534 }
Douglas Gregor44b43212008-12-11 16:49:14 +0000535
536 // Insert this declaration into the map.
537 StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(LookupPtr.getPointer());
538 StoredDeclsMap::iterator Pos = Map->find(D->getDeclName());
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000539 if (Pos != Map->end()) {
540 if (MayBeRedeclaration) {
541 // Determine if this declaration is actually a redeclaration.
Douglas Gregor4afa39d2009-01-20 01:17:11 +0000542 std::vector<NamedDecl *>::iterator Redecl
Douglas Gregor6ed40e32008-12-23 21:05:05 +0000543 = std::find_if(Pos->second.begin(), Pos->second.end(),
Douglas Gregor4afa39d2009-01-20 01:17:11 +0000544 std::bind1st(std::mem_fun(&NamedDecl::declarationReplaces),
Douglas Gregor6ed40e32008-12-23 21:05:05 +0000545 D));
546 if (Redecl != Pos->second.end()) {
547 *Redecl = D;
548 return;
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000549 }
550 }
Douglas Gregor44b43212008-12-11 16:49:14 +0000551
Douglas Gregor44b43212008-12-11 16:49:14 +0000552 // Put this declaration into the appropriate slot.
Douglas Gregor2a3009a2009-02-03 19:21:40 +0000553 if (D->getKind() == Decl::UsingDirective ||
554 D->getIdentifierNamespace() == Decl::IDNS_Tag
555 || Pos->second.empty())
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000556 Pos->second.push_back(D);
557 else if (Pos->second.back()->getIdentifierNamespace() == Decl::IDNS_Tag) {
Douglas Gregor4afa39d2009-01-20 01:17:11 +0000558 NamedDecl *TagD = Pos->second.back();
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000559 Pos->second.back() = D;
560 Pos->second.push_back(TagD);
561 } else
562 Pos->second.push_back(D);
Douglas Gregor44b43212008-12-11 16:49:14 +0000563 } else {
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000564 (*Map)[D->getDeclName()].push_back(D);
Douglas Gregor44b43212008-12-11 16:49:14 +0000565 }
566}
Douglas Gregor2a3009a2009-02-03 19:21:40 +0000567
568/// Returns iterator range [First, Last) of UsingDirectiveDecls stored within
569/// this context.
570DeclContext::udir_iterator_range DeclContext::getUsingDirectives() const {
571 lookup_const_result Result = lookup(UsingDirectiveDecl::getName());
572 return udir_iterator_range(reinterpret_cast<udir_iterator>(Result.first),
573 reinterpret_cast<udir_iterator>(Result.second));
574}
575