Decl.cpp revision 082d936a5b8323ac2c04558d8bca277a647831a3
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/ASTContext.h" 18#include "clang/AST/Stmt.h" 19#include "clang/AST/Expr.h" 20#include "clang/Basic/IdentifierTable.h" 21#include <vector> 22 23using namespace clang; 24 25void Attr::Destroy(ASTContext &C) { 26 if (Next) { 27 Next->Destroy(C); 28 Next = 0; 29 } 30 this->~Attr(); 31 C.Deallocate((void*)this); 32} 33 34 35//===----------------------------------------------------------------------===// 36// Decl Allocation/Deallocation Method Implementations 37//===----------------------------------------------------------------------===// 38 39 40TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) { 41 return new (C) TranslationUnitDecl(); 42} 43 44NamespaceDecl *NamespaceDecl::Create(ASTContext &C, DeclContext *DC, 45 SourceLocation L, IdentifierInfo *Id) { 46 return new (C) NamespaceDecl(DC, L, Id); 47} 48 49void NamespaceDecl::Destroy(ASTContext& C) { 50 // NamespaceDecl uses "NextDeclarator" to chain namespace declarations 51 // together. They are all top-level Decls. 52 53 this->~NamespaceDecl(); 54 C.Deallocate((void *)this); 55} 56 57 58ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, DeclContext *DC, 59 SourceLocation L, IdentifierInfo *Id, QualType T) { 60 return new (C) ImplicitParamDecl(ImplicitParam, DC, L, Id, T); 61} 62 63ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC, 64 SourceLocation L, IdentifierInfo *Id, 65 QualType T, StorageClass S, 66 Expr *DefArg) { 67 return new (C) ParmVarDecl(ParmVar, DC, L, Id, T, S, DefArg); 68} 69 70QualType ParmVarDecl::getOriginalType() const { 71 if (const OriginalParmVarDecl *PVD = 72 dyn_cast<OriginalParmVarDecl>(this)) 73 return PVD->OriginalType; 74 return getType(); 75} 76 77bool VarDecl::isExternC(ASTContext &Context) const { 78 if (!Context.getLangOptions().CPlusPlus) 79 return (getDeclContext()->isTranslationUnit() && 80 getStorageClass() != Static) || 81 (getDeclContext()->isFunctionOrMethod() && hasExternalStorage()); 82 83 for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit(); 84 DC = DC->getParent()) { 85 if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) { 86 if (Linkage->getLanguage() == LinkageSpecDecl::lang_c) 87 return getStorageClass() != Static; 88 89 break; 90 } 91 92 if (DC->isFunctionOrMethod()) 93 return false; 94 } 95 96 return false; 97} 98 99OriginalParmVarDecl *OriginalParmVarDecl::Create( 100 ASTContext &C, DeclContext *DC, 101 SourceLocation L, IdentifierInfo *Id, 102 QualType T, QualType OT, StorageClass S, 103 Expr *DefArg) { 104 return new (C) OriginalParmVarDecl(DC, L, Id, T, OT, S, DefArg); 105} 106 107FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC, 108 SourceLocation L, 109 DeclarationName N, QualType T, 110 StorageClass S, bool isInline, 111 bool hasPrototype, 112 SourceLocation TypeSpecStartLoc) { 113 FunctionDecl *New 114 = new (C) FunctionDecl(Function, DC, L, N, T, S, isInline, 115 TypeSpecStartLoc); 116 New->HasPrototype = hasPrototype; 117 return New; 118} 119 120BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) { 121 return new (C) BlockDecl(DC, L); 122} 123 124FieldDecl *FieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, 125 IdentifierInfo *Id, QualType T, Expr *BW, 126 bool Mutable) { 127 return new (C) FieldDecl(Decl::Field, DC, L, Id, T, BW, Mutable); 128} 129 130bool FieldDecl::isAnonymousStructOrUnion() const { 131 if (!isImplicit() || getDeclName()) 132 return false; 133 134 if (const RecordType *Record = getType()->getAsRecordType()) 135 return Record->getDecl()->isAnonymousStructOrUnion(); 136 137 return false; 138} 139 140EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD, 141 SourceLocation L, 142 IdentifierInfo *Id, QualType T, 143 Expr *E, const llvm::APSInt &V) { 144 return new (C) EnumConstantDecl(CD, L, Id, T, E, V); 145} 146 147void EnumConstantDecl::Destroy(ASTContext& C) { 148 if (Init) Init->Destroy(C); 149 Decl::Destroy(C); 150} 151 152TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC, 153 SourceLocation L, 154 IdentifierInfo *Id, QualType T) { 155 return new (C) TypedefDecl(DC, L, Id, T); 156} 157 158EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, 159 IdentifierInfo *Id, 160 EnumDecl *PrevDecl) { 161 EnumDecl *Enum = new (C) EnumDecl(DC, L, Id); 162 C.getTypeDeclType(Enum, PrevDecl); 163 return Enum; 164} 165 166void EnumDecl::Destroy(ASTContext& C) { 167 Decl::Destroy(C); 168} 169 170void EnumDecl::completeDefinition(ASTContext &C, QualType NewType) { 171 assert(!isDefinition() && "Cannot redefine enums!"); 172 IntegerType = NewType; 173 TagDecl::completeDefinition(); 174} 175 176FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C, DeclContext *DC, 177 SourceLocation L, 178 StringLiteral *Str) { 179 return new (C) FileScopeAsmDecl(DC, L, Str); 180} 181 182//===----------------------------------------------------------------------===// 183// NamedDecl Implementation 184//===----------------------------------------------------------------------===// 185 186std::string NamedDecl::getQualifiedNameAsString() const { 187 std::vector<std::string> Names; 188 std::string QualName; 189 const DeclContext *Ctx = getDeclContext(); 190 191 if (Ctx->isFunctionOrMethod()) 192 return getNameAsString(); 193 194 while (Ctx) { 195 if (Ctx->isFunctionOrMethod()) 196 // FIXME: That probably will happen, when D was member of local 197 // scope class/struct/union. How do we handle this case? 198 break; 199 200 if (const NamedDecl *ND = dyn_cast<NamedDecl>(Ctx)) 201 Names.push_back(ND->getNameAsString()); 202 else 203 break; 204 205 Ctx = Ctx->getParent(); 206 } 207 208 std::vector<std::string>::reverse_iterator 209 I = Names.rbegin(), 210 End = Names.rend(); 211 212 for (; I!=End; ++I) 213 QualName += *I + "::"; 214 215 QualName += getNameAsString(); 216 217 return QualName; 218} 219 220 221bool NamedDecl::declarationReplaces(NamedDecl *OldD) const { 222 assert(getDeclName() == OldD->getDeclName() && "Declaration name mismatch"); 223 224 // UsingDirectiveDecl's are not really NamedDecl's, and all have same name. 225 // We want to keep it, unless it nominates same namespace. 226 if (getKind() == Decl::UsingDirective) { 227 return cast<UsingDirectiveDecl>(this)->getNominatedNamespace() == 228 cast<UsingDirectiveDecl>(OldD)->getNominatedNamespace(); 229 } 230 231 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(this)) 232 // For function declarations, we keep track of redeclarations. 233 return FD->getPreviousDeclaration() == OldD; 234 235 // For method declarations, we keep track of redeclarations. 236 if (isa<ObjCMethodDecl>(this)) 237 return false; 238 239 // For non-function declarations, if the declarations are of the 240 // same kind then this must be a redeclaration, or semantic analysis 241 // would not have given us the new declaration. 242 return this->getKind() == OldD->getKind(); 243} 244 245bool NamedDecl::hasLinkage() const { 246 if (const VarDecl *VD = dyn_cast<VarDecl>(this)) 247 return VD->hasExternalStorage() || VD->isFileVarDecl(); 248 249 if (isa<FunctionDecl>(this) && !isa<CXXMethodDecl>(this)) 250 return true; 251 252 return false; 253} 254 255//===----------------------------------------------------------------------===// 256// VarDecl Implementation 257//===----------------------------------------------------------------------===// 258 259VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, 260 IdentifierInfo *Id, QualType T, StorageClass S, 261 SourceLocation TypeSpecStartLoc) { 262 return new (C) VarDecl(Var, DC, L, Id, T, S, TypeSpecStartLoc); 263} 264 265void VarDecl::Destroy(ASTContext& C) { 266 Expr *Init = getInit(); 267 if (Init) 268 Init->Destroy(C); 269 this->~VarDecl(); 270 C.Deallocate((void *)this); 271} 272 273VarDecl::~VarDecl() { 274} 275 276bool VarDecl::isTentativeDefinition(ASTContext &Context) const { 277 if (!isFileVarDecl() || Context.getLangOptions().CPlusPlus) 278 return false; 279 280 return (!getInit() && 281 (getStorageClass() == None || getStorageClass() == Static)); 282} 283 284const Expr *VarDecl::getDefinition(const VarDecl *&Def) const { 285 Def = this; 286 while (Def && !Def->getInit()) 287 Def = Def->getPreviousDeclaration(); 288 289 return Def? Def->getInit() : 0; 290} 291 292//===----------------------------------------------------------------------===// 293// FunctionDecl Implementation 294//===----------------------------------------------------------------------===// 295 296void FunctionDecl::Destroy(ASTContext& C) { 297 if (Body) 298 Body->Destroy(C); 299 300 for (param_iterator I=param_begin(), E=param_end(); I!=E; ++I) 301 (*I)->Destroy(C); 302 303 C.Deallocate(ParamInfo); 304 305 Decl::Destroy(C); 306} 307 308 309CompoundStmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const { 310 for (const FunctionDecl *FD = this; FD != 0; FD = FD->PreviousDeclaration) { 311 if (FD->Body) { 312 Definition = FD; 313 return cast<CompoundStmt>(FD->Body); 314 } 315 } 316 317 return 0; 318} 319 320bool FunctionDecl::isMain() const { 321 return getDeclContext()->getLookupContext()->isTranslationUnit() && 322 getIdentifier() && getIdentifier()->isStr("main"); 323} 324 325bool FunctionDecl::isExternC(ASTContext &Context) const { 326 // In C, any non-static, non-overloadable function has external 327 // linkage. 328 if (!Context.getLangOptions().CPlusPlus) 329 return getStorageClass() != Static && !getAttr<OverloadableAttr>(); 330 331 for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit(); 332 DC = DC->getParent()) { 333 if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) { 334 if (Linkage->getLanguage() == LinkageSpecDecl::lang_c) 335 return getStorageClass() != Static && !getAttr<OverloadableAttr>(); 336 337 break; 338 } 339 } 340 341 return false; 342} 343 344/// \brief Returns a value indicating whether this function 345/// corresponds to a builtin function. 346/// 347/// The function corresponds to a built-in function if it is 348/// declared at translation scope or within an extern "C" block and 349/// its name matches with the name of a builtin. The returned value 350/// will be 0 for functions that do not correspond to a builtin, a 351/// value of type \c Builtin::ID if in the target-independent range 352/// \c [1,Builtin::First), or a target-specific builtin value. 353unsigned FunctionDecl::getBuiltinID(ASTContext &Context) const { 354 if (!getIdentifier() || !getIdentifier()->getBuiltinID()) 355 return 0; 356 357 unsigned BuiltinID = getIdentifier()->getBuiltinID(); 358 if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) 359 return BuiltinID; 360 361 // This function has the name of a known C library 362 // function. Determine whether it actually refers to the C library 363 // function or whether it just has the same name. 364 365 // If this is a static function, it's not a builtin. 366 if (getStorageClass() == Static) 367 return 0; 368 369 // If this function is at translation-unit scope and we're not in 370 // C++, it refers to the C library function. 371 if (!Context.getLangOptions().CPlusPlus && 372 getDeclContext()->isTranslationUnit()) 373 return BuiltinID; 374 375 // If the function is in an extern "C" linkage specification and is 376 // not marked "overloadable", it's the real function. 377 if (isa<LinkageSpecDecl>(getDeclContext()) && 378 cast<LinkageSpecDecl>(getDeclContext())->getLanguage() 379 == LinkageSpecDecl::lang_c && 380 !getAttr<OverloadableAttr>()) 381 return BuiltinID; 382 383 // Not a builtin 384 return 0; 385} 386 387 388// Helper function for FunctionDecl::getNumParams and FunctionDecl::setParams() 389static unsigned getNumTypeParams(QualType T) { 390 const FunctionType *FT = T->getAsFunctionType(); 391 if (isa<FunctionNoProtoType>(FT)) 392 return 0; 393 return cast<FunctionProtoType>(FT)->getNumArgs(); 394} 395 396unsigned FunctionDecl::getNumParams() const { 397 // Can happen if a FunctionDecl is declared using typeof(some_other_func) bar; 398 if (!ParamInfo) 399 return 0; 400 401 return getNumTypeParams(getType()); 402} 403 404void FunctionDecl::setParams(ASTContext& C, ParmVarDecl **NewParamInfo, 405 unsigned NumParams) { 406 assert(ParamInfo == 0 && "Already has param info!"); 407 assert(NumParams == getNumTypeParams(getType()) && 408 "Parameter count mismatch!"); 409 410 // Zero params -> null pointer. 411 if (NumParams) { 412 void *Mem = C.Allocate(sizeof(ParmVarDecl*)*NumParams); 413 ParamInfo = new (Mem) ParmVarDecl*[NumParams]; 414 memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*NumParams); 415 } 416} 417 418/// getMinRequiredArguments - Returns the minimum number of arguments 419/// needed to call this function. This may be fewer than the number of 420/// function parameters, if some of the parameters have default 421/// arguments (in C++). 422unsigned FunctionDecl::getMinRequiredArguments() const { 423 unsigned NumRequiredArgs = getNumParams(); 424 while (NumRequiredArgs > 0 425 && getParamDecl(NumRequiredArgs-1)->getDefaultArg()) 426 --NumRequiredArgs; 427 428 return NumRequiredArgs; 429} 430 431/// getOverloadedOperator - Which C++ overloaded operator this 432/// function represents, if any. 433OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const { 434 if (getDeclName().getNameKind() == DeclarationName::CXXOperatorName) 435 return getDeclName().getCXXOverloadedOperator(); 436 else 437 return OO_None; 438} 439 440//===----------------------------------------------------------------------===// 441// TagDecl Implementation 442//===----------------------------------------------------------------------===// 443 444void TagDecl::startDefinition() { 445 TagType *TagT = const_cast<TagType *>(TypeForDecl->getAsTagType()); 446 TagT->decl.setPointer(this); 447 TagT->getAsTagType()->decl.setInt(1); 448} 449 450void TagDecl::completeDefinition() { 451 assert((!TypeForDecl || 452 TypeForDecl->getAsTagType()->decl.getPointer() == this) && 453 "Attempt to redefine a tag definition?"); 454 IsDefinition = true; 455 TagType *TagT = const_cast<TagType *>(TypeForDecl->getAsTagType()); 456 TagT->decl.setPointer(this); 457 TagT->decl.setInt(0); 458} 459 460TagDecl* TagDecl::getDefinition(ASTContext& C) const { 461 QualType T = C.getTypeDeclType(const_cast<TagDecl*>(this)); 462 TagDecl* D = cast<TagDecl>(T->getAsTagType()->getDecl()); 463 return D->isDefinition() ? D : 0; 464} 465 466//===----------------------------------------------------------------------===// 467// RecordDecl Implementation 468//===----------------------------------------------------------------------===// 469 470RecordDecl::RecordDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L, 471 IdentifierInfo *Id) 472 : TagDecl(DK, TK, DC, L, Id) { 473 HasFlexibleArrayMember = false; 474 AnonymousStructOrUnion = false; 475 assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!"); 476} 477 478RecordDecl *RecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC, 479 SourceLocation L, IdentifierInfo *Id, 480 RecordDecl* PrevDecl) { 481 482 RecordDecl* R = new (C) RecordDecl(Record, TK, DC, L, Id); 483 C.getTypeDeclType(R, PrevDecl); 484 return R; 485} 486 487RecordDecl::~RecordDecl() { 488} 489 490void RecordDecl::Destroy(ASTContext& C) { 491 TagDecl::Destroy(C); 492} 493 494/// completeDefinition - Notes that the definition of this type is now 495/// complete. 496void RecordDecl::completeDefinition(ASTContext& C) { 497 assert(!isDefinition() && "Cannot redefine record!"); 498 TagDecl::completeDefinition(); 499} 500 501//===----------------------------------------------------------------------===// 502// BlockDecl Implementation 503//===----------------------------------------------------------------------===// 504 505BlockDecl::~BlockDecl() { 506} 507 508void BlockDecl::Destroy(ASTContext& C) { 509 if (Body) 510 Body->Destroy(C); 511 512 for (param_iterator I=param_begin(), E=param_end(); I!=E; ++I) 513 (*I)->Destroy(C); 514 515 C.Deallocate(ParamInfo); 516 Decl::Destroy(C); 517} 518 519void BlockDecl::setParams(ASTContext& C, ParmVarDecl **NewParamInfo, 520 unsigned NParms) { 521 assert(ParamInfo == 0 && "Already has param info!"); 522 523 // Zero params -> null pointer. 524 if (NParms) { 525 NumParams = NParms; 526 void *Mem = C.Allocate(sizeof(ParmVarDecl*)*NumParams); 527 ParamInfo = new (Mem) ParmVarDecl*[NumParams]; 528 memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*NumParams); 529 } 530} 531 532unsigned BlockDecl::getNumParams() const { 533 return NumParams; 534} 535