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 subclasses. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "clang/AST/Decl.h" 15 #include "clang/AST/DeclCXX.h" 16 #include "clang/AST/DeclObjC.h" 17 #include "clang/AST/DeclTemplate.h" 18 #include "clang/AST/ASTContext.h" 19 #include "clang/AST/Stmt.h" 20 #include "clang/AST/Expr.h" 21 #include "clang/AST/PrettyPrinter.h" 22 #include "clang/Basic/Builtins.h" 23 #include "clang/Basic/IdentifierTable.h" 24 #include <vector> 25 26 using namespace clang; 27 28 void Attr::Destroy(ASTContext &C) { 29 if (Next) { 30 Next->Destroy(C); 31 Next = 0; 32 } 33 this->~Attr(); 34 C.Deallocate((void*)this); 35 } 36 37 38 //===----------------------------------------------------------------------===// 39 // Decl Allocation/Deallocation Method Implementations 40 //===----------------------------------------------------------------------===// 41 42 43 TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) { 44 return new (C) TranslationUnitDecl(C); 45 } 46 47 NamespaceDecl *NamespaceDecl::Create(ASTContext &C, DeclContext *DC, 48 SourceLocation L, IdentifierInfo *Id) { 49 return new (C) NamespaceDecl(DC, L, Id); 50 } 51 52 void NamespaceDecl::Destroy(ASTContext& C) { 53 // NamespaceDecl uses "NextDeclarator" to chain namespace declarations 54 // together. They are all top-level Decls. 55 56 this->~NamespaceDecl(); 57 C.Deallocate((void *)this); 58 } 59 60 61 ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, DeclContext *DC, 62 SourceLocation L, IdentifierInfo *Id, QualType T) { 63 return new (C) ImplicitParamDecl(ImplicitParam, DC, L, Id, T); 64 } 65 66 const char *VarDecl::getStorageClassSpecifierString(StorageClass SC) { 67 switch (SC) { 68 case VarDecl::None: break; 69 case VarDecl::Auto: return "auto"; break; 70 case VarDecl::Extern: return "extern"; break; 71 case VarDecl::PrivateExtern: return "__private_extern__"; break; 72 case VarDecl::Register: return "register"; break; 73 case VarDecl::Static: return "static"; break; 74 } 75 76 assert(0 && "Invalid storage class"); 77 return 0; 78 } 79 80 ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC, 81 SourceLocation L, IdentifierInfo *Id, 82 QualType T, StorageClass S, 83 Expr *DefArg) { 84 return new (C) ParmVarDecl(ParmVar, DC, L, Id, T, S, DefArg); 85 } 86 87 QualType ParmVarDecl::getOriginalType() const { 88 if (const OriginalParmVarDecl *PVD = 89 dyn_cast<OriginalParmVarDecl>(this)) 90 return PVD->OriginalType; 91 return getType(); 92 } 93 94 void VarDecl::setInit(ASTContext &C, Expr *I) { 95 if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>()) { 96 Eval->~EvaluatedStmt(); 97 C.Deallocate(Eval); 98 } 99 100 Init = I; 101 } 102 103 bool VarDecl::isExternC(ASTContext &Context) const { 104 if (!Context.getLangOptions().CPlusPlus) 105 return (getDeclContext()->isTranslationUnit() && 106 getStorageClass() != Static) || 107 (getDeclContext()->isFunctionOrMethod() && hasExternalStorage()); 108 109 for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit(); 110 DC = DC->getParent()) { 111 if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) { 112 if (Linkage->getLanguage() == LinkageSpecDecl::lang_c) 113 return getStorageClass() != Static; 114 115 break; 116 } 117 118 if (DC->isFunctionOrMethod()) 119 return false; 120 } 121 122 return false; 123 } 124 125 OriginalParmVarDecl *OriginalParmVarDecl::Create( 126 ASTContext &C, DeclContext *DC, 127 SourceLocation L, IdentifierInfo *Id, 128 QualType T, QualType OT, StorageClass S, 129 Expr *DefArg) { 130 return new (C) OriginalParmVarDecl(DC, L, Id, T, OT, S, DefArg); 131 } 132 133 FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC, 134 SourceLocation L, 135 DeclarationName N, QualType T, 136 StorageClass S, bool isInline, 137 bool hasWrittenPrototype, 138 SourceLocation TypeSpecStartLoc) { 139 FunctionDecl *New 140 = new (C) FunctionDecl(Function, DC, L, N, T, S, isInline, 141 TypeSpecStartLoc); 142 New->HasWrittenPrototype = hasWrittenPrototype; 143 return New; 144 } 145 146 BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) { 147 return new (C) BlockDecl(DC, L); 148 } 149 150 FieldDecl *FieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, 151 IdentifierInfo *Id, QualType T, Expr *BW, 152 bool Mutable, SourceLocation TSSL) { 153 return new (C) FieldDecl(Decl::Field, DC, L, Id, T, BW, Mutable, TSSL); 154 } 155 156 bool FieldDecl::isAnonymousStructOrUnion() const { 157 if (!isImplicit() || getDeclName()) 158 return false; 159 160 if (const RecordType *Record = getType()->getAs<RecordType>()) 161 return Record->getDecl()->isAnonymousStructOrUnion(); 162 163 return false; 164 } 165 166 EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD, 167 SourceLocation L, 168 IdentifierInfo *Id, QualType T, 169 Expr *E, const llvm::APSInt &V) { 170 return new (C) EnumConstantDecl(CD, L, Id, T, E, V); 171 } 172 173 void EnumConstantDecl::Destroy(ASTContext& C) { 174 if (Init) Init->Destroy(C); 175 Decl::Destroy(C); 176 } 177 178 TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC, 179 SourceLocation L, 180 IdentifierInfo *Id, QualType T) { 181 return new (C) TypedefDecl(DC, L, Id, T); 182 } 183 184 EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, 185 IdentifierInfo *Id, SourceLocation TKL, 186 EnumDecl *PrevDecl) { 187 EnumDecl *Enum = new (C) EnumDecl(DC, L, Id, PrevDecl, TKL); 188 C.getTypeDeclType(Enum, PrevDecl); 189 return Enum; 190 } 191 192 void EnumDecl::Destroy(ASTContext& C) { 193 Decl::Destroy(C); 194 } 195 196 void EnumDecl::completeDefinition(ASTContext &C, QualType NewType) { 197 assert(!isDefinition() && "Cannot redefine enums!"); 198 IntegerType = NewType; 199 TagDecl::completeDefinition(); 200 } 201 202 FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C, DeclContext *DC, 203 SourceLocation L, 204 StringLiteral *Str) { 205 return new (C) FileScopeAsmDecl(DC, L, Str); 206 } 207 208 //===----------------------------------------------------------------------===// 209 // NamedDecl Implementation 210 //===----------------------------------------------------------------------===// 211 212 std::string NamedDecl::getQualifiedNameAsString() const { 213 std::vector<std::string> Names; 214 std::string QualName; 215 const DeclContext *Ctx = getDeclContext(); 216 217 if (Ctx->isFunctionOrMethod()) 218 return getNameAsString(); 219 220 while (Ctx) { 221 if (Ctx->isFunctionOrMethod()) 222 // FIXME: That probably will happen, when D was member of local 223 // scope class/struct/union. How do we handle this case? 224 break; 225 226 if (const ClassTemplateSpecializationDecl *Spec 227 = dyn_cast<ClassTemplateSpecializationDecl>(Ctx)) { 228 const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); 229 PrintingPolicy Policy(getASTContext().getLangOptions()); 230 std::string TemplateArgsStr 231 = TemplateSpecializationType::PrintTemplateArgumentList( 232 TemplateArgs.getFlatArgumentList(), 233 TemplateArgs.flat_size(), 234 Policy); 235 Names.push_back(Spec->getIdentifier()->getName() + TemplateArgsStr); 236 } else if (const NamedDecl *ND = dyn_cast<NamedDecl>(Ctx)) 237 Names.push_back(ND->getNameAsString()); 238 else 239 break; 240 241 Ctx = Ctx->getParent(); 242 } 243 244 std::vector<std::string>::reverse_iterator 245 I = Names.rbegin(), 246 End = Names.rend(); 247 248 for (; I!=End; ++I) 249 QualName += *I + "::"; 250 251 QualName += getNameAsString(); 252 253 return QualName; 254 } 255 256 257 bool NamedDecl::declarationReplaces(NamedDecl *OldD) const { 258 assert(getDeclName() == OldD->getDeclName() && "Declaration name mismatch"); 259 260 // UsingDirectiveDecl's are not really NamedDecl's, and all have same name. 261 // We want to keep it, unless it nominates same namespace. 262 if (getKind() == Decl::UsingDirective) { 263 return cast<UsingDirectiveDecl>(this)->getNominatedNamespace() == 264 cast<UsingDirectiveDecl>(OldD)->getNominatedNamespace(); 265 } 266 267 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(this)) 268 // For function declarations, we keep track of redeclarations. 269 return FD->getPreviousDeclaration() == OldD; 270 271 // For function templates, the underlying function declarations are linked. 272 if (const FunctionTemplateDecl *FunctionTemplate 273 = dyn_cast<FunctionTemplateDecl>(this)) 274 if (const FunctionTemplateDecl *OldFunctionTemplate 275 = dyn_cast<FunctionTemplateDecl>(OldD)) 276 return FunctionTemplate->getTemplatedDecl() 277 ->declarationReplaces(OldFunctionTemplate->getTemplatedDecl()); 278 279 // For method declarations, we keep track of redeclarations. 280 if (isa<ObjCMethodDecl>(this)) 281 return false; 282 283 // For non-function declarations, if the declarations are of the 284 // same kind then this must be a redeclaration, or semantic analysis 285 // would not have given us the new declaration. 286 return this->getKind() == OldD->getKind(); 287 } 288 289 bool NamedDecl::hasLinkage() const { 290 if (const VarDecl *VD = dyn_cast<VarDecl>(this)) 291 return VD->hasExternalStorage() || VD->isFileVarDecl(); 292 293 if (isa<FunctionDecl>(this) && !isa<CXXMethodDecl>(this)) 294 return true; 295 296 return false; 297 } 298 299 NamedDecl *NamedDecl::getUnderlyingDecl() { 300 NamedDecl *ND = this; 301 while (true) { 302 if (UsingDecl *UD = dyn_cast<UsingDecl>(ND)) 303 ND = UD->getTargetDecl(); 304 else if (ObjCCompatibleAliasDecl *AD 305 = dyn_cast<ObjCCompatibleAliasDecl>(ND)) 306 return AD->getClassInterface(); 307 else 308 return ND; 309 } 310 } 311 312 //===----------------------------------------------------------------------===// 313 // VarDecl Implementation 314 //===----------------------------------------------------------------------===// 315 316 VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, 317 IdentifierInfo *Id, QualType T, StorageClass S, 318 SourceLocation TypeSpecStartLoc) { 319 return new (C) VarDecl(Var, DC, L, Id, T, S, TypeSpecStartLoc); 320 } 321 322 void VarDecl::Destroy(ASTContext& C) { 323 Expr *Init = getInit(); 324 if (Init) { 325 Init->Destroy(C); 326 if (EvaluatedStmt *Eval = this->Init.dyn_cast<EvaluatedStmt *>()) { 327 Eval->~EvaluatedStmt(); 328 C.Deallocate(Eval); 329 } 330 } 331 this->~VarDecl(); 332 C.Deallocate((void *)this); 333 } 334 335 VarDecl::~VarDecl() { 336 } 337 338 SourceRange VarDecl::getSourceRange() const { 339 if (getInit()) 340 return SourceRange(getLocation(), getInit()->getLocEnd()); 341 return SourceRange(getLocation(), getLocation()); 342 } 343 344 VarDecl *VarDecl::getInstantiatedFromStaticDataMember() { 345 return getASTContext().getInstantiatedFromStaticDataMember(this); 346 } 347 348 bool VarDecl::isTentativeDefinition(ASTContext &Context) const { 349 if (!isFileVarDecl() || Context.getLangOptions().CPlusPlus) 350 return false; 351 352 const VarDecl *Def = 0; 353 return (!getDefinition(Def) && 354 (getStorageClass() == None || getStorageClass() == Static)); 355 } 356 357 const Expr *VarDecl::getDefinition(const VarDecl *&Def) const { 358 redecl_iterator I = redecls_begin(), E = redecls_end(); 359 while (I != E && !I->getInit()) 360 ++I; 361 362 if (I != E) { 363 Def = *I; 364 return I->getInit(); 365 } 366 return 0; 367 } 368 369 VarDecl *VarDecl::getCanonicalDecl() { 370 return getFirstDeclaration(); 371 } 372 373 //===----------------------------------------------------------------------===// 374 // FunctionDecl Implementation 375 //===----------------------------------------------------------------------===// 376 377 void FunctionDecl::Destroy(ASTContext& C) { 378 if (Body && Body.isOffset()) 379 Body.get(C.getExternalSource())->Destroy(C); 380 381 for (param_iterator I=param_begin(), E=param_end(); I!=E; ++I) 382 (*I)->Destroy(C); 383 384 C.Deallocate(ParamInfo); 385 386 Decl::Destroy(C); 387 } 388 389 390 Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const { 391 for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) { 392 if (I->Body) { 393 Definition = *I; 394 return I->Body.get(getASTContext().getExternalSource()); 395 } 396 } 397 398 return 0; 399 } 400 401 Stmt *FunctionDecl::getBodyIfAvailable() const { 402 for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) { 403 if (I->Body && !I->Body.isOffset()) { 404 return I->Body.get(0); 405 } 406 } 407 408 return 0; 409 } 410 411 void FunctionDecl::setBody(Stmt *B) { 412 Body = B; 413 if (B) 414 EndRangeLoc = B->getLocEnd(); 415 } 416 417 bool FunctionDecl::isMain() const { 418 return getDeclContext()->getLookupContext()->isTranslationUnit() && 419 getIdentifier() && getIdentifier()->isStr("main"); 420 } 421 422 bool FunctionDecl::isExternC(ASTContext &Context) const { 423 // In C, any non-static, non-overloadable function has external 424 // linkage. 425 if (!Context.getLangOptions().CPlusPlus) 426 return getStorageClass() != Static && !getAttr<OverloadableAttr>(); 427 428 for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit(); 429 DC = DC->getParent()) { 430 if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) { 431 if (Linkage->getLanguage() == LinkageSpecDecl::lang_c) 432 return getStorageClass() != Static && 433 !getAttr<OverloadableAttr>(); 434 435 break; 436 } 437 } 438 439 return false; 440 } 441 442 bool FunctionDecl::isGlobal() const { 443 if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(this)) 444 return Method->isStatic(); 445 446 if (getStorageClass() == Static) 447 return false; 448 449 for (const DeclContext *DC = getDeclContext(); 450 DC->isNamespace(); 451 DC = DC->getParent()) { 452 if (const NamespaceDecl *Namespace = cast<NamespaceDecl>(DC)) { 453 if (!Namespace->getDeclName()) 454 return false; 455 break; 456 } 457 } 458 459 return true; 460 } 461 462 /// \brief Returns a value indicating whether this function 463 /// corresponds to a builtin function. 464 /// 465 /// The function corresponds to a built-in function if it is 466 /// declared at translation scope or within an extern "C" block and 467 /// its name matches with the name of a builtin. The returned value 468 /// will be 0 for functions that do not correspond to a builtin, a 469 /// value of type \c Builtin::ID if in the target-independent range 470 /// \c [1,Builtin::First), or a target-specific builtin value. 471 unsigned FunctionDecl::getBuiltinID(ASTContext &Context) const { 472 if (!getIdentifier() || !getIdentifier()->getBuiltinID()) 473 return 0; 474 475 unsigned BuiltinID = getIdentifier()->getBuiltinID(); 476 if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) 477 return BuiltinID; 478 479 // This function has the name of a known C library 480 // function. Determine whether it actually refers to the C library 481 // function or whether it just has the same name. 482 483 // If this is a static function, it's not a builtin. 484 if (getStorageClass() == Static) 485 return 0; 486 487 // If this function is at translation-unit scope and we're not in 488 // C++, it refers to the C library function. 489 if (!Context.getLangOptions().CPlusPlus && 490 getDeclContext()->isTranslationUnit()) 491 return BuiltinID; 492 493 // If the function is in an extern "C" linkage specification and is 494 // not marked "overloadable", it's the real function. 495 if (isa<LinkageSpecDecl>(getDeclContext()) && 496 cast<LinkageSpecDecl>(getDeclContext())->getLanguage() 497 == LinkageSpecDecl::lang_c && 498 !getAttr<OverloadableAttr>()) 499 return BuiltinID; 500 501 // Not a builtin 502 return 0; 503 } 504 505 506 /// getNumParams - Return the number of parameters this function must have 507 /// based on its FunctionType. This is the length of the PararmInfo array 508 /// after it has been created. 509 unsigned FunctionDecl::getNumParams() const { 510 const FunctionType *FT = getType()->getAsFunctionType(); 511 if (isa<FunctionNoProtoType>(FT)) 512 return 0; 513 return cast<FunctionProtoType>(FT)->getNumArgs(); 514 515 } 516 517 void FunctionDecl::setParams(ASTContext& C, ParmVarDecl **NewParamInfo, 518 unsigned NumParams) { 519 assert(ParamInfo == 0 && "Already has param info!"); 520 assert(NumParams == getNumParams() && "Parameter count mismatch!"); 521 522 // Zero params -> null pointer. 523 if (NumParams) { 524 void *Mem = C.Allocate(sizeof(ParmVarDecl*)*NumParams); 525 ParamInfo = new (Mem) ParmVarDecl*[NumParams]; 526 memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*NumParams); 527 528 // Update source range. The check below allows us to set EndRangeLoc before 529 // setting the parameters. 530 if (EndRangeLoc.isInvalid() || EndRangeLoc == getLocation()) 531 EndRangeLoc = NewParamInfo[NumParams-1]->getLocEnd(); 532 } 533 } 534 535 /// getMinRequiredArguments - Returns the minimum number of arguments 536 /// needed to call this function. This may be fewer than the number of 537 /// function parameters, if some of the parameters have default 538 /// arguments (in C++). 539 unsigned FunctionDecl::getMinRequiredArguments() const { 540 unsigned NumRequiredArgs = getNumParams(); 541 while (NumRequiredArgs > 0 542 && getParamDecl(NumRequiredArgs-1)->hasDefaultArg()) 543 --NumRequiredArgs; 544 545 return NumRequiredArgs; 546 } 547 548 bool FunctionDecl::hasActiveGNUInlineAttribute(ASTContext &Context) const { 549 if (!isInline() || !hasAttr<GNUInlineAttr>()) 550 return false; 551 552 for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) 553 if (I->isInline() && !I->hasAttr<GNUInlineAttr>()) 554 return false; 555 556 return true; 557 } 558 559 bool FunctionDecl::isExternGNUInline(ASTContext &Context) const { 560 if (!hasActiveGNUInlineAttribute(Context)) 561 return false; 562 563 for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) 564 if (I->getStorageClass() == Extern && I->hasAttr<GNUInlineAttr>()) 565 return true; 566 567 return false; 568 } 569 570 void 571 FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) { 572 redeclarable_base::setPreviousDeclaration(PrevDecl); 573 574 if (FunctionTemplateDecl *FunTmpl = getDescribedFunctionTemplate()) { 575 FunctionTemplateDecl *PrevFunTmpl 576 = PrevDecl? PrevDecl->getDescribedFunctionTemplate() : 0; 577 assert((!PrevDecl || PrevFunTmpl) && "Function/function template mismatch"); 578 FunTmpl->setPreviousDeclaration(PrevFunTmpl); 579 } 580 } 581 582 FunctionDecl *FunctionDecl::getCanonicalDecl() { 583 return getFirstDeclaration(); 584 } 585 586 /// getOverloadedOperator - Which C++ overloaded operator this 587 /// function represents, if any. 588 OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const { 589 if (getDeclName().getNameKind() == DeclarationName::CXXOperatorName) 590 return getDeclName().getCXXOverloadedOperator(); 591 else 592 return OO_None; 593 } 594 595 FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const { 596 if (FunctionTemplateSpecializationInfo *Info 597 = TemplateOrSpecialization 598 .dyn_cast<FunctionTemplateSpecializationInfo*>()) { 599 return Info->Template.getPointer(); 600 } 601 return 0; 602 } 603 604 const TemplateArgumentList * 605 FunctionDecl::getTemplateSpecializationArgs() const { 606 if (FunctionTemplateSpecializationInfo *Info 607 = TemplateOrSpecialization 608 .dyn_cast<FunctionTemplateSpecializationInfo*>()) { 609 return Info->TemplateArguments; 610 } 611 return 0; 612 } 613 614 void 615 FunctionDecl::setFunctionTemplateSpecialization(ASTContext &Context, 616 FunctionTemplateDecl *Template, 617 const TemplateArgumentList *TemplateArgs, 618 void *InsertPos) { 619 FunctionTemplateSpecializationInfo *Info 620 = TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>(); 621 if (!Info) 622 Info = new (Context) FunctionTemplateSpecializationInfo; 623 624 Info->Function = this; 625 Info->Template.setPointer(Template); 626 Info->Template.setInt(0); // Implicit instantiation, unless told otherwise 627 Info->TemplateArguments = TemplateArgs; 628 TemplateOrSpecialization = Info; 629 630 // Insert this function template specialization into the set of known 631 // function template specialiations. 632 Template->getSpecializations().InsertNode(Info, InsertPos); 633 } 634 635 bool FunctionDecl::isExplicitSpecialization() const { 636 // FIXME: check this property for explicit specializations of member 637 // functions of class templates. 638 FunctionTemplateSpecializationInfo *Info 639 = TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>(); 640 if (!Info) 641 return false; 642 643 return Info->isExplicitSpecialization(); 644 } 645 646 void FunctionDecl::setExplicitSpecialization(bool ES) { 647 // FIXME: set this property for explicit specializations of member functions 648 // of class templates. 649 FunctionTemplateSpecializationInfo *Info 650 = TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>(); 651 if (Info) 652 Info->setExplicitSpecialization(ES); 653 } 654 655 //===----------------------------------------------------------------------===// 656 // TagDecl Implementation 657 //===----------------------------------------------------------------------===// 658 659 SourceRange TagDecl::getSourceRange() const { 660 SourceLocation E = RBraceLoc.isValid() ? RBraceLoc : getLocation(); 661 return SourceRange(TagKeywordLoc, E); 662 } 663 664 TagDecl* TagDecl::getCanonicalDecl() { 665 return getFirstDeclaration(); 666 } 667 668 void TagDecl::startDefinition() { 669 if (TagType *TagT = const_cast<TagType *>(TypeForDecl->getAs<TagType>())) { 670 TagT->decl.setPointer(this); 671 TagT->decl.setInt(1); 672 } 673 } 674 675 void TagDecl::completeDefinition() { 676 IsDefinition = true; 677 if (TagType *TagT = const_cast<TagType *>(TypeForDecl->getAs<TagType>())) { 678 assert(TagT->decl.getPointer() == this && 679 "Attempt to redefine a tag definition?"); 680 TagT->decl.setInt(0); 681 } 682 } 683 684 TagDecl* TagDecl::getDefinition(ASTContext& C) const { 685 if (isDefinition()) 686 return const_cast<TagDecl *>(this); 687 688 for (redecl_iterator R = redecls_begin(), REnd = redecls_end(); 689 R != REnd; ++R) 690 if (R->isDefinition()) 691 return *R; 692 693 return 0; 694 } 695 696 //===----------------------------------------------------------------------===// 697 // RecordDecl Implementation 698 //===----------------------------------------------------------------------===// 699 700 RecordDecl::RecordDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L, 701 IdentifierInfo *Id, RecordDecl *PrevDecl, 702 SourceLocation TKL) 703 : TagDecl(DK, TK, DC, L, Id, PrevDecl, TKL) { 704 HasFlexibleArrayMember = false; 705 AnonymousStructOrUnion = false; 706 HasObjectMember = false; 707 assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!"); 708 } 709 710 RecordDecl *RecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC, 711 SourceLocation L, IdentifierInfo *Id, 712 SourceLocation TKL, RecordDecl* PrevDecl) { 713 714 RecordDecl* R = new (C) RecordDecl(Record, TK, DC, L, Id, PrevDecl, TKL); 715 C.getTypeDeclType(R, PrevDecl); 716 return R; 717 } 718 719 RecordDecl::~RecordDecl() { 720 } 721 722 void RecordDecl::Destroy(ASTContext& C) { 723 TagDecl::Destroy(C); 724 } 725 726 bool RecordDecl::isInjectedClassName() const { 727 return isImplicit() && getDeclName() && getDeclContext()->isRecord() && 728 cast<RecordDecl>(getDeclContext())->getDeclName() == getDeclName(); 729 } 730 731 /// completeDefinition - Notes that the definition of this type is now 732 /// complete. 733 void RecordDecl::completeDefinition(ASTContext& C) { 734 assert(!isDefinition() && "Cannot redefine record!"); 735 TagDecl::completeDefinition(); 736 } 737 738 //===----------------------------------------------------------------------===// 739 // BlockDecl Implementation 740 //===----------------------------------------------------------------------===// 741 742 BlockDecl::~BlockDecl() { 743 } 744 745 void BlockDecl::Destroy(ASTContext& C) { 746 if (Body) 747 Body->Destroy(C); 748 749 for (param_iterator I=param_begin(), E=param_end(); I!=E; ++I) 750 (*I)->Destroy(C); 751 752 C.Deallocate(ParamInfo); 753 Decl::Destroy(C); 754 } 755 756 void BlockDecl::setParams(ASTContext& C, ParmVarDecl **NewParamInfo, 757 unsigned NParms) { 758 assert(ParamInfo == 0 && "Already has param info!"); 759 760 // Zero params -> null pointer. 761 if (NParms) { 762 NumParams = NParms; 763 void *Mem = C.Allocate(sizeof(ParmVarDecl*)*NumParams); 764 ParamInfo = new (Mem) ParmVarDecl*[NumParams]; 765 memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*NumParams); 766 } 767 } 768 769 unsigned BlockDecl::getNumParams() const { 770 return NumParams; 771 } 772