Decl.cpp revision 328bdf212a0515875a0064832a02c9565be55280
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 PropertyDecl: 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, ContextDecl *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, ContextDecl *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, ContextDecl *CD, 225 SourceLocation L, IdentifierInfo *Id, 226 QualType T, StorageClass S, 227 ScopedDecl *PrevDecl) { 228 void *Mem = C.getAllocator().Allocate<ParmVarDecl>(); 229 return new (Mem) ParmVarDecl(CD, L, Id, T, S, PrevDecl); 230} 231 232FunctionDecl *FunctionDecl::Create(ASTContext &C, ContextDecl *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, RecordDecl *CD, SourceLocation L, 242 IdentifierInfo *Id, QualType T, Expr *BW) { 243 void *Mem = C.getAllocator().Allocate<FieldDecl>(); 244 return new (Mem) FieldDecl(CD, 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, ContextDecl *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, ContextDecl *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, ContextDecl *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// ContextDecl Implementation 334//===----------------------------------------------------------------------===// 335 336ContextDecl *ContextDecl::getParent() const { 337 if (ScopedDecl *SD = dyn_cast<ScopedDecl>(this)) 338 return SD->getContextDecl(); 339 else 340 return NULL; 341} 342 343Decl *ContextDecl::ToDecl (const ContextDecl *D) { 344 return CastTo<Decl>(D); 345} 346 347ContextDecl *ContextDecl::FromDecl (const Decl *D) { 348 return CastTo<ContextDecl>(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 if (isa<FunctionTypeNoProto>(getCanonicalType())) 372 return 0; 373 return cast<FunctionTypeProto>(getCanonicalType())->getNumArgs(); 374} 375 376void FunctionDecl::setParams(ParmVarDecl **NewParamInfo, unsigned NumParams) { 377 assert(ParamInfo == 0 && "Already has param info!"); 378 assert(NumParams == getNumParams() && "Parameter count mismatch!"); 379 380 // Zero params -> null pointer. 381 if (NumParams) { 382 ParamInfo = new ParmVarDecl*[NumParams]; 383 memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*NumParams); 384 } 385} 386 387//===----------------------------------------------------------------------===// 388// RecordDecl Implementation 389//===----------------------------------------------------------------------===// 390 391/// defineBody - When created, RecordDecl's correspond to a forward declared 392/// record. This method is used to mark the decl as being defined, with the 393/// specified contents. 394void RecordDecl::defineBody(FieldDecl **members, unsigned numMembers) { 395 assert(!isDefinition() && "Cannot redefine record!"); 396 setDefinition(true); 397 NumMembers = numMembers; 398 if (numMembers) { 399 Members = new FieldDecl*[numMembers]; 400 memcpy(Members, members, numMembers*sizeof(Decl*)); 401 } 402} 403 404FieldDecl *RecordDecl::getMember(IdentifierInfo *II) { 405 if (Members == 0 || NumMembers < 0) 406 return 0; 407 408 // Linear search. When C++ classes come along, will likely need to revisit. 409 for (int i = 0; i != NumMembers; ++i) 410 if (Members[i]->getIdentifier() == II) 411 return Members[i]; 412 return 0; 413} 414