DeclCXX.cpp revision c0ac4923f08b25ae973a8ee7942cf3eb89da57b7
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" 17#include "llvm/ADT/STLExtras.h" 18using namespace clang; 19 20//===----------------------------------------------------------------------===// 21// Decl Allocation/Deallocation Method Implementations 22//===----------------------------------------------------------------------===// 23 24TemplateTypeParmDecl * 25TemplateTypeParmDecl::Create(ASTContext &C, DeclContext *DC, 26 SourceLocation L, IdentifierInfo *Id, 27 bool Typename) { 28 return new (C) 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 return new (C) NonTypeTemplateParmDecl(DC, L, Id, T, TypeSpecStartLoc); 36} 37 38TemplateParameterList::TemplateParameterList(Decl **Params, unsigned NumParams) 39 : NumParams(NumParams) { 40 for (unsigned Idx = 0; Idx < NumParams; ++Idx) 41 begin()[Idx] = Params[Idx]; 42} 43 44TemplateParameterList * 45TemplateParameterList::Create(ASTContext &C, Decl **Params, 46 unsigned NumParams) { 47 // FIXME: how do I pass in Size to ASTContext::new? 48 unsigned Size = sizeof(TemplateParameterList) + sizeof(Decl *) * NumParams; 49 unsigned Align = llvm::AlignOf<TemplateParameterList>::Alignment; 50 void *Mem = C.Allocate(Size, Align); 51 return new (Mem) TemplateParameterList(Params, NumParams); 52} 53 54CXXRecordDecl::CXXRecordDecl(TagKind TK, DeclContext *DC, 55 SourceLocation L, IdentifierInfo *Id) 56 : RecordDecl(CXXRecord, TK, DC, L, Id), 57 UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false), 58 UserDeclaredCopyAssignment(false), UserDeclaredDestructor(false), 59 Aggregate(true), PlainOldData(true), Polymorphic(false), Bases(0), 60 NumBases(0), Conversions(DC, DeclarationName()) { } 61 62CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC, 63 SourceLocation L, IdentifierInfo *Id, 64 CXXRecordDecl* PrevDecl) { 65 CXXRecordDecl* R = new (C) CXXRecordDecl(TK, DC, L, Id); 66 C.getTypeDeclType(R, PrevDecl); 67 return R; 68} 69 70CXXRecordDecl::~CXXRecordDecl() { 71 delete [] Bases; 72} 73 74void 75CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, 76 unsigned NumBases) { 77 // C++ [dcl.init.aggr]p1: 78 // An aggregate is an array or a class (clause 9) with [...] 79 // no base classes [...]. 80 Aggregate = false; 81 82 if (this->Bases) 83 delete [] this->Bases; 84 85 this->Bases = new CXXBaseSpecifier[NumBases]; 86 this->NumBases = NumBases; 87 for (unsigned i = 0; i < NumBases; ++i) 88 this->Bases[i] = *Bases[i]; 89} 90 91bool CXXRecordDecl::hasConstCopyConstructor(ASTContext &Context) const { 92 QualType ClassType 93 = Context.getTypeDeclType(const_cast<CXXRecordDecl*>(this)); 94 DeclarationName ConstructorName 95 = Context.DeclarationNames.getCXXConstructorName( 96 Context.getCanonicalType(ClassType)); 97 unsigned TypeQuals; 98 DeclContext::lookup_const_iterator Con, ConEnd; 99 for (llvm::tie(Con, ConEnd) = this->lookup(ConstructorName); 100 Con != ConEnd; ++Con) { 101 if (cast<CXXConstructorDecl>(*Con)->isCopyConstructor(Context, TypeQuals) && 102 (TypeQuals & QualType::Const) != 0) 103 return true; 104 } 105 106 return false; 107} 108 109bool CXXRecordDecl::hasConstCopyAssignment(ASTContext &Context) const { 110 QualType ClassType = Context.getCanonicalType(Context.getTypeDeclType( 111 const_cast<CXXRecordDecl*>(this))); 112 DeclarationName OpName =Context.DeclarationNames.getCXXOperatorName(OO_Equal); 113 114 DeclContext::lookup_const_iterator Op, OpEnd; 115 for (llvm::tie(Op, OpEnd) = this->lookup(OpName); 116 Op != OpEnd; ++Op) { 117 // C++ [class.copy]p9: 118 // A user-declared copy assignment operator is a non-static non-template 119 // member function of class X with exactly one parameter of type X, X&, 120 // const X&, volatile X& or const volatile X&. 121 const CXXMethodDecl* Method = cast<CXXMethodDecl>(*Op); 122 if (Method->isStatic()) 123 continue; 124 // TODO: Skip templates? Or is this implicitly done due to parameter types? 125 const FunctionTypeProto *FnType = 126 Method->getType()->getAsFunctionTypeProto(); 127 assert(FnType && "Overloaded operator has no prototype."); 128 // Don't assert on this; an invalid decl might have been left in the AST. 129 if (FnType->getNumArgs() != 1 || FnType->isVariadic()) 130 continue; 131 bool AcceptsConst = true; 132 QualType ArgType = FnType->getArgType(0); 133 if (const ReferenceType *Ref = ArgType->getAsReferenceType()) { 134 ArgType = Ref->getPointeeType(); 135 // Is it a non-const reference? 136 if (!ArgType.isConstQualified()) 137 AcceptsConst = false; 138 } 139 if (Context.getCanonicalType(ArgType).getUnqualifiedType() != ClassType) 140 continue; 141 142 // We have a single argument of type cv X or cv X&, i.e. we've found the 143 // copy assignment operator. Return whether it accepts const arguments. 144 return AcceptsConst; 145 } 146 assert(isInvalidDecl() && 147 "No copy assignment operator declared in valid code."); 148 return false; 149} 150 151void 152CXXRecordDecl::addedConstructor(ASTContext &Context, 153 CXXConstructorDecl *ConDecl) { 154 if (!ConDecl->isImplicit()) { 155 // Note that we have a user-declared constructor. 156 UserDeclaredConstructor = true; 157 158 // C++ [dcl.init.aggr]p1: 159 // An aggregate is an array or a class (clause 9) with no 160 // user-declared constructors (12.1) [...]. 161 Aggregate = false; 162 163 // C++ [class]p4: 164 // A POD-struct is an aggregate class [...] 165 PlainOldData = false; 166 167 // Note when we have a user-declared copy constructor, which will 168 // suppress the implicit declaration of a copy constructor. 169 if (ConDecl->isCopyConstructor(Context)) 170 UserDeclaredCopyConstructor = true; 171 } 172} 173 174void CXXRecordDecl::addedAssignmentOperator(ASTContext &Context, 175 CXXMethodDecl *OpDecl) { 176 // We're interested specifically in copy assignment operators. 177 // Unlike addedConstructor, this method is not called for implicit 178 // declarations. 179 const FunctionTypeProto *FnType = OpDecl->getType()->getAsFunctionTypeProto(); 180 assert(FnType && "Overloaded operator has no proto function type."); 181 assert(FnType->getNumArgs() == 1 && !FnType->isVariadic()); 182 QualType ArgType = FnType->getArgType(0); 183 if (const ReferenceType *Ref = ArgType->getAsReferenceType()) 184 ArgType = Ref->getPointeeType(); 185 186 ArgType = ArgType.getUnqualifiedType(); 187 QualType ClassType = Context.getCanonicalType(Context.getTypeDeclType( 188 const_cast<CXXRecordDecl*>(this))); 189 190 if (ClassType != Context.getCanonicalType(ArgType)) 191 return; 192 193 // This is a copy assignment operator. 194 // Suppress the implicit declaration of a copy constructor. 195 UserDeclaredCopyAssignment = true; 196 197 // C++ [class]p4: 198 // A POD-struct is an aggregate class that [...] has no user-defined copy 199 // assignment operator [...]. 200 PlainOldData = false; 201} 202 203void CXXRecordDecl::addConversionFunction(ASTContext &Context, 204 CXXConversionDecl *ConvDecl) { 205 Conversions.addOverload(ConvDecl); 206} 207 208CXXMethodDecl * 209CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD, 210 SourceLocation L, DeclarationName N, 211 QualType T, bool isStatic, bool isInline) { 212 return new (C) CXXMethodDecl(CXXMethod, RD, L, N, T, isStatic, isInline); 213} 214 215QualType CXXMethodDecl::getThisType(ASTContext &C) const { 216 // C++ 9.3.2p1: The type of this in a member function of a class X is X*. 217 // If the member function is declared const, the type of this is const X*, 218 // if the member function is declared volatile, the type of this is 219 // volatile X*, and if the member function is declared const volatile, 220 // the type of this is const volatile X*. 221 222 assert(isInstance() && "No 'this' for static methods!"); 223 QualType ClassTy = C.getTagDeclType(const_cast<CXXRecordDecl*>(getParent())); 224 ClassTy = ClassTy.getWithAdditionalQualifiers(getTypeQualifiers()); 225 return C.getPointerType(ClassTy).withConst(); 226} 227 228CXXBaseOrMemberInitializer:: 229CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs) 230 : Args(0), NumArgs(0) { 231 BaseOrMember = reinterpret_cast<uintptr_t>(BaseType.getTypePtr()); 232 assert((BaseOrMember & 0x01) == 0 && "Invalid base class type pointer"); 233 BaseOrMember |= 0x01; 234 235 if (NumArgs > 0) { 236 this->NumArgs = NumArgs; 237 this->Args = new Expr*[NumArgs]; 238 for (unsigned Idx = 0; Idx < NumArgs; ++Idx) 239 this->Args[Idx] = Args[Idx]; 240 } 241} 242 243CXXBaseOrMemberInitializer:: 244CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs) 245 : Args(0), NumArgs(0) { 246 BaseOrMember = reinterpret_cast<uintptr_t>(Member); 247 assert((BaseOrMember & 0x01) == 0 && "Invalid member pointer"); 248 249 if (NumArgs > 0) { 250 this->NumArgs = NumArgs; 251 this->Args = new Expr*[NumArgs]; 252 for (unsigned Idx = 0; Idx < NumArgs; ++Idx) 253 this->Args[Idx] = Args[Idx]; 254 } 255} 256 257CXXBaseOrMemberInitializer::~CXXBaseOrMemberInitializer() { 258 delete [] Args; 259} 260 261CXXConstructorDecl * 262CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD, 263 SourceLocation L, DeclarationName N, 264 QualType T, bool isExplicit, 265 bool isInline, bool isImplicitlyDeclared) { 266 assert(N.getNameKind() == DeclarationName::CXXConstructorName && 267 "Name must refer to a constructor"); 268 return new (C) CXXConstructorDecl(RD, L, N, T, isExplicit, isInline, 269 isImplicitlyDeclared); 270} 271 272bool CXXConstructorDecl::isDefaultConstructor() const { 273 // C++ [class.ctor]p5: 274 // A default constructor for a class X is a constructor of class 275 // X that can be called without an argument. 276 return (getNumParams() == 0) || 277 (getNumParams() > 0 && getParamDecl(0)->getDefaultArg() != 0); 278} 279 280bool 281CXXConstructorDecl::isCopyConstructor(ASTContext &Context, 282 unsigned &TypeQuals) const { 283 // C++ [class.copy]p2: 284 // A non-template constructor for class X is a copy constructor 285 // if its first parameter is of type X&, const X&, volatile X& or 286 // const volatile X&, and either there are no other parameters 287 // or else all other parameters have default arguments (8.3.6). 288 if ((getNumParams() < 1) || 289 (getNumParams() > 1 && getParamDecl(1)->getDefaultArg() == 0)) 290 return false; 291 292 const ParmVarDecl *Param = getParamDecl(0); 293 294 // Do we have a reference type? 295 const ReferenceType *ParamRefType = Param->getType()->getAsReferenceType(); 296 if (!ParamRefType) 297 return false; 298 299 // Is it a reference to our class type? 300 QualType PointeeType 301 = Context.getCanonicalType(ParamRefType->getPointeeType()); 302 QualType ClassTy 303 = Context.getTagDeclType(const_cast<CXXRecordDecl*>(getParent())); 304 if (PointeeType.getUnqualifiedType() != ClassTy) 305 return false; 306 307 // We have a copy constructor. 308 TypeQuals = PointeeType.getCVRQualifiers(); 309 return true; 310} 311 312bool CXXConstructorDecl::isConvertingConstructor() const { 313 // C++ [class.conv.ctor]p1: 314 // A constructor declared without the function-specifier explicit 315 // that can be called with a single parameter specifies a 316 // conversion from the type of its first parameter to the type of 317 // its class. Such a constructor is called a converting 318 // constructor. 319 if (isExplicit()) 320 return false; 321 322 return (getNumParams() == 0 && 323 getType()->getAsFunctionTypeProto()->isVariadic()) || 324 (getNumParams() == 1) || 325 (getNumParams() > 1 && getParamDecl(1)->getDefaultArg() != 0); 326} 327 328CXXDestructorDecl * 329CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD, 330 SourceLocation L, DeclarationName N, 331 QualType T, bool isInline, 332 bool isImplicitlyDeclared) { 333 assert(N.getNameKind() == DeclarationName::CXXDestructorName && 334 "Name must refer to a destructor"); 335 return new (C) CXXDestructorDecl(RD, L, N, T, isInline, 336 isImplicitlyDeclared); 337} 338 339CXXConversionDecl * 340CXXConversionDecl::Create(ASTContext &C, CXXRecordDecl *RD, 341 SourceLocation L, DeclarationName N, 342 QualType T, bool isInline, bool isExplicit) { 343 assert(N.getNameKind() == DeclarationName::CXXConversionFunctionName && 344 "Name must refer to a conversion function"); 345 return new (C) CXXConversionDecl(RD, L, N, T, isInline, isExplicit); 346} 347 348CXXClassVarDecl *CXXClassVarDecl::Create(ASTContext &C, CXXRecordDecl *RD, 349 SourceLocation L, IdentifierInfo *Id, 350 QualType T) { 351 return new (C) CXXClassVarDecl(RD, L, Id, T); 352} 353 354OverloadedFunctionDecl * 355OverloadedFunctionDecl::Create(ASTContext &C, DeclContext *DC, 356 DeclarationName N) { 357 return new (C) OverloadedFunctionDecl(DC, N); 358} 359 360LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C, 361 DeclContext *DC, 362 SourceLocation L, 363 LanguageIDs Lang, bool Braces) { 364 return new (C) LinkageSpecDecl(DC, L, Lang, Braces); 365} 366