blob: cb12618443506bca5e0322bb9eacf10491036ab0 [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"
Argyrios Kyrtzidisd3bb44f2008-06-09 21:05:31 +000016#include "clang/AST/DeclCXX.h"
Douglas Gregoraaba5e32009-02-04 19:02:06 +000017#include "clang/AST/DeclObjC.h"
18#include "clang/AST/DeclTemplate.h"
Eli Friedman56d29372008-06-07 16:52:53 +000019#include "clang/AST/ASTContext.h"
Douglas Gregor44b43212008-12-11 16:49:14 +000020#include "clang/AST/Type.h"
Eli Friedman56d29372008-06-07 16:52:53 +000021#include "llvm/ADT/DenseMap.h"
Chris Lattner49f28ca2009-03-05 08:00:35 +000022#include "llvm/Support/raw_ostream.h"
Douglas Gregor6ed40e32008-12-23 21:05:05 +000023#include <algorithm>
Chris Lattner3daed522009-03-02 22:20:04 +000024#include <cstdio>
Douglas Gregor6ed40e32008-12-23 21:05:05 +000025#include <functional>
Douglas Gregor3fc749d2008-12-23 00:26:44 +000026#include <vector>
Eli Friedman56d29372008-06-07 16:52:53 +000027using namespace clang;
28
29//===----------------------------------------------------------------------===//
30// Statistics
31//===----------------------------------------------------------------------===//
32
Douglas Gregor64650af2009-02-02 23:39:07 +000033#define DECL(Derived, Base) static int n##Derived##s = 0;
34#include "clang/AST/DeclNodes.def"
Eli Friedman56d29372008-06-07 16:52:53 +000035
36static bool StatSwitch = false;
37
38// This keeps track of all decl attributes. Since so few decls have attrs, we
39// keep them in a hash map instead of wasting space in the Decl class.
40typedef llvm::DenseMap<const Decl*, Attr*> DeclAttrMapTy;
41
42static DeclAttrMapTy *DeclAttrs = 0;
43
44const char *Decl::getDeclKindName() const {
45 switch (DeclKind) {
Douglas Gregor64650af2009-02-02 23:39:07 +000046 default: assert(0 && "Declaration not in DeclNodes.def!");
47#define DECL(Derived, Base) case Derived: return #Derived;
48#include "clang/AST/DeclNodes.def"
Eli Friedman56d29372008-06-07 16:52:53 +000049 }
50}
51
Steve Naroff0a473932009-01-20 19:53:53 +000052const char *DeclContext::getDeclKindName() const {
53 switch (DeclKind) {
Douglas Gregor64650af2009-02-02 23:39:07 +000054 default: assert(0 && "Declaration context not in DeclNodes.def!");
Argyrios Kyrtzidis1ad4dd72009-02-16 14:28:33 +000055#define DECL(Derived, Base) case Decl::Derived: return #Derived;
Douglas Gregor64650af2009-02-02 23:39:07 +000056#include "clang/AST/DeclNodes.def"
Steve Naroff0a473932009-01-20 19:53:53 +000057 }
58}
59
Eli Friedman56d29372008-06-07 16:52:53 +000060bool Decl::CollectingStats(bool Enable) {
61 if (Enable)
62 StatSwitch = true;
63 return StatSwitch;
64}
65
66void Decl::PrintStats() {
67 fprintf(stderr, "*** Decl Stats:\n");
Eli Friedman56d29372008-06-07 16:52:53 +000068
Douglas Gregor64650af2009-02-02 23:39:07 +000069 int totalDecls = 0;
70#define DECL(Derived, Base) totalDecls += n##Derived##s;
71#include "clang/AST/DeclNodes.def"
72 fprintf(stderr, " %d decls total.\n", totalDecls);
73
74 int totalBytes = 0;
75#define DECL(Derived, Base) \
76 if (n##Derived##s > 0) { \
77 totalBytes += (int)(n##Derived##s * sizeof(Derived##Decl)); \
78 fprintf(stderr, " %d " #Derived " decls, %d each (%d bytes)\n", \
79 n##Derived##s, (int)sizeof(Derived##Decl), \
80 (int)(n##Derived##s * sizeof(Derived##Decl))); \
81 }
82#include "clang/AST/DeclNodes.def"
Eli Friedman56d29372008-06-07 16:52:53 +000083
Douglas Gregor64650af2009-02-02 23:39:07 +000084 fprintf(stderr, "Total bytes = %d\n", totalBytes);
Eli Friedman56d29372008-06-07 16:52:53 +000085}
86
87void Decl::addDeclKind(Kind k) {
88 switch (k) {
Douglas Gregor64650af2009-02-02 23:39:07 +000089 default: assert(0 && "Declaration not in DeclNodes.def!");
90#define DECL(Derived, Base) case Derived: ++n##Derived##s; break;
91#include "clang/AST/DeclNodes.def"
Eli Friedman56d29372008-06-07 16:52:53 +000092 }
93}
94
95//===----------------------------------------------------------------------===//
Chris Lattner49f28ca2009-03-05 08:00:35 +000096// PrettyStackTraceDecl Implementation
97//===----------------------------------------------------------------------===//
98
99void PrettyStackTraceDecl::print(llvm::raw_ostream &OS) const {
100 SourceLocation TheLoc = Loc;
101 if (TheLoc.isInvalid() && TheDecl)
102 TheLoc = TheDecl->getLocation();
103
104 if (TheLoc.isValid()) {
105 TheLoc.print(OS, SM);
106 OS << ": ";
107 }
108
109 OS << Message;
110
111 if (NamedDecl *DN = dyn_cast_or_null<NamedDecl>(TheDecl))
112 OS << " '" << DN->getQualifiedNameAsString() << '\'';
113 OS << '\n';
114}
115
116//===----------------------------------------------------------------------===//
Eli Friedman56d29372008-06-07 16:52:53 +0000117// Decl Implementation
118//===----------------------------------------------------------------------===//
119
Douglas Gregor4afa39d2009-01-20 01:17:11 +0000120void Decl::setDeclContext(DeclContext *DC) {
121 if (isOutOfSemaDC())
122 delete getMultipleDC();
123
124 DeclCtx = reinterpret_cast<uintptr_t>(DC);
125}
126
127void Decl::setLexicalDeclContext(DeclContext *DC) {
128 if (DC == getLexicalDeclContext())
129 return;
130
131 if (isInSemaDC()) {
132 MultipleDC *MDC = new MultipleDC();
133 MDC->SemanticDC = getDeclContext();
134 MDC->LexicalDC = DC;
135 DeclCtx = reinterpret_cast<uintptr_t>(MDC) | 0x1;
136 } else {
137 getMultipleDC()->LexicalDC = DC;
138 }
139}
140
Eli Friedman56d29372008-06-07 16:52:53 +0000141// Out-of-line virtual method providing a home for Decl.
142Decl::~Decl() {
Douglas Gregor4afa39d2009-01-20 01:17:11 +0000143 if (isOutOfSemaDC())
144 delete getMultipleDC();
145
Chris Lattnercc581472009-03-04 06:05:19 +0000146 assert(!HasAttrs && "attributes should have been freed by Destroy");
Eli Friedman56d29372008-06-07 16:52:53 +0000147}
148
149void Decl::addAttr(Attr *NewAttr) {
150 if (!DeclAttrs)
151 DeclAttrs = new DeclAttrMapTy();
152
153 Attr *&ExistingAttr = (*DeclAttrs)[this];
154
155 NewAttr->setNext(ExistingAttr);
156 ExistingAttr = NewAttr;
157
158 HasAttrs = true;
159}
160
161void Decl::invalidateAttrs() {
162 if (!HasAttrs) return;
163
164 HasAttrs = false;
165 (*DeclAttrs)[this] = 0;
166 DeclAttrs->erase(this);
167
168 if (DeclAttrs->empty()) {
169 delete DeclAttrs;
170 DeclAttrs = 0;
171 }
172}
173
Chris Lattner81abbdd2009-03-21 06:27:31 +0000174const Attr *Decl::getAttrsImpl() const {
175 assert(HasAttrs && "getAttrs() should verify this!");
Eli Friedman56d29372008-06-07 16:52:53 +0000176 return (*DeclAttrs)[this];
177}
178
179void Decl::swapAttrs(Decl *RHS) {
180 bool HasLHSAttr = this->HasAttrs;
181 bool HasRHSAttr = RHS->HasAttrs;
182
183 // Usually, neither decl has attrs, nothing to do.
184 if (!HasLHSAttr && !HasRHSAttr) return;
185
186 // If 'this' has no attrs, swap the other way.
187 if (!HasLHSAttr)
188 return RHS->swapAttrs(this);
189
190 // Handle the case when both decls have attrs.
191 if (HasRHSAttr) {
192 std::swap((*DeclAttrs)[this], (*DeclAttrs)[RHS]);
193 return;
194 }
195
196 // Otherwise, LHS has an attr and RHS doesn't.
197 (*DeclAttrs)[RHS] = (*DeclAttrs)[this];
198 (*DeclAttrs).erase(this);
199 this->HasAttrs = false;
200 RHS->HasAttrs = true;
201}
202
203
Chris Lattnercc581472009-03-04 06:05:19 +0000204void Decl::Destroy(ASTContext &C) {
205 // Free attributes for this decl.
206 if (HasAttrs) {
207 DeclAttrMapTy::iterator it = DeclAttrs->find(this);
208 assert(it != DeclAttrs->end() && "No attrs found but HasAttrs is true!");
209
210 // release attributes.
211 it->second->Destroy(C);
212 invalidateAttrs();
213 HasAttrs = false;
214 }
215
Douglas Gregora0fc55f2009-01-13 19:47:12 +0000216#if 0
Douglas Gregor00ad0ef2009-01-20 04:25:11 +0000217 // FIXME: Once ownership is fully understood, we can enable this code
218 if (DeclContext *DC = dyn_cast<DeclContext>(this))
219 DC->decls_begin()->Destroy(C);
Eli Friedman56d29372008-06-07 16:52:53 +0000220
Douglas Gregor00ad0ef2009-01-20 04:25:11 +0000221 // Observe the unrolled recursion. By setting N->NextDeclInScope = 0x0
Douglas Gregor4afa39d2009-01-20 01:17:11 +0000222 // within the loop, only the Destroy method for the first Decl
223 // will deallocate all of the Decls in a chain.
224
Douglas Gregor00ad0ef2009-01-20 04:25:11 +0000225 Decl* N = NextDeclInScope;
Douglas Gregor4afa39d2009-01-20 01:17:11 +0000226
227 while (N) {
Douglas Gregor00ad0ef2009-01-20 04:25:11 +0000228 Decl* Tmp = N->NextDeclInScope;
229 N->NextDeclInScope = 0;
Douglas Gregor4afa39d2009-01-20 01:17:11 +0000230 N->Destroy(C);
231 N = Tmp;
Eli Friedman56d29372008-06-07 16:52:53 +0000232 }
Douglas Gregora0fc55f2009-01-13 19:47:12 +0000233
Eli Friedman56d29372008-06-07 16:52:53 +0000234 this->~Decl();
Steve Naroff3e970492009-01-27 21:25:57 +0000235 C.Deallocate((void *)this);
Douglas Gregor00ad0ef2009-01-20 04:25:11 +0000236#endif
Eli Friedman56d29372008-06-07 16:52:53 +0000237}
238
Argyrios Kyrtzidis42220c52008-10-12 16:14:48 +0000239Decl *Decl::castFromDeclContext (const DeclContext *D) {
Argyrios Kyrtzidis3d7641e2009-02-16 14:29:28 +0000240 Decl::Kind DK = D->getDeclKind();
241 switch(DK) {
242#define DECL_CONTEXT(Name) \
243 case Decl::Name: \
244 return static_cast<Name##Decl*>(const_cast<DeclContext*>(D));
245#define DECL_CONTEXT_BASE(Name)
246#include "clang/AST/DeclNodes.def"
247 default:
248#define DECL_CONTEXT_BASE(Name) \
249 if (DK >= Decl::Name##First && DK <= Decl::Name##Last) \
250 return static_cast<Name##Decl*>(const_cast<DeclContext*>(D));
251#include "clang/AST/DeclNodes.def"
252 assert(false && "a decl that inherits DeclContext isn't handled");
253 return 0;
254 }
Argyrios Kyrtzidis42220c52008-10-12 16:14:48 +0000255}
256
257DeclContext *Decl::castToDeclContext(const Decl *D) {
Argyrios Kyrtzidis3d7641e2009-02-16 14:29:28 +0000258 Decl::Kind DK = D->getKind();
259 switch(DK) {
260#define DECL_CONTEXT(Name) \
261 case Decl::Name: \
262 return static_cast<Name##Decl*>(const_cast<Decl*>(D));
263#define DECL_CONTEXT_BASE(Name)
264#include "clang/AST/DeclNodes.def"
265 default:
266#define DECL_CONTEXT_BASE(Name) \
267 if (DK >= Decl::Name##First && DK <= Decl::Name##Last) \
268 return static_cast<Name##Decl*>(const_cast<Decl*>(D));
269#include "clang/AST/DeclNodes.def"
270 assert(false && "a decl that inherits DeclContext isn't handled");
271 return 0;
272 }
Argyrios Kyrtzidis42220c52008-10-12 16:14:48 +0000273}
274
Anders Carlsson1329c272009-03-25 23:38:06 +0000275#ifndef NDEBUG
276void Decl::CheckAccessDeclContext() const {
277 assert((Access != AS_none || !isa<CXXRecordDecl>(getDeclContext())) &&
278 "Access specifier is AS_none inside a record decl");
279}
280
281#endif
282
Eli Friedman56d29372008-06-07 16:52:53 +0000283//===----------------------------------------------------------------------===//
284// DeclContext Implementation
285//===----------------------------------------------------------------------===//
286
Argyrios Kyrtzidis3d7641e2009-02-16 14:29:28 +0000287bool DeclContext::classof(const Decl *D) {
288 switch (D->getKind()) {
289#define DECL_CONTEXT(Name) case Decl::Name:
290#define DECL_CONTEXT_BASE(Name)
291#include "clang/AST/DeclNodes.def"
292 return true;
293 default:
294#define DECL_CONTEXT_BASE(Name) \
295 if (D->getKind() >= Decl::Name##First && \
296 D->getKind() <= Decl::Name##Last) \
297 return true;
298#include "clang/AST/DeclNodes.def"
299 return false;
300 }
301}
302
Chris Lattner67762a32009-02-20 01:44:05 +0000303/// StoredDeclsList - This is an array of decls optimized a common case of only
304/// containing one entry.
305struct StoredDeclsList {
306 /// Data - If the integer is 0, then the pointer is a NamedDecl*. If the
307 /// integer is 1, then it is a VectorTy;
308 llvm::PointerIntPair<void*, 1, bool> Data;
309
310 /// VectorTy - When in vector form, this is what the Data pointer points to.
311 typedef llvm::SmallVector<NamedDecl*, 4> VectorTy;
312public:
313 StoredDeclsList() {}
314 StoredDeclsList(const StoredDeclsList &RHS) : Data(RHS.Data) {
315 if (isVector())
316 Data.setPointer(new VectorTy(getVector()));
317 }
318
319 ~StoredDeclsList() {
320 // If this is a vector-form, free the vector.
321 if (isVector())
322 delete &getVector();
323 }
324
Chris Lattner01011d42009-02-23 18:17:44 +0000325 StoredDeclsList &operator=(const StoredDeclsList &RHS) {
326 if (isVector())
327 delete &getVector();
328 Data = RHS.Data;
329 if (isVector())
330 Data.setPointer(new VectorTy(getVector()));
331 return *this;
332 }
333
Chris Lattner67762a32009-02-20 01:44:05 +0000334 bool isVector() const { return Data.getInt() != 0; }
335 bool isInline() const { return Data.getInt() == 0; }
336 bool isNull() const { return Data.getPointer() == 0; }
337
338 void setOnlyValue(NamedDecl *ND) {
339 assert(isInline() && "Not inline");
340 Data.setPointer(ND);
341 }
342
343 /// getLookupResult - Return an array of all the decls that this list
344 /// represents.
345 DeclContext::lookup_result getLookupResult() {
346 // If we have a single inline unit, return it.
347 if (isInline()) {
348 assert(!isNull() && "Empty list isn't allowed");
349
350 // Data is a raw pointer to a NamedDecl*, return it.
351 void *Ptr = &Data;
352 return DeclContext::lookup_result((NamedDecl**)Ptr, (NamedDecl**)Ptr+1);
353 }
354
355 // Otherwise, we have a range result.
356 VectorTy &V = getVector();
357 return DeclContext::lookup_result(&V[0], &V[0]+V.size());
358 }
359
360 /// HandleRedeclaration - If this is a redeclaration of an existing decl,
361 /// replace the old one with D and return true. Otherwise return false.
362 bool HandleRedeclaration(NamedDecl *D) {
363 // Most decls only have one entry in their list, special case it.
364 if (isInline()) {
365 if (!D->declarationReplaces(getInlineValue()))
366 return false;
367 setOnlyValue(D);
368 return true;
369 }
370
371 // Determine if this declaration is actually a redeclaration.
372 VectorTy &Vec = getVector();
373 VectorTy::iterator RDI
374 = std::find_if(Vec.begin(), Vec.end(),
375 std::bind1st(std::mem_fun(&NamedDecl::declarationReplaces),
376 D));
377 if (RDI == Vec.end())
378 return false;
379 *RDI = D;
380 return true;
381 }
382
383 /// AddSubsequentDecl - This is called on the second and later decl when it is
384 /// not a redeclaration to merge it into the appropriate place in our list.
385 ///
386 void AddSubsequentDecl(NamedDecl *D) {
387 // If this is the second decl added to the list, convert this to vector
388 // form.
389 if (isInline()) {
390 NamedDecl *OldD = getInlineValue();
391 Data.setInt(1);
392 VectorTy *VT = new VectorTy();
393 VT->push_back(OldD);
394 Data.setPointer(VT);
395 }
396
397 VectorTy &Vec = getVector();
398 if (isa<UsingDirectiveDecl>(D) ||
399 D->getIdentifierNamespace() == Decl::IDNS_Tag)
400 Vec.push_back(D);
401 else if (Vec.back()->getIdentifierNamespace() == Decl::IDNS_Tag) {
402 NamedDecl *TagD = Vec.back();
403 Vec.back() = D;
404 Vec.push_back(TagD);
405 } else
406 Vec.push_back(D);
407 }
408
409
410private:
411 VectorTy &getVector() const {
412 assert(isVector() && "Not in vector form");
413 return *static_cast<VectorTy*>(Data.getPointer());
414 }
415
416 NamedDecl *getInlineValue() const {
417 assert(isInline() && "Not in inline form");
418 return (NamedDecl*)Data.getPointer();
419 }
420};
421
422
423
424typedef llvm::DenseMap<DeclarationName, StoredDeclsList> StoredDeclsMap;
Douglas Gregor44b43212008-12-11 16:49:14 +0000425
426DeclContext::~DeclContext() {
427 unsigned Size = LookupPtr.getInt();
Chris Lattner91942502009-02-20 00:55:03 +0000428 if (Size == LookupIsMap)
429 delete static_cast<StoredDeclsMap*>(LookupPtr.getPointer());
430 else
431 delete [] static_cast<NamedDecl**>(LookupPtr.getPointer());
Douglas Gregor44b43212008-12-11 16:49:14 +0000432}
433
434void DeclContext::DestroyDecls(ASTContext &C) {
Douglas Gregor00ad0ef2009-01-20 04:25:11 +0000435 for (decl_iterator D = decls_begin(); D != decls_end(); )
436 (*D++)->Destroy(C);
Douglas Gregor44b43212008-12-11 16:49:14 +0000437}
438
Douglas Gregor074149e2009-01-05 19:45:36 +0000439bool DeclContext::isTransparentContext() const {
440 if (DeclKind == Decl::Enum)
441 return true; // FIXME: Check for C++0x scoped enums
442 else if (DeclKind == Decl::LinkageSpec)
443 return true;
Douglas Gregor65100792009-02-26 00:02:51 +0000444 else if (DeclKind >= Decl::RecordFirst && DeclKind <= Decl::RecordLast)
Douglas Gregorbcbffc42009-01-07 00:43:41 +0000445 return cast<RecordDecl>(this)->isAnonymousStructOrUnion();
Douglas Gregor074149e2009-01-05 19:45:36 +0000446 else if (DeclKind == Decl::Namespace)
447 return false; // FIXME: Check for C++0x inline namespaces
448
449 return false;
450}
451
Steve Naroff0701bbb2009-01-08 17:28:14 +0000452DeclContext *DeclContext::getPrimaryContext() {
Douglas Gregor44b43212008-12-11 16:49:14 +0000453 switch (DeclKind) {
Douglas Gregor44b43212008-12-11 16:49:14 +0000454 case Decl::TranslationUnit:
Douglas Gregor074149e2009-01-05 19:45:36 +0000455 case Decl::LinkageSpec:
456 case Decl::Block:
Douglas Gregor44b43212008-12-11 16:49:14 +0000457 // There is only one DeclContext for these entities.
458 return this;
459
460 case Decl::Namespace:
461 // The original namespace is our primary context.
462 return static_cast<NamespaceDecl*>(this)->getOriginalNamespace();
463
Douglas Gregor44b43212008-12-11 16:49:14 +0000464 case Decl::ObjCMethod:
465 return this;
466
467 case Decl::ObjCInterface:
Steve Naroff0701bbb2009-01-08 17:28:14 +0000468 case Decl::ObjCProtocol:
469 case Decl::ObjCCategory:
Douglas Gregor44b43212008-12-11 16:49:14 +0000470 // FIXME: Can Objective-C interfaces be forward-declared?
471 return this;
472
Steve Naroff0701bbb2009-01-08 17:28:14 +0000473 case Decl::ObjCImplementation:
474 case Decl::ObjCCategoryImpl:
475 return this;
476
Douglas Gregor44b43212008-12-11 16:49:14 +0000477 default:
Douglas Gregorcc636682009-02-17 23:15:12 +0000478 if (DeclKind >= Decl::TagFirst && DeclKind <= Decl::TagLast) {
479 // If this is a tag type that has a definition or is currently
480 // being defined, that definition is our primary context.
Douglas Gregorfc705b82009-02-26 22:19:44 +0000481 if (const TagType *TagT = cast<TagDecl>(this)->TypeForDecl->getAsTagType())
Douglas Gregorcc636682009-02-17 23:15:12 +0000482 if (TagT->isBeingDefined() ||
483 (TagT->getDecl() && TagT->getDecl()->isDefinition()))
484 return TagT->getDecl();
485 return this;
486 }
487
Douglas Gregor44b43212008-12-11 16:49:14 +0000488 assert(DeclKind >= Decl::FunctionFirst && DeclKind <= Decl::FunctionLast &&
489 "Unknown DeclContext kind");
490 return this;
491 }
492}
493
494DeclContext *DeclContext::getNextContext() {
495 switch (DeclKind) {
Douglas Gregor44b43212008-12-11 16:49:14 +0000496 case Decl::Namespace:
497 // Return the next namespace
498 return static_cast<NamespaceDecl*>(this)->getNextNamespace();
499
500 default:
Douglas Gregor44b43212008-12-11 16:49:14 +0000501 return 0;
502 }
503}
504
Douglas Gregor4afa39d2009-01-20 01:17:11 +0000505void DeclContext::addDecl(Decl *D) {
Chris Lattner7f0be132009-02-20 00:56:18 +0000506 assert(D->getLexicalDeclContext() == this &&
507 "Decl inserted into wrong lexical context");
Douglas Gregor6037fcb2009-01-09 19:42:16 +0000508 assert(!D->NextDeclInScope && D != LastDecl &&
509 "Decl already inserted into a DeclContext");
510
511 if (FirstDecl) {
512 LastDecl->NextDeclInScope = D;
513 LastDecl = D;
514 } else {
515 FirstDecl = LastDecl = D;
516 }
Douglas Gregor4afa39d2009-01-20 01:17:11 +0000517
518 if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
Douglas Gregor40f4e692009-01-20 16:54:50 +0000519 ND->getDeclContext()->makeDeclVisibleInContext(ND);
Douglas Gregor44b43212008-12-11 16:49:14 +0000520}
521
Douglas Gregor074149e2009-01-05 19:45:36 +0000522/// buildLookup - Build the lookup data structure with all of the
523/// declarations in DCtx (and any other contexts linked to it or
524/// transparent contexts nested within it).
Steve Naroff0701bbb2009-01-08 17:28:14 +0000525void DeclContext::buildLookup(DeclContext *DCtx) {
Douglas Gregor074149e2009-01-05 19:45:36 +0000526 for (; DCtx; DCtx = DCtx->getNextContext()) {
Douglas Gregor4f3b8f82009-01-06 07:17:58 +0000527 for (decl_iterator D = DCtx->decls_begin(), DEnd = DCtx->decls_end();
528 D != DEnd; ++D) {
Douglas Gregor074149e2009-01-05 19:45:36 +0000529 // Insert this declaration into the lookup structure
Douglas Gregor4afa39d2009-01-20 01:17:11 +0000530 if (NamedDecl *ND = dyn_cast<NamedDecl>(*D))
Douglas Gregor40f4e692009-01-20 16:54:50 +0000531 makeDeclVisibleInContextImpl(ND);
Douglas Gregor074149e2009-01-05 19:45:36 +0000532
533 // If this declaration is itself a transparent declaration context,
534 // add its members (recursively).
535 if (DeclContext *InnerCtx = dyn_cast<DeclContext>(*D))
536 if (InnerCtx->isTransparentContext())
Steve Naroff0701bbb2009-01-08 17:28:14 +0000537 buildLookup(InnerCtx->getPrimaryContext());
Douglas Gregor074149e2009-01-05 19:45:36 +0000538 }
539 }
540}
541
Douglas Gregor44b43212008-12-11 16:49:14 +0000542DeclContext::lookup_result
Steve Naroff0701bbb2009-01-08 17:28:14 +0000543DeclContext::lookup(DeclarationName Name) {
544 DeclContext *PrimaryContext = getPrimaryContext();
Douglas Gregor44b43212008-12-11 16:49:14 +0000545 if (PrimaryContext != this)
Steve Naroff0701bbb2009-01-08 17:28:14 +0000546 return PrimaryContext->lookup(Name);
Douglas Gregor44b43212008-12-11 16:49:14 +0000547
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000548 /// If there is no lookup data structure, build one now by walking
Douglas Gregor44b43212008-12-11 16:49:14 +0000549 /// all of the linked DeclContexts (in declaration order!) and
550 /// inserting their values.
Douglas Gregor074149e2009-01-05 19:45:36 +0000551 if (LookupPtr.getPointer() == 0)
Steve Naroff0701bbb2009-01-08 17:28:14 +0000552 buildLookup(this);
Douglas Gregor44b43212008-12-11 16:49:14 +0000553
Douglas Gregor44b43212008-12-11 16:49:14 +0000554 if (isLookupMap()) {
555 StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(LookupPtr.getPointer());
556 StoredDeclsMap::iterator Pos = Map->find(Name);
Chris Lattner91942502009-02-20 00:55:03 +0000557 if (Pos == Map->end())
558 return lookup_result(0, 0);
Chris Lattner67762a32009-02-20 01:44:05 +0000559 return Pos->second.getLookupResult();
Douglas Gregor44b43212008-12-11 16:49:14 +0000560 }
561
562 // We have a small array. Look into it.
563 unsigned Size = LookupPtr.getInt();
Douglas Gregor4afa39d2009-01-20 01:17:11 +0000564 NamedDecl **Array = static_cast<NamedDecl**>(LookupPtr.getPointer());
Douglas Gregore267ff32008-12-11 20:41:00 +0000565 for (unsigned Idx = 0; Idx != Size; ++Idx)
Douglas Gregor44b43212008-12-11 16:49:14 +0000566 if (Array[Idx]->getDeclName() == Name) {
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000567 unsigned Last = Idx + 1;
568 while (Last != Size && Array[Last]->getDeclName() == Name)
569 ++Last;
570 return lookup_result(&Array[Idx], &Array[Last]);
Douglas Gregor44b43212008-12-11 16:49:14 +0000571 }
572
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000573 return lookup_result(0, 0);
Douglas Gregor44b43212008-12-11 16:49:14 +0000574}
575
576DeclContext::lookup_const_result
Steve Naroff0701bbb2009-01-08 17:28:14 +0000577DeclContext::lookup(DeclarationName Name) const {
578 return const_cast<DeclContext*>(this)->lookup(Name);
Douglas Gregor44b43212008-12-11 16:49:14 +0000579}
580
Douglas Gregor17a9b9e2009-01-07 02:48:43 +0000581const DeclContext *DeclContext::getLookupContext() const {
582 const DeclContext *Ctx = this;
Douglas Gregor72de6672009-01-08 20:45:30 +0000583 // Skip through transparent contexts.
Douglas Gregorce356072009-01-06 23:51:29 +0000584 while (Ctx->isTransparentContext())
585 Ctx = Ctx->getParent();
586 return Ctx;
587}
588
Douglas Gregor88b70942009-02-25 22:02:03 +0000589DeclContext *DeclContext::getEnclosingNamespaceContext() {
590 DeclContext *Ctx = this;
591 // Skip through non-namespace, non-translation-unit contexts.
592 while (!Ctx->isFileContext() || Ctx->isTransparentContext())
593 Ctx = Ctx->getParent();
594 return Ctx->getPrimaryContext();
595}
596
Douglas Gregor40f4e692009-01-20 16:54:50 +0000597void DeclContext::makeDeclVisibleInContext(NamedDecl *D) {
Douglas Gregorcc636682009-02-17 23:15:12 +0000598 // FIXME: This feels like a hack. Should DeclarationName support
599 // template-ids, or is there a better way to keep specializations
600 // from being visible?
601 if (isa<ClassTemplateSpecializationDecl>(D))
602 return;
603
Steve Naroff0701bbb2009-01-08 17:28:14 +0000604 DeclContext *PrimaryContext = getPrimaryContext();
Douglas Gregor44b43212008-12-11 16:49:14 +0000605 if (PrimaryContext != this) {
Douglas Gregor40f4e692009-01-20 16:54:50 +0000606 PrimaryContext->makeDeclVisibleInContext(D);
Douglas Gregor44b43212008-12-11 16:49:14 +0000607 return;
608 }
609
610 // If we already have a lookup data structure, perform the insertion
611 // into it. Otherwise, be lazy and don't build that structure until
612 // someone asks for it.
613 if (LookupPtr.getPointer())
Douglas Gregor40f4e692009-01-20 16:54:50 +0000614 makeDeclVisibleInContextImpl(D);
Douglas Gregor074149e2009-01-05 19:45:36 +0000615
Douglas Gregor074149e2009-01-05 19:45:36 +0000616 // If we are a transparent context, insert into our parent context,
617 // too. This operation is recursive.
618 if (isTransparentContext())
Douglas Gregor40f4e692009-01-20 16:54:50 +0000619 getParent()->makeDeclVisibleInContext(D);
Douglas Gregor44b43212008-12-11 16:49:14 +0000620}
621
Douglas Gregor40f4e692009-01-20 16:54:50 +0000622void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D) {
Douglas Gregor074149e2009-01-05 19:45:36 +0000623 // Skip unnamed declarations.
624 if (!D->getDeclName())
625 return;
626
Douglas Gregorcc636682009-02-17 23:15:12 +0000627 // FIXME: This feels like a hack. Should DeclarationName support
628 // template-ids, or is there a better way to keep specializations
629 // from being visible?
630 if (isa<ClassTemplateSpecializationDecl>(D))
631 return;
632
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000633 bool MayBeRedeclaration = true;
634
Douglas Gregor44b43212008-12-11 16:49:14 +0000635 if (!isLookupMap()) {
636 unsigned Size = LookupPtr.getInt();
637
638 // The lookup data is stored as an array. Search through the array
639 // to find the insertion location.
Douglas Gregor4afa39d2009-01-20 01:17:11 +0000640 NamedDecl **Array;
Douglas Gregor44b43212008-12-11 16:49:14 +0000641 if (Size == 0) {
Douglas Gregor4afa39d2009-01-20 01:17:11 +0000642 Array = new NamedDecl*[LookupIsMap - 1];
Douglas Gregor44b43212008-12-11 16:49:14 +0000643 LookupPtr.setPointer(Array);
644 } else {
Douglas Gregor4afa39d2009-01-20 01:17:11 +0000645 Array = static_cast<NamedDecl **>(LookupPtr.getPointer());
Douglas Gregor44b43212008-12-11 16:49:14 +0000646 }
647
648 // We always keep declarations of the same name next to each other
649 // in the array, so that it is easy to return multiple results
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000650 // from lookup().
651 unsigned FirstMatch;
652 for (FirstMatch = 0; FirstMatch != Size; ++FirstMatch)
653 if (Array[FirstMatch]->getDeclName() == D->getDeclName())
Douglas Gregore267ff32008-12-11 20:41:00 +0000654 break;
Douglas Gregor44b43212008-12-11 16:49:14 +0000655
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000656 unsigned InsertPos = FirstMatch;
657 if (FirstMatch != Size) {
658 // We found another declaration with the same name. First
659 // determine whether this is a redeclaration of an existing
660 // declaration in this scope, in which case we will replace the
661 // existing declaration.
662 unsigned LastMatch = FirstMatch;
663 for (; LastMatch != Size; ++LastMatch) {
664 if (Array[LastMatch]->getDeclName() != D->getDeclName())
665 break;
666
Douglas Gregor6ed40e32008-12-23 21:05:05 +0000667 if (D->declarationReplaces(Array[LastMatch])) {
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000668 // D is a redeclaration of an existing element in the
669 // array. Replace that element with D.
670 Array[LastMatch] = D;
671 return;
672 }
Douglas Gregor44b43212008-12-11 16:49:14 +0000673 }
674
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000675 // [FirstMatch, LastMatch) contains the set of declarations that
676 // have the same name as this declaration. Determine where the
Douglas Gregor2a3009a2009-02-03 19:21:40 +0000677 // declaration D will be inserted into this range.
678 if (D->getKind() == Decl::UsingDirective ||
679 D->getIdentifierNamespace() == Decl::IDNS_Tag)
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000680 InsertPos = LastMatch;
681 else if (Array[LastMatch-1]->getIdentifierNamespace() == Decl::IDNS_Tag)
682 InsertPos = LastMatch - 1;
683 else
684 InsertPos = LastMatch;
Douglas Gregor44b43212008-12-11 16:49:14 +0000685 }
686
687 if (Size < LookupIsMap - 1) {
688 // The new declaration will fit in the array. Insert the new
689 // declaration at the position Match in the array.
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000690 for (unsigned Idx = Size; Idx > InsertPos; --Idx)
Douglas Gregor44b43212008-12-11 16:49:14 +0000691 Array[Idx] = Array[Idx-1];
692
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000693 Array[InsertPos] = D;
Douglas Gregor44b43212008-12-11 16:49:14 +0000694 LookupPtr.setInt(Size + 1);
695 return;
696 }
697
698 // We've reached capacity in this array. Create a map and copy in
699 // all of the declarations that were stored in the array.
700 StoredDeclsMap *Map = new StoredDeclsMap(16);
701 LookupPtr.setPointer(Map);
702 LookupPtr.setInt(LookupIsMap);
Douglas Gregore267ff32008-12-11 20:41:00 +0000703 for (unsigned Idx = 0; Idx != LookupIsMap - 1; ++Idx)
Douglas Gregor40f4e692009-01-20 16:54:50 +0000704 makeDeclVisibleInContextImpl(Array[Idx]);
Douglas Gregor44b43212008-12-11 16:49:14 +0000705 delete [] Array;
706
707 // Fall through to perform insertion into the map.
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000708 MayBeRedeclaration = false;
709 }
Douglas Gregor44b43212008-12-11 16:49:14 +0000710
711 // Insert this declaration into the map.
Chris Lattner67762a32009-02-20 01:44:05 +0000712 StoredDeclsMap &Map = *static_cast<StoredDeclsMap*>(LookupPtr.getPointer());
713 StoredDeclsList &DeclNameEntries = Map[D->getDeclName()];
714 if (DeclNameEntries.isNull()) {
715 DeclNameEntries.setOnlyValue(D);
Chris Lattnerbd6c8002009-02-19 07:00:44 +0000716 return;
Douglas Gregor44b43212008-12-11 16:49:14 +0000717 }
Chris Lattner91942502009-02-20 00:55:03 +0000718
Chris Lattnerbdc3d002009-02-20 01:10:07 +0000719 // If it is possible that this is a redeclaration, check to see if there is
720 // already a decl for which declarationReplaces returns true. If there is
721 // one, just replace it and return.
Chris Lattner67762a32009-02-20 01:44:05 +0000722 if (MayBeRedeclaration && DeclNameEntries.HandleRedeclaration(D))
723 return;
Chris Lattner91942502009-02-20 00:55:03 +0000724
Chris Lattnerbd6c8002009-02-19 07:00:44 +0000725 // Put this declaration into the appropriate slot.
Chris Lattner67762a32009-02-20 01:44:05 +0000726 DeclNameEntries.AddSubsequentDecl(D);
Douglas Gregor44b43212008-12-11 16:49:14 +0000727}
Douglas Gregor2a3009a2009-02-03 19:21:40 +0000728
729/// Returns iterator range [First, Last) of UsingDirectiveDecls stored within
730/// this context.
731DeclContext::udir_iterator_range DeclContext::getUsingDirectives() const {
732 lookup_const_result Result = lookup(UsingDirectiveDecl::getName());
733 return udir_iterator_range(reinterpret_cast<udir_iterator>(Result.first),
734 reinterpret_cast<udir_iterator>(Result.second));
735}
736