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