DeclCXX.cpp revision f44515a49b549171dc3ee9faa6281b72609da563
1//===--- DeclCXX.cpp - C++ 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 C++ related Decl classes. 11// 12//===----------------------------------------------------------------------===// 13 14#include "clang/AST/DeclCXX.h" 15#include "clang/AST/ASTContext.h" 16#include "clang/Basic/IdentifierTable.h" 17using namespace clang; 18 19//===----------------------------------------------------------------------===// 20// Decl Allocation/Deallocation Method Implementations 21//===----------------------------------------------------------------------===// 22 23TemplateTypeParmDecl * 24TemplateTypeParmDecl::Create(ASTContext &C, DeclContext *DC, 25 SourceLocation L, IdentifierInfo *Id, 26 bool Typename) { 27 void *Mem = C.getAllocator().Allocate<TemplateTypeParmDecl>(); 28 return new (Mem) TemplateTypeParmDecl(DC, L, Id, Typename); 29} 30 31NonTypeTemplateParmDecl * 32NonTypeTemplateParmDecl::Create(ASTContext &C, DeclContext *DC, 33 SourceLocation L, IdentifierInfo *Id, 34 QualType T, SourceLocation TypeSpecStartLoc) { 35 void *Mem = C.getAllocator().Allocate<NonTypeTemplateParmDecl>(); 36 return new (Mem) NonTypeTemplateParmDecl(DC, L, Id, T, TypeSpecStartLoc); 37} 38 39CXXRecordDecl::CXXRecordDecl(TagKind TK, DeclContext *DC, 40 SourceLocation L, IdentifierInfo *Id) 41 : RecordDecl(CXXRecord, TK, DC, L, Id), 42 UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false), 43 UserDeclaredDestructor(false), Aggregate(true), Polymorphic(false), 44 Bases(0), NumBases(0), 45 Conversions(DC, DeclarationName()) { } 46 47CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC, 48 SourceLocation L, IdentifierInfo *Id, 49 CXXRecordDecl* PrevDecl) { 50 void *Mem = C.getAllocator().Allocate<CXXRecordDecl>(); 51 CXXRecordDecl* R = new (Mem) CXXRecordDecl(TK, DC, L, Id); 52 C.getTypeDeclType(R, PrevDecl); 53 return R; 54} 55 56CXXRecordDecl::~CXXRecordDecl() { 57 delete [] Bases; 58} 59 60void 61CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, 62 unsigned NumBases) { 63 // C++ [dcl.init.aggr]p1: 64 // An aggregate is an array or a class (clause 9) with [...] 65 // no base classes [...]. 66 Aggregate = false; 67 68 if (this->Bases) 69 delete [] this->Bases; 70 71 this->Bases = new CXXBaseSpecifier[NumBases]; 72 this->NumBases = NumBases; 73 for (unsigned i = 0; i < NumBases; ++i) 74 this->Bases[i] = *Bases[i]; 75} 76 77bool CXXRecordDecl::hasConstCopyConstructor(ASTContext &Context) const { 78 QualType ClassType = Context.getTypeDeclType(const_cast<CXXRecordDecl*>(this)); 79 DeclarationName ConstructorName 80 = Context.DeclarationNames.getCXXConstructorName( 81 Context.getCanonicalType(ClassType)); 82 unsigned TypeQuals; 83 DeclContext::lookup_const_result Lookup 84 = this->lookup(Context, ConstructorName); 85 if (Lookup.first == Lookup.second) 86 return false; 87 else if (OverloadedFunctionDecl *Constructors 88 = dyn_cast<OverloadedFunctionDecl>(*Lookup.first)) { 89 for (OverloadedFunctionDecl::function_const_iterator Con 90 = Constructors->function_begin(); 91 Con != Constructors->function_end(); ++Con) { 92 if (cast<CXXConstructorDecl>(*Con)->isCopyConstructor(Context, TypeQuals) && 93 (TypeQuals & QualType::Const) != 0) 94 return true; 95 } 96 } else if (CXXConstructorDecl *Constructor 97 = dyn_cast<CXXConstructorDecl>(*Lookup.first)) { 98 return Constructor->isCopyConstructor(Context, TypeQuals) && 99 (TypeQuals & QualType::Const) != 0; 100 } 101 return false; 102} 103 104void 105CXXRecordDecl::addedConstructor(ASTContext &Context, 106 CXXConstructorDecl *ConDecl) { 107 if (!ConDecl->isImplicitlyDeclared()) { 108 // Note that we have a user-declared constructor. 109 UserDeclaredConstructor = true; 110 111 // C++ [dcl.init.aggr]p1: 112 // An aggregate is an array or a class (clause 9) with no 113 // user-declared constructors (12.1) [...]. 114 Aggregate = false; 115 116 // Note when we have a user-declared copy constructor, which will 117 // suppress the implicit declaration of a copy constructor. 118 if (ConDecl->isCopyConstructor(Context)) 119 UserDeclaredCopyConstructor = true; 120 } 121} 122 123void CXXRecordDecl::addConversionFunction(ASTContext &Context, 124 CXXConversionDecl *ConvDecl) { 125 Conversions.addOverload(ConvDecl); 126} 127 128CXXMethodDecl * 129CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD, 130 SourceLocation L, DeclarationName N, 131 QualType T, bool isStatic, bool isInline, 132 ScopedDecl *PrevDecl) { 133 void *Mem = C.getAllocator().Allocate<CXXMethodDecl>(); 134 return new (Mem) CXXMethodDecl(CXXMethod, RD, L, N, T, isStatic, isInline, 135 PrevDecl); 136} 137 138QualType CXXMethodDecl::getThisType(ASTContext &C) const { 139 // C++ 9.3.2p1: The type of this in a member function of a class X is X*. 140 // If the member function is declared const, the type of this is const X*, 141 // if the member function is declared volatile, the type of this is 142 // volatile X*, and if the member function is declared const volatile, 143 // the type of this is const volatile X*. 144 145 assert(isInstance() && "No 'this' for static methods!"); 146 QualType ClassTy = C.getTagDeclType(const_cast<CXXRecordDecl*>(getParent())); 147 ClassTy = ClassTy.getWithAdditionalQualifiers(getTypeQualifiers()); 148 return C.getPointerType(ClassTy).withConst(); 149} 150 151CXXBaseOrMemberInitializer:: 152CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs) 153 : Args(0), NumArgs(0) { 154 BaseOrMember = reinterpret_cast<uintptr_t>(BaseType.getTypePtr()); 155 assert((BaseOrMember & 0x01) == 0 && "Invalid base class type pointer"); 156 BaseOrMember |= 0x01; 157 158 if (NumArgs > 0) { 159 this->NumArgs = NumArgs; 160 this->Args = new Expr*[NumArgs]; 161 for (unsigned Idx = 0; Idx < NumArgs; ++Idx) 162 this->Args[Idx] = Args[Idx]; 163 } 164} 165 166CXXBaseOrMemberInitializer:: 167CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs) 168 : Args(0), NumArgs(0) { 169 BaseOrMember = reinterpret_cast<uintptr_t>(Member); 170 assert((BaseOrMember & 0x01) == 0 && "Invalid member pointer"); 171 172 if (NumArgs > 0) { 173 this->NumArgs = NumArgs; 174 this->Args = new Expr*[NumArgs]; 175 for (unsigned Idx = 0; Idx < NumArgs; ++Idx) 176 this->Args[Idx] = Args[Idx]; 177 } 178} 179 180CXXBaseOrMemberInitializer::~CXXBaseOrMemberInitializer() { 181 delete [] Args; 182} 183 184CXXConstructorDecl * 185CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD, 186 SourceLocation L, DeclarationName N, 187 QualType T, bool isExplicit, 188 bool isInline, bool isImplicitlyDeclared) { 189 assert(N.getNameKind() == DeclarationName::CXXConstructorName && 190 "Name must refer to a constructor"); 191 void *Mem = C.getAllocator().Allocate<CXXConstructorDecl>(); 192 return new (Mem) CXXConstructorDecl(RD, L, N, T, isExplicit, isInline, 193 isImplicitlyDeclared); 194} 195 196bool CXXConstructorDecl::isDefaultConstructor() const { 197 // C++ [class.ctor]p5: 198 // A default constructor for a class X is a constructor of class 199 // X that can be called without an argument. 200 return (getNumParams() == 0) || 201 (getNumParams() > 0 && getParamDecl(0)->getDefaultArg() != 0); 202} 203 204bool 205CXXConstructorDecl::isCopyConstructor(ASTContext &Context, 206 unsigned &TypeQuals) const { 207 // C++ [class.copy]p2: 208 // A non-template constructor for class X is a copy constructor 209 // if its first parameter is of type X&, const X&, volatile X& or 210 // const volatile X&, and either there are no other parameters 211 // or else all other parameters have default arguments (8.3.6). 212 if ((getNumParams() < 1) || 213 (getNumParams() > 1 && getParamDecl(1)->getDefaultArg() == 0)) 214 return false; 215 216 const ParmVarDecl *Param = getParamDecl(0); 217 218 // Do we have a reference type? 219 const ReferenceType *ParamRefType = Param->getType()->getAsReferenceType(); 220 if (!ParamRefType) 221 return false; 222 223 // Is it a reference to our class type? 224 QualType PointeeType 225 = Context.getCanonicalType(ParamRefType->getPointeeType()); 226 QualType ClassTy 227 = Context.getTagDeclType(const_cast<CXXRecordDecl*>(getParent())); 228 if (PointeeType.getUnqualifiedType() != ClassTy) 229 return false; 230 231 // We have a copy constructor. 232 TypeQuals = PointeeType.getCVRQualifiers(); 233 return true; 234} 235 236bool CXXConstructorDecl::isConvertingConstructor() const { 237 // C++ [class.conv.ctor]p1: 238 // A constructor declared without the function-specifier explicit 239 // that can be called with a single parameter specifies a 240 // conversion from the type of its first parameter to the type of 241 // its class. Such a constructor is called a converting 242 // constructor. 243 if (isExplicit()) 244 return false; 245 246 return (getNumParams() == 0 && 247 getType()->getAsFunctionTypeProto()->isVariadic()) || 248 (getNumParams() == 1) || 249 (getNumParams() > 1 && getParamDecl(1)->getDefaultArg() != 0); 250} 251 252CXXDestructorDecl * 253CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD, 254 SourceLocation L, DeclarationName N, 255 QualType T, bool isInline, 256 bool isImplicitlyDeclared) { 257 assert(N.getNameKind() == DeclarationName::CXXDestructorName && 258 "Name must refer to a destructor"); 259 void *Mem = C.getAllocator().Allocate<CXXDestructorDecl>(); 260 return new (Mem) CXXDestructorDecl(RD, L, N, T, isInline, 261 isImplicitlyDeclared); 262} 263 264CXXConversionDecl * 265CXXConversionDecl::Create(ASTContext &C, CXXRecordDecl *RD, 266 SourceLocation L, DeclarationName N, 267 QualType T, bool isInline, bool isExplicit) { 268 assert(N.getNameKind() == DeclarationName::CXXConversionFunctionName && 269 "Name must refer to a conversion function"); 270 void *Mem = C.getAllocator().Allocate<CXXConversionDecl>(); 271 return new (Mem) CXXConversionDecl(RD, L, N, T, isInline, isExplicit); 272} 273 274CXXClassVarDecl *CXXClassVarDecl::Create(ASTContext &C, CXXRecordDecl *RD, 275 SourceLocation L, IdentifierInfo *Id, 276 QualType T, ScopedDecl *PrevDecl) { 277 void *Mem = C.getAllocator().Allocate<CXXClassVarDecl>(); 278 return new (Mem) CXXClassVarDecl(RD, L, Id, T, PrevDecl); 279} 280 281OverloadedFunctionDecl * 282OverloadedFunctionDecl::Create(ASTContext &C, DeclContext *DC, 283 DeclarationName N) { 284 void *Mem = C.getAllocator().Allocate<OverloadedFunctionDecl>(); 285 return new (Mem) OverloadedFunctionDecl(DC, N); 286} 287 288LinkageSpecDecl::LinkageSpecDecl(SourceLocation L, LanguageIDs lang, 289 Decl **InDecls, unsigned InNumDecls) 290 : Decl(LinkageSpec, L), Language(lang), HadBraces(true), 291 Decls(0), NumDecls(InNumDecls) { 292 Decl **NewDecls = new Decl*[NumDecls]; 293 for (unsigned I = 0; I < NumDecls; ++I) 294 NewDecls[I] = InDecls[I]; 295 Decls = NewDecls; 296} 297 298LinkageSpecDecl::~LinkageSpecDecl() { 299 if (HadBraces) 300 delete [] (Decl**)Decls; 301} 302 303LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C, 304 SourceLocation L, 305 LanguageIDs Lang, Decl *D) { 306 void *Mem = C.getAllocator().Allocate<LinkageSpecDecl>(); 307 return new (Mem) LinkageSpecDecl(L, Lang, D); 308} 309 310LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C, 311 SourceLocation L, 312 LanguageIDs Lang, 313 Decl **Decls, unsigned NumDecls) { 314 void *Mem = C.getAllocator().Allocate<LinkageSpecDecl>(); 315 return new (Mem) LinkageSpecDecl(L, Lang, Decls, NumDecls); 316} 317 318LinkageSpecDecl::decl_const_iterator LinkageSpecDecl::decls_begin() const { 319 if (hasBraces()) return (Decl**)Decls; 320 else return (Decl**)&Decls; 321} 322 323LinkageSpecDecl::decl_iterator LinkageSpecDecl::decls_end() const { 324 if (hasBraces()) return (Decl**)Decls + NumDecls; 325 else return (Decl**)&Decls + 1; 326} 327