Decl.cpp revision f00068bd7540639405130ff658025d863da41744
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 26using namespace clang; 27 28void 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 43TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) { 44 return new (C) TranslationUnitDecl(C); 45} 46 47NamespaceDecl *NamespaceDecl::Create(ASTContext &C, DeclContext *DC, 48 SourceLocation L, IdentifierInfo *Id) { 49 return new (C) NamespaceDecl(DC, L, Id); 50} 51 52void 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 61ImplicitParamDecl *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 66const 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 80ParmVarDecl *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 87QualType ParmVarDecl::getOriginalType() const { 88 if (const OriginalParmVarDecl *PVD = 89 dyn_cast<OriginalParmVarDecl>(this)) 90 return PVD->OriginalType; 91 return getType(); 92} 93 94void 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 103bool 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 125OriginalParmVarDecl *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 133FunctionDecl *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 146BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) { 147 return new (C) BlockDecl(DC, L); 148} 149 150FieldDecl *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 156bool FieldDecl::isAnonymousStructOrUnion() const { 157 if (!isImplicit() || getDeclName()) 158 return false; 159 160 if (const RecordType *Record = getType()->getAsRecordType()) 161 return Record->getDecl()->isAnonymousStructOrUnion(); 162 163 return false; 164} 165 166EnumConstantDecl *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 173void EnumConstantDecl::Destroy(ASTContext& C) { 174 if (Init) Init->Destroy(C); 175 Decl::Destroy(C); 176} 177 178TypedefDecl *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 184EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, 185 IdentifierInfo *Id, 186 EnumDecl *PrevDecl) { 187 EnumDecl *Enum = new (C) EnumDecl(DC, L, Id); 188 C.getTypeDeclType(Enum, PrevDecl); 189 return Enum; 190} 191 192void EnumDecl::Destroy(ASTContext& C) { 193 Decl::Destroy(C); 194} 195 196void EnumDecl::completeDefinition(ASTContext &C, QualType NewType) { 197 assert(!isDefinition() && "Cannot redefine enums!"); 198 IntegerType = NewType; 199 TagDecl::completeDefinition(); 200} 201 202FileScopeAsmDecl *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 212std::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 257bool 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 289bool 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 299NamedDecl *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 316VarDecl *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 322void 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 335VarDecl::~VarDecl() { 336} 337 338SourceRange VarDecl::getSourceRange() const { 339 if (getInit()) 340 return SourceRange(getLocation(), getInit()->getLocEnd()); 341 return SourceRange(getLocation(), getLocation()); 342} 343 344bool VarDecl::isTentativeDefinition(ASTContext &Context) const { 345 if (!isFileVarDecl() || Context.getLangOptions().CPlusPlus) 346 return false; 347 348 const VarDecl *Def = 0; 349 return (!getDefinition(Def) && 350 (getStorageClass() == None || getStorageClass() == Static)); 351} 352 353const Expr *VarDecl::getDefinition(const VarDecl *&Def) const { 354 redecl_iterator I = redecls_begin(), E = redecls_end(); 355 while (I != E && !I->getInit()) 356 ++I; 357 358 if (I != E) { 359 Def = *I; 360 return I->getInit(); 361 } 362 return 0; 363} 364 365void VarDecl::setPreviousDeclaration(VarDecl *PrevDecl) { 366 if (PrevDecl) { 367 // Point to previous. 368 PreviousDeclaration.setPointer(PrevDecl); 369 PreviousDeclaration.setInt(0); 370 371 // First one will point to this one as latest. 372 // getCanonicalDecl returns the first one. 373 VarDecl *First = PrevDecl->getCanonicalDecl(); 374 assert(First->PreviousDeclaration.getInt() == 1 && "Expected first"); 375 First->PreviousDeclaration.setPointer(this); 376 } else { 377 // This is first. 378 PreviousDeclaration.setPointer(this); 379 PreviousDeclaration.setInt(1); 380 } 381} 382 383VarDecl *VarDecl::getCanonicalDecl() { 384 VarDecl *Var = this; 385 while (Var->getPreviousDeclaration()) 386 Var = Var->getPreviousDeclaration(); 387 return Var; 388} 389 390//===----------------------------------------------------------------------===// 391// FunctionDecl Implementation 392//===----------------------------------------------------------------------===// 393 394void FunctionDecl::Destroy(ASTContext& C) { 395 if (Body && Body.isOffset()) 396 Body.get(C.getExternalSource())->Destroy(C); 397 398 for (param_iterator I=param_begin(), E=param_end(); I!=E; ++I) 399 (*I)->Destroy(C); 400 401 C.Deallocate(ParamInfo); 402 403 Decl::Destroy(C); 404} 405 406 407Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const { 408 for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) { 409 if (I->Body) { 410 Definition = *I; 411 return I->Body.get(getASTContext().getExternalSource()); 412 } 413 } 414 415 return 0; 416} 417 418Stmt *FunctionDecl::getBodyIfAvailable() const { 419 for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) { 420 if (I->Body && !I->Body.isOffset()) { 421 return I->Body.get(0); 422 } 423 } 424 425 return 0; 426} 427 428void FunctionDecl::setBody(Stmt *B) { 429 Body = B; 430 if (B) 431 EndRangeLoc = B->getLocEnd(); 432} 433 434bool FunctionDecl::isMain() const { 435 return getDeclContext()->getLookupContext()->isTranslationUnit() && 436 getIdentifier() && getIdentifier()->isStr("main"); 437} 438 439bool FunctionDecl::isExternC(ASTContext &Context) const { 440 // In C, any non-static, non-overloadable function has external 441 // linkage. 442 if (!Context.getLangOptions().CPlusPlus) 443 return getStorageClass() != Static && !getAttr<OverloadableAttr>(); 444 445 for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit(); 446 DC = DC->getParent()) { 447 if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) { 448 if (Linkage->getLanguage() == LinkageSpecDecl::lang_c) 449 return getStorageClass() != Static && 450 !getAttr<OverloadableAttr>(); 451 452 break; 453 } 454 } 455 456 return false; 457} 458 459bool FunctionDecl::isGlobal() const { 460 if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(this)) 461 return Method->isStatic(); 462 463 if (getStorageClass() == Static) 464 return false; 465 466 for (const DeclContext *DC = getDeclContext(); 467 DC->isNamespace(); 468 DC = DC->getParent()) { 469 if (const NamespaceDecl *Namespace = cast<NamespaceDecl>(DC)) { 470 if (!Namespace->getDeclName()) 471 return false; 472 break; 473 } 474 } 475 476 return true; 477} 478 479/// \brief Returns a value indicating whether this function 480/// corresponds to a builtin function. 481/// 482/// The function corresponds to a built-in function if it is 483/// declared at translation scope or within an extern "C" block and 484/// its name matches with the name of a builtin. The returned value 485/// will be 0 for functions that do not correspond to a builtin, a 486/// value of type \c Builtin::ID if in the target-independent range 487/// \c [1,Builtin::First), or a target-specific builtin value. 488unsigned FunctionDecl::getBuiltinID(ASTContext &Context) const { 489 if (!getIdentifier() || !getIdentifier()->getBuiltinID()) 490 return 0; 491 492 unsigned BuiltinID = getIdentifier()->getBuiltinID(); 493 if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) 494 return BuiltinID; 495 496 // This function has the name of a known C library 497 // function. Determine whether it actually refers to the C library 498 // function or whether it just has the same name. 499 500 // If this is a static function, it's not a builtin. 501 if (getStorageClass() == Static) 502 return 0; 503 504 // If this function is at translation-unit scope and we're not in 505 // C++, it refers to the C library function. 506 if (!Context.getLangOptions().CPlusPlus && 507 getDeclContext()->isTranslationUnit()) 508 return BuiltinID; 509 510 // If the function is in an extern "C" linkage specification and is 511 // not marked "overloadable", it's the real function. 512 if (isa<LinkageSpecDecl>(getDeclContext()) && 513 cast<LinkageSpecDecl>(getDeclContext())->getLanguage() 514 == LinkageSpecDecl::lang_c && 515 !getAttr<OverloadableAttr>()) 516 return BuiltinID; 517 518 // Not a builtin 519 return 0; 520} 521 522 523/// getNumParams - Return the number of parameters this function must have 524/// based on its FunctionType. This is the length of the PararmInfo array 525/// after it has been created. 526unsigned FunctionDecl::getNumParams() const { 527 const FunctionType *FT = getType()->getAsFunctionType(); 528 if (isa<FunctionNoProtoType>(FT)) 529 return 0; 530 return cast<FunctionProtoType>(FT)->getNumArgs(); 531 532} 533 534void FunctionDecl::setParams(ASTContext& C, ParmVarDecl **NewParamInfo, 535 unsigned NumParams) { 536 assert(ParamInfo == 0 && "Already has param info!"); 537 assert(NumParams == getNumParams() && "Parameter count mismatch!"); 538 539 // Zero params -> null pointer. 540 if (NumParams) { 541 void *Mem = C.Allocate(sizeof(ParmVarDecl*)*NumParams); 542 ParamInfo = new (Mem) ParmVarDecl*[NumParams]; 543 memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*NumParams); 544 545 // Update source range. The check below allows us to set EndRangeLoc before 546 // setting the parameters. 547 if (EndRangeLoc.isInvalid() || EndRangeLoc == getLocation()) 548 EndRangeLoc = NewParamInfo[NumParams-1]->getLocEnd(); 549 } 550} 551 552/// getMinRequiredArguments - Returns the minimum number of arguments 553/// needed to call this function. This may be fewer than the number of 554/// function parameters, if some of the parameters have default 555/// arguments (in C++). 556unsigned FunctionDecl::getMinRequiredArguments() const { 557 unsigned NumRequiredArgs = getNumParams(); 558 while (NumRequiredArgs > 0 559 && getParamDecl(NumRequiredArgs-1)->hasDefaultArg()) 560 --NumRequiredArgs; 561 562 return NumRequiredArgs; 563} 564 565bool FunctionDecl::hasActiveGNUInlineAttribute(ASTContext &Context) const { 566 if (!isInline() || !hasAttr<GNUInlineAttr>()) 567 return false; 568 569 for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) 570 if (I->isInline() && !I->hasAttr<GNUInlineAttr>()) 571 return false; 572 573 return true; 574} 575 576bool FunctionDecl::isExternGNUInline(ASTContext &Context) const { 577 if (!hasActiveGNUInlineAttribute(Context)) 578 return false; 579 580 for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) 581 if (I->getStorageClass() == Extern && I->hasAttr<GNUInlineAttr>()) 582 return true; 583 584 return false; 585} 586 587void 588FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) { 589 if (PrevDecl) { 590 // Point to previous. 591 PreviousDeclaration.setPointer(PrevDecl); 592 PreviousDeclaration.setInt(0); 593 594 // First one will point to this one as latest. 595 // getCanonicalDecl returns the first one. 596 FunctionDecl *First = PrevDecl->getCanonicalDecl(); 597 assert(First->PreviousDeclaration.getInt() == 1 && "Expected first"); 598 First->PreviousDeclaration.setPointer(this); 599 } else { 600 // This is first. 601 PreviousDeclaration.setPointer(this); 602 PreviousDeclaration.setInt(1); 603 } 604 605 if (FunctionTemplateDecl *FunTmpl = getDescribedFunctionTemplate()) { 606 FunctionTemplateDecl *PrevFunTmpl 607 = PrevDecl? PrevDecl->getDescribedFunctionTemplate() : 0; 608 assert((!PrevDecl || PrevFunTmpl) && "Function/function template mismatch"); 609 FunTmpl->setPreviousDeclaration(PrevFunTmpl); 610 } 611} 612 613FunctionDecl *FunctionDecl::getCanonicalDecl() { 614 FunctionDecl *FD = this; 615 while (FD->getPreviousDeclaration()) 616 FD = FD->getPreviousDeclaration(); 617 return FD; 618} 619 620/// getOverloadedOperator - Which C++ overloaded operator this 621/// function represents, if any. 622OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const { 623 if (getDeclName().getNameKind() == DeclarationName::CXXOperatorName) 624 return getDeclName().getCXXOverloadedOperator(); 625 else 626 return OO_None; 627} 628 629FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const { 630 if (FunctionTemplateSpecializationInfo *Info 631 = TemplateOrSpecialization 632 .dyn_cast<FunctionTemplateSpecializationInfo*>()) { 633 return Info->Template.getPointer(); 634 } 635 return 0; 636} 637 638const TemplateArgumentList * 639FunctionDecl::getTemplateSpecializationArgs() const { 640 if (FunctionTemplateSpecializationInfo *Info 641 = TemplateOrSpecialization 642 .dyn_cast<FunctionTemplateSpecializationInfo*>()) { 643 return Info->TemplateArguments; 644 } 645 return 0; 646} 647 648void 649FunctionDecl::setFunctionTemplateSpecialization(ASTContext &Context, 650 FunctionTemplateDecl *Template, 651 const TemplateArgumentList *TemplateArgs, 652 void *InsertPos) { 653 FunctionTemplateSpecializationInfo *Info 654 = TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>(); 655 if (!Info) 656 Info = new (Context) FunctionTemplateSpecializationInfo; 657 658 Info->Function = this; 659 Info->Template.setPointer(Template); 660 Info->Template.setInt(0); // Implicit instantiation, unless told otherwise 661 Info->TemplateArguments = TemplateArgs; 662 TemplateOrSpecialization = Info; 663 664 // Insert this function template specialization into the set of known 665 // function template specialiations. 666 Template->getSpecializations().InsertNode(Info, InsertPos); 667} 668 669bool FunctionDecl::isExplicitSpecialization() const { 670 // FIXME: check this property for explicit specializations of member 671 // functions of class templates. 672 FunctionTemplateSpecializationInfo *Info 673 = TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>(); 674 if (!Info) 675 return false; 676 677 return Info->isExplicitSpecialization(); 678} 679 680void FunctionDecl::setExplicitSpecialization(bool ES) { 681 // FIXME: set this property for explicit specializations of member functions 682 // of class templates. 683 FunctionTemplateSpecializationInfo *Info 684 = TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>(); 685 if (Info) 686 Info->setExplicitSpecialization(ES); 687} 688 689//===----------------------------------------------------------------------===// 690// TagDecl Implementation 691//===----------------------------------------------------------------------===// 692 693SourceRange TagDecl::getSourceRange() const { 694 SourceLocation E = RBraceLoc.isValid() ? RBraceLoc : getLocation(); 695 return SourceRange(getLocation(), E); 696} 697 698TagDecl* TagDecl::getCanonicalDecl() { 699 Type *T = getTypeForDecl(); 700 if (T == 0) 701 T = getASTContext().getTagDeclType(this).getTypePtr(); 702 703 return cast<TagDecl>(cast<TagType>(T->getCanonicalTypeInternal())->getDecl()); 704} 705 706void TagDecl::startDefinition() { 707 TagType *TagT = const_cast<TagType *>(TypeForDecl->getAsTagType()); 708 TagT->decl.setPointer(this); 709 TagT->getAsTagType()->decl.setInt(1); 710} 711 712void TagDecl::completeDefinition() { 713 assert((!TypeForDecl || 714 TypeForDecl->getAsTagType()->decl.getPointer() == this) && 715 "Attempt to redefine a tag definition?"); 716 IsDefinition = true; 717 TagType *TagT = const_cast<TagType *>(TypeForDecl->getAsTagType()); 718 TagT->decl.setPointer(this); 719 TagT->decl.setInt(0); 720} 721 722TagDecl* TagDecl::getDefinition(ASTContext& C) const { 723 QualType T = C.getTypeDeclType(const_cast<TagDecl*>(this)); 724 TagDecl* D = cast<TagDecl>(T->getAsTagType()->getDecl()); 725 return D->isDefinition() ? D : 0; 726} 727 728//===----------------------------------------------------------------------===// 729// RecordDecl Implementation 730//===----------------------------------------------------------------------===// 731 732RecordDecl::RecordDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L, 733 IdentifierInfo *Id) 734 : TagDecl(DK, TK, DC, L, Id) { 735 HasFlexibleArrayMember = false; 736 AnonymousStructOrUnion = false; 737 HasObjectMember = false; 738 assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!"); 739} 740 741RecordDecl *RecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC, 742 SourceLocation L, IdentifierInfo *Id, 743 RecordDecl* PrevDecl) { 744 745 RecordDecl* R = new (C) RecordDecl(Record, TK, DC, L, Id); 746 C.getTypeDeclType(R, PrevDecl); 747 return R; 748} 749 750RecordDecl::~RecordDecl() { 751} 752 753void RecordDecl::Destroy(ASTContext& C) { 754 TagDecl::Destroy(C); 755} 756 757bool RecordDecl::isInjectedClassName() const { 758 return isImplicit() && getDeclName() && getDeclContext()->isRecord() && 759 cast<RecordDecl>(getDeclContext())->getDeclName() == getDeclName(); 760} 761 762/// completeDefinition - Notes that the definition of this type is now 763/// complete. 764void RecordDecl::completeDefinition(ASTContext& C) { 765 assert(!isDefinition() && "Cannot redefine record!"); 766 TagDecl::completeDefinition(); 767} 768 769//===----------------------------------------------------------------------===// 770// BlockDecl Implementation 771//===----------------------------------------------------------------------===// 772 773BlockDecl::~BlockDecl() { 774} 775 776void BlockDecl::Destroy(ASTContext& C) { 777 if (Body) 778 Body->Destroy(C); 779 780 for (param_iterator I=param_begin(), E=param_end(); I!=E; ++I) 781 (*I)->Destroy(C); 782 783 C.Deallocate(ParamInfo); 784 Decl::Destroy(C); 785} 786 787void BlockDecl::setParams(ASTContext& C, ParmVarDecl **NewParamInfo, 788 unsigned NParms) { 789 assert(ParamInfo == 0 && "Already has param info!"); 790 791 // Zero params -> null pointer. 792 if (NParms) { 793 NumParams = NParms; 794 void *Mem = C.Allocate(sizeof(ParmVarDecl*)*NumParams); 795 ParamInfo = new (Mem) ParmVarDecl*[NumParams]; 796 memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*NumParams); 797 } 798} 799 800unsigned BlockDecl::getNumParams() const { 801 return NumParams; 802} 803