Decl.cpp revision d249e1d1f1498b81314459ceda19d6ff25c278ad
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/IdentifierTable.h" 23#include <vector> 24 25using namespace clang; 26 27void Attr::Destroy(ASTContext &C) { 28 if (Next) { 29 Next->Destroy(C); 30 Next = 0; 31 } 32 this->~Attr(); 33 C.Deallocate((void*)this); 34} 35 36 37//===----------------------------------------------------------------------===// 38// Decl Allocation/Deallocation Method Implementations 39//===----------------------------------------------------------------------===// 40 41 42TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) { 43 return new (C) TranslationUnitDecl(); 44} 45 46NamespaceDecl *NamespaceDecl::Create(ASTContext &C, DeclContext *DC, 47 SourceLocation L, IdentifierInfo *Id) { 48 return new (C) NamespaceDecl(DC, L, Id); 49} 50 51void NamespaceDecl::Destroy(ASTContext& C) { 52 // NamespaceDecl uses "NextDeclarator" to chain namespace declarations 53 // together. They are all top-level Decls. 54 55 this->~NamespaceDecl(); 56 C.Deallocate((void *)this); 57} 58 59 60ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, DeclContext *DC, 61 SourceLocation L, IdentifierInfo *Id, QualType T) { 62 return new (C) ImplicitParamDecl(ImplicitParam, DC, L, Id, T); 63} 64 65const char *VarDecl::getStorageClassSpecifierString(StorageClass SC) { 66 switch (SC) { 67 case VarDecl::None: break; 68 case VarDecl::Auto: return "auto"; break; 69 case VarDecl::Extern: return "extern"; break; 70 case VarDecl::PrivateExtern: return "__private_extern__"; break; 71 case VarDecl::Register: return "register"; break; 72 case VarDecl::Static: return "static"; break; 73 } 74 75 assert(0 && "Invalid storage class"); 76 return 0; 77} 78 79ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC, 80 SourceLocation L, IdentifierInfo *Id, 81 QualType T, StorageClass S, 82 Expr *DefArg) { 83 return new (C) ParmVarDecl(ParmVar, DC, L, Id, T, S, DefArg); 84} 85 86QualType ParmVarDecl::getOriginalType() const { 87 if (const OriginalParmVarDecl *PVD = 88 dyn_cast<OriginalParmVarDecl>(this)) 89 return PVD->OriginalType; 90 return getType(); 91} 92 93void VarDecl::setInit(ASTContext &C, Expr *I) { 94 if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>()) { 95 Eval->~EvaluatedStmt(); 96 C.Deallocate(Eval); 97 } 98 99 Init = I; 100 } 101 102bool VarDecl::isExternC(ASTContext &Context) const { 103 if (!Context.getLangOptions().CPlusPlus) 104 return (getDeclContext()->isTranslationUnit() && 105 getStorageClass() != Static) || 106 (getDeclContext()->isFunctionOrMethod() && hasExternalStorage()); 107 108 for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit(); 109 DC = DC->getParent()) { 110 if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) { 111 if (Linkage->getLanguage() == LinkageSpecDecl::lang_c) 112 return getStorageClass() != Static; 113 114 break; 115 } 116 117 if (DC->isFunctionOrMethod()) 118 return false; 119 } 120 121 return false; 122} 123 124OriginalParmVarDecl *OriginalParmVarDecl::Create( 125 ASTContext &C, DeclContext *DC, 126 SourceLocation L, IdentifierInfo *Id, 127 QualType T, QualType OT, StorageClass S, 128 Expr *DefArg) { 129 return new (C) OriginalParmVarDecl(DC, L, Id, T, OT, S, DefArg); 130} 131 132FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC, 133 SourceLocation L, 134 DeclarationName N, QualType T, 135 StorageClass S, bool isInline, 136 bool hasWrittenPrototype, 137 SourceLocation TypeSpecStartLoc) { 138 FunctionDecl *New 139 = new (C) FunctionDecl(Function, DC, L, N, T, S, isInline, 140 TypeSpecStartLoc); 141 New->HasWrittenPrototype = hasWrittenPrototype; 142 return New; 143} 144 145BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) { 146 return new (C) BlockDecl(DC, L); 147} 148 149FieldDecl *FieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, 150 IdentifierInfo *Id, QualType T, Expr *BW, 151 bool Mutable) { 152 return new (C) FieldDecl(Decl::Field, DC, L, Id, T, BW, Mutable); 153} 154 155bool FieldDecl::isAnonymousStructOrUnion() const { 156 if (!isImplicit() || getDeclName()) 157 return false; 158 159 if (const RecordType *Record = getType()->getAsRecordType()) 160 return Record->getDecl()->isAnonymousStructOrUnion(); 161 162 return false; 163} 164 165EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD, 166 SourceLocation L, 167 IdentifierInfo *Id, QualType T, 168 Expr *E, const llvm::APSInt &V) { 169 return new (C) EnumConstantDecl(CD, L, Id, T, E, V); 170} 171 172void EnumConstantDecl::Destroy(ASTContext& C) { 173 if (Init) Init->Destroy(C); 174 Decl::Destroy(C); 175} 176 177TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC, 178 SourceLocation L, 179 IdentifierInfo *Id, QualType T) { 180 return new (C) TypedefDecl(DC, L, Id, T); 181} 182 183EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, 184 IdentifierInfo *Id, 185 EnumDecl *PrevDecl) { 186 EnumDecl *Enum = new (C) EnumDecl(DC, L, Id); 187 C.getTypeDeclType(Enum, PrevDecl); 188 return Enum; 189} 190 191void EnumDecl::Destroy(ASTContext& C) { 192 Decl::Destroy(C); 193} 194 195void EnumDecl::completeDefinition(ASTContext &C, QualType NewType) { 196 assert(!isDefinition() && "Cannot redefine enums!"); 197 IntegerType = NewType; 198 TagDecl::completeDefinition(); 199} 200 201FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C, DeclContext *DC, 202 SourceLocation L, 203 StringLiteral *Str) { 204 return new (C) FileScopeAsmDecl(DC, L, Str); 205} 206 207//===----------------------------------------------------------------------===// 208// NamedDecl Implementation 209//===----------------------------------------------------------------------===// 210 211std::string NamedDecl::getQualifiedNameAsString() const { 212 std::vector<std::string> Names; 213 std::string QualName; 214 const DeclContext *Ctx = getDeclContext(); 215 216 if (Ctx->isFunctionOrMethod()) 217 return getNameAsString(); 218 219 while (Ctx) { 220 if (Ctx->isFunctionOrMethod()) 221 // FIXME: That probably will happen, when D was member of local 222 // scope class/struct/union. How do we handle this case? 223 break; 224 225 if (const ClassTemplateSpecializationDecl *Spec 226 = dyn_cast<ClassTemplateSpecializationDecl>(Ctx)) { 227 const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); 228 PrintingPolicy Policy; 229 Policy.CPlusPlus = true; 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 method declarations, we keep track of redeclarations. 272 if (isa<ObjCMethodDecl>(this)) 273 return false; 274 275 // For non-function declarations, if the declarations are of the 276 // same kind then this must be a redeclaration, or semantic analysis 277 // would not have given us the new declaration. 278 return this->getKind() == OldD->getKind(); 279} 280 281bool NamedDecl::hasLinkage() const { 282 if (const VarDecl *VD = dyn_cast<VarDecl>(this)) 283 return VD->hasExternalStorage() || VD->isFileVarDecl(); 284 285 if (isa<FunctionDecl>(this) && !isa<CXXMethodDecl>(this)) 286 return true; 287 288 return false; 289} 290 291//===----------------------------------------------------------------------===// 292// VarDecl Implementation 293//===----------------------------------------------------------------------===// 294 295VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, 296 IdentifierInfo *Id, QualType T, StorageClass S, 297 SourceLocation TypeSpecStartLoc) { 298 return new (C) VarDecl(Var, DC, L, Id, T, S, TypeSpecStartLoc); 299} 300 301void VarDecl::Destroy(ASTContext& C) { 302 Expr *Init = getInit(); 303 if (Init) { 304 Init->Destroy(C); 305 if (EvaluatedStmt *Eval = this->Init.dyn_cast<EvaluatedStmt *>()) { 306 Eval->~EvaluatedStmt(); 307 C.Deallocate(Eval); 308 } 309 } 310 this->~VarDecl(); 311 C.Deallocate((void *)this); 312} 313 314VarDecl::~VarDecl() { 315} 316 317bool VarDecl::isTentativeDefinition(ASTContext &Context) const { 318 if (!isFileVarDecl() || Context.getLangOptions().CPlusPlus) 319 return false; 320 321 const VarDecl *Def = 0; 322 return (!getDefinition(Def) && 323 (getStorageClass() == None || getStorageClass() == Static)); 324} 325 326const Expr *VarDecl::getDefinition(const VarDecl *&Def) const { 327 Def = this; 328 while (Def && !Def->getInit()) 329 Def = Def->getPreviousDeclaration(); 330 331 return Def? Def->getInit() : 0; 332} 333 334//===----------------------------------------------------------------------===// 335// FunctionDecl Implementation 336//===----------------------------------------------------------------------===// 337 338void FunctionDecl::Destroy(ASTContext& C) { 339 if (Body && Body.isOffset()) 340 Body.get(C.getExternalSource())->Destroy(C); 341 342 for (param_iterator I=param_begin(), E=param_end(); I!=E; ++I) 343 (*I)->Destroy(C); 344 345 C.Deallocate(ParamInfo); 346 347 Decl::Destroy(C); 348} 349 350 351Stmt *FunctionDecl::getBody(ASTContext &Context, 352 const FunctionDecl *&Definition) const { 353 for (const FunctionDecl *FD = this; FD != 0; FD = FD->PreviousDeclaration) { 354 if (FD->Body) { 355 Definition = FD; 356 return FD->Body.get(Context.getExternalSource()); 357 } 358 } 359 360 return 0; 361} 362 363Stmt *FunctionDecl::getBodyIfAvailable() const { 364 for (const FunctionDecl *FD = this; FD != 0; FD = FD->PreviousDeclaration) { 365 if (FD->Body && !FD->Body.isOffset()) { 366 return FD->Body.get(0); 367 } 368 } 369 370 return 0; 371} 372 373bool FunctionDecl::isMain() const { 374 return getDeclContext()->getLookupContext()->isTranslationUnit() && 375 getIdentifier() && getIdentifier()->isStr("main"); 376} 377 378bool FunctionDecl::isExternC(ASTContext &Context) const { 379 // In C, any non-static, non-overloadable function has external 380 // linkage. 381 if (!Context.getLangOptions().CPlusPlus) 382 return getStorageClass() != Static && !getAttr<OverloadableAttr>(); 383 384 for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit(); 385 DC = DC->getParent()) { 386 if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) { 387 if (Linkage->getLanguage() == LinkageSpecDecl::lang_c) 388 return getStorageClass() != Static && !getAttr<OverloadableAttr>(); 389 390 break; 391 } 392 } 393 394 return false; 395} 396 397bool FunctionDecl::isGlobal() const { 398 if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(this)) 399 return Method->isStatic(); 400 401 if (getStorageClass() == Static) 402 return false; 403 404 for (const DeclContext *DC = getDeclContext(); 405 DC->isNamespace(); 406 DC = DC->getParent()) { 407 if (const NamespaceDecl *Namespace = cast<NamespaceDecl>(DC)) { 408 if (!Namespace->getDeclName()) 409 return false; 410 break; 411 } 412 } 413 414 return true; 415} 416 417/// \brief Returns a value indicating whether this function 418/// corresponds to a builtin function. 419/// 420/// The function corresponds to a built-in function if it is 421/// declared at translation scope or within an extern "C" block and 422/// its name matches with the name of a builtin. The returned value 423/// will be 0 for functions that do not correspond to a builtin, a 424/// value of type \c Builtin::ID if in the target-independent range 425/// \c [1,Builtin::First), or a target-specific builtin value. 426unsigned FunctionDecl::getBuiltinID(ASTContext &Context) const { 427 if (!getIdentifier() || !getIdentifier()->getBuiltinID()) 428 return 0; 429 430 unsigned BuiltinID = getIdentifier()->getBuiltinID(); 431 if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) 432 return BuiltinID; 433 434 // This function has the name of a known C library 435 // function. Determine whether it actually refers to the C library 436 // function or whether it just has the same name. 437 438 // If this is a static function, it's not a builtin. 439 if (getStorageClass() == Static) 440 return 0; 441 442 // If this function is at translation-unit scope and we're not in 443 // C++, it refers to the C library function. 444 if (!Context.getLangOptions().CPlusPlus && 445 getDeclContext()->isTranslationUnit()) 446 return BuiltinID; 447 448 // If the function is in an extern "C" linkage specification and is 449 // not marked "overloadable", it's the real function. 450 if (isa<LinkageSpecDecl>(getDeclContext()) && 451 cast<LinkageSpecDecl>(getDeclContext())->getLanguage() 452 == LinkageSpecDecl::lang_c && 453 !getAttr<OverloadableAttr>()) 454 return BuiltinID; 455 456 // Not a builtin 457 return 0; 458} 459 460 461/// getNumParams - Return the number of parameters this function must have 462/// based on its FunctionType. This is the length of the PararmInfo array 463/// after it has been created. 464unsigned FunctionDecl::getNumParams() const { 465 const FunctionType *FT = getType()->getAsFunctionType(); 466 if (isa<FunctionNoProtoType>(FT)) 467 return 0; 468 return cast<FunctionProtoType>(FT)->getNumArgs(); 469 470} 471 472void FunctionDecl::setParams(ASTContext& C, ParmVarDecl **NewParamInfo, 473 unsigned NumParams) { 474 assert(ParamInfo == 0 && "Already has param info!"); 475 assert(NumParams == getNumParams() && "Parameter count mismatch!"); 476 477 // Zero params -> null pointer. 478 if (NumParams) { 479 void *Mem = C.Allocate(sizeof(ParmVarDecl*)*NumParams); 480 ParamInfo = new (Mem) ParmVarDecl*[NumParams]; 481 memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*NumParams); 482 } 483} 484 485/// getMinRequiredArguments - Returns the minimum number of arguments 486/// needed to call this function. This may be fewer than the number of 487/// function parameters, if some of the parameters have default 488/// arguments (in C++). 489unsigned FunctionDecl::getMinRequiredArguments() const { 490 unsigned NumRequiredArgs = getNumParams(); 491 while (NumRequiredArgs > 0 492 && getParamDecl(NumRequiredArgs-1)->getDefaultArg()) 493 --NumRequiredArgs; 494 495 return NumRequiredArgs; 496} 497 498bool FunctionDecl::hasActiveGNUInlineAttribute() const { 499 if (!isInline() || !hasAttr<GNUInlineAttr>()) 500 return false; 501 502 for (const FunctionDecl *FD = getPreviousDeclaration(); FD; 503 FD = FD->getPreviousDeclaration()) { 504 if (FD->isInline() && !FD->hasAttr<GNUInlineAttr>()) 505 return false; 506 } 507 508 return true; 509} 510 511bool FunctionDecl::isExternGNUInline() const { 512 if (!hasActiveGNUInlineAttribute()) 513 return false; 514 515 for (const FunctionDecl *FD = this; FD; FD = FD->getPreviousDeclaration()) 516 if (FD->getStorageClass() == Extern && FD->hasAttr<GNUInlineAttr>()) 517 return true; 518 519 return false; 520} 521 522/// getOverloadedOperator - Which C++ overloaded operator this 523/// function represents, if any. 524OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const { 525 if (getDeclName().getNameKind() == DeclarationName::CXXOperatorName) 526 return getDeclName().getCXXOverloadedOperator(); 527 else 528 return OO_None; 529} 530 531//===----------------------------------------------------------------------===// 532// TagDecl Implementation 533//===----------------------------------------------------------------------===// 534 535void TagDecl::startDefinition() { 536 TagType *TagT = const_cast<TagType *>(TypeForDecl->getAsTagType()); 537 TagT->decl.setPointer(this); 538 TagT->getAsTagType()->decl.setInt(1); 539} 540 541void TagDecl::completeDefinition() { 542 assert((!TypeForDecl || 543 TypeForDecl->getAsTagType()->decl.getPointer() == this) && 544 "Attempt to redefine a tag definition?"); 545 IsDefinition = true; 546 TagType *TagT = const_cast<TagType *>(TypeForDecl->getAsTagType()); 547 TagT->decl.setPointer(this); 548 TagT->decl.setInt(0); 549} 550 551TagDecl* TagDecl::getDefinition(ASTContext& C) const { 552 QualType T = C.getTypeDeclType(const_cast<TagDecl*>(this)); 553 TagDecl* D = cast<TagDecl>(T->getAsTagType()->getDecl()); 554 return D->isDefinition() ? D : 0; 555} 556 557//===----------------------------------------------------------------------===// 558// RecordDecl Implementation 559//===----------------------------------------------------------------------===// 560 561RecordDecl::RecordDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L, 562 IdentifierInfo *Id) 563 : TagDecl(DK, TK, DC, L, Id) { 564 HasFlexibleArrayMember = false; 565 AnonymousStructOrUnion = false; 566 assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!"); 567} 568 569RecordDecl *RecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC, 570 SourceLocation L, IdentifierInfo *Id, 571 RecordDecl* PrevDecl) { 572 573 RecordDecl* R = new (C) RecordDecl(Record, TK, DC, L, Id); 574 C.getTypeDeclType(R, PrevDecl); 575 return R; 576} 577 578RecordDecl::~RecordDecl() { 579} 580 581void RecordDecl::Destroy(ASTContext& C) { 582 TagDecl::Destroy(C); 583} 584 585bool RecordDecl::isInjectedClassName() const { 586 return isImplicit() && getDeclName() && getDeclContext()->isRecord() && 587 cast<RecordDecl>(getDeclContext())->getDeclName() == getDeclName(); 588} 589 590/// completeDefinition - Notes that the definition of this type is now 591/// complete. 592void RecordDecl::completeDefinition(ASTContext& C) { 593 assert(!isDefinition() && "Cannot redefine record!"); 594 TagDecl::completeDefinition(); 595} 596 597//===----------------------------------------------------------------------===// 598// BlockDecl Implementation 599//===----------------------------------------------------------------------===// 600 601BlockDecl::~BlockDecl() { 602} 603 604void BlockDecl::Destroy(ASTContext& C) { 605 if (Body) 606 Body->Destroy(C); 607 608 for (param_iterator I=param_begin(), E=param_end(); I!=E; ++I) 609 (*I)->Destroy(C); 610 611 C.Deallocate(ParamInfo); 612 Decl::Destroy(C); 613} 614 615void BlockDecl::setParams(ASTContext& C, ParmVarDecl **NewParamInfo, 616 unsigned NParms) { 617 assert(ParamInfo == 0 && "Already has param info!"); 618 619 // Zero params -> null pointer. 620 if (NParms) { 621 NumParams = NParms; 622 void *Mem = C.Allocate(sizeof(ParmVarDecl*)*NumParams); 623 ParamInfo = new (Mem) ParmVarDecl*[NumParams]; 624 memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*NumParams); 625 } 626} 627 628unsigned BlockDecl::getNumParams() const { 629 return NumParams; 630} 631