Decl.cpp revision 090276f5e164d491a1bb3f541bafdb394f5e6f04
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/ASTContext.h" 16#include "clang/AST/Stmt.h" 17#include "clang/Basic/IdentifierTable.h" 18 19using namespace clang; 20 21//===----------------------------------------------------------------------===// 22// Decl Allocation/Deallocation Method Implementations 23//===----------------------------------------------------------------------===// 24 25TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) { 26 void *Mem = C.getAllocator().Allocate<TranslationUnitDecl>(); 27 return new (Mem) TranslationUnitDecl(); 28} 29 30NamespaceDecl *NamespaceDecl::Create(ASTContext &C, DeclContext *DC, 31 SourceLocation L, IdentifierInfo *Id) { 32 void *Mem = C.getAllocator().Allocate<NamespaceDecl>(); 33 return new (Mem) NamespaceDecl(DC, L, Id); 34} 35 36void NamespaceDecl::Destroy(ASTContext& C) { 37 // NamespaceDecl uses "NextDeclarator" to chain namespace declarations 38 // together. They are all top-level Decls. 39 40 this->~NamespaceDecl(); 41 C.getAllocator().Deallocate((void *)this); 42} 43 44 45ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, DeclContext *DC, 46 SourceLocation L, IdentifierInfo *Id, QualType T, ScopedDecl *PrevDecl) { 47 void *Mem = C.getAllocator().Allocate<ImplicitParamDecl>(); 48 return new (Mem) ImplicitParamDecl(ImplicitParam, DC, L, Id, T, PrevDecl); 49} 50 51VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC, 52 SourceLocation L, 53 IdentifierInfo *Id, QualType T, 54 StorageClass S, ScopedDecl *PrevDecl, 55 SourceLocation TypeSpecStartLoc) { 56 void *Mem = C.getAllocator().Allocate<VarDecl>(); 57 return new (Mem) VarDecl(Var, DC, L, Id, T, S, PrevDecl, TypeSpecStartLoc); 58} 59 60ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC, 61 SourceLocation L, IdentifierInfo *Id, 62 QualType T, StorageClass S, 63 Expr *DefArg, ScopedDecl *PrevDecl) { 64 void *Mem = C.getAllocator().Allocate<ParmVarDecl>(); 65 return new (Mem) ParmVarDecl(DC, L, Id, T, S, DefArg, PrevDecl); 66} 67 68FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC, 69 SourceLocation L, 70 IdentifierInfo *Id, QualType T, 71 StorageClass S, bool isInline, 72 ScopedDecl *PrevDecl, 73 SourceLocation TypeSpecStartLoc) { 74 void *Mem = C.getAllocator().Allocate<FunctionDecl>(); 75 return new (Mem) FunctionDecl(Function, DC, L, Id, T, S, isInline, PrevDecl, 76 TypeSpecStartLoc); 77} 78 79BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) { 80 void *Mem = C.getAllocator().Allocate<BlockDecl>(); 81 return new (Mem) BlockDecl(DC, L); 82} 83 84FieldDecl *FieldDecl::Create(ASTContext &C, SourceLocation L, 85 IdentifierInfo *Id, QualType T, Expr *BW) { 86 void *Mem = C.getAllocator().Allocate<FieldDecl>(); 87 return new (Mem) FieldDecl(L, Id, T, BW); 88} 89 90 91EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD, 92 SourceLocation L, 93 IdentifierInfo *Id, QualType T, 94 Expr *E, const llvm::APSInt &V, 95 ScopedDecl *PrevDecl){ 96 void *Mem = C.getAllocator().Allocate<EnumConstantDecl>(); 97 return new (Mem) EnumConstantDecl(CD, L, Id, T, E, V, PrevDecl); 98} 99 100void EnumConstantDecl::Destroy(ASTContext& C) { 101 if (Init) Init->Destroy(C); 102 Decl::Destroy(C); 103} 104 105TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC, 106 SourceLocation L, 107 IdentifierInfo *Id, QualType T, 108 ScopedDecl *PD) { 109 void *Mem = C.getAllocator().Allocate<TypedefDecl>(); 110 return new (Mem) TypedefDecl(DC, L, Id, T, PD); 111} 112 113EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, 114 IdentifierInfo *Id, 115 ScopedDecl *PrevDecl) { 116 void *Mem = C.getAllocator().Allocate<EnumDecl>(); 117 return new (Mem) EnumDecl(DC, L, Id, PrevDecl); 118} 119 120void EnumDecl::Destroy(ASTContext& C) { 121 if (getEnumConstantList()) getEnumConstantList()->Destroy(C); 122 Decl::Destroy(C); 123} 124 125FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C, 126 SourceLocation L, 127 StringLiteral *Str) { 128 void *Mem = C.getAllocator().Allocate<FileScopeAsmDecl>(); 129 return new (Mem) FileScopeAsmDecl(L, Str); 130} 131 132LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C, 133 SourceLocation L, 134 LanguageIDs Lang, Decl *D) { 135 void *Mem = C.getAllocator().Allocate<LinkageSpecDecl>(); 136 return new (Mem) LinkageSpecDecl(L, Lang, D); 137} 138 139//===----------------------------------------------------------------------===// 140// NamedDecl Implementation 141//===----------------------------------------------------------------------===// 142 143const char *NamedDecl::getName() const { 144 if (const IdentifierInfo *II = getIdentifier()) 145 return II->getName(); 146 return ""; 147} 148 149//===----------------------------------------------------------------------===// 150// FunctionDecl Implementation 151//===----------------------------------------------------------------------===// 152 153FunctionDecl::~FunctionDecl() { 154 delete[] ParamInfo; 155} 156 157void FunctionDecl::Destroy(ASTContext& C) { 158 if (Body) 159 Body->Destroy(C); 160 161 for (param_iterator I=param_begin(), E=param_end(); I!=E; ++I) 162 (*I)->Destroy(C); 163 164 Decl::Destroy(C); 165} 166 167 168Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const { 169 for (const FunctionDecl *FD = this; FD != 0; FD = FD->PreviousDeclaration) { 170 if (FD->Body) { 171 Definition = FD; 172 return FD->Body; 173 } 174 } 175 176 return 0; 177} 178 179unsigned FunctionDecl::getNumParams() const { 180 const FunctionType *FT = getType()->getAsFunctionType(); 181 if (isa<FunctionTypeNoProto>(FT)) 182 return 0; 183 return cast<FunctionTypeProto>(FT)->getNumArgs(); 184} 185 186void FunctionDecl::setParams(ParmVarDecl **NewParamInfo, unsigned NumParams) { 187 assert(ParamInfo == 0 && "Already has param info!"); 188 assert(NumParams == getNumParams() && "Parameter count mismatch!"); 189 190 // Zero params -> null pointer. 191 if (NumParams) { 192 ParamInfo = new ParmVarDecl*[NumParams]; 193 memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*NumParams); 194 } 195} 196 197/// getMinRequiredArguments - Returns the minimum number of arguments 198/// needed to call this function. This may be fewer than the number of 199/// function parameters, if some of the parameters have default 200/// arguments (in C++). 201unsigned FunctionDecl::getMinRequiredArguments() const { 202 unsigned NumRequiredArgs = getNumParams(); 203 while (NumRequiredArgs > 0 204 && getParamDecl(NumRequiredArgs-1)->getDefaultArg()) 205 --NumRequiredArgs; 206 207 return NumRequiredArgs; 208} 209 210//===----------------------------------------------------------------------===// 211// TagdDecl Implementation 212//===----------------------------------------------------------------------===// 213 214TagDecl* TagDecl::getDefinition(ASTContext& C) const { 215 QualType T = C.getTypeDeclType(const_cast<TagDecl*>(this)); 216 TagDecl* D = cast<TagDecl>(cast<TagType>(T)->getDecl()); 217 return D->isDefinition() ? D : 0; 218} 219 220//===----------------------------------------------------------------------===// 221// RecordDecl Implementation 222//===----------------------------------------------------------------------===// 223 224RecordDecl::RecordDecl(Kind DK, DeclContext *DC, SourceLocation L, 225 IdentifierInfo *Id) 226: TagDecl(DK, DC, L, Id, 0) { 227 228 HasFlexibleArrayMember = false; 229 assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!"); 230 Members = 0; 231 NumMembers = -1; 232} 233 234RecordDecl *RecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC, 235 SourceLocation L, IdentifierInfo *Id, 236 RecordDecl* PrevDecl) { 237 238 void *Mem = C.getAllocator().Allocate<RecordDecl>(); 239 Kind DK; 240 switch (TK) { 241 default: assert(0 && "Invalid TagKind!"); 242 case TK_enum: assert(0 && "Enum TagKind passed for Record!"); 243 case TK_struct: DK = Struct; break; 244 case TK_union: DK = Union; break; 245 case TK_class: DK = Class; break; 246 } 247 248 RecordDecl* R = new (Mem) RecordDecl(DK, DC, L, Id); 249 C.getTypeDeclType(R, PrevDecl); 250 return R; 251} 252 253RecordDecl::~RecordDecl() { 254 delete[] Members; 255} 256 257void RecordDecl::Destroy(ASTContext& C) { 258 if (isDefinition()) 259 for (field_iterator I=field_begin(), E=field_end(); I!=E; ++I) 260 (*I)->Destroy(C); 261 262 TagDecl::Destroy(C); 263} 264 265/// defineBody - When created, RecordDecl's correspond to a forward declared 266/// record. This method is used to mark the decl as being defined, with the 267/// specified contents. 268void RecordDecl::defineBody(ASTContext& C, FieldDecl **members, 269 unsigned numMembers) { 270 assert(!isDefinition() && "Cannot redefine record!"); 271 setDefinition(true); 272 NumMembers = numMembers; 273 if (numMembers) { 274 Members = new FieldDecl*[numMembers]; 275 memcpy(Members, members, numMembers*sizeof(Decl*)); 276 } 277 278 // Let ASTContext know that this is the defining RecordDecl this type. 279 C.setTagDefinition(this); 280} 281 282 283FieldDecl *RecordDecl::getMember(IdentifierInfo *II) { 284 if (Members == 0 || NumMembers < 0) 285 return 0; 286 287 // Linear search. When C++ classes come along, will likely need to revisit. 288 for (int i = 0; i != NumMembers; ++i) 289 if (Members[i]->getIdentifier() == II) 290 return Members[i]; 291 return 0; 292} 293 294//===----------------------------------------------------------------------===// 295// BlockDecl Implementation 296//===----------------------------------------------------------------------===// 297 298BlockDecl::~BlockDecl() { 299} 300 301void BlockDecl::Destroy(ASTContext& C) { 302 if (Body) 303 Body->Destroy(C); 304 305 for (param_iterator I=param_begin(), E=param_end(); I!=E; ++I) 306 (*I)->Destroy(C); 307 308 Decl::Destroy(C); 309} 310