blob: 45ba794d6bcc009a44e9f89890a8c73117eb63ce [file] [log] [blame]
Eli Friedmana8a09ac2008-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"
Daniel Dunbarde300732008-08-11 04:54:23 +000015#include "clang/AST/DeclObjC.h"
Argiris Kirtzidis6df1fc02008-06-09 21:05:31 +000016#include "clang/AST/DeclCXX.h"
Eli Friedmana8a09ac2008-06-07 16:52:53 +000017#include "clang/AST/ASTContext.h"
Douglas Gregor8acb7272008-12-11 16:49:14 +000018#include "clang/AST/Type.h"
Eli Friedmana8a09ac2008-06-07 16:52:53 +000019#include "llvm/ADT/DenseMap.h"
20using namespace clang;
21
22//===----------------------------------------------------------------------===//
23// Statistics
24//===----------------------------------------------------------------------===//
25
26// temporary statistics gathering
27static unsigned nFuncs = 0;
28static unsigned nVars = 0;
29static unsigned nParmVars = 0;
30static unsigned nSUC = 0;
Argiris Kirtzidisaefcabd2008-08-10 01:47:31 +000031static unsigned nCXXSUC = 0;
Eli Friedmana8a09ac2008-06-07 16:52:53 +000032static unsigned nEnumConst = 0;
33static unsigned nEnumDecls = 0;
34static unsigned nNamespaces = 0;
Douglas Gregord2baafd2008-10-21 16:13:35 +000035static unsigned nOverFuncs = 0;
Eli Friedmana8a09ac2008-06-07 16:52:53 +000036static unsigned nTypedef = 0;
37static unsigned nFieldDecls = 0;
38static unsigned nInterfaceDecls = 0;
39static unsigned nClassDecls = 0;
40static unsigned nMethodDecls = 0;
41static unsigned nProtocolDecls = 0;
42static unsigned nForwardProtocolDecls = 0;
43static unsigned nCategoryDecls = 0;
44static unsigned nIvarDecls = 0;
Ted Kremeneke5bedfe2008-08-20 03:26:33 +000045static unsigned nAtDefsFieldDecls = 0;
Eli Friedmana8a09ac2008-06-07 16:52:53 +000046static unsigned nObjCImplementationDecls = 0;
47static unsigned nObjCCategoryImpl = 0;
48static unsigned nObjCCompatibleAlias = 0;
49static unsigned nObjCPropertyDecl = 0;
50static unsigned nObjCPropertyImplDecl = 0;
51static unsigned nLinkageSpecDecl = 0;
52static unsigned nFileScopeAsmDecl = 0;
Steve Naroff9ac456d2008-10-08 17:01:13 +000053static unsigned nBlockDecls = 0;
Eli Friedmana8a09ac2008-06-07 16:52:53 +000054
55static bool StatSwitch = false;
56
57// This keeps track of all decl attributes. Since so few decls have attrs, we
58// keep them in a hash map instead of wasting space in the Decl class.
59typedef llvm::DenseMap<const Decl*, Attr*> DeclAttrMapTy;
60
61static DeclAttrMapTy *DeclAttrs = 0;
62
63const char *Decl::getDeclKindName() const {
64 switch (DeclKind) {
65 default: assert(0 && "Unknown decl kind!");
66 case Namespace: return "Namespace";
Douglas Gregord2baafd2008-10-21 16:13:35 +000067 case OverloadedFunction: return "OverloadedFunction";
Eli Friedmana8a09ac2008-06-07 16:52:53 +000068 case Typedef: return "Typedef";
69 case Function: return "Function";
70 case Var: return "Var";
71 case ParmVar: return "ParmVar";
72 case EnumConstant: return "EnumConstant";
73 case ObjCIvar: return "ObjCIvar";
74 case ObjCInterface: return "ObjCInterface";
Steve Naroff110be842008-12-01 20:33:01 +000075 case ObjCImplementation: return "ObjCImplementation";
Eli Friedmana8a09ac2008-06-07 16:52:53 +000076 case ObjCClass: return "ObjCClass";
77 case ObjCMethod: return "ObjCMethod";
78 case ObjCProtocol: return "ObjCProtocol";
Steve Naroff110be842008-12-01 20:33:01 +000079 case ObjCProperty: return "ObjCProperty";
80 case ObjCPropertyImpl: return "ObjCPropertyImpl";
Eli Friedmana8a09ac2008-06-07 16:52:53 +000081 case ObjCForwardProtocol: return "ObjCForwardProtocol";
Argiris Kirtzidis2538a8c2008-10-15 00:42:39 +000082 case Record: return "Record";
83 case CXXRecord: return "CXXRecord";
Eli Friedmana8a09ac2008-06-07 16:52:53 +000084 case Enum: return "Enum";
Steve Naroff9ac456d2008-10-08 17:01:13 +000085 case Block: return "Block";
Eli Friedmana8a09ac2008-06-07 16:52:53 +000086 }
87}
88
89bool Decl::CollectingStats(bool Enable) {
90 if (Enable)
91 StatSwitch = true;
92 return StatSwitch;
93}
94
95void Decl::PrintStats() {
96 fprintf(stderr, "*** Decl Stats:\n");
97 fprintf(stderr, " %d decls total.\n",
Douglas Gregor8acb7272008-12-11 16:49:14 +000098 int(nFuncs+nVars+nParmVars+nFieldDecls+nSUC+nCXXSUC+
Eli Friedmana8a09ac2008-06-07 16:52:53 +000099 nEnumDecls+nEnumConst+nTypedef+nInterfaceDecls+nClassDecls+
100 nMethodDecls+nProtocolDecls+nCategoryDecls+nIvarDecls+
Douglas Gregord2baafd2008-10-21 16:13:35 +0000101 nAtDefsFieldDecls+nNamespaces+nOverFuncs));
Eli Friedmana8a09ac2008-06-07 16:52:53 +0000102 fprintf(stderr, " %d namespace decls, %d each (%d bytes)\n",
103 nNamespaces, (int)sizeof(NamespaceDecl),
104 int(nNamespaces*sizeof(NamespaceDecl)));
Douglas Gregord2baafd2008-10-21 16:13:35 +0000105 fprintf(stderr, " %d overloaded function decls, %d each (%d bytes)\n",
106 nOverFuncs, (int)sizeof(OverloadedFunctionDecl),
107 int(nOverFuncs*sizeof(OverloadedFunctionDecl)));
Eli Friedmana8a09ac2008-06-07 16:52:53 +0000108 fprintf(stderr, " %d function decls, %d each (%d bytes)\n",
109 nFuncs, (int)sizeof(FunctionDecl), int(nFuncs*sizeof(FunctionDecl)));
110 fprintf(stderr, " %d variable decls, %d each (%d bytes)\n",
111 nVars, (int)sizeof(VarDecl),
112 int(nVars*sizeof(VarDecl)));
113 fprintf(stderr, " %d parameter variable decls, %d each (%d bytes)\n",
114 nParmVars, (int)sizeof(ParmVarDecl),
115 int(nParmVars*sizeof(ParmVarDecl)));
116 fprintf(stderr, " %d field decls, %d each (%d bytes)\n",
117 nFieldDecls, (int)sizeof(FieldDecl),
118 int(nFieldDecls*sizeof(FieldDecl)));
Ted Kremeneke5bedfe2008-08-20 03:26:33 +0000119 fprintf(stderr, " %d @defs generated field decls, %d each (%d bytes)\n",
120 nAtDefsFieldDecls, (int)sizeof(ObjCAtDefsFieldDecl),
121 int(nAtDefsFieldDecls*sizeof(ObjCAtDefsFieldDecl)));
Eli Friedmana8a09ac2008-06-07 16:52:53 +0000122 fprintf(stderr, " %d struct/union/class decls, %d each (%d bytes)\n",
123 nSUC, (int)sizeof(RecordDecl),
124 int(nSUC*sizeof(RecordDecl)));
Argiris Kirtzidisaefcabd2008-08-10 01:47:31 +0000125 fprintf(stderr, " %d C++ struct/union/class decls, %d each (%d bytes)\n",
126 nCXXSUC, (int)sizeof(CXXRecordDecl),
127 int(nCXXSUC*sizeof(CXXRecordDecl)));
Eli Friedmana8a09ac2008-06-07 16:52:53 +0000128 fprintf(stderr, " %d enum decls, %d each (%d bytes)\n",
129 nEnumDecls, (int)sizeof(EnumDecl),
130 int(nEnumDecls*sizeof(EnumDecl)));
131 fprintf(stderr, " %d enum constant decls, %d each (%d bytes)\n",
132 nEnumConst, (int)sizeof(EnumConstantDecl),
133 int(nEnumConst*sizeof(EnumConstantDecl)));
134 fprintf(stderr, " %d typedef decls, %d each (%d bytes)\n",
135 nTypedef, (int)sizeof(TypedefDecl),int(nTypedef*sizeof(TypedefDecl)));
136 // Objective-C decls...
137 fprintf(stderr, " %d interface decls, %d each (%d bytes)\n",
138 nInterfaceDecls, (int)sizeof(ObjCInterfaceDecl),
139 int(nInterfaceDecls*sizeof(ObjCInterfaceDecl)));
140 fprintf(stderr, " %d instance variable decls, %d each (%d bytes)\n",
141 nIvarDecls, (int)sizeof(ObjCIvarDecl),
142 int(nIvarDecls*sizeof(ObjCIvarDecl)));
143 fprintf(stderr, " %d class decls, %d each (%d bytes)\n",
144 nClassDecls, (int)sizeof(ObjCClassDecl),
145 int(nClassDecls*sizeof(ObjCClassDecl)));
146 fprintf(stderr, " %d method decls, %d each (%d bytes)\n",
147 nMethodDecls, (int)sizeof(ObjCMethodDecl),
148 int(nMethodDecls*sizeof(ObjCMethodDecl)));
149 fprintf(stderr, " %d protocol decls, %d each (%d bytes)\n",
150 nProtocolDecls, (int)sizeof(ObjCProtocolDecl),
151 int(nProtocolDecls*sizeof(ObjCProtocolDecl)));
152 fprintf(stderr, " %d forward protocol decls, %d each (%d bytes)\n",
153 nForwardProtocolDecls, (int)sizeof(ObjCForwardProtocolDecl),
154 int(nForwardProtocolDecls*sizeof(ObjCForwardProtocolDecl)));
155 fprintf(stderr, " %d category decls, %d each (%d bytes)\n",
156 nCategoryDecls, (int)sizeof(ObjCCategoryDecl),
157 int(nCategoryDecls*sizeof(ObjCCategoryDecl)));
158
159 fprintf(stderr, " %d class implementation decls, %d each (%d bytes)\n",
160 nObjCImplementationDecls, (int)sizeof(ObjCImplementationDecl),
161 int(nObjCImplementationDecls*sizeof(ObjCImplementationDecl)));
162
163 fprintf(stderr, " %d class implementation decls, %d each (%d bytes)\n",
164 nObjCCategoryImpl, (int)sizeof(ObjCCategoryImplDecl),
165 int(nObjCCategoryImpl*sizeof(ObjCCategoryImplDecl)));
166
167 fprintf(stderr, " %d compatibility alias decls, %d each (%d bytes)\n",
168 nObjCCompatibleAlias, (int)sizeof(ObjCCompatibleAliasDecl),
169 int(nObjCCompatibleAlias*sizeof(ObjCCompatibleAliasDecl)));
170
171 fprintf(stderr, " %d property decls, %d each (%d bytes)\n",
172 nObjCPropertyDecl, (int)sizeof(ObjCPropertyDecl),
173 int(nObjCPropertyDecl*sizeof(ObjCPropertyDecl)));
174
175 fprintf(stderr, " %d property implementation decls, %d each (%d bytes)\n",
176 nObjCPropertyImplDecl, (int)sizeof(ObjCPropertyImplDecl),
177 int(nObjCPropertyImplDecl*sizeof(ObjCPropertyImplDecl)));
178
179 fprintf(stderr, "Total bytes = %d\n",
180 int(nFuncs*sizeof(FunctionDecl)+
181 nVars*sizeof(VarDecl)+nParmVars*sizeof(ParmVarDecl)+
182 nFieldDecls*sizeof(FieldDecl)+nSUC*sizeof(RecordDecl)+
Douglas Gregor8acb7272008-12-11 16:49:14 +0000183 nCXXSUC*sizeof(CXXRecordDecl)+
Eli Friedmana8a09ac2008-06-07 16:52:53 +0000184 nEnumDecls*sizeof(EnumDecl)+nEnumConst*sizeof(EnumConstantDecl)+
185 nTypedef*sizeof(TypedefDecl)+
186 nInterfaceDecls*sizeof(ObjCInterfaceDecl)+
187 nIvarDecls*sizeof(ObjCIvarDecl)+
188 nClassDecls*sizeof(ObjCClassDecl)+
189 nMethodDecls*sizeof(ObjCMethodDecl)+
190 nProtocolDecls*sizeof(ObjCProtocolDecl)+
191 nForwardProtocolDecls*sizeof(ObjCForwardProtocolDecl)+
192 nCategoryDecls*sizeof(ObjCCategoryDecl)+
193 nObjCImplementationDecls*sizeof(ObjCImplementationDecl)+
194 nObjCCategoryImpl*sizeof(ObjCCategoryImplDecl)+
195 nObjCCompatibleAlias*sizeof(ObjCCompatibleAliasDecl)+
196 nObjCPropertyDecl*sizeof(ObjCPropertyDecl)+
197 nObjCPropertyImplDecl*sizeof(ObjCPropertyImplDecl)+
198 nLinkageSpecDecl*sizeof(LinkageSpecDecl)+
199 nFileScopeAsmDecl*sizeof(FileScopeAsmDecl)+
Douglas Gregord2baafd2008-10-21 16:13:35 +0000200 nNamespaces*sizeof(NamespaceDecl)+
201 nOverFuncs*sizeof(OverloadedFunctionDecl)));
Eli Friedmana8a09ac2008-06-07 16:52:53 +0000202
203}
204
205void Decl::addDeclKind(Kind k) {
206 switch (k) {
207 case Namespace: nNamespaces++; break;
Douglas Gregord2baafd2008-10-21 16:13:35 +0000208 case OverloadedFunction: nOverFuncs++; break;
Eli Friedmana8a09ac2008-06-07 16:52:53 +0000209 case Typedef: nTypedef++; break;
210 case Function: nFuncs++; break;
211 case Var: nVars++; break;
212 case ParmVar: nParmVars++; break;
213 case EnumConstant: nEnumConst++; break;
214 case Field: nFieldDecls++; break;
Argiris Kirtzidis2538a8c2008-10-15 00:42:39 +0000215 case Record: nSUC++; break;
Eli Friedmana8a09ac2008-06-07 16:52:53 +0000216 case Enum: nEnumDecls++; break;
217 case ObjCInterface: nInterfaceDecls++; break;
218 case ObjCClass: nClassDecls++; break;
219 case ObjCMethod: nMethodDecls++; break;
220 case ObjCProtocol: nProtocolDecls++; break;
221 case ObjCForwardProtocol: nForwardProtocolDecls++; break;
222 case ObjCCategory: nCategoryDecls++; break;
223 case ObjCIvar: nIvarDecls++; break;
Ted Kremeneke5bedfe2008-08-20 03:26:33 +0000224 case ObjCAtDefsField: nAtDefsFieldDecls++; break;
Eli Friedmana8a09ac2008-06-07 16:52:53 +0000225 case ObjCImplementation: nObjCImplementationDecls++; break;
226 case ObjCCategoryImpl: nObjCCategoryImpl++; break;
227 case ObjCCompatibleAlias: nObjCCompatibleAlias++; break;
228 case ObjCProperty: nObjCPropertyDecl++; break;
229 case ObjCPropertyImpl: nObjCPropertyImplDecl++; break;
230 case LinkageSpec: nLinkageSpecDecl++; break;
231 case FileScopeAsm: nFileScopeAsmDecl++; break;
Steve Naroff9ac456d2008-10-08 17:01:13 +0000232 case Block: nBlockDecls++; break;
Chris Lattner8c7c6a12008-06-17 18:05:57 +0000233 case ImplicitParam:
Eli Friedmana8a09ac2008-06-07 16:52:53 +0000234 case TranslationUnit: break;
Argiris Kirtzidis6df1fc02008-06-09 21:05:31 +0000235
Argiris Kirtzidis2538a8c2008-10-15 00:42:39 +0000236 case CXXRecord: nCXXSUC++; break;
Argiris Kirtzidis6df1fc02008-06-09 21:05:31 +0000237 // FIXME: Statistics for C++ decls.
Douglas Gregordd861062008-12-05 18:15:24 +0000238 case TemplateTypeParm:
239 case NonTypeTemplateParm:
Argiris Kirtzidis6df1fc02008-06-09 21:05:31 +0000240 case CXXMethod:
Douglas Gregorf15ac4b2008-10-31 09:07:45 +0000241 case CXXConstructor:
Douglas Gregor8210a8e2008-11-05 20:51:48 +0000242 case CXXDestructor:
Douglas Gregor3ef6c972008-11-07 20:08:42 +0000243 case CXXConversion:
Argiris Kirtzidis6df1fc02008-06-09 21:05:31 +0000244 case CXXClassVar:
245 break;
Eli Friedmana8a09ac2008-06-07 16:52:53 +0000246 }
247}
248
249//===----------------------------------------------------------------------===//
250// Decl Implementation
251//===----------------------------------------------------------------------===//
252
253// Out-of-line virtual method providing a home for Decl.
254Decl::~Decl() {
255 if (!HasAttrs)
256 return;
257
258 DeclAttrMapTy::iterator it = DeclAttrs->find(this);
259 assert(it != DeclAttrs->end() && "No attrs found but HasAttrs is true!");
260
261 // release attributes.
262 delete it->second;
263 invalidateAttrs();
264}
265
266void Decl::addAttr(Attr *NewAttr) {
267 if (!DeclAttrs)
268 DeclAttrs = new DeclAttrMapTy();
269
270 Attr *&ExistingAttr = (*DeclAttrs)[this];
271
272 NewAttr->setNext(ExistingAttr);
273 ExistingAttr = NewAttr;
274
275 HasAttrs = true;
276}
277
278void Decl::invalidateAttrs() {
279 if (!HasAttrs) return;
280
281 HasAttrs = false;
282 (*DeclAttrs)[this] = 0;
283 DeclAttrs->erase(this);
284
285 if (DeclAttrs->empty()) {
286 delete DeclAttrs;
287 DeclAttrs = 0;
288 }
289}
290
291const Attr *Decl::getAttrs() const {
292 if (!HasAttrs)
293 return 0;
294
295 return (*DeclAttrs)[this];
296}
297
298void Decl::swapAttrs(Decl *RHS) {
299 bool HasLHSAttr = this->HasAttrs;
300 bool HasRHSAttr = RHS->HasAttrs;
301
302 // Usually, neither decl has attrs, nothing to do.
303 if (!HasLHSAttr && !HasRHSAttr) return;
304
305 // If 'this' has no attrs, swap the other way.
306 if (!HasLHSAttr)
307 return RHS->swapAttrs(this);
308
309 // Handle the case when both decls have attrs.
310 if (HasRHSAttr) {
311 std::swap((*DeclAttrs)[this], (*DeclAttrs)[RHS]);
312 return;
313 }
314
315 // Otherwise, LHS has an attr and RHS doesn't.
316 (*DeclAttrs)[RHS] = (*DeclAttrs)[this];
317 (*DeclAttrs).erase(this);
318 this->HasAttrs = false;
319 RHS->HasAttrs = true;
320}
321
322
323void Decl::Destroy(ASTContext& C) {
Eli Friedmana8a09ac2008-06-07 16:52:53 +0000324 if (ScopedDecl* SD = dyn_cast<ScopedDecl>(this)) {
325
326 // Observe the unrolled recursion. By setting N->NextDeclarator = 0x0
327 // within the loop, only the Destroy method for the first ScopedDecl
328 // will deallocate all of the ScopedDecls in a chain.
329
330 ScopedDecl* N = SD->getNextDeclarator();
331
332 while (N) {
333 ScopedDecl* Tmp = N->getNextDeclarator();
334 N->NextDeclarator = 0x0;
335 N->Destroy(C);
336 N = Tmp;
337 }
338 }
339
340 this->~Decl();
341 C.getAllocator().Deallocate((void *)this);
342}
343
Argiris Kirtzidis4b662ea2008-10-12 16:14:48 +0000344Decl *Decl::castFromDeclContext (const DeclContext *D) {
345 return DeclContext::CastTo<Decl>(D);
346}
347
348DeclContext *Decl::castToDeclContext(const Decl *D) {
349 return DeclContext::CastTo<DeclContext>(D);
350}
351
Eli Friedmana8a09ac2008-06-07 16:52:53 +0000352//===----------------------------------------------------------------------===//
353// DeclContext Implementation
354//===----------------------------------------------------------------------===//
355
Argiris Kirtzidis5703f442008-11-19 17:36:39 +0000356const DeclContext *DeclContext::getParent() const {
357 if (const ScopedDecl *SD = dyn_cast<ScopedDecl>(this))
Eli Friedmana8a09ac2008-06-07 16:52:53 +0000358 return SD->getDeclContext();
Argiris Kirtzidis5703f442008-11-19 17:36:39 +0000359 else if (const BlockDecl *BD = dyn_cast<BlockDecl>(this))
Steve Naroff52059382008-10-10 01:28:17 +0000360 return BD->getParentContext();
Eli Friedmana8a09ac2008-06-07 16:52:53 +0000361 else
362 return NULL;
363}
Argiris Kirtzidis9cd599b2008-11-19 18:01:13 +0000364
365const DeclContext *DeclContext::getLexicalParent() const {
366 if (const ScopedDecl *SD = dyn_cast<ScopedDecl>(this))
367 return SD->getLexicalDeclContext();
Argiris Kirtzidisbc470282008-11-19 18:07:24 +0000368 return getParent();
Argiris Kirtzidis9cd599b2008-11-19 18:01:13 +0000369}
Douglas Gregor8acb7272008-12-11 16:49:14 +0000370
371/// TwoNamedDecls - Stores up to two NamedDecls. The first
372/// declaration, if any, is in the ordinary identifier namespace, and
373/// corresponds to values (functions, variables, etc.). The second
374/// declaration, if any, is in the tag identifier namespace, and
375/// corresponds to tag types (classes, enums).
376struct TwoNamedDecls {
377 NamedDecl* Decls[2];
378};
379
380// FIXME: We really want to use a DenseSet here to eliminate the
381// redundant storage of the declaration names, but (1) it doesn't give
382// us the ability to search based on DeclarationName, (2) we really
383// need something more like a DenseMultiSet, and (3) it's
384// implemented in terms of DenseMap anyway.
385typedef llvm::DenseMap<DeclarationName, TwoNamedDecls> StoredDeclsMap;
386
387DeclContext::~DeclContext() {
388 unsigned Size = LookupPtr.getInt();
389 if (Size == LookupIsMap) {
390 StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(LookupPtr.getPointer());
391 delete Map;
392 } else {
393 NamedDecl **Array = static_cast<NamedDecl**>(LookupPtr.getPointer());
394 delete [] Array;
395 }
396}
397
398void DeclContext::DestroyDecls(ASTContext &C) {
399 for (decl_iterator D = Decls.begin(); D != Decls.end(); ++D) {
400 if ((*D)->getLexicalDeclContext() == this)
401 (*D)->Destroy(C);
402 }
403}
404
405DeclContext *DeclContext::getPrimaryContext(ASTContext &Context) {
406 switch (DeclKind) {
407 case Decl::Block:
408 case Decl::TranslationUnit:
409 // There is only one DeclContext for these entities.
410 return this;
411
412 case Decl::Namespace:
413 // The original namespace is our primary context.
414 return static_cast<NamespaceDecl*>(this)->getOriginalNamespace();
415
416 case Decl::Enum:
417 // The declaration associated with the enumeration type is our
418 // primary context.
419 return Context.getTypeDeclType(static_cast<EnumDecl*>(this))
420 ->getAsEnumType()->getDecl();
421
422 case Decl::Record:
423 case Decl::CXXRecord: {
424 // The declaration associated with the type is be our primary
425 // context.
426#if 0
427 // FIXME: This is what we expect to do. However, it doesn't work
428 // because ASTContext::setTagDefinition changes the result of
429 // Context.getTypeDeclType, meaning that our "primary" declaration
430 // of a RecordDecl/CXXRecordDecl will change, and we won't be able
431 // to find any values inserted into the earlier "primary"
432 // declaration. We need better tracking of redeclarations and
433 // definitions.
434 QualType Type = Context.getTypeDeclType(static_cast<RecordDecl*>(this));
435 return Type->getAsRecordType()->getDecl();
436#else
437 // FIXME: This hack will work for now, because the declaration we
438 // create when we're defining the record is the one we'll use as
439 // the definition later.
440 return this;
441#endif
442 }
443
444 case Decl::ObjCMethod:
445 return this;
446
447 case Decl::ObjCInterface:
448 // FIXME: Can Objective-C interfaces be forward-declared?
449 return this;
450
451 default:
452 assert(DeclKind >= Decl::FunctionFirst && DeclKind <= Decl::FunctionLast &&
453 "Unknown DeclContext kind");
454 return this;
455 }
456}
457
458DeclContext *DeclContext::getNextContext() {
459 switch (DeclKind) {
460 case Decl::Block:
461 case Decl::TranslationUnit:
462 case Decl::Enum:
463 case Decl::Record:
464 case Decl::CXXRecord:
465 case Decl::ObjCMethod:
466 case Decl::ObjCInterface:
467 // There is only one DeclContext for these entities.
468 return 0;
469
470 case Decl::Namespace:
471 // Return the next namespace
472 return static_cast<NamespaceDecl*>(this)->getNextNamespace();
473
474 default:
475 assert(DeclKind >= Decl::FunctionFirst && DeclKind <= Decl::FunctionLast &&
476 "Unknown DeclContext kind");
477 return 0;
478 }
479}
480
481void DeclContext::addDecl(ASTContext &Context, ScopedDecl *D, bool AllowLookup) {
482 Decls.push_back(D);
483 if (AllowLookup)
484 D->getDeclContext()->insert(Context, D);
485}
486
487DeclContext::lookup_result
488DeclContext::lookup(ASTContext &Context, DeclarationName Name) {
489 DeclContext *PrimaryContext = getPrimaryContext(Context);
490 if (PrimaryContext != this)
491 return PrimaryContext->lookup(Context, Name);
492
493 /// If there is no lookup data structure, build one now by talking
494 /// all of the linked DeclContexts (in declaration order!) and
495 /// inserting their values.
496 if (LookupPtr.getPointer() == 0) {
497 for (DeclContext *DCtx = this; DCtx; DCtx = DCtx->getNextContext())
498 for (decl_iterator D = DCtx->decls_begin(); D != DCtx->decls_end(); ++D)
499 insertImpl(*D);
500 }
501
502 lookup_result Result(0, 0);
503 if (isLookupMap()) {
504 StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(LookupPtr.getPointer());
505 StoredDeclsMap::iterator Pos = Map->find(Name);
506 if (Pos != Map->end()) {
507 Result.first = Pos->second.Decls[0]? &Pos->second.Decls[0]
508 : &Pos->second.Decls[1];
509 Result.second = Pos->second.Decls[1]? &Pos->second.Decls[2]
510 : &Pos->second.Decls[1];
511 }
512 return Result;
513 }
514
515 // We have a small array. Look into it.
516 unsigned Size = LookupPtr.getInt();
517 NamedDecl **Array = static_cast<NamedDecl**>(LookupPtr.getPointer());
Douglas Gregor39677622008-12-11 20:41:00 +0000518 for (unsigned Idx = 0; Idx != Size; ++Idx)
Douglas Gregor8acb7272008-12-11 16:49:14 +0000519 if (Array[Idx]->getDeclName() == Name) {
520 Result.first = &Array[Idx];
521 Result.second = Result.first + 1;
522 if (Idx + 1 < Size && Array[Idx + 1]->getDeclName() == Name)
523 ++Result.second;
524 break;
525 }
526
527 return Result;
528}
529
530DeclContext::lookup_const_result
531DeclContext::lookup(ASTContext &Context, DeclarationName Name) const {
532 return const_cast<DeclContext*>(this)->lookup(Context, Name);
533}
534
535void DeclContext::insert(ASTContext &Context, NamedDecl *D) {
536 DeclContext *PrimaryContext = getPrimaryContext(Context);
537 if (PrimaryContext != this) {
538 PrimaryContext->insert(Context, D);
539 return;
540 }
541
542 // If we already have a lookup data structure, perform the insertion
543 // into it. Otherwise, be lazy and don't build that structure until
544 // someone asks for it.
545 if (LookupPtr.getPointer())
546 insertImpl(D);
547}
548
549void DeclContext::insertImpl(NamedDecl *D) {
550 if (!isLookupMap()) {
551 unsigned Size = LookupPtr.getInt();
552
553 // The lookup data is stored as an array. Search through the array
554 // to find the insertion location.
555 NamedDecl **Array;
556 if (Size == 0) {
557 Array = new NamedDecl*[LookupIsMap - 1];
558 LookupPtr.setPointer(Array);
559 } else {
560 Array = static_cast<NamedDecl **>(LookupPtr.getPointer());
561 }
562
563 // We always keep declarations of the same name next to each other
564 // in the array, so that it is easy to return multiple results
565 // from lookup(). There will be zero, one, or two declarations of
566 // the same name.
567 unsigned Match;
Douglas Gregor39677622008-12-11 20:41:00 +0000568 for (Match = 0; Match != Size; ++Match)
Douglas Gregor8acb7272008-12-11 16:49:14 +0000569 if (Array[Match]->getDeclName() == D->getDeclName())
Douglas Gregor39677622008-12-11 20:41:00 +0000570 break;
Douglas Gregor8acb7272008-12-11 16:49:14 +0000571
Douglas Gregor39677622008-12-11 20:41:00 +0000572 if (Match != Size) {
Douglas Gregor8acb7272008-12-11 16:49:14 +0000573 // We found another declaration with the same name. If it's also
574 // in the same identifier namespace, update the declaration in
575 // place.
576 Decl::IdentifierNamespace NS = D->getIdentifierNamespace();
577 if (Array[Match]->getIdentifierNamespace() == NS) {
578 Array[Match] = D;
579 return;
580 }
581 if (Match + 1 < Size && Array[Match + 1]->getIdentifierNamespace() == NS) {
582 Array[Match + 1] = D;
583 return;
584 }
585
586 // If there is an existing declaration in the namespace of
587 // ordinary identifiers, then it must precede the tag
588 // declaration for C++ name lookup to operate properly. Therefore,
589 // if our match is an ordinary name and the new name is in the
590 // tag namespace, we'll insert the new declaration after it.
Douglas Gregor39677622008-12-11 20:41:00 +0000591 if (Match != Size && (NS == Decl::IDNS_Tag) &&
Douglas Gregor8acb7272008-12-11 16:49:14 +0000592 (Array[Match]->getIdentifierNamespace() & Decl::IDNS_Ordinary))
593 ++Match;
594 }
595
596 if (Size < LookupIsMap - 1) {
597 // The new declaration will fit in the array. Insert the new
598 // declaration at the position Match in the array.
599 for (unsigned Idx = Size; Idx > Match; --Idx)
600 Array[Idx] = Array[Idx-1];
601
602 Array[Match] = D;
603 LookupPtr.setInt(Size + 1);
604 return;
605 }
606
607 // We've reached capacity in this array. Create a map and copy in
608 // all of the declarations that were stored in the array.
609 StoredDeclsMap *Map = new StoredDeclsMap(16);
610 LookupPtr.setPointer(Map);
611 LookupPtr.setInt(LookupIsMap);
Douglas Gregor39677622008-12-11 20:41:00 +0000612 for (unsigned Idx = 0; Idx != LookupIsMap - 1; ++Idx)
Douglas Gregor8acb7272008-12-11 16:49:14 +0000613 insertImpl(Array[Idx]);
614 delete [] Array;
615
616 // Fall through to perform insertion into the map.
617 }
618
619 // Insert this declaration into the map.
620 StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(LookupPtr.getPointer());
621 StoredDeclsMap::iterator Pos = Map->find(D->getDeclName());
622 unsigned IndexOfD = D->getIdentifierNamespace() & Decl::IDNS_Ordinary? 0 : 1;
623
624 if (Pos == Map->end()) {
625 // Put this declaration into the appropriate slot.
626 TwoNamedDecls Val;
Douglas Gregor8acb7272008-12-11 16:49:14 +0000627 Val.Decls[IndexOfD] = D;
Douglas Gregor39677622008-12-11 20:41:00 +0000628 Val.Decls[!IndexOfD] = 0;
629 Map->insert(std::make_pair(D->getDeclName(),Val)).first;
Douglas Gregor8acb7272008-12-11 16:49:14 +0000630 } else {
631 Pos->second.Decls[IndexOfD] = D;
632 }
633}