blob: 87ebf85b41d3079bb398acb83b3ea9558a07c9ce [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"
Daniel Dunbare91593e2008-08-11 04:54:23 +000015#include "clang/AST/DeclObjC.h"
Argyrios Kyrtzidisd3bb44f2008-06-09 21:05:31 +000016#include "clang/AST/DeclCXX.h"
Eli Friedman56d29372008-06-07 16:52:53 +000017#include "clang/AST/ASTContext.h"
Douglas Gregor44b43212008-12-11 16:49:14 +000018#include "clang/AST/Type.h"
Eli Friedman56d29372008-06-07 16:52:53 +000019#include "llvm/ADT/DenseMap.h"
Douglas Gregor3fc749d2008-12-23 00:26:44 +000020#include <vector>
Eli Friedman56d29372008-06-07 16:52:53 +000021using namespace clang;
22
23//===----------------------------------------------------------------------===//
24// Statistics
25//===----------------------------------------------------------------------===//
26
27// temporary statistics gathering
28static unsigned nFuncs = 0;
29static unsigned nVars = 0;
30static unsigned nParmVars = 0;
Fariborz Jahanian4f5420d2008-12-20 21:06:28 +000031static unsigned nOriginalParmVars = 0;
Eli Friedman56d29372008-06-07 16:52:53 +000032static unsigned nSUC = 0;
Argyrios Kyrtzidis55d71f92008-08-10 01:47:31 +000033static unsigned nCXXSUC = 0;
Eli Friedman56d29372008-06-07 16:52:53 +000034static unsigned nEnumConst = 0;
35static unsigned nEnumDecls = 0;
36static unsigned nNamespaces = 0;
Douglas Gregor8e9bebd2008-10-21 16:13:35 +000037static unsigned nOverFuncs = 0;
Eli Friedman56d29372008-06-07 16:52:53 +000038static unsigned nTypedef = 0;
39static unsigned nFieldDecls = 0;
40static unsigned nInterfaceDecls = 0;
41static unsigned nClassDecls = 0;
42static unsigned nMethodDecls = 0;
43static unsigned nProtocolDecls = 0;
44static unsigned nForwardProtocolDecls = 0;
45static unsigned nCategoryDecls = 0;
46static unsigned nIvarDecls = 0;
Ted Kremenek01e67792008-08-20 03:26:33 +000047static unsigned nAtDefsFieldDecls = 0;
Eli Friedman56d29372008-06-07 16:52:53 +000048static unsigned nObjCImplementationDecls = 0;
49static unsigned nObjCCategoryImpl = 0;
50static unsigned nObjCCompatibleAlias = 0;
51static unsigned nObjCPropertyDecl = 0;
52static unsigned nObjCPropertyImplDecl = 0;
53static unsigned nLinkageSpecDecl = 0;
54static unsigned nFileScopeAsmDecl = 0;
Steve Naroff56ee6892008-10-08 17:01:13 +000055static unsigned nBlockDecls = 0;
Eli Friedman56d29372008-06-07 16:52:53 +000056
57static bool StatSwitch = false;
58
59// This keeps track of all decl attributes. Since so few decls have attrs, we
60// keep them in a hash map instead of wasting space in the Decl class.
61typedef llvm::DenseMap<const Decl*, Attr*> DeclAttrMapTy;
62
63static DeclAttrMapTy *DeclAttrs = 0;
64
65const char *Decl::getDeclKindName() const {
66 switch (DeclKind) {
67 default: assert(0 && "Unknown decl kind!");
68 case Namespace: return "Namespace";
Douglas Gregor8e9bebd2008-10-21 16:13:35 +000069 case OverloadedFunction: return "OverloadedFunction";
Eli Friedman56d29372008-06-07 16:52:53 +000070 case Typedef: return "Typedef";
71 case Function: return "Function";
72 case Var: return "Var";
73 case ParmVar: return "ParmVar";
Fariborz Jahanian4f5420d2008-12-20 21:06:28 +000074 case OriginalParmVar: return "OriginalParmVar";
Eli Friedman56d29372008-06-07 16:52:53 +000075 case EnumConstant: return "EnumConstant";
76 case ObjCIvar: return "ObjCIvar";
77 case ObjCInterface: return "ObjCInterface";
Steve Naroffd40910b2008-12-01 20:33:01 +000078 case ObjCImplementation: return "ObjCImplementation";
Eli Friedman56d29372008-06-07 16:52:53 +000079 case ObjCClass: return "ObjCClass";
80 case ObjCMethod: return "ObjCMethod";
81 case ObjCProtocol: return "ObjCProtocol";
Steve Naroffd40910b2008-12-01 20:33:01 +000082 case ObjCProperty: return "ObjCProperty";
83 case ObjCPropertyImpl: return "ObjCPropertyImpl";
Eli Friedman56d29372008-06-07 16:52:53 +000084 case ObjCForwardProtocol: return "ObjCForwardProtocol";
Argyrios Kyrtzidis35bc0822008-10-15 00:42:39 +000085 case Record: return "Record";
86 case CXXRecord: return "CXXRecord";
Eli Friedman56d29372008-06-07 16:52:53 +000087 case Enum: return "Enum";
Steve Naroff56ee6892008-10-08 17:01:13 +000088 case Block: return "Block";
Eli Friedman56d29372008-06-07 16:52:53 +000089 }
90}
91
92bool Decl::CollectingStats(bool Enable) {
93 if (Enable)
94 StatSwitch = true;
95 return StatSwitch;
96}
97
98void Decl::PrintStats() {
99 fprintf(stderr, "*** Decl Stats:\n");
100 fprintf(stderr, " %d decls total.\n",
Fariborz Jahanian4f5420d2008-12-20 21:06:28 +0000101 int(nFuncs+nVars+nParmVars+nOriginalParmVars+nFieldDecls+nSUC+nCXXSUC+
Eli Friedman56d29372008-06-07 16:52:53 +0000102 nEnumDecls+nEnumConst+nTypedef+nInterfaceDecls+nClassDecls+
103 nMethodDecls+nProtocolDecls+nCategoryDecls+nIvarDecls+
Douglas Gregor8e9bebd2008-10-21 16:13:35 +0000104 nAtDefsFieldDecls+nNamespaces+nOverFuncs));
Eli Friedman56d29372008-06-07 16:52:53 +0000105 fprintf(stderr, " %d namespace decls, %d each (%d bytes)\n",
106 nNamespaces, (int)sizeof(NamespaceDecl),
107 int(nNamespaces*sizeof(NamespaceDecl)));
Douglas Gregor8e9bebd2008-10-21 16:13:35 +0000108 fprintf(stderr, " %d overloaded function decls, %d each (%d bytes)\n",
109 nOverFuncs, (int)sizeof(OverloadedFunctionDecl),
110 int(nOverFuncs*sizeof(OverloadedFunctionDecl)));
Eli Friedman56d29372008-06-07 16:52:53 +0000111 fprintf(stderr, " %d function decls, %d each (%d bytes)\n",
112 nFuncs, (int)sizeof(FunctionDecl), int(nFuncs*sizeof(FunctionDecl)));
113 fprintf(stderr, " %d variable decls, %d each (%d bytes)\n",
114 nVars, (int)sizeof(VarDecl),
115 int(nVars*sizeof(VarDecl)));
116 fprintf(stderr, " %d parameter variable decls, %d each (%d bytes)\n",
117 nParmVars, (int)sizeof(ParmVarDecl),
118 int(nParmVars*sizeof(ParmVarDecl)));
Fariborz Jahanian4f5420d2008-12-20 21:06:28 +0000119 fprintf(stderr, " %d original parameter variable decls, %d each (%d bytes)\n",
120 nOriginalParmVars, (int)sizeof(ParmVarWithOriginalTypeDecl),
121 int(nOriginalParmVars*sizeof(ParmVarWithOriginalTypeDecl)));
Eli Friedman56d29372008-06-07 16:52:53 +0000122 fprintf(stderr, " %d field decls, %d each (%d bytes)\n",
123 nFieldDecls, (int)sizeof(FieldDecl),
124 int(nFieldDecls*sizeof(FieldDecl)));
Ted Kremenek01e67792008-08-20 03:26:33 +0000125 fprintf(stderr, " %d @defs generated field decls, %d each (%d bytes)\n",
126 nAtDefsFieldDecls, (int)sizeof(ObjCAtDefsFieldDecl),
127 int(nAtDefsFieldDecls*sizeof(ObjCAtDefsFieldDecl)));
Eli Friedman56d29372008-06-07 16:52:53 +0000128 fprintf(stderr, " %d struct/union/class decls, %d each (%d bytes)\n",
129 nSUC, (int)sizeof(RecordDecl),
130 int(nSUC*sizeof(RecordDecl)));
Argyrios Kyrtzidis55d71f92008-08-10 01:47:31 +0000131 fprintf(stderr, " %d C++ struct/union/class decls, %d each (%d bytes)\n",
132 nCXXSUC, (int)sizeof(CXXRecordDecl),
133 int(nCXXSUC*sizeof(CXXRecordDecl)));
Eli Friedman56d29372008-06-07 16:52:53 +0000134 fprintf(stderr, " %d enum decls, %d each (%d bytes)\n",
135 nEnumDecls, (int)sizeof(EnumDecl),
136 int(nEnumDecls*sizeof(EnumDecl)));
137 fprintf(stderr, " %d enum constant decls, %d each (%d bytes)\n",
138 nEnumConst, (int)sizeof(EnumConstantDecl),
139 int(nEnumConst*sizeof(EnumConstantDecl)));
140 fprintf(stderr, " %d typedef decls, %d each (%d bytes)\n",
141 nTypedef, (int)sizeof(TypedefDecl),int(nTypedef*sizeof(TypedefDecl)));
142 // Objective-C decls...
143 fprintf(stderr, " %d interface decls, %d each (%d bytes)\n",
144 nInterfaceDecls, (int)sizeof(ObjCInterfaceDecl),
145 int(nInterfaceDecls*sizeof(ObjCInterfaceDecl)));
146 fprintf(stderr, " %d instance variable decls, %d each (%d bytes)\n",
147 nIvarDecls, (int)sizeof(ObjCIvarDecl),
148 int(nIvarDecls*sizeof(ObjCIvarDecl)));
149 fprintf(stderr, " %d class decls, %d each (%d bytes)\n",
150 nClassDecls, (int)sizeof(ObjCClassDecl),
151 int(nClassDecls*sizeof(ObjCClassDecl)));
152 fprintf(stderr, " %d method decls, %d each (%d bytes)\n",
153 nMethodDecls, (int)sizeof(ObjCMethodDecl),
154 int(nMethodDecls*sizeof(ObjCMethodDecl)));
155 fprintf(stderr, " %d protocol decls, %d each (%d bytes)\n",
156 nProtocolDecls, (int)sizeof(ObjCProtocolDecl),
157 int(nProtocolDecls*sizeof(ObjCProtocolDecl)));
158 fprintf(stderr, " %d forward protocol decls, %d each (%d bytes)\n",
159 nForwardProtocolDecls, (int)sizeof(ObjCForwardProtocolDecl),
160 int(nForwardProtocolDecls*sizeof(ObjCForwardProtocolDecl)));
161 fprintf(stderr, " %d category decls, %d each (%d bytes)\n",
162 nCategoryDecls, (int)sizeof(ObjCCategoryDecl),
163 int(nCategoryDecls*sizeof(ObjCCategoryDecl)));
164
165 fprintf(stderr, " %d class implementation decls, %d each (%d bytes)\n",
166 nObjCImplementationDecls, (int)sizeof(ObjCImplementationDecl),
167 int(nObjCImplementationDecls*sizeof(ObjCImplementationDecl)));
168
169 fprintf(stderr, " %d class implementation decls, %d each (%d bytes)\n",
170 nObjCCategoryImpl, (int)sizeof(ObjCCategoryImplDecl),
171 int(nObjCCategoryImpl*sizeof(ObjCCategoryImplDecl)));
172
173 fprintf(stderr, " %d compatibility alias decls, %d each (%d bytes)\n",
174 nObjCCompatibleAlias, (int)sizeof(ObjCCompatibleAliasDecl),
175 int(nObjCCompatibleAlias*sizeof(ObjCCompatibleAliasDecl)));
176
177 fprintf(stderr, " %d property decls, %d each (%d bytes)\n",
178 nObjCPropertyDecl, (int)sizeof(ObjCPropertyDecl),
179 int(nObjCPropertyDecl*sizeof(ObjCPropertyDecl)));
180
181 fprintf(stderr, " %d property implementation decls, %d each (%d bytes)\n",
182 nObjCPropertyImplDecl, (int)sizeof(ObjCPropertyImplDecl),
183 int(nObjCPropertyImplDecl*sizeof(ObjCPropertyImplDecl)));
184
185 fprintf(stderr, "Total bytes = %d\n",
186 int(nFuncs*sizeof(FunctionDecl)+
187 nVars*sizeof(VarDecl)+nParmVars*sizeof(ParmVarDecl)+
Fariborz Jahanian4f5420d2008-12-20 21:06:28 +0000188 nOriginalParmVars*sizeof(ParmVarWithOriginalTypeDecl)+
Eli Friedman56d29372008-06-07 16:52:53 +0000189 nFieldDecls*sizeof(FieldDecl)+nSUC*sizeof(RecordDecl)+
Douglas Gregor44b43212008-12-11 16:49:14 +0000190 nCXXSUC*sizeof(CXXRecordDecl)+
Eli Friedman56d29372008-06-07 16:52:53 +0000191 nEnumDecls*sizeof(EnumDecl)+nEnumConst*sizeof(EnumConstantDecl)+
192 nTypedef*sizeof(TypedefDecl)+
193 nInterfaceDecls*sizeof(ObjCInterfaceDecl)+
194 nIvarDecls*sizeof(ObjCIvarDecl)+
195 nClassDecls*sizeof(ObjCClassDecl)+
196 nMethodDecls*sizeof(ObjCMethodDecl)+
197 nProtocolDecls*sizeof(ObjCProtocolDecl)+
198 nForwardProtocolDecls*sizeof(ObjCForwardProtocolDecl)+
199 nCategoryDecls*sizeof(ObjCCategoryDecl)+
200 nObjCImplementationDecls*sizeof(ObjCImplementationDecl)+
201 nObjCCategoryImpl*sizeof(ObjCCategoryImplDecl)+
202 nObjCCompatibleAlias*sizeof(ObjCCompatibleAliasDecl)+
203 nObjCPropertyDecl*sizeof(ObjCPropertyDecl)+
204 nObjCPropertyImplDecl*sizeof(ObjCPropertyImplDecl)+
205 nLinkageSpecDecl*sizeof(LinkageSpecDecl)+
206 nFileScopeAsmDecl*sizeof(FileScopeAsmDecl)+
Douglas Gregor8e9bebd2008-10-21 16:13:35 +0000207 nNamespaces*sizeof(NamespaceDecl)+
208 nOverFuncs*sizeof(OverloadedFunctionDecl)));
Eli Friedman56d29372008-06-07 16:52:53 +0000209
210}
211
212void Decl::addDeclKind(Kind k) {
213 switch (k) {
214 case Namespace: nNamespaces++; break;
Douglas Gregor8e9bebd2008-10-21 16:13:35 +0000215 case OverloadedFunction: nOverFuncs++; break;
Eli Friedman56d29372008-06-07 16:52:53 +0000216 case Typedef: nTypedef++; break;
217 case Function: nFuncs++; break;
218 case Var: nVars++; break;
219 case ParmVar: nParmVars++; break;
Fariborz Jahanian4f5420d2008-12-20 21:06:28 +0000220 case OriginalParmVar: nOriginalParmVars++; break;
Eli Friedman56d29372008-06-07 16:52:53 +0000221 case EnumConstant: nEnumConst++; break;
222 case Field: nFieldDecls++; break;
Argyrios Kyrtzidis35bc0822008-10-15 00:42:39 +0000223 case Record: nSUC++; break;
Eli Friedman56d29372008-06-07 16:52:53 +0000224 case Enum: nEnumDecls++; break;
225 case ObjCInterface: nInterfaceDecls++; break;
226 case ObjCClass: nClassDecls++; break;
227 case ObjCMethod: nMethodDecls++; break;
228 case ObjCProtocol: nProtocolDecls++; break;
229 case ObjCForwardProtocol: nForwardProtocolDecls++; break;
230 case ObjCCategory: nCategoryDecls++; break;
231 case ObjCIvar: nIvarDecls++; break;
Ted Kremenek01e67792008-08-20 03:26:33 +0000232 case ObjCAtDefsField: nAtDefsFieldDecls++; break;
Eli Friedman56d29372008-06-07 16:52:53 +0000233 case ObjCImplementation: nObjCImplementationDecls++; break;
234 case ObjCCategoryImpl: nObjCCategoryImpl++; break;
235 case ObjCCompatibleAlias: nObjCCompatibleAlias++; break;
236 case ObjCProperty: nObjCPropertyDecl++; break;
237 case ObjCPropertyImpl: nObjCPropertyImplDecl++; break;
238 case LinkageSpec: nLinkageSpecDecl++; break;
239 case FileScopeAsm: nFileScopeAsmDecl++; break;
Steve Naroff56ee6892008-10-08 17:01:13 +0000240 case Block: nBlockDecls++; break;
Chris Lattner41110242008-06-17 18:05:57 +0000241 case ImplicitParam:
Eli Friedman56d29372008-06-07 16:52:53 +0000242 case TranslationUnit: break;
Argyrios Kyrtzidisd3bb44f2008-06-09 21:05:31 +0000243
Argyrios Kyrtzidis35bc0822008-10-15 00:42:39 +0000244 case CXXRecord: nCXXSUC++; break;
Argyrios Kyrtzidisd3bb44f2008-06-09 21:05:31 +0000245 // FIXME: Statistics for C++ decls.
Douglas Gregor72c3f312008-12-05 18:15:24 +0000246 case TemplateTypeParm:
247 case NonTypeTemplateParm:
Argyrios Kyrtzidisd3bb44f2008-06-09 21:05:31 +0000248 case CXXMethod:
Douglas Gregorb48fe382008-10-31 09:07:45 +0000249 case CXXConstructor:
Douglas Gregor42a552f2008-11-05 20:51:48 +0000250 case CXXDestructor:
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000251 case CXXConversion:
Argyrios Kyrtzidisd3bb44f2008-06-09 21:05:31 +0000252 case CXXClassVar:
253 break;
Eli Friedman56d29372008-06-07 16:52:53 +0000254 }
255}
256
257//===----------------------------------------------------------------------===//
258// Decl Implementation
259//===----------------------------------------------------------------------===//
260
261// Out-of-line virtual method providing a home for Decl.
262Decl::~Decl() {
263 if (!HasAttrs)
264 return;
265
266 DeclAttrMapTy::iterator it = DeclAttrs->find(this);
267 assert(it != DeclAttrs->end() && "No attrs found but HasAttrs is true!");
268
269 // release attributes.
270 delete it->second;
271 invalidateAttrs();
272}
273
274void Decl::addAttr(Attr *NewAttr) {
275 if (!DeclAttrs)
276 DeclAttrs = new DeclAttrMapTy();
277
278 Attr *&ExistingAttr = (*DeclAttrs)[this];
279
280 NewAttr->setNext(ExistingAttr);
281 ExistingAttr = NewAttr;
282
283 HasAttrs = true;
284}
285
286void Decl::invalidateAttrs() {
287 if (!HasAttrs) return;
288
289 HasAttrs = false;
290 (*DeclAttrs)[this] = 0;
291 DeclAttrs->erase(this);
292
293 if (DeclAttrs->empty()) {
294 delete DeclAttrs;
295 DeclAttrs = 0;
296 }
297}
298
299const Attr *Decl::getAttrs() const {
300 if (!HasAttrs)
301 return 0;
302
303 return (*DeclAttrs)[this];
304}
305
306void Decl::swapAttrs(Decl *RHS) {
307 bool HasLHSAttr = this->HasAttrs;
308 bool HasRHSAttr = RHS->HasAttrs;
309
310 // Usually, neither decl has attrs, nothing to do.
311 if (!HasLHSAttr && !HasRHSAttr) return;
312
313 // If 'this' has no attrs, swap the other way.
314 if (!HasLHSAttr)
315 return RHS->swapAttrs(this);
316
317 // Handle the case when both decls have attrs.
318 if (HasRHSAttr) {
319 std::swap((*DeclAttrs)[this], (*DeclAttrs)[RHS]);
320 return;
321 }
322
323 // Otherwise, LHS has an attr and RHS doesn't.
324 (*DeclAttrs)[RHS] = (*DeclAttrs)[this];
325 (*DeclAttrs).erase(this);
326 this->HasAttrs = false;
327 RHS->HasAttrs = true;
328}
329
330
331void Decl::Destroy(ASTContext& C) {
Eli Friedman56d29372008-06-07 16:52:53 +0000332 if (ScopedDecl* SD = dyn_cast<ScopedDecl>(this)) {
333
334 // Observe the unrolled recursion. By setting N->NextDeclarator = 0x0
335 // within the loop, only the Destroy method for the first ScopedDecl
336 // will deallocate all of the ScopedDecls in a chain.
337
338 ScopedDecl* N = SD->getNextDeclarator();
339
340 while (N) {
341 ScopedDecl* Tmp = N->getNextDeclarator();
342 N->NextDeclarator = 0x0;
343 N->Destroy(C);
344 N = Tmp;
345 }
346 }
347
348 this->~Decl();
349 C.getAllocator().Deallocate((void *)this);
350}
351
Argyrios Kyrtzidis42220c52008-10-12 16:14:48 +0000352Decl *Decl::castFromDeclContext (const DeclContext *D) {
353 return DeclContext::CastTo<Decl>(D);
354}
355
356DeclContext *Decl::castToDeclContext(const Decl *D) {
357 return DeclContext::CastTo<DeclContext>(D);
358}
359
Eli Friedman56d29372008-06-07 16:52:53 +0000360//===----------------------------------------------------------------------===//
361// DeclContext Implementation
362//===----------------------------------------------------------------------===//
363
Argyrios Kyrtzidis20bc6762008-11-19 17:36:39 +0000364const DeclContext *DeclContext::getParent() const {
365 if (const ScopedDecl *SD = dyn_cast<ScopedDecl>(this))
Eli Friedman56d29372008-06-07 16:52:53 +0000366 return SD->getDeclContext();
Argyrios Kyrtzidis20bc6762008-11-19 17:36:39 +0000367 else if (const BlockDecl *BD = dyn_cast<BlockDecl>(this))
Steve Naroff090276f2008-10-10 01:28:17 +0000368 return BD->getParentContext();
Eli Friedman56d29372008-06-07 16:52:53 +0000369 else
370 return NULL;
371}
Argyrios Kyrtzidis77407b82008-11-19 18:01:13 +0000372
373const DeclContext *DeclContext::getLexicalParent() const {
374 if (const ScopedDecl *SD = dyn_cast<ScopedDecl>(this))
375 return SD->getLexicalDeclContext();
Argyrios Kyrtzidis051c13a2008-11-19 18:07:24 +0000376 return getParent();
Argyrios Kyrtzidis77407b82008-11-19 18:01:13 +0000377}
Douglas Gregor44b43212008-12-11 16:49:14 +0000378
Douglas Gregor44b43212008-12-11 16:49:14 +0000379// FIXME: We really want to use a DenseSet here to eliminate the
380// redundant storage of the declaration names, but (1) it doesn't give
381// us the ability to search based on DeclarationName, (2) we really
382// need something more like a DenseMultiSet, and (3) it's
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000383// implemented in terms of DenseMap anyway. However, this data
384// structure is really space-inefficient, so we'll have to do
385// something.
386typedef llvm::DenseMap<DeclarationName, std::vector<ScopedDecl*> >
387 StoredDeclsMap;
Douglas Gregor44b43212008-12-11 16:49:14 +0000388
389DeclContext::~DeclContext() {
390 unsigned Size = LookupPtr.getInt();
391 if (Size == LookupIsMap) {
392 StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(LookupPtr.getPointer());
393 delete Map;
394 } else {
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000395 ScopedDecl **Array = static_cast<ScopedDecl**>(LookupPtr.getPointer());
Douglas Gregor44b43212008-12-11 16:49:14 +0000396 delete [] Array;
397 }
398}
399
400void DeclContext::DestroyDecls(ASTContext &C) {
401 for (decl_iterator D = Decls.begin(); D != Decls.end(); ++D) {
402 if ((*D)->getLexicalDeclContext() == this)
403 (*D)->Destroy(C);
404 }
405}
406
407DeclContext *DeclContext::getPrimaryContext(ASTContext &Context) {
408 switch (DeclKind) {
409 case Decl::Block:
410 case Decl::TranslationUnit:
411 // There is only one DeclContext for these entities.
412 return this;
413
414 case Decl::Namespace:
415 // The original namespace is our primary context.
416 return static_cast<NamespaceDecl*>(this)->getOriginalNamespace();
417
418 case Decl::Enum:
419 // The declaration associated with the enumeration type is our
420 // primary context.
421 return Context.getTypeDeclType(static_cast<EnumDecl*>(this))
422 ->getAsEnumType()->getDecl();
423
424 case Decl::Record:
425 case Decl::CXXRecord: {
426 // The declaration associated with the type is be our primary
427 // context.
428#if 0
429 // FIXME: This is what we expect to do. However, it doesn't work
430 // because ASTContext::setTagDefinition changes the result of
431 // Context.getTypeDeclType, meaning that our "primary" declaration
432 // of a RecordDecl/CXXRecordDecl will change, and we won't be able
433 // to find any values inserted into the earlier "primary"
434 // declaration. We need better tracking of redeclarations and
435 // definitions.
436 QualType Type = Context.getTypeDeclType(static_cast<RecordDecl*>(this));
437 return Type->getAsRecordType()->getDecl();
438#else
439 // FIXME: This hack will work for now, because the declaration we
440 // create when we're defining the record is the one we'll use as
441 // the definition later.
442 return this;
443#endif
444 }
445
446 case Decl::ObjCMethod:
447 return this;
448
449 case Decl::ObjCInterface:
450 // FIXME: Can Objective-C interfaces be forward-declared?
451 return this;
452
453 default:
454 assert(DeclKind >= Decl::FunctionFirst && DeclKind <= Decl::FunctionLast &&
455 "Unknown DeclContext kind");
456 return this;
457 }
458}
459
460DeclContext *DeclContext::getNextContext() {
461 switch (DeclKind) {
462 case Decl::Block:
463 case Decl::TranslationUnit:
464 case Decl::Enum:
465 case Decl::Record:
466 case Decl::CXXRecord:
467 case Decl::ObjCMethod:
468 case Decl::ObjCInterface:
469 // There is only one DeclContext for these entities.
470 return 0;
471
472 case Decl::Namespace:
473 // Return the next namespace
474 return static_cast<NamespaceDecl*>(this)->getNextNamespace();
475
476 default:
477 assert(DeclKind >= Decl::FunctionFirst && DeclKind <= Decl::FunctionLast &&
478 "Unknown DeclContext kind");
479 return 0;
480 }
481}
482
483void DeclContext::addDecl(ASTContext &Context, ScopedDecl *D, bool AllowLookup) {
484 Decls.push_back(D);
485 if (AllowLookup)
486 D->getDeclContext()->insert(Context, D);
487}
488
489DeclContext::lookup_result
490DeclContext::lookup(ASTContext &Context, DeclarationName Name) {
491 DeclContext *PrimaryContext = getPrimaryContext(Context);
492 if (PrimaryContext != this)
493 return PrimaryContext->lookup(Context, Name);
494
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000495 /// If there is no lookup data structure, build one now by walking
Douglas Gregor44b43212008-12-11 16:49:14 +0000496 /// all of the linked DeclContexts (in declaration order!) and
497 /// inserting their values.
498 if (LookupPtr.getPointer() == 0) {
499 for (DeclContext *DCtx = this; DCtx; DCtx = DCtx->getNextContext())
500 for (decl_iterator D = DCtx->decls_begin(); D != DCtx->decls_end(); ++D)
501 insertImpl(*D);
502 }
503
Douglas Gregor44b43212008-12-11 16:49:14 +0000504 if (isLookupMap()) {
505 StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(LookupPtr.getPointer());
506 StoredDeclsMap::iterator Pos = Map->find(Name);
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000507 if (Pos != Map->end())
508 return lookup_result(&Pos->second.front(),
509 &Pos->second.front() + Pos->second.size());
510 return lookup_result(0, 0);
Douglas Gregor44b43212008-12-11 16:49:14 +0000511 }
512
513 // We have a small array. Look into it.
514 unsigned Size = LookupPtr.getInt();
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000515 ScopedDecl **Array = static_cast<ScopedDecl**>(LookupPtr.getPointer());
Douglas Gregore267ff32008-12-11 20:41:00 +0000516 for (unsigned Idx = 0; Idx != Size; ++Idx)
Douglas Gregor44b43212008-12-11 16:49:14 +0000517 if (Array[Idx]->getDeclName() == Name) {
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000518 unsigned Last = Idx + 1;
519 while (Last != Size && Array[Last]->getDeclName() == Name)
520 ++Last;
521 return lookup_result(&Array[Idx], &Array[Last]);
Douglas Gregor44b43212008-12-11 16:49:14 +0000522 }
523
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000524 return lookup_result(0, 0);
Douglas Gregor44b43212008-12-11 16:49:14 +0000525}
526
527DeclContext::lookup_const_result
528DeclContext::lookup(ASTContext &Context, DeclarationName Name) const {
529 return const_cast<DeclContext*>(this)->lookup(Context, Name);
530}
531
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000532void DeclContext::insert(ASTContext &Context, ScopedDecl *D) {
Douglas Gregor44b43212008-12-11 16:49:14 +0000533 DeclContext *PrimaryContext = getPrimaryContext(Context);
534 if (PrimaryContext != this) {
535 PrimaryContext->insert(Context, D);
536 return;
537 }
538
539 // If we already have a lookup data structure, perform the insertion
540 // into it. Otherwise, be lazy and don't build that structure until
541 // someone asks for it.
542 if (LookupPtr.getPointer())
543 insertImpl(D);
544}
545
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000546static bool isRedeclarationOf(ScopedDecl *D, ScopedDecl *OldD) {
547 assert(D->getDeclName() == OldD->getDeclName() && "Declaration name mismatch");
548
549 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
550 // For function declarations, we keep track of redeclarations.
551 return FD->getPreviousDeclaration() == OldD;
552
553 // For non-function declarations, if the declarations are of the
554 // same kind then this must be a redeclaration, or semantic analysis
555 // would not have given us the new declaration.
556 return D->getKind() == OldD->getKind();
557}
558
559void DeclContext::insertImpl(ScopedDecl *D) {
560 bool MayBeRedeclaration = true;
561
Douglas Gregor44b43212008-12-11 16:49:14 +0000562 if (!isLookupMap()) {
563 unsigned Size = LookupPtr.getInt();
564
565 // The lookup data is stored as an array. Search through the array
566 // to find the insertion location.
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000567 ScopedDecl **Array;
Douglas Gregor44b43212008-12-11 16:49:14 +0000568 if (Size == 0) {
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000569 Array = new ScopedDecl*[LookupIsMap - 1];
Douglas Gregor44b43212008-12-11 16:49:14 +0000570 LookupPtr.setPointer(Array);
571 } else {
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000572 Array = static_cast<ScopedDecl **>(LookupPtr.getPointer());
Douglas Gregor44b43212008-12-11 16:49:14 +0000573 }
574
575 // We always keep declarations of the same name next to each other
576 // in the array, so that it is easy to return multiple results
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000577 // from lookup().
578 unsigned FirstMatch;
579 for (FirstMatch = 0; FirstMatch != Size; ++FirstMatch)
580 if (Array[FirstMatch]->getDeclName() == D->getDeclName())
Douglas Gregore267ff32008-12-11 20:41:00 +0000581 break;
Douglas Gregor44b43212008-12-11 16:49:14 +0000582
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000583 unsigned InsertPos = FirstMatch;
584 if (FirstMatch != Size) {
585 // We found another declaration with the same name. First
586 // determine whether this is a redeclaration of an existing
587 // declaration in this scope, in which case we will replace the
588 // existing declaration.
589 unsigned LastMatch = FirstMatch;
590 for (; LastMatch != Size; ++LastMatch) {
591 if (Array[LastMatch]->getDeclName() != D->getDeclName())
592 break;
593
594 if (isRedeclarationOf(D, Array[LastMatch])) {
595 // D is a redeclaration of an existing element in the
596 // array. Replace that element with D.
597 Array[LastMatch] = D;
598 return;
599 }
Douglas Gregor44b43212008-12-11 16:49:14 +0000600 }
601
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000602 // [FirstMatch, LastMatch) contains the set of declarations that
603 // have the same name as this declaration. Determine where the
604 // declaration D will be inserted into this range.
605 if (D->getIdentifierNamespace() == Decl::IDNS_Tag)
606 InsertPos = LastMatch;
607 else if (Array[LastMatch-1]->getIdentifierNamespace() == Decl::IDNS_Tag)
608 InsertPos = LastMatch - 1;
609 else
610 InsertPos = LastMatch;
Douglas Gregor44b43212008-12-11 16:49:14 +0000611 }
612
613 if (Size < LookupIsMap - 1) {
614 // The new declaration will fit in the array. Insert the new
615 // declaration at the position Match in the array.
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000616 for (unsigned Idx = Size; Idx > InsertPos; --Idx)
Douglas Gregor44b43212008-12-11 16:49:14 +0000617 Array[Idx] = Array[Idx-1];
618
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000619 Array[InsertPos] = D;
Douglas Gregor44b43212008-12-11 16:49:14 +0000620 LookupPtr.setInt(Size + 1);
621 return;
622 }
623
624 // We've reached capacity in this array. Create a map and copy in
625 // all of the declarations that were stored in the array.
626 StoredDeclsMap *Map = new StoredDeclsMap(16);
627 LookupPtr.setPointer(Map);
628 LookupPtr.setInt(LookupIsMap);
Douglas Gregore267ff32008-12-11 20:41:00 +0000629 for (unsigned Idx = 0; Idx != LookupIsMap - 1; ++Idx)
Douglas Gregor44b43212008-12-11 16:49:14 +0000630 insertImpl(Array[Idx]);
631 delete [] Array;
632
633 // Fall through to perform insertion into the map.
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000634 MayBeRedeclaration = false;
635 }
Douglas Gregor44b43212008-12-11 16:49:14 +0000636
637 // Insert this declaration into the map.
638 StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(LookupPtr.getPointer());
639 StoredDeclsMap::iterator Pos = Map->find(D->getDeclName());
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000640 if (Pos != Map->end()) {
641 if (MayBeRedeclaration) {
642 // Determine if this declaration is actually a redeclaration.
643 for (std::vector<ScopedDecl *>::iterator I = Pos->second.begin(),
644 IEnd = Pos->second.end();
645 I != IEnd; ++I) {
646 if (isRedeclarationOf(D, *I)) {
647 // D is a redeclaration of *I. Replace *I with D and we're
648 // done.
649 *I = D;
650 return;
651 }
652 }
653 }
Douglas Gregor44b43212008-12-11 16:49:14 +0000654
Douglas Gregor44b43212008-12-11 16:49:14 +0000655 // Put this declaration into the appropriate slot.
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000656 if (D->getIdentifierNamespace() == Decl::IDNS_Tag || Pos->second.empty())
657 Pos->second.push_back(D);
658 else if (Pos->second.back()->getIdentifierNamespace() == Decl::IDNS_Tag) {
659 ScopedDecl *TagD = Pos->second.back();
660 Pos->second.back() = D;
661 Pos->second.push_back(TagD);
662 } else
663 Pos->second.push_back(D);
Douglas Gregor44b43212008-12-11 16:49:14 +0000664 } else {
Douglas Gregor3fc749d2008-12-23 00:26:44 +0000665 (*Map)[D->getDeclName()].push_back(D);
Douglas Gregor44b43212008-12-11 16:49:14 +0000666 }
667}