Decl.cpp revision 9141bee299a05349924a34a7153d7064c9e0a107
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" 19 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; 31static unsigned nEnumConst = 0; 32static unsigned nEnumDecls = 0; 33static unsigned nNamespaces = 0; 34static unsigned nTypedef = 0; 35static unsigned nFieldDecls = 0; 36static unsigned nInterfaceDecls = 0; 37static unsigned nClassDecls = 0; 38static unsigned nMethodDecls = 0; 39static unsigned nProtocolDecls = 0; 40static unsigned nForwardProtocolDecls = 0; 41static unsigned nCategoryDecls = 0; 42static unsigned nIvarDecls = 0; 43static unsigned nObjCImplementationDecls = 0; 44static unsigned nObjCCategoryImpl = 0; 45static unsigned nObjCCompatibleAlias = 0; 46static unsigned nObjCPropertyDecl = 0; 47static unsigned nObjCPropertyImplDecl = 0; 48static unsigned nLinkageSpecDecl = 0; 49static unsigned nFileScopeAsmDecl = 0; 50 51static bool StatSwitch = false; 52 53// This keeps track of all decl attributes. Since so few decls have attrs, we 54// keep them in a hash map instead of wasting space in the Decl class. 55typedef llvm::DenseMap<const Decl*, Attr*> DeclAttrMapTy; 56 57static DeclAttrMapTy *DeclAttrs = 0; 58 59const char *Decl::getDeclKindName() const { 60 switch (DeclKind) { 61 default: assert(0 && "Unknown decl kind!"); 62 case Namespace: return "Namespace"; 63 case Typedef: return "Typedef"; 64 case Function: return "Function"; 65 case Var: return "Var"; 66 case ParmVar: return "ParmVar"; 67 case EnumConstant: return "EnumConstant"; 68 case ObjCIvar: return "ObjCIvar"; 69 case ObjCInterface: return "ObjCInterface"; 70 case ObjCClass: return "ObjCClass"; 71 case ObjCMethod: return "ObjCMethod"; 72 case ObjCProtocol: return "ObjCProtocol"; 73 case ObjCForwardProtocol: return "ObjCForwardProtocol"; 74 case Struct: return "Struct"; 75 case Union: return "Union"; 76 case Class: return "Class"; 77 case Enum: return "Enum"; 78 } 79} 80 81bool Decl::CollectingStats(bool Enable) { 82 if (Enable) 83 StatSwitch = true; 84 return StatSwitch; 85} 86 87void Decl::PrintStats() { 88 fprintf(stderr, "*** Decl Stats:\n"); 89 fprintf(stderr, " %d decls total.\n", 90 int(nFuncs+nVars+nParmVars+nFieldDecls+nSUC+ 91 nEnumDecls+nEnumConst+nTypedef+nInterfaceDecls+nClassDecls+ 92 nMethodDecls+nProtocolDecls+nCategoryDecls+nIvarDecls+ 93 nNamespaces)); 94 fprintf(stderr, " %d namespace decls, %d each (%d bytes)\n", 95 nNamespaces, (int)sizeof(NamespaceDecl), 96 int(nNamespaces*sizeof(NamespaceDecl))); 97 fprintf(stderr, " %d function decls, %d each (%d bytes)\n", 98 nFuncs, (int)sizeof(FunctionDecl), int(nFuncs*sizeof(FunctionDecl))); 99 fprintf(stderr, " %d variable decls, %d each (%d bytes)\n", 100 nVars, (int)sizeof(VarDecl), 101 int(nVars*sizeof(VarDecl))); 102 fprintf(stderr, " %d parameter variable decls, %d each (%d bytes)\n", 103 nParmVars, (int)sizeof(ParmVarDecl), 104 int(nParmVars*sizeof(ParmVarDecl))); 105 fprintf(stderr, " %d field decls, %d each (%d bytes)\n", 106 nFieldDecls, (int)sizeof(FieldDecl), 107 int(nFieldDecls*sizeof(FieldDecl))); 108 fprintf(stderr, " %d struct/union/class decls, %d each (%d bytes)\n", 109 nSUC, (int)sizeof(RecordDecl), 110 int(nSUC*sizeof(RecordDecl))); 111 fprintf(stderr, " %d enum decls, %d each (%d bytes)\n", 112 nEnumDecls, (int)sizeof(EnumDecl), 113 int(nEnumDecls*sizeof(EnumDecl))); 114 fprintf(stderr, " %d enum constant decls, %d each (%d bytes)\n", 115 nEnumConst, (int)sizeof(EnumConstantDecl), 116 int(nEnumConst*sizeof(EnumConstantDecl))); 117 fprintf(stderr, " %d typedef decls, %d each (%d bytes)\n", 118 nTypedef, (int)sizeof(TypedefDecl),int(nTypedef*sizeof(TypedefDecl))); 119 // Objective-C decls... 120 fprintf(stderr, " %d interface decls, %d each (%d bytes)\n", 121 nInterfaceDecls, (int)sizeof(ObjCInterfaceDecl), 122 int(nInterfaceDecls*sizeof(ObjCInterfaceDecl))); 123 fprintf(stderr, " %d instance variable decls, %d each (%d bytes)\n", 124 nIvarDecls, (int)sizeof(ObjCIvarDecl), 125 int(nIvarDecls*sizeof(ObjCIvarDecl))); 126 fprintf(stderr, " %d class decls, %d each (%d bytes)\n", 127 nClassDecls, (int)sizeof(ObjCClassDecl), 128 int(nClassDecls*sizeof(ObjCClassDecl))); 129 fprintf(stderr, " %d method decls, %d each (%d bytes)\n", 130 nMethodDecls, (int)sizeof(ObjCMethodDecl), 131 int(nMethodDecls*sizeof(ObjCMethodDecl))); 132 fprintf(stderr, " %d protocol decls, %d each (%d bytes)\n", 133 nProtocolDecls, (int)sizeof(ObjCProtocolDecl), 134 int(nProtocolDecls*sizeof(ObjCProtocolDecl))); 135 fprintf(stderr, " %d forward protocol decls, %d each (%d bytes)\n", 136 nForwardProtocolDecls, (int)sizeof(ObjCForwardProtocolDecl), 137 int(nForwardProtocolDecls*sizeof(ObjCForwardProtocolDecl))); 138 fprintf(stderr, " %d category decls, %d each (%d bytes)\n", 139 nCategoryDecls, (int)sizeof(ObjCCategoryDecl), 140 int(nCategoryDecls*sizeof(ObjCCategoryDecl))); 141 142 fprintf(stderr, " %d class implementation decls, %d each (%d bytes)\n", 143 nObjCImplementationDecls, (int)sizeof(ObjCImplementationDecl), 144 int(nObjCImplementationDecls*sizeof(ObjCImplementationDecl))); 145 146 fprintf(stderr, " %d class implementation decls, %d each (%d bytes)\n", 147 nObjCCategoryImpl, (int)sizeof(ObjCCategoryImplDecl), 148 int(nObjCCategoryImpl*sizeof(ObjCCategoryImplDecl))); 149 150 fprintf(stderr, " %d compatibility alias decls, %d each (%d bytes)\n", 151 nObjCCompatibleAlias, (int)sizeof(ObjCCompatibleAliasDecl), 152 int(nObjCCompatibleAlias*sizeof(ObjCCompatibleAliasDecl))); 153 154 fprintf(stderr, " %d property decls, %d each (%d bytes)\n", 155 nObjCPropertyDecl, (int)sizeof(ObjCPropertyDecl), 156 int(nObjCPropertyDecl*sizeof(ObjCPropertyDecl))); 157 158 fprintf(stderr, " %d property implementation decls, %d each (%d bytes)\n", 159 nObjCPropertyImplDecl, (int)sizeof(ObjCPropertyImplDecl), 160 int(nObjCPropertyImplDecl*sizeof(ObjCPropertyImplDecl))); 161 162 fprintf(stderr, "Total bytes = %d\n", 163 int(nFuncs*sizeof(FunctionDecl)+ 164 nVars*sizeof(VarDecl)+nParmVars*sizeof(ParmVarDecl)+ 165 nFieldDecls*sizeof(FieldDecl)+nSUC*sizeof(RecordDecl)+ 166 nEnumDecls*sizeof(EnumDecl)+nEnumConst*sizeof(EnumConstantDecl)+ 167 nTypedef*sizeof(TypedefDecl)+ 168 nInterfaceDecls*sizeof(ObjCInterfaceDecl)+ 169 nIvarDecls*sizeof(ObjCIvarDecl)+ 170 nClassDecls*sizeof(ObjCClassDecl)+ 171 nMethodDecls*sizeof(ObjCMethodDecl)+ 172 nProtocolDecls*sizeof(ObjCProtocolDecl)+ 173 nForwardProtocolDecls*sizeof(ObjCForwardProtocolDecl)+ 174 nCategoryDecls*sizeof(ObjCCategoryDecl)+ 175 nObjCImplementationDecls*sizeof(ObjCImplementationDecl)+ 176 nObjCCategoryImpl*sizeof(ObjCCategoryImplDecl)+ 177 nObjCCompatibleAlias*sizeof(ObjCCompatibleAliasDecl)+ 178 nObjCPropertyDecl*sizeof(ObjCPropertyDecl)+ 179 nObjCPropertyImplDecl*sizeof(ObjCPropertyImplDecl)+ 180 nLinkageSpecDecl*sizeof(LinkageSpecDecl)+ 181 nFileScopeAsmDecl*sizeof(FileScopeAsmDecl)+ 182 nNamespaces*sizeof(NamespaceDecl))); 183 184} 185 186void Decl::addDeclKind(Kind k) { 187 switch (k) { 188 case Namespace: nNamespaces++; break; 189 case Typedef: nTypedef++; break; 190 case Function: nFuncs++; break; 191 case Var: nVars++; break; 192 case ParmVar: nParmVars++; break; 193 case EnumConstant: nEnumConst++; break; 194 case Field: nFieldDecls++; break; 195 case Struct: case Union: case Class: nSUC++; break; 196 case Enum: nEnumDecls++; break; 197 case ObjCInterface: nInterfaceDecls++; break; 198 case ObjCClass: nClassDecls++; break; 199 case ObjCMethod: nMethodDecls++; break; 200 case ObjCProtocol: nProtocolDecls++; break; 201 case ObjCForwardProtocol: nForwardProtocolDecls++; break; 202 case ObjCCategory: nCategoryDecls++; break; 203 case ObjCIvar: nIvarDecls++; break; 204 case ObjCImplementation: nObjCImplementationDecls++; break; 205 case ObjCCategoryImpl: nObjCCategoryImpl++; break; 206 case ObjCCompatibleAlias: nObjCCompatibleAlias++; break; 207 case ObjCProperty: nObjCPropertyDecl++; break; 208 case ObjCPropertyImpl: nObjCPropertyImplDecl++; break; 209 case LinkageSpec: nLinkageSpecDecl++; break; 210 case FileScopeAsm: nFileScopeAsmDecl++; break; 211 case TranslationUnit: break; 212 } 213} 214 215//===----------------------------------------------------------------------===// 216// Decl Allocation/Deallocation Method Implementations 217//===----------------------------------------------------------------------===// 218 219TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) { 220 void *Mem = C.getAllocator().Allocate<TranslationUnitDecl>(); 221 return new (Mem) TranslationUnitDecl(); 222} 223 224NamespaceDecl *NamespaceDecl::Create(ASTContext &C, DeclContext *DC, 225 SourceLocation L, IdentifierInfo *Id) { 226 void *Mem = C.getAllocator().Allocate<NamespaceDecl>(); 227 return new (Mem) NamespaceDecl(DC, L, Id); 228} 229 230void NamespaceDecl::Destroy(ASTContext& C) { 231 // NamespaceDecl uses "NextDeclarator" to chain namespace declarations 232 // together. They are all top-level Decls. 233 234 this->~NamespaceDecl(); 235 C.getAllocator().Deallocate((void *)this); 236} 237 238 239VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC, 240 SourceLocation L, 241 IdentifierInfo *Id, QualType T, 242 StorageClass S, ScopedDecl *PrevDecl) { 243 void *Mem = C.getAllocator().Allocate<VarDecl>(); 244 return new (Mem) VarDecl(Var, DC, L, Id, T, S, PrevDecl); 245} 246 247ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC, 248 SourceLocation L, IdentifierInfo *Id, 249 QualType T, StorageClass S, 250 Expr *DefArg, ScopedDecl *PrevDecl) { 251 void *Mem = C.getAllocator().Allocate<ParmVarDecl>(); 252 return new (Mem) ParmVarDecl(DC, L, Id, T, S, DefArg, PrevDecl); 253} 254 255FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC, 256 SourceLocation L, 257 IdentifierInfo *Id, QualType T, 258 StorageClass S, bool isInline, 259 ScopedDecl *PrevDecl) { 260 void *Mem = C.getAllocator().Allocate<FunctionDecl>(); 261 return new (Mem) FunctionDecl(DC, L, Id, T, S, isInline, PrevDecl); 262} 263 264FieldDecl *FieldDecl::Create(ASTContext &C, SourceLocation L, 265 IdentifierInfo *Id, QualType T, Expr *BW) { 266 void *Mem = C.getAllocator().Allocate<FieldDecl>(); 267 return new (Mem) FieldDecl(L, Id, T, BW); 268} 269 270 271EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD, 272 SourceLocation L, 273 IdentifierInfo *Id, QualType T, 274 Expr *E, const llvm::APSInt &V, 275 ScopedDecl *PrevDecl){ 276 void *Mem = C.getAllocator().Allocate<EnumConstantDecl>(); 277 return new (Mem) EnumConstantDecl(CD, L, Id, T, E, V, PrevDecl); 278} 279 280void EnumConstantDecl::Destroy(ASTContext& C) { 281 if (Init) Init->Destroy(C); 282 Decl::Destroy(C); 283} 284 285TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC, 286 SourceLocation L, 287 IdentifierInfo *Id, QualType T, 288 ScopedDecl *PD) { 289 void *Mem = C.getAllocator().Allocate<TypedefDecl>(); 290 return new (Mem) TypedefDecl(DC, L, Id, T, PD); 291} 292 293EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, 294 IdentifierInfo *Id, 295 ScopedDecl *PrevDecl) { 296 void *Mem = C.getAllocator().Allocate<EnumDecl>(); 297 return new (Mem) EnumDecl(DC, L, Id, PrevDecl); 298} 299 300RecordDecl *RecordDecl::Create(ASTContext &C, Kind DK, DeclContext *DC, 301 SourceLocation L, IdentifierInfo *Id, 302 ScopedDecl *PrevDecl) { 303 void *Mem = C.getAllocator().Allocate<RecordDecl>(); 304 return new (Mem) RecordDecl(DK, DC, L, Id, PrevDecl); 305} 306 307void EnumDecl::Destroy(ASTContext& C) { 308 if (ElementList) ElementList->Destroy(C); 309 Decl::Destroy(C); 310} 311 312 313FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C, 314 SourceLocation L, 315 StringLiteral *Str) { 316 void *Mem = C.getAllocator().Allocate<FileScopeAsmDecl>(); 317 return new (Mem) FileScopeAsmDecl(L, Str); 318} 319 320LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C, 321 SourceLocation L, 322 LanguageIDs Lang, Decl *D) { 323 void *Mem = C.getAllocator().Allocate<LinkageSpecDecl>(); 324 return new (Mem) LinkageSpecDecl(L, Lang, D); 325} 326 327//===----------------------------------------------------------------------===// 328// Decl Implementation 329//===----------------------------------------------------------------------===// 330 331// Out-of-line virtual method providing a home for Decl. 332Decl::~Decl() { 333 if (!HasAttrs) 334 return; 335 336 DeclAttrMapTy::iterator it = DeclAttrs->find(this); 337 assert(it != DeclAttrs->end() && "No attrs found but HasAttrs is true!"); 338 339 // release attributes. 340 delete it->second; 341 invalidateAttrs(); 342} 343 344void Decl::addAttr(Attr *NewAttr) { 345 if (!DeclAttrs) 346 DeclAttrs = new DeclAttrMapTy(); 347 348 Attr *&ExistingAttr = (*DeclAttrs)[this]; 349 350 NewAttr->setNext(ExistingAttr); 351 ExistingAttr = NewAttr; 352 353 HasAttrs = true; 354} 355 356void Decl::invalidateAttrs() { 357 if (!HasAttrs) return; 358 359 HasAttrs = false; 360 (*DeclAttrs)[this] = 0; 361 DeclAttrs->erase(this); 362 363 if (DeclAttrs->empty()) { 364 delete DeclAttrs; 365 DeclAttrs = 0; 366 } 367} 368 369const Attr *Decl::getAttrs() const { 370 if (!HasAttrs) 371 return 0; 372 373 return (*DeclAttrs)[this]; 374} 375 376void Decl::swapAttrs(Decl *RHS) { 377 bool HasLHSAttr = this->HasAttrs; 378 bool HasRHSAttr = RHS->HasAttrs; 379 380 // Usually, neither decl has attrs, nothing to do. 381 if (!HasLHSAttr && !HasRHSAttr) return; 382 383 // If 'this' has no attrs, swap the other way. 384 if (!HasLHSAttr) 385 return RHS->swapAttrs(this); 386 387 // Handle the case when both decls have attrs. 388 if (HasRHSAttr) { 389 std::swap((*DeclAttrs)[this], (*DeclAttrs)[RHS]); 390 return; 391 } 392 393 // Otherwise, LHS has an attr and RHS doesn't. 394 (*DeclAttrs)[RHS] = (*DeclAttrs)[this]; 395 (*DeclAttrs).erase(this); 396 this->HasAttrs = false; 397 RHS->HasAttrs = true; 398} 399 400 401void Decl::Destroy(ASTContext& C) { 402 403 if (ScopedDecl* SD = dyn_cast<ScopedDecl>(this)) { 404 405 // Observe the unrolled recursion. By setting N->NextDeclarator = 0x0 406 // within the loop, only the Destroy method for the first ScopedDecl 407 // will deallocate all of the ScopedDecls in a chain. 408 409 ScopedDecl* N = SD->getNextDeclarator(); 410 411 while (N) { 412 ScopedDecl* Tmp = N->getNextDeclarator(); 413 N->NextDeclarator = 0x0; 414 N->Destroy(C); 415 N = Tmp; 416 } 417 } 418 419 this->~Decl(); 420 C.getAllocator().Deallocate((void *)this); 421} 422 423//===----------------------------------------------------------------------===// 424// DeclContext Implementation 425//===----------------------------------------------------------------------===// 426 427DeclContext *DeclContext::getParent() const { 428 if (ScopedDecl *SD = dyn_cast<ScopedDecl>(this)) 429 return SD->getDeclContext(); 430 else 431 return NULL; 432} 433 434Decl *DeclContext::ToDecl (const DeclContext *D) { 435 return CastTo<Decl>(D); 436} 437 438DeclContext *DeclContext::FromDecl (const Decl *D) { 439 return CastTo<DeclContext>(D); 440} 441 442//===----------------------------------------------------------------------===// 443// NamedDecl Implementation 444//===----------------------------------------------------------------------===// 445 446const char *NamedDecl::getName() const { 447 if (const IdentifierInfo *II = getIdentifier()) 448 return II->getName(); 449 return ""; 450} 451 452//===----------------------------------------------------------------------===// 453// FunctionDecl Implementation 454//===----------------------------------------------------------------------===// 455 456FunctionDecl::~FunctionDecl() { 457 delete[] ParamInfo; 458} 459 460void FunctionDecl::Destroy(ASTContext& C) { 461 if (Body) 462 Body->Destroy(C); 463 464 for (param_iterator I=param_begin(), E=param_end(); I!=E; ++I) 465 (*I)->Destroy(C); 466 467 Decl::Destroy(C); 468} 469 470 471Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const { 472 for (const FunctionDecl *FD = this; FD != 0; FD = FD->PreviousDeclaration) { 473 if (FD->Body) { 474 Definition = FD; 475 return FD->Body; 476 } 477 } 478 479 return 0; 480} 481 482unsigned FunctionDecl::getNumParams() const { 483 const FunctionType *FT = getType()->getAsFunctionType(); 484 if (isa<FunctionTypeNoProto>(FT)) 485 return 0; 486 return cast<FunctionTypeProto>(FT)->getNumArgs(); 487} 488 489void FunctionDecl::setParams(ParmVarDecl **NewParamInfo, unsigned NumParams) { 490 assert(ParamInfo == 0 && "Already has param info!"); 491 assert(NumParams == getNumParams() && "Parameter count mismatch!"); 492 493 // Zero params -> null pointer. 494 if (NumParams) { 495 ParamInfo = new ParmVarDecl*[NumParams]; 496 memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*NumParams); 497 } 498} 499 500/// getMinRequiredArguments - Returns the minimum number of arguments 501/// needed to call this function. This may be fewer than the number of 502/// function parameters, if some of the parameters have default 503/// arguments (in C++). 504unsigned FunctionDecl::getMinRequiredArguments() const { 505 unsigned NumRequiredArgs = getNumParams(); 506 while (NumRequiredArgs > 0 507 && getParamDecl(NumRequiredArgs-1)->getDefaultArg()) 508 --NumRequiredArgs; 509 510 return NumRequiredArgs; 511} 512 513//===----------------------------------------------------------------------===// 514// RecordDecl Implementation 515//===----------------------------------------------------------------------===// 516 517/// defineBody - When created, RecordDecl's correspond to a forward declared 518/// record. This method is used to mark the decl as being defined, with the 519/// specified contents. 520void RecordDecl::defineBody(FieldDecl **members, unsigned numMembers) { 521 assert(!isDefinition() && "Cannot redefine record!"); 522 setDefinition(true); 523 NumMembers = numMembers; 524 if (numMembers) { 525 Members = new FieldDecl*[numMembers]; 526 memcpy(Members, members, numMembers*sizeof(Decl*)); 527 } 528} 529 530FieldDecl *RecordDecl::getMember(IdentifierInfo *II) { 531 if (Members == 0 || NumMembers < 0) 532 return 0; 533 534 // Linear search. When C++ classes come along, will likely need to revisit. 535 for (int i = 0; i != NumMembers; ++i) 536 if (Members[i]->getIdentifier() == II) 537 return Members[i]; 538 return 0; 539} 540