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