Decl.cpp revision c38f4355490401da74c72ead46be6380d5a7643d
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->~Decl(); 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 // FIXME: Properly release attributes. 340 // delete it->second; 341 DeclAttrs->erase(it); 342 343 if (DeclAttrs->empty()) { 344 delete DeclAttrs; 345 DeclAttrs = 0; 346 } 347} 348 349void Decl::addAttr(Attr *NewAttr) { 350 if (!DeclAttrs) 351 DeclAttrs = new DeclAttrMapTy(); 352 353 Attr *&ExistingAttr = (*DeclAttrs)[this]; 354 355 NewAttr->setNext(ExistingAttr); 356 ExistingAttr = NewAttr; 357 358 HasAttrs = true; 359} 360 361const Attr *Decl::getAttrs() const { 362 if (!HasAttrs) 363 return 0; 364 365 return (*DeclAttrs)[this]; 366} 367 368void Decl::swapAttrs(Decl *RHS) { 369 bool HasLHSAttr = this->HasAttrs; 370 bool HasRHSAttr = RHS->HasAttrs; 371 372 // Usually, neither decl has attrs, nothing to do. 373 if (!HasLHSAttr && !HasRHSAttr) return; 374 375 // If 'this' has no attrs, swap the other way. 376 if (!HasLHSAttr) 377 return RHS->swapAttrs(this); 378 379 // Handle the case when both decls have attrs. 380 if (HasRHSAttr) { 381 std::swap((*DeclAttrs)[this], (*DeclAttrs)[RHS]); 382 return; 383 } 384 385 // Otherwise, LHS has an attr and RHS doesn't. 386 (*DeclAttrs)[RHS] = (*DeclAttrs)[this]; 387 (*DeclAttrs).erase(this); 388 this->HasAttrs = false; 389 RHS->HasAttrs = true; 390} 391 392 393void Decl::Destroy(ASTContext& C) { 394 395 if (ScopedDecl* SD = dyn_cast<ScopedDecl>(this)) { 396 397 // Observe the unrolled recursion. By setting N->NextDeclarator = 0x0 398 // within the loop, only the Destroy method for the first ScopedDecl 399 // will deallocate all of the ScopedDecls in a chain. 400 401 ScopedDecl* N = SD->getNextDeclarator(); 402 403 while (N) { 404 ScopedDecl* Tmp = N->getNextDeclarator(); 405 N->NextDeclarator = 0x0; 406 N->Destroy(C); 407 N = Tmp; 408 } 409 } 410 411 this->~Decl(); 412 C.getAllocator().Deallocate((void *)this); 413} 414 415//===----------------------------------------------------------------------===// 416// DeclContext Implementation 417//===----------------------------------------------------------------------===// 418 419DeclContext *DeclContext::getParent() const { 420 if (ScopedDecl *SD = dyn_cast<ScopedDecl>(this)) 421 return SD->getDeclContext(); 422 else 423 return NULL; 424} 425 426Decl *DeclContext::ToDecl (const DeclContext *D) { 427 return CastTo<Decl>(D); 428} 429 430DeclContext *DeclContext::FromDecl (const Decl *D) { 431 return CastTo<DeclContext>(D); 432} 433 434//===----------------------------------------------------------------------===// 435// NamedDecl Implementation 436//===----------------------------------------------------------------------===// 437 438const char *NamedDecl::getName() const { 439 if (const IdentifierInfo *II = getIdentifier()) 440 return II->getName(); 441 return ""; 442} 443 444//===----------------------------------------------------------------------===// 445// FunctionDecl Implementation 446//===----------------------------------------------------------------------===// 447 448FunctionDecl::~FunctionDecl() { 449 delete[] ParamInfo; 450} 451 452void FunctionDecl::Destroy(ASTContext& C) { 453 if (Body) 454 Body->Destroy(C); 455 456 for (param_iterator I=param_begin(), E=param_end(); I!=E; ++I) 457 (*I)->Destroy(C); 458 459 Decl::Destroy(C); 460} 461 462 463Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const { 464 for (const FunctionDecl *FD = this; FD != 0; FD = FD->PreviousDeclaration) { 465 if (FD->Body) { 466 Definition = FD; 467 return FD->Body; 468 } 469 } 470 471 return 0; 472} 473 474unsigned FunctionDecl::getNumParams() const { 475 const FunctionType *FT = getType()->getAsFunctionType(); 476 if (isa<FunctionTypeNoProto>(FT)) 477 return 0; 478 return cast<FunctionTypeProto>(FT)->getNumArgs(); 479} 480 481void FunctionDecl::setParams(ParmVarDecl **NewParamInfo, unsigned NumParams) { 482 assert(ParamInfo == 0 && "Already has param info!"); 483 assert(NumParams == getNumParams() && "Parameter count mismatch!"); 484 485 // Zero params -> null pointer. 486 if (NumParams) { 487 ParamInfo = new ParmVarDecl*[NumParams]; 488 memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*NumParams); 489 } 490} 491 492/// getMinRequiredArguments - Returns the minimum number of arguments 493/// needed to call this function. This may be fewer than the number of 494/// function parameters, if some of the parameters have default 495/// arguments (in C++). 496unsigned FunctionDecl::getMinRequiredArguments() const { 497 unsigned NumRequiredArgs = getNumParams(); 498 while (NumRequiredArgs > 0 499 && getParamDecl(NumRequiredArgs-1)->getDefaultArg()) 500 --NumRequiredArgs; 501 502 return NumRequiredArgs; 503} 504 505/// AddRedeclaration - Specifies that this function declaration has been 506/// redeclared by the function declaration FD. FD must be a 507/// redeclaration of this based on the semantics of the language being 508/// translated ("compatible" function types in C, same signatures in 509/// C++). 510void FunctionDecl::AddRedeclaration(FunctionDecl *FD) { 511 assert(FD->PreviousDeclaration == 0 && 512 "Redeclaration already has a previous declaration!"); 513 514 // Insert FD into the list of previous declarations of this 515 // function. 516 FD->PreviousDeclaration = this->PreviousDeclaration; 517 this->PreviousDeclaration = FD; 518 519 // Swap the contents of this function declaration and FD. This 520 // effectively transforms the original declaration into the most 521 // recent declaration, so that all references to this declaration 522 // remain valid (and have information from *all* declarations), 523 // while retaining all of the information about previous 524 // declarations as well. 525 526 // Swap parameters, so that the most recent parameter names and 527 // exact types (e.g., enum vs int) show up in the original 528 // declaration. 529 std::swap(this->ParamInfo, FD->ParamInfo); 530 531 // Swap the function body: all declarations share the same function 532 // body, but we keep track of who actually defined that function 533 // body by keeping the pointer to the body stored in that node. 534 std::swap(this->Body, FD->Body); 535 536 // Swap type information: this is important because in C, later 537 // declarations can provide slightly different types (enum vs. int, 538 // for example). 539 QualType thisType = this->getType(); 540 this->setType(FD->getType()); 541 FD->setType(thisType); 542 543 // Swap location information: this allows us to produce diagnostics 544 // later on that reference the most recent declaration (which has 545 // the most information!) while retaining the location of previous 546 // declarations (good for "redefinition" diagnostics). 547 SourceLocation thisLocation = this->getLocation(); 548 this->setLocation(FD->getLocation()); 549 FD->setLocation(thisLocation); 550 551 // Swap attributes. FD will have the union of the attributes from 552 // all previous declarations. 553 this->swapAttrs(FD); 554 555 // If any declaration is inline, the function is inline. 556 this->IsInline |= FD->IsInline; 557 558 // FIXME: Is this the right way to handle storage specifiers? 559 if (FD->SClass) this->SClass = FD->SClass; 560} 561 562//===----------------------------------------------------------------------===// 563// RecordDecl Implementation 564//===----------------------------------------------------------------------===// 565 566/// defineBody - When created, RecordDecl's correspond to a forward declared 567/// record. This method is used to mark the decl as being defined, with the 568/// specified contents. 569void RecordDecl::defineBody(FieldDecl **members, unsigned numMembers) { 570 assert(!isDefinition() && "Cannot redefine record!"); 571 setDefinition(true); 572 NumMembers = numMembers; 573 if (numMembers) { 574 Members = new FieldDecl*[numMembers]; 575 memcpy(Members, members, numMembers*sizeof(Decl*)); 576 } 577} 578 579FieldDecl *RecordDecl::getMember(IdentifierInfo *II) { 580 if (Members == 0 || NumMembers < 0) 581 return 0; 582 583 // Linear search. When C++ classes come along, will likely need to revisit. 584 for (int i = 0; i != NumMembers; ++i) 585 if (Members[i]->getIdentifier() == II) 586 return Members[i]; 587 return 0; 588} 589