Decl.cpp revision 8123a95c33b792d35c2e4992ba6e27882748fb0d
1//===--- Decl.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 class and subclasses.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/AST/Decl.h"
15#include "clang/AST/ASTContext.h"
16#include "clang/AST/Attr.h"
17#include "clang/Basic/IdentifierTable.h"
18#include "llvm/ADT/DenseMap.h"
19using namespace clang;
20
21//===----------------------------------------------------------------------===//
22//  Statistics
23//===----------------------------------------------------------------------===//
24
25// temporary statistics gathering
26static unsigned nFuncs = 0;
27static unsigned nBlockVars = 0;
28static unsigned nFileVars = 0;
29static unsigned nParmVars = 0;
30static unsigned nSUC = 0;
31static unsigned nEnumConst = 0;
32static unsigned nEnumDecls = 0;
33static unsigned nTypedef = 0;
34static unsigned nFieldDecls = 0;
35static unsigned nInterfaceDecls = 0;
36static unsigned nClassDecls = 0;
37static unsigned nMethodDecls = 0;
38static unsigned nProtocolDecls = 0;
39static unsigned nForwardProtocolDecls = 0;
40static unsigned nCategoryDecls = 0;
41static unsigned nIvarDecls = 0;
42static unsigned nObjCImplementationDecls = 0;
43static unsigned nObjCCategoryImpl = 0;
44static unsigned nObjCCompatibleAlias = 0;
45static unsigned nObjCPropertyDecl = 0;
46static unsigned nLinkageSpecDecl = 0;
47static unsigned nFileScopeAsmDecl = 0;
48
49static bool StatSwitch = false;
50
51// This keeps track of all decl attributes. Since so few decls have attrs, we
52// keep them in a hash map instead of wasting space in the Decl class.
53typedef llvm::DenseMap<const Decl*, Attr*> DeclAttrMapTy;
54
55static DeclAttrMapTy *DeclAttrs = 0;
56
57const char *Decl::getDeclKindName() const {
58  switch (DeclKind) {
59  default: assert(0 && "Unknown decl kind!");
60  case Typedef:             return "Typedef";
61  case Function:            return "Function";
62  case BlockVar:            return "BlockVar";
63  case FileVar:             return "FileVar";
64  case ParmVar:             return "ParmVar";
65  case EnumConstant:        return "EnumConstant";
66  case ObjCInterface:       return "ObjCInterface";
67  case ObjCClass:           return "ObjCClass";
68  case ObjCMethod:          return "ObjCMethod";
69  case ObjCProtocol:        return "ObjCProtocol";
70  case ObjCForwardProtocol: return "ObjCForwardProtocol";
71  case Struct:              return "Struct";
72  case Union:               return "Union";
73  case Class:               return "Class";
74  case Enum:                return "Enum";
75  }
76}
77
78bool Decl::CollectingStats(bool Enable) {
79  if (Enable)
80    StatSwitch = true;
81  return StatSwitch;
82}
83
84void Decl::PrintStats() {
85  fprintf(stderr, "*** Decl Stats:\n");
86  fprintf(stderr, "  %d decls total.\n",
87          int(nFuncs+nBlockVars+nFileVars+nParmVars+nFieldDecls+nSUC+
88              nEnumDecls+nEnumConst+nTypedef+nInterfaceDecls+nClassDecls+
89              nMethodDecls+nProtocolDecls+nCategoryDecls+nIvarDecls));
90  fprintf(stderr, "    %d function decls, %d each (%d bytes)\n",
91          nFuncs, (int)sizeof(FunctionDecl), int(nFuncs*sizeof(FunctionDecl)));
92  fprintf(stderr, "    %d block variable decls, %d each (%d bytes)\n",
93          nBlockVars, (int)sizeof(BlockVarDecl),
94          int(nBlockVars*sizeof(BlockVarDecl)));
95  fprintf(stderr, "    %d file variable decls, %d each (%d bytes)\n",
96          nFileVars, (int)sizeof(FileVarDecl),
97          int(nFileVars*sizeof(FileVarDecl)));
98  fprintf(stderr, "    %d parameter variable decls, %d each (%d bytes)\n",
99          nParmVars, (int)sizeof(ParmVarDecl),
100          int(nParmVars*sizeof(ParmVarDecl)));
101  fprintf(stderr, "    %d field decls, %d each (%d bytes)\n",
102          nFieldDecls, (int)sizeof(FieldDecl),
103          int(nFieldDecls*sizeof(FieldDecl)));
104  fprintf(stderr, "    %d struct/union/class decls, %d each (%d bytes)\n",
105          nSUC, (int)sizeof(RecordDecl),
106          int(nSUC*sizeof(RecordDecl)));
107  fprintf(stderr, "    %d enum decls, %d each (%d bytes)\n",
108          nEnumDecls, (int)sizeof(EnumDecl),
109          int(nEnumDecls*sizeof(EnumDecl)));
110  fprintf(stderr, "    %d enum constant decls, %d each (%d bytes)\n",
111          nEnumConst, (int)sizeof(EnumConstantDecl),
112          int(nEnumConst*sizeof(EnumConstantDecl)));
113  fprintf(stderr, "    %d typedef decls, %d each (%d bytes)\n",
114          nTypedef, (int)sizeof(TypedefDecl),int(nTypedef*sizeof(TypedefDecl)));
115  // Objective-C decls...
116  fprintf(stderr, "    %d interface decls, %d each (%d bytes)\n",
117          nInterfaceDecls, (int)sizeof(ObjCInterfaceDecl),
118          int(nInterfaceDecls*sizeof(ObjCInterfaceDecl)));
119  fprintf(stderr, "    %d instance variable decls, %d each (%d bytes)\n",
120          nIvarDecls, (int)sizeof(ObjCIvarDecl),
121          int(nIvarDecls*sizeof(ObjCIvarDecl)));
122  fprintf(stderr, "    %d class decls, %d each (%d bytes)\n",
123          nClassDecls, (int)sizeof(ObjCClassDecl),
124          int(nClassDecls*sizeof(ObjCClassDecl)));
125  fprintf(stderr, "    %d method decls, %d each (%d bytes)\n",
126          nMethodDecls, (int)sizeof(ObjCMethodDecl),
127          int(nMethodDecls*sizeof(ObjCMethodDecl)));
128  fprintf(stderr, "    %d protocol decls, %d each (%d bytes)\n",
129          nProtocolDecls, (int)sizeof(ObjCProtocolDecl),
130          int(nProtocolDecls*sizeof(ObjCProtocolDecl)));
131  fprintf(stderr, "    %d forward protocol decls, %d each (%d bytes)\n",
132          nForwardProtocolDecls, (int)sizeof(ObjCForwardProtocolDecl),
133          int(nForwardProtocolDecls*sizeof(ObjCForwardProtocolDecl)));
134  fprintf(stderr, "    %d category decls, %d each (%d bytes)\n",
135          nCategoryDecls, (int)sizeof(ObjCCategoryDecl),
136          int(nCategoryDecls*sizeof(ObjCCategoryDecl)));
137
138  fprintf(stderr, "    %d class implementation decls, %d each (%d bytes)\n",
139          nObjCImplementationDecls, (int)sizeof(ObjCImplementationDecl),
140          int(nObjCImplementationDecls*sizeof(ObjCImplementationDecl)));
141
142  fprintf(stderr, "    %d class implementation decls, %d each (%d bytes)\n",
143          nObjCCategoryImpl, (int)sizeof(ObjCCategoryImplDecl),
144          int(nObjCCategoryImpl*sizeof(ObjCCategoryImplDecl)));
145
146  fprintf(stderr, "    %d compatibility alias decls, %d each (%d bytes)\n",
147          nObjCCompatibleAlias, (int)sizeof(ObjCCompatibleAliasDecl),
148          int(nObjCCompatibleAlias*sizeof(ObjCCompatibleAliasDecl)));
149
150  fprintf(stderr, "    %d property decls, %d each (%d bytes)\n",
151          nObjCPropertyDecl, (int)sizeof(ObjCPropertyDecl),
152          int(nObjCPropertyDecl*sizeof(ObjCPropertyDecl)));
153
154  fprintf(stderr, "Total bytes = %d\n",
155          int(nFuncs*sizeof(FunctionDecl)+nBlockVars*sizeof(BlockVarDecl)+
156              nFileVars*sizeof(FileVarDecl)+nParmVars*sizeof(ParmVarDecl)+
157              nFieldDecls*sizeof(FieldDecl)+nSUC*sizeof(RecordDecl)+
158              nEnumDecls*sizeof(EnumDecl)+nEnumConst*sizeof(EnumConstantDecl)+
159              nTypedef*sizeof(TypedefDecl)+
160              nInterfaceDecls*sizeof(ObjCInterfaceDecl)+
161              nIvarDecls*sizeof(ObjCIvarDecl)+
162              nClassDecls*sizeof(ObjCClassDecl)+
163              nMethodDecls*sizeof(ObjCMethodDecl)+
164              nProtocolDecls*sizeof(ObjCProtocolDecl)+
165              nForwardProtocolDecls*sizeof(ObjCForwardProtocolDecl)+
166              nCategoryDecls*sizeof(ObjCCategoryDecl)+
167              nObjCImplementationDecls*sizeof(ObjCImplementationDecl)+
168              nObjCCategoryImpl*sizeof(ObjCCategoryImplDecl)+
169              nObjCCompatibleAlias*sizeof(ObjCCompatibleAliasDecl)+
170              nObjCPropertyDecl*sizeof(ObjCPropertyDecl)+
171              nLinkageSpecDecl*sizeof(LinkageSpecDecl)+
172              nFileScopeAsmDecl*sizeof(FileScopeAsmDecl)));
173
174}
175
176void Decl::addDeclKind(Kind k) {
177  switch (k) {
178  case Typedef:             nTypedef++; break;
179  case Function:            nFuncs++; break;
180  case BlockVar:            nBlockVars++; break;
181  case FileVar:             nFileVars++; break;
182  case ParmVar:             nParmVars++; break;
183  case EnumConstant:        nEnumConst++; break;
184  case Field:               nFieldDecls++; break;
185  case Struct: case Union: case Class: nSUC++; break;
186  case Enum:                nEnumDecls++; break;
187  case ObjCInterface:       nInterfaceDecls++; break;
188  case ObjCClass:           nClassDecls++; break;
189  case ObjCMethod:          nMethodDecls++; break;
190  case ObjCProtocol:        nProtocolDecls++; break;
191  case ObjCForwardProtocol: nForwardProtocolDecls++; break;
192  case ObjCCategory:        nCategoryDecls++; break;
193  case ObjCIvar:            nIvarDecls++; break;
194  case ObjCImplementation:  nObjCImplementationDecls++; break;
195  case ObjCCategoryImpl:    nObjCCategoryImpl++; break;
196  case ObjCCompatibleAlias: nObjCCompatibleAlias++; break;
197  case ObjCProperty:        nObjCPropertyDecl++; break;
198  case LinkageSpec:         nLinkageSpecDecl++; break;
199  case FileScopeAsm:        nFileScopeAsmDecl++; break;
200  }
201}
202
203//===----------------------------------------------------------------------===//
204// Decl Allocation/Deallocation Method Implementations
205//===----------------------------------------------------------------------===//
206
207BlockVarDecl *BlockVarDecl::Create(ASTContext &C, DeclContext *CD,
208                                   SourceLocation L,
209                                   IdentifierInfo *Id, QualType T,
210                                   StorageClass S, ScopedDecl *PrevDecl) {
211  void *Mem = C.getAllocator().Allocate<BlockVarDecl>();
212  return new (Mem) BlockVarDecl(CD, L, Id, T, S, PrevDecl);
213}
214
215
216FileVarDecl *FileVarDecl::Create(ASTContext &C, DeclContext *CD,
217                                 SourceLocation L, IdentifierInfo *Id,
218                                 QualType T, StorageClass S,
219                                 ScopedDecl *PrevDecl) {
220  void *Mem = C.getAllocator().Allocate<FileVarDecl>();
221  return new (Mem) FileVarDecl(CD, L, Id, T, S, PrevDecl);
222}
223
224ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *CD,
225                                 SourceLocation L, IdentifierInfo *Id,
226                                 QualType T, StorageClass S,
227                                 Expr *DefArg, ScopedDecl *PrevDecl) {
228  void *Mem = C.getAllocator().Allocate<ParmVarDecl>();
229  return new (Mem) ParmVarDecl(CD, L, Id, T, S, DefArg, PrevDecl);
230}
231
232FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *CD,
233                                   SourceLocation L,
234                                   IdentifierInfo *Id, QualType T,
235                                   StorageClass S, bool isInline,
236                                   ScopedDecl *PrevDecl) {
237  void *Mem = C.getAllocator().Allocate<FunctionDecl>();
238  return new (Mem) FunctionDecl(CD, L, Id, T, S, isInline, PrevDecl);
239}
240
241FieldDecl *FieldDecl::Create(ASTContext &C, SourceLocation L,
242                             IdentifierInfo *Id, QualType T, Expr *BW) {
243  void *Mem = C.getAllocator().Allocate<FieldDecl>();
244  return new (Mem) FieldDecl(L, Id, T, BW);
245}
246
247
248EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD,
249                                           SourceLocation L,
250                                           IdentifierInfo *Id, QualType T,
251                                           Expr *E, const llvm::APSInt &V,
252                                           ScopedDecl *PrevDecl){
253  void *Mem = C.getAllocator().Allocate<EnumConstantDecl>();
254  return new (Mem) EnumConstantDecl(CD, L, Id, T, E, V, PrevDecl);
255}
256
257TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *CD,
258                                 SourceLocation L,
259                                 IdentifierInfo *Id, QualType T,
260                                 ScopedDecl *PD) {
261  void *Mem = C.getAllocator().Allocate<TypedefDecl>();
262  return new (Mem) TypedefDecl(CD, L, Id, T, PD);
263}
264
265EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *CD, SourceLocation L,
266                           IdentifierInfo *Id,
267                           ScopedDecl *PrevDecl) {
268  void *Mem = C.getAllocator().Allocate<EnumDecl>();
269  return new (Mem) EnumDecl(CD, L, Id, PrevDecl);
270}
271
272RecordDecl *RecordDecl::Create(ASTContext &C, Kind DK, DeclContext *CD,
273                               SourceLocation L, IdentifierInfo *Id,
274                               ScopedDecl *PrevDecl) {
275  void *Mem = C.getAllocator().Allocate<RecordDecl>();
276  return new (Mem) RecordDecl(DK, CD, L, Id, PrevDecl);
277}
278
279FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C,
280                                           SourceLocation L,
281                                           StringLiteral *Str) {
282  void *Mem = C.getAllocator().Allocate<FileScopeAsmDecl>();
283  return new (Mem) FileScopeAsmDecl(L, Str);
284}
285
286LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
287                                         SourceLocation L,
288                                         LanguageIDs Lang, Decl *D) {
289  void *Mem = C.getAllocator().Allocate<LinkageSpecDecl>();
290  return new (Mem) LinkageSpecDecl(L, Lang, D);
291}
292
293//===----------------------------------------------------------------------===//
294// Decl Implementation
295//===----------------------------------------------------------------------===//
296
297// Out-of-line virtual method providing a home for Decl.
298Decl::~Decl() {
299  if (!HasAttrs)
300    return;
301
302  DeclAttrMapTy::iterator it = DeclAttrs->find(this);
303  assert(it != DeclAttrs->end() && "No attrs found but HasAttrs is true!");
304
305  delete it->second;
306  DeclAttrs->erase(it);
307  if (DeclAttrs->empty()) {
308    delete DeclAttrs;
309    DeclAttrs = 0;
310  }
311}
312
313void Decl::addAttr(Attr *NewAttr) {
314  if (!DeclAttrs)
315    DeclAttrs = new DeclAttrMapTy();
316
317  Attr *&ExistingAttr = (*DeclAttrs)[this];
318
319  NewAttr->setNext(ExistingAttr);
320  ExistingAttr = NewAttr;
321
322  HasAttrs = true;
323}
324
325const Attr *Decl::getAttrs() const {
326  if (!HasAttrs)
327    return 0;
328
329  return (*DeclAttrs)[this];
330}
331
332//===----------------------------------------------------------------------===//
333// DeclContext Implementation
334//===----------------------------------------------------------------------===//
335
336DeclContext *DeclContext::getParent() const {
337  if (ScopedDecl *SD = dyn_cast<ScopedDecl>(this))
338    return SD->getDeclContext();
339  else
340    return NULL;
341}
342
343Decl *DeclContext::ToDecl (const DeclContext *D) {
344  return CastTo<Decl>(D);
345}
346
347DeclContext *DeclContext::FromDecl (const Decl *D) {
348  return CastTo<DeclContext>(D);
349}
350
351//===----------------------------------------------------------------------===//
352// NamedDecl Implementation
353//===----------------------------------------------------------------------===//
354
355const char *NamedDecl::getName() const {
356  if (const IdentifierInfo *II = getIdentifier())
357    return II->getName();
358  return "";
359}
360
361//===----------------------------------------------------------------------===//
362// FunctionDecl Implementation
363//===----------------------------------------------------------------------===//
364
365FunctionDecl::~FunctionDecl() {
366  delete[] ParamInfo;
367  delete Body;
368}
369
370unsigned FunctionDecl::getNumParams() const {
371  const FunctionType *FT = getType()->getAsFunctionType();
372  if (isa<FunctionTypeNoProto>(FT))
373    return 0;
374  return cast<FunctionTypeProto>(FT)->getNumArgs();
375}
376
377void FunctionDecl::setParams(ParmVarDecl **NewParamInfo, unsigned NumParams) {
378  assert(ParamInfo == 0 && "Already has param info!");
379  assert(NumParams == getNumParams() && "Parameter count mismatch!");
380
381  // Zero params -> null pointer.
382  if (NumParams) {
383    ParamInfo = new ParmVarDecl*[NumParams];
384    memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*NumParams);
385  }
386}
387
388/// getMinRequiredArguments - Returns the minimum number of arguments
389/// needed to call this function. This may be fewer than the number of
390/// function parameters, if some of the parameters have default
391/// arguments.
392unsigned FunctionDecl::getMinRequiredArguments() const {
393  unsigned NumRequiredArgs = getNumParams();
394  while (NumRequiredArgs > 0
395         && getParamDecl(NumRequiredArgs-1)->getDefaultArg())
396    --NumRequiredArgs;
397
398  return NumRequiredArgs;
399}
400
401//===----------------------------------------------------------------------===//
402// RecordDecl Implementation
403//===----------------------------------------------------------------------===//
404
405/// defineBody - When created, RecordDecl's correspond to a forward declared
406/// record.  This method is used to mark the decl as being defined, with the
407/// specified contents.
408void RecordDecl::defineBody(FieldDecl **members, unsigned numMembers) {
409  assert(!isDefinition() && "Cannot redefine record!");
410  setDefinition(true);
411  NumMembers = numMembers;
412  if (numMembers) {
413    Members = new FieldDecl*[numMembers];
414    memcpy(Members, members, numMembers*sizeof(Decl*));
415  }
416}
417
418FieldDecl *RecordDecl::getMember(IdentifierInfo *II) {
419  if (Members == 0 || NumMembers < 0)
420    return 0;
421
422  // Linear search.  When C++ classes come along, will likely need to revisit.
423  for (int i = 0; i != NumMembers; ++i)
424    if (Members[i]->getIdentifier() == II)
425      return Members[i];
426  return 0;
427}
428