1193326Sed//===--- DeclCXX.cpp - C++ Declaration AST Node Implementation ------------===// 2193326Sed// 3193326Sed// The LLVM Compiler Infrastructure 4193326Sed// 5193326Sed// This file is distributed under the University of Illinois Open Source 6193326Sed// License. See LICENSE.TXT for details. 7193326Sed// 8193326Sed//===----------------------------------------------------------------------===// 9193326Sed// 10193326Sed// This file implements the C++ related Decl classes. 11193326Sed// 12193326Sed//===----------------------------------------------------------------------===// 13193326Sed#include "clang/AST/DeclCXX.h" 14193326Sed#include "clang/AST/ASTContext.h" 15263508Sdim#include "clang/AST/ASTLambda.h" 16218893Sdim#include "clang/AST/ASTMutationListener.h" 17218893Sdim#include "clang/AST/CXXInheritance.h" 18249423Sdim#include "clang/AST/DeclTemplate.h" 19193326Sed#include "clang/AST/Expr.h" 20234353Sdim#include "clang/AST/ExprCXX.h" 21200583Srdivacky#include "clang/AST/TypeLoc.h" 22193326Sed#include "clang/Basic/IdentifierTable.h" 23193326Sed#include "llvm/ADT/STLExtras.h" 24198092Srdivacky#include "llvm/ADT/SmallPtrSet.h" 25193326Sedusing namespace clang; 26193326Sed 27193326Sed//===----------------------------------------------------------------------===// 28193326Sed// Decl Allocation/Deallocation Method Implementations 29193326Sed//===----------------------------------------------------------------------===// 30193326Sed 31234353Sdimvoid AccessSpecDecl::anchor() { } 32234353Sdim 33234353SdimAccessSpecDecl *AccessSpecDecl::CreateDeserialized(ASTContext &C, unsigned ID) { 34234353Sdim void *Mem = AllocateDeserializedDecl(C, ID, sizeof(AccessSpecDecl)); 35234353Sdim return new (Mem) AccessSpecDecl(EmptyShell()); 36234353Sdim} 37234353Sdim 38263508Sdimvoid LazyASTUnresolvedSet::getFromExternalSource(ASTContext &C) const { 39263508Sdim ExternalASTSource *Source = C.getExternalSource(); 40263508Sdim assert(Impl.Decls.isLazy() && "getFromExternalSource for non-lazy set"); 41263508Sdim assert(Source && "getFromExternalSource with no external source"); 42263508Sdim 43263508Sdim for (ASTUnresolvedSet::iterator I = Impl.begin(); I != Impl.end(); ++I) 44263508Sdim I.setDecl(cast<NamedDecl>(Source->GetExternalDecl( 45263508Sdim reinterpret_cast<uintptr_t>(I.getDecl()) >> 2))); 46263508Sdim Impl.Decls.setLazy(false); 47263508Sdim} 48263508Sdim 49203955SrdivackyCXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D) 50249423Sdim : UserDeclaredConstructor(false), UserDeclaredSpecialMembers(0), 51198092Srdivacky Aggregate(true), PlainOldData(true), Empty(true), Polymorphic(false), 52221345Sdim Abstract(false), IsStandardLayout(true), HasNoNonEmptyBases(true), 53221345Sdim HasPrivateFields(false), HasProtectedFields(false), HasPublicFields(false), 54234353Sdim HasMutableFields(false), HasOnlyCMembers(true), 55249423Sdim HasInClassInitializer(false), HasUninitializedReferenceMember(false), 56249423Sdim NeedOverloadResolutionForMoveConstructor(false), 57249423Sdim NeedOverloadResolutionForMoveAssignment(false), 58249423Sdim NeedOverloadResolutionForDestructor(false), 59249423Sdim DefaultedMoveConstructorIsDeleted(false), 60249423Sdim DefaultedMoveAssignmentIsDeleted(false), 61249423Sdim DefaultedDestructorIsDeleted(false), 62249423Sdim HasTrivialSpecialMembers(SMF_All), 63249423Sdim DeclaredNonTrivialSpecialMembers(0), 64249423Sdim HasIrrelevantDestructor(true), 65234353Sdim HasConstexprNonCopyMoveConstructor(false), 66234353Sdim DefaultedDefaultConstructorIsConstexpr(true), 67249423Sdim HasConstexprDefaultConstructor(false), 68223017Sdim HasNonLiteralTypeFieldsOrBases(false), ComputedVisibleConversions(false), 69249423Sdim UserProvidedDefaultConstructor(false), DeclaredSpecialMembers(0), 70249423Sdim ImplicitCopyConstructorHasConstParam(true), 71249423Sdim ImplicitCopyAssignmentHasConstParam(true), 72249423Sdim HasDeclaredCopyConstructorWithConstParam(false), 73249423Sdim HasDeclaredCopyAssignmentWithConstParam(false), 74249423Sdim IsLambda(false), NumBases(0), NumVBases(0), Bases(), VBases(), 75263508Sdim Definition(D), FirstFriend() { 76203955Srdivacky} 77203955Srdivacky 78239462SdimCXXBaseSpecifier *CXXRecordDecl::DefinitionData::getBasesSlowCase() const { 79239462Sdim return Bases.get(Definition->getASTContext().getExternalSource()); 80239462Sdim} 81239462Sdim 82239462SdimCXXBaseSpecifier *CXXRecordDecl::DefinitionData::getVBasesSlowCase() const { 83239462Sdim return VBases.get(Definition->getASTContext().getExternalSource()); 84239462Sdim} 85239462Sdim 86203955SrdivackyCXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC, 87221345Sdim SourceLocation StartLoc, SourceLocation IdLoc, 88221345Sdim IdentifierInfo *Id, CXXRecordDecl *PrevDecl) 89221345Sdim : RecordDecl(K, TK, DC, StartLoc, IdLoc, Id, PrevDecl), 90203955Srdivacky DefinitionData(PrevDecl ? PrevDecl->DefinitionData : 0), 91193326Sed TemplateOrInstantiation() { } 92193326Sed 93218893SdimCXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK, 94221345Sdim DeclContext *DC, SourceLocation StartLoc, 95221345Sdim SourceLocation IdLoc, IdentifierInfo *Id, 96193326Sed CXXRecordDecl* PrevDecl, 97193326Sed bool DelayTypeCreation) { 98221345Sdim CXXRecordDecl* R = new (C) CXXRecordDecl(CXXRecord, TK, DC, StartLoc, IdLoc, 99221345Sdim Id, PrevDecl); 100249423Sdim R->MayHaveOutOfDateDef = C.getLangOpts().Modules; 101198092Srdivacky 102198092Srdivacky // FIXME: DelayTypeCreation seems like such a hack 103193326Sed if (!DelayTypeCreation) 104198092Srdivacky C.getTypeDeclType(R, PrevDecl); 105193326Sed return R; 106193326Sed} 107193326Sed 108234353SdimCXXRecordDecl *CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC, 109243830Sdim TypeSourceInfo *Info, SourceLocation Loc, 110263508Sdim bool Dependent, bool IsGeneric, 111263508Sdim LambdaCaptureDefault CaptureDefault) { 112234353Sdim CXXRecordDecl* R = new (C) CXXRecordDecl(CXXRecord, TTK_Class, DC, Loc, Loc, 113234353Sdim 0, 0); 114234353Sdim R->IsBeingDefined = true; 115263508Sdim R->DefinitionData = new (C) struct LambdaDefinitionData(R, Info, 116263508Sdim Dependent, 117263508Sdim IsGeneric, 118263508Sdim CaptureDefault); 119249423Sdim R->MayHaveOutOfDateDef = false; 120263508Sdim R->setImplicit(true); 121234353Sdim C.getTypeDeclType(R, /*PrevDecl=*/0); 122234353Sdim return R; 123210299Sed} 124210299Sed 125234353SdimCXXRecordDecl * 126234353SdimCXXRecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) { 127234353Sdim void *Mem = AllocateDeserializedDecl(C, ID, sizeof(CXXRecordDecl)); 128249423Sdim CXXRecordDecl *R = new (Mem) CXXRecordDecl(CXXRecord, TTK_Struct, 0, 129249423Sdim SourceLocation(), SourceLocation(), 130249423Sdim 0, 0); 131249423Sdim R->MayHaveOutOfDateDef = false; 132249423Sdim return R; 133234353Sdim} 134234353Sdim 135198092Srdivackyvoid 136203955SrdivackyCXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, 137193326Sed unsigned NumBases) { 138203955Srdivacky ASTContext &C = getASTContext(); 139193326Sed 140218893Sdim if (!data().Bases.isOffset() && data().NumBases > 0) 141218893Sdim C.Deallocate(data().getBases()); 142193326Sed 143234353Sdim if (NumBases) { 144234353Sdim // C++ [dcl.init.aggr]p1: 145234353Sdim // An aggregate is [...] a class with [...] no base classes [...]. 146234353Sdim data().Aggregate = false; 147234353Sdim 148234353Sdim // C++ [class]p4: 149234353Sdim // A POD-struct is an aggregate class... 150234353Sdim data().PlainOldData = false; 151234353Sdim } 152234353Sdim 153206084Srdivacky // The set of seen virtual base types. 154206084Srdivacky llvm::SmallPtrSet<CanQualType, 8> SeenVBaseTypes; 155206084Srdivacky 156206084Srdivacky // The virtual bases of this class. 157226633Sdim SmallVector<const CXXBaseSpecifier *, 8> VBases; 158198092Srdivacky 159203955Srdivacky data().Bases = new(C) CXXBaseSpecifier [NumBases]; 160203955Srdivacky data().NumBases = NumBases; 161198092Srdivacky for (unsigned i = 0; i < NumBases; ++i) { 162218893Sdim data().getBases()[i] = *Bases[i]; 163198092Srdivacky // Keep track of inherited vbases for this base class. 164198092Srdivacky const CXXBaseSpecifier *Base = Bases[i]; 165198092Srdivacky QualType BaseType = Base->getType(); 166204643Srdivacky // Skip dependent types; we can't do any checking on them now. 167198092Srdivacky if (BaseType->isDependentType()) 168198092Srdivacky continue; 169198092Srdivacky CXXRecordDecl *BaseClassDecl 170198092Srdivacky = cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl()); 171206084Srdivacky 172218893Sdim // A class with a non-empty base class is not empty. 173218893Sdim // FIXME: Standard ref? 174221345Sdim if (!BaseClassDecl->isEmpty()) { 175221345Sdim if (!data().Empty) { 176221345Sdim // C++0x [class]p7: 177221345Sdim // A standard-layout class is a class that: 178221345Sdim // [...] 179221345Sdim // -- either has no non-static data members in the most derived 180221345Sdim // class and at most one base class with non-static data members, 181221345Sdim // or has no base classes with non-static data members, and 182221345Sdim // If this is the second non-empty base, then neither of these two 183221345Sdim // clauses can be true. 184221345Sdim data().IsStandardLayout = false; 185221345Sdim } 186221345Sdim 187218893Sdim data().Empty = false; 188221345Sdim data().HasNoNonEmptyBases = false; 189221345Sdim } 190218893Sdim 191218893Sdim // C++ [class.virtual]p1: 192218893Sdim // A class that declares or inherits a virtual function is called a 193218893Sdim // polymorphic class. 194218893Sdim if (BaseClassDecl->isPolymorphic()) 195218893Sdim data().Polymorphic = true; 196221345Sdim 197221345Sdim // C++0x [class]p7: 198221345Sdim // A standard-layout class is a class that: [...] 199221345Sdim // -- has no non-standard-layout base classes 200221345Sdim if (!BaseClassDecl->isStandardLayout()) 201221345Sdim data().IsStandardLayout = false; 202221345Sdim 203221345Sdim // Record if this base is the first non-literal field or base. 204251662Sdim if (!hasNonLiteralTypeFieldsOrBases() && !BaseType->isLiteralType(C)) 205221345Sdim data().HasNonLiteralTypeFieldsOrBases = true; 206218893Sdim 207206084Srdivacky // Now go through all virtual bases of this base and add them. 208198092Srdivacky for (CXXRecordDecl::base_class_iterator VBase = 209198092Srdivacky BaseClassDecl->vbases_begin(), 210198092Srdivacky E = BaseClassDecl->vbases_end(); VBase != E; ++VBase) { 211206084Srdivacky // Add this base if it's not already in the list. 212249423Sdim if (SeenVBaseTypes.insert(C.getCanonicalType(VBase->getType()))) { 213206084Srdivacky VBases.push_back(VBase); 214249423Sdim 215249423Sdim // C++11 [class.copy]p8: 216249423Sdim // The implicitly-declared copy constructor for a class X will have 217249423Sdim // the form 'X::X(const X&)' if each [...] virtual base class B of X 218249423Sdim // has a copy constructor whose first parameter is of type 219249423Sdim // 'const B&' or 'const volatile B&' [...] 220249423Sdim if (CXXRecordDecl *VBaseDecl = VBase->getType()->getAsCXXRecordDecl()) 221249423Sdim if (!VBaseDecl->hasCopyConstructorWithConstParam()) 222249423Sdim data().ImplicitCopyConstructorHasConstParam = false; 223249423Sdim } 224198092Srdivacky } 225206084Srdivacky 226206084Srdivacky if (Base->isVirtual()) { 227206084Srdivacky // Add this base if it's not already in the list. 228206084Srdivacky if (SeenVBaseTypes.insert(C.getCanonicalType(BaseType))) 229249423Sdim VBases.push_back(Base); 230249423Sdim 231218893Sdim // C++0x [meta.unary.prop] is_empty: 232218893Sdim // T is a class type, but not a union type, with ... no virtual base 233218893Sdim // classes 234218893Sdim data().Empty = false; 235221345Sdim 236249423Sdim // C++11 [class.ctor]p5, C++11 [class.copy]p12, C++11 [class.copy]p25: 237249423Sdim // A [default constructor, copy/move constructor, or copy/move assignment 238249423Sdim // operator for a class X] is trivial [...] if: 239249423Sdim // -- class X has [...] no virtual base classes 240249423Sdim data().HasTrivialSpecialMembers &= SMF_Destructor; 241221345Sdim 242221345Sdim // C++0x [class]p7: 243221345Sdim // A standard-layout class is a class that: [...] 244221345Sdim // -- has [...] no virtual base classes 245221345Sdim data().IsStandardLayout = false; 246234353Sdim 247234353Sdim // C++11 [dcl.constexpr]p4: 248234353Sdim // In the definition of a constexpr constructor [...] 249234353Sdim // -- the class shall not have any virtual base classes 250234353Sdim data().DefaultedDefaultConstructorIsConstexpr = false; 251218893Sdim } else { 252218893Sdim // C++ [class.ctor]p5: 253223017Sdim // A default constructor is trivial [...] if: 254223017Sdim // -- all the direct base classes of its class have trivial default 255223017Sdim // constructors. 256223017Sdim if (!BaseClassDecl->hasTrivialDefaultConstructor()) 257249423Sdim data().HasTrivialSpecialMembers &= ~SMF_DefaultConstructor; 258249423Sdim 259221345Sdim // C++0x [class.copy]p13: 260221345Sdim // A copy/move constructor for class X is trivial if [...] 261221345Sdim // [...] 262221345Sdim // -- the constructor selected to copy/move each direct base class 263221345Sdim // subobject is trivial, and 264218893Sdim if (!BaseClassDecl->hasTrivialCopyConstructor()) 265249423Sdim data().HasTrivialSpecialMembers &= ~SMF_CopyConstructor; 266249423Sdim // If the base class doesn't have a simple move constructor, we'll eagerly 267249423Sdim // declare it and perform overload resolution to determine which function 268249423Sdim // it actually calls. If it does have a simple move constructor, this 269249423Sdim // check is correct. 270249423Sdim if (!BaseClassDecl->hasTrivialMoveConstructor()) 271249423Sdim data().HasTrivialSpecialMembers &= ~SMF_MoveConstructor; 272221345Sdim 273221345Sdim // C++0x [class.copy]p27: 274221345Sdim // A copy/move assignment operator for class X is trivial if [...] 275221345Sdim // [...] 276221345Sdim // -- the assignment operator selected to copy/move each direct base 277221345Sdim // class subobject is trivial, and 278218893Sdim if (!BaseClassDecl->hasTrivialCopyAssignment()) 279249423Sdim data().HasTrivialSpecialMembers &= ~SMF_CopyAssignment; 280249423Sdim // If the base class doesn't have a simple move assignment, we'll eagerly 281249423Sdim // declare it and perform overload resolution to determine which function 282249423Sdim // it actually calls. If it does have a simple move assignment, this 283249423Sdim // check is correct. 284249423Sdim if (!BaseClassDecl->hasTrivialMoveAssignment()) 285249423Sdim data().HasTrivialSpecialMembers &= ~SMF_MoveAssignment; 286234353Sdim 287234353Sdim // C++11 [class.ctor]p6: 288234353Sdim // If that user-written default constructor would satisfy the 289234353Sdim // requirements of a constexpr constructor, the implicitly-defined 290234353Sdim // default constructor is constexpr. 291234353Sdim if (!BaseClassDecl->hasConstexprDefaultConstructor()) 292234353Sdim data().DefaultedDefaultConstructorIsConstexpr = false; 293198092Srdivacky } 294249423Sdim 295218893Sdim // C++ [class.ctor]p3: 296218893Sdim // A destructor is trivial if all the direct base classes of its class 297218893Sdim // have trivial destructors. 298218893Sdim if (!BaseClassDecl->hasTrivialDestructor()) 299249423Sdim data().HasTrivialSpecialMembers &= ~SMF_Destructor; 300234353Sdim 301234353Sdim if (!BaseClassDecl->hasIrrelevantDestructor()) 302234353Sdim data().HasIrrelevantDestructor = false; 303234353Sdim 304249423Sdim // C++11 [class.copy]p18: 305249423Sdim // The implicitly-declared copy assignment oeprator for a class X will 306249423Sdim // have the form 'X& X::operator=(const X&)' if each direct base class B 307249423Sdim // of X has a copy assignment operator whose parameter is of type 'const 308249423Sdim // B&', 'const volatile B&', or 'B' [...] 309249423Sdim if (!BaseClassDecl->hasCopyAssignmentWithConstParam()) 310249423Sdim data().ImplicitCopyAssignmentHasConstParam = false; 311249423Sdim 312249423Sdim // C++11 [class.copy]p8: 313249423Sdim // The implicitly-declared copy constructor for a class X will have 314249423Sdim // the form 'X::X(const X&)' if each direct [...] base class B of X 315249423Sdim // has a copy constructor whose first parameter is of type 316249423Sdim // 'const B&' or 'const volatile B&' [...] 317249423Sdim if (!BaseClassDecl->hasCopyConstructorWithConstParam()) 318249423Sdim data().ImplicitCopyConstructorHasConstParam = false; 319249423Sdim 320224145Sdim // A class has an Objective-C object member if... or any of its bases 321224145Sdim // has an Objective-C object member. 322224145Sdim if (BaseClassDecl->hasObjectMember()) 323224145Sdim setHasObjectMember(true); 324249423Sdim 325249423Sdim if (BaseClassDecl->hasVolatileMember()) 326249423Sdim setHasVolatileMember(true); 327224145Sdim 328223017Sdim // Keep track of the presence of mutable fields. 329223017Sdim if (BaseClassDecl->hasMutableFields()) 330223017Sdim data().HasMutableFields = true; 331249423Sdim 332249423Sdim if (BaseClassDecl->hasUninitializedReferenceMember()) 333249423Sdim data().HasUninitializedReferenceMember = true; 334249423Sdim 335249423Sdim addedClassSubobject(BaseClassDecl); 336198092Srdivacky } 337206084Srdivacky 338206084Srdivacky if (VBases.empty()) 339206084Srdivacky return; 340206084Srdivacky 341206084Srdivacky // Create base specifier for any direct or indirect virtual bases. 342206084Srdivacky data().VBases = new (C) CXXBaseSpecifier[VBases.size()]; 343206084Srdivacky data().NumVBases = VBases.size(); 344249423Sdim for (int I = 0, E = VBases.size(); I != E; ++I) { 345249423Sdim QualType Type = VBases[I]->getType(); 346249423Sdim if (!Type->isDependentType()) 347249423Sdim addedClassSubobject(Type->getAsCXXRecordDecl()); 348224145Sdim data().getVBases()[I] = *VBases[I]; 349249423Sdim } 350193326Sed} 351193326Sed 352249423Sdimvoid CXXRecordDecl::addedClassSubobject(CXXRecordDecl *Subobj) { 353249423Sdim // C++11 [class.copy]p11: 354249423Sdim // A defaulted copy/move constructor for a class X is defined as 355249423Sdim // deleted if X has: 356249423Sdim // -- a direct or virtual base class B that cannot be copied/moved [...] 357249423Sdim // -- a non-static data member of class type M (or array thereof) 358249423Sdim // that cannot be copied or moved [...] 359249423Sdim if (!Subobj->hasSimpleMoveConstructor()) 360249423Sdim data().NeedOverloadResolutionForMoveConstructor = true; 361249423Sdim 362249423Sdim // C++11 [class.copy]p23: 363249423Sdim // A defaulted copy/move assignment operator for a class X is defined as 364249423Sdim // deleted if X has: 365249423Sdim // -- a direct or virtual base class B that cannot be copied/moved [...] 366249423Sdim // -- a non-static data member of class type M (or array thereof) 367249423Sdim // that cannot be copied or moved [...] 368249423Sdim if (!Subobj->hasSimpleMoveAssignment()) 369249423Sdim data().NeedOverloadResolutionForMoveAssignment = true; 370249423Sdim 371249423Sdim // C++11 [class.ctor]p5, C++11 [class.copy]p11, C++11 [class.dtor]p5: 372249423Sdim // A defaulted [ctor or dtor] for a class X is defined as 373249423Sdim // deleted if X has: 374249423Sdim // -- any direct or virtual base class [...] has a type with a destructor 375249423Sdim // that is deleted or inaccessible from the defaulted [ctor or dtor]. 376249423Sdim // -- any non-static data member has a type with a destructor 377249423Sdim // that is deleted or inaccessible from the defaulted [ctor or dtor]. 378249423Sdim if (!Subobj->hasSimpleDestructor()) { 379249423Sdim data().NeedOverloadResolutionForMoveConstructor = true; 380249423Sdim data().NeedOverloadResolutionForDestructor = true; 381249423Sdim } 382249423Sdim} 383249423Sdim 384202379Srdivacky/// Callback function for CXXRecordDecl::forallBases that acknowledges 385202379Srdivacky/// that it saw a base class. 386202379Srdivackystatic bool SawBase(const CXXRecordDecl *, void *) { 387202379Srdivacky return true; 388202379Srdivacky} 389202379Srdivacky 390202379Srdivackybool CXXRecordDecl::hasAnyDependentBases() const { 391202379Srdivacky if (!isDependentContext()) 392202379Srdivacky return false; 393202379Srdivacky 394202379Srdivacky return !forallBases(SawBase, 0); 395202379Srdivacky} 396202379Srdivacky 397221345Sdimbool CXXRecordDecl::isTriviallyCopyable() const { 398221345Sdim // C++0x [class]p5: 399221345Sdim // A trivially copyable class is a class that: 400221345Sdim // -- has no non-trivial copy constructors, 401249423Sdim if (hasNonTrivialCopyConstructor()) return false; 402221345Sdim // -- has no non-trivial move constructors, 403249423Sdim if (hasNonTrivialMoveConstructor()) return false; 404221345Sdim // -- has no non-trivial copy assignment operators, 405249423Sdim if (hasNonTrivialCopyAssignment()) return false; 406221345Sdim // -- has no non-trivial move assignment operators, and 407249423Sdim if (hasNonTrivialMoveAssignment()) return false; 408221345Sdim // -- has a trivial destructor. 409221345Sdim if (!hasTrivialDestructor()) return false; 410221345Sdim 411221345Sdim return true; 412221345Sdim} 413221345Sdim 414218893Sdimvoid CXXRecordDecl::markedVirtualFunctionPure() { 415218893Sdim // C++ [class.abstract]p2: 416218893Sdim // A class is abstract if it has at least one pure virtual function. 417218893Sdim data().Abstract = true; 418218893Sdim} 419193326Sed 420218893Sdimvoid CXXRecordDecl::addedMember(Decl *D) { 421234353Sdim if (!D->isImplicit() && 422234353Sdim !isa<FieldDecl>(D) && 423234353Sdim !isa<IndirectFieldDecl>(D) && 424243830Sdim (!isa<TagDecl>(D) || cast<TagDecl>(D)->getTagKind() == TTK_Class || 425243830Sdim cast<TagDecl>(D)->getTagKind() == TTK_Interface)) 426234353Sdim data().HasOnlyCMembers = false; 427234353Sdim 428218893Sdim // Ignore friends and invalid declarations. 429218893Sdim if (D->getFriendObjectKind() || D->isInvalidDecl()) 430218893Sdim return; 431210299Sed 432218893Sdim FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D); 433218893Sdim if (FunTmpl) 434218893Sdim D = FunTmpl->getTemplatedDecl(); 435218893Sdim 436218893Sdim if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) { 437218893Sdim if (Method->isVirtual()) { 438218893Sdim // C++ [dcl.init.aggr]p1: 439218893Sdim // An aggregate is an array or a class with [...] no virtual functions. 440218893Sdim data().Aggregate = false; 441218893Sdim 442218893Sdim // C++ [class]p4: 443218893Sdim // A POD-struct is an aggregate class... 444218893Sdim data().PlainOldData = false; 445218893Sdim 446218893Sdim // Virtual functions make the class non-empty. 447218893Sdim // FIXME: Standard ref? 448218893Sdim data().Empty = false; 449193326Sed 450218893Sdim // C++ [class.virtual]p1: 451218893Sdim // A class that declares or inherits a virtual function is called a 452218893Sdim // polymorphic class. 453218893Sdim data().Polymorphic = true; 454221345Sdim 455249423Sdim // C++11 [class.ctor]p5, C++11 [class.copy]p12, C++11 [class.copy]p25: 456249423Sdim // A [default constructor, copy/move constructor, or copy/move 457249423Sdim // assignment operator for a class X] is trivial [...] if: 458221345Sdim // -- class X has no virtual functions [...] 459249423Sdim data().HasTrivialSpecialMembers &= SMF_Destructor; 460221345Sdim 461221345Sdim // C++0x [class]p7: 462221345Sdim // A standard-layout class is a class that: [...] 463221345Sdim // -- has no virtual functions 464221345Sdim data().IsStandardLayout = false; 465218893Sdim } 466218893Sdim } 467193326Sed 468249423Sdim // Notify the listener if an implicit member was added after the definition 469249423Sdim // was completed. 470249423Sdim if (!isBeingDefined() && D->isImplicit()) 471249423Sdim if (ASTMutationListener *L = getASTMutationListener()) 472249423Sdim L->AddedCXXImplicitMember(data().Definition, D); 473218893Sdim 474249423Sdim // The kind of special member this declaration is, if any. 475249423Sdim unsigned SMKind = 0; 476249423Sdim 477249423Sdim // Handle constructors. 478218893Sdim if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) { 479249423Sdim if (!Constructor->isImplicit()) { 480249423Sdim // Note that we have a user-declared constructor. 481249423Sdim data().UserDeclaredConstructor = true; 482218893Sdim 483249423Sdim // C++ [class]p4: 484249423Sdim // A POD-struct is an aggregate class [...] 485249423Sdim // Since the POD bit is meant to be C++03 POD-ness, clear it even if the 486249423Sdim // type is technically an aggregate in C++0x since it wouldn't be in 03. 487249423Sdim data().PlainOldData = false; 488249423Sdim } 489249423Sdim 490226633Sdim // Technically, "user-provided" is only defined for special member 491226633Sdim // functions, but the intent of the standard is clearly that it should apply 492226633Sdim // to all functions. 493226633Sdim bool UserProvided = Constructor->isUserProvided(); 494218893Sdim 495223017Sdim if (Constructor->isDefaultConstructor()) { 496249423Sdim SMKind |= SMF_DefaultConstructor; 497249423Sdim 498249423Sdim if (UserProvided) 499223017Sdim data().UserProvidedDefaultConstructor = true; 500249423Sdim if (Constructor->isConstexpr()) 501234353Sdim data().HasConstexprDefaultConstructor = true; 502223017Sdim } 503218893Sdim 504221345Sdim if (!FunTmpl) { 505249423Sdim unsigned Quals; 506249423Sdim if (Constructor->isCopyConstructor(Quals)) { 507249423Sdim SMKind |= SMF_CopyConstructor; 508221345Sdim 509249423Sdim if (Quals & Qualifiers::Const) 510249423Sdim data().HasDeclaredCopyConstructorWithConstParam = true; 511249423Sdim } else if (Constructor->isMoveConstructor()) 512249423Sdim SMKind |= SMF_MoveConstructor; 513249423Sdim } 514223017Sdim 515249423Sdim // Record if we see any constexpr constructors which are neither copy 516249423Sdim // nor move constructors. 517249423Sdim if (Constructor->isConstexpr() && !Constructor->isCopyOrMoveConstructor()) 518226633Sdim data().HasConstexprNonCopyMoveConstructor = true; 519221345Sdim 520223017Sdim // C++ [dcl.init.aggr]p1: 521223017Sdim // An aggregate is an array or a class with no user-declared 522223017Sdim // constructors [...]. 523251662Sdim // C++11 [dcl.init.aggr]p1: 524223017Sdim // An aggregate is an array or a class with no user-provided 525223017Sdim // constructors [...]. 526249423Sdim if (getASTContext().getLangOpts().CPlusPlus11 527249423Sdim ? UserProvided : !Constructor->isImplicit()) 528223017Sdim data().Aggregate = false; 529198092Srdivacky } 530193326Sed 531249423Sdim // Handle destructors. 532223017Sdim if (CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(D)) { 533249423Sdim SMKind |= SMF_Destructor; 534234353Sdim 535249423Sdim if (!DD->isImplicit()) 536249423Sdim data().HasIrrelevantDestructor = false; 537239462Sdim 538249423Sdim // C++11 [class.dtor]p5: 539249423Sdim // A destructor is trivial if [...] the destructor is not virtual. 540249423Sdim if (DD->isVirtual()) 541249423Sdim data().HasTrivialSpecialMembers &= ~SMF_Destructor; 542218893Sdim } 543249423Sdim 544249423Sdim // Handle member functions. 545218893Sdim if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) { 546223017Sdim if (Method->isCopyAssignmentOperator()) { 547249423Sdim SMKind |= SMF_CopyAssignment; 548221345Sdim 549249423Sdim const ReferenceType *ParamTy = 550249423Sdim Method->getParamDecl(0)->getType()->getAs<ReferenceType>(); 551249423Sdim if (!ParamTy || ParamTy->getPointeeType().isConstQualified()) 552249423Sdim data().HasDeclaredCopyAssignmentWithConstParam = true; 553223017Sdim } 554223017Sdim 555249423Sdim if (Method->isMoveAssignmentOperator()) 556249423Sdim SMKind |= SMF_MoveAssignment; 557223017Sdim 558218893Sdim // Keep the list of conversion functions up-to-date. 559218893Sdim if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(D)) { 560251662Sdim // FIXME: We use the 'unsafe' accessor for the access specifier here, 561251662Sdim // because Sema may not have set it yet. That's really just a misdesign 562251662Sdim // in Sema. However, LLDB *will* have set the access specifier correctly, 563251662Sdim // and adds declarations after the class is technically completed, 564251662Sdim // so completeDefinition()'s overriding of the access specifiers doesn't 565251662Sdim // work. 566251662Sdim AccessSpecifier AS = Conversion->getAccessUnsafe(); 567251662Sdim 568249423Sdim if (Conversion->getPrimaryTemplate()) { 569249423Sdim // We don't record specializations. 570218893Sdim } else { 571263508Sdim ASTContext &Ctx = getASTContext(); 572263508Sdim ASTUnresolvedSet &Conversions = data().Conversions.get(Ctx); 573263508Sdim NamedDecl *Primary = 574263508Sdim FunTmpl ? cast<NamedDecl>(FunTmpl) : cast<NamedDecl>(Conversion); 575263508Sdim if (Primary->getPreviousDecl()) 576263508Sdim Conversions.replace(cast<NamedDecl>(Primary->getPreviousDecl()), 577263508Sdim Primary, AS); 578218893Sdim else 579263508Sdim Conversions.addDecl(Ctx, Primary, AS); 580218893Sdim } 581218893Sdim } 582249423Sdim 583249423Sdim if (SMKind) { 584249423Sdim // If this is the first declaration of a special member, we no longer have 585249423Sdim // an implicit trivial special member. 586249423Sdim data().HasTrivialSpecialMembers &= 587249423Sdim data().DeclaredSpecialMembers | ~SMKind; 588249423Sdim 589249423Sdim if (!Method->isImplicit() && !Method->isUserProvided()) { 590249423Sdim // This method is user-declared but not user-provided. We can't work out 591249423Sdim // whether it's trivial yet (not until we get to the end of the class). 592249423Sdim // We'll handle this method in finishedDefaultedOrDeletedMember. 593249423Sdim } else if (Method->isTrivial()) 594249423Sdim data().HasTrivialSpecialMembers |= SMKind; 595249423Sdim else 596249423Sdim data().DeclaredNonTrivialSpecialMembers |= SMKind; 597249423Sdim 598249423Sdim // Note when we have declared a declared special member, and suppress the 599249423Sdim // implicit declaration of this special member. 600249423Sdim data().DeclaredSpecialMembers |= SMKind; 601249423Sdim 602249423Sdim if (!Method->isImplicit()) { 603249423Sdim data().UserDeclaredSpecialMembers |= SMKind; 604249423Sdim 605249423Sdim // C++03 [class]p4: 606249423Sdim // A POD-struct is an aggregate class that has [...] no user-defined 607249423Sdim // copy assignment operator and no user-defined destructor. 608249423Sdim // 609249423Sdim // Since the POD bit is meant to be C++03 POD-ness, and in C++03, 610249423Sdim // aggregates could not have any constructors, clear it even for an 611249423Sdim // explicitly defaulted or deleted constructor. 612249423Sdim // type is technically an aggregate in C++0x since it wouldn't be in 03. 613249423Sdim // 614249423Sdim // Also, a user-declared move assignment operator makes a class non-POD. 615249423Sdim // This is an extension in C++03. 616249423Sdim data().PlainOldData = false; 617249423Sdim } 618249423Sdim } 619249423Sdim 620193326Sed return; 621218893Sdim } 622249423Sdim 623218893Sdim // Handle non-static data members. 624218893Sdim if (FieldDecl *Field = dyn_cast<FieldDecl>(D)) { 625226633Sdim // C++ [class.bit]p2: 626226633Sdim // A declaration for a bit-field that omits the identifier declares an 627226633Sdim // unnamed bit-field. Unnamed bit-fields are not members and cannot be 628226633Sdim // initialized. 629226633Sdim if (Field->isUnnamedBitfield()) 630226633Sdim return; 631226633Sdim 632218893Sdim // C++ [dcl.init.aggr]p1: 633218893Sdim // An aggregate is an array or a class (clause 9) with [...] no 634218893Sdim // private or protected non-static data members (clause 11). 635218893Sdim // 636218893Sdim // A POD must be an aggregate. 637218893Sdim if (D->getAccess() == AS_private || D->getAccess() == AS_protected) { 638218893Sdim data().Aggregate = false; 639218893Sdim data().PlainOldData = false; 640218893Sdim } 641221345Sdim 642221345Sdim // C++0x [class]p7: 643221345Sdim // A standard-layout class is a class that: 644221345Sdim // [...] 645221345Sdim // -- has the same access control for all non-static data members, 646221345Sdim switch (D->getAccess()) { 647221345Sdim case AS_private: data().HasPrivateFields = true; break; 648221345Sdim case AS_protected: data().HasProtectedFields = true; break; 649221345Sdim case AS_public: data().HasPublicFields = true; break; 650226633Sdim case AS_none: llvm_unreachable("Invalid access specifier"); 651221345Sdim }; 652221345Sdim if ((data().HasPrivateFields + data().HasProtectedFields + 653221345Sdim data().HasPublicFields) > 1) 654221345Sdim data().IsStandardLayout = false; 655221345Sdim 656223017Sdim // Keep track of the presence of mutable fields. 657223017Sdim if (Field->isMutable()) 658223017Sdim data().HasMutableFields = true; 659223017Sdim 660221345Sdim // C++0x [class]p9: 661218893Sdim // A POD struct is a class that is both a trivial class and a 662218893Sdim // standard-layout class, and has no non-static data members of type 663218893Sdim // non-POD struct, non-POD union (or array of such types). 664224145Sdim // 665224145Sdim // Automatic Reference Counting: the presence of a member of Objective-C pointer type 666224145Sdim // that does not explicitly have no lifetime makes the class a non-POD. 667224145Sdim // However, we delay setting PlainOldData to false in this case so that 668224145Sdim // Sema has a chance to diagnostic causes where the same class will be 669239462Sdim // non-POD with Automatic Reference Counting but a POD without ARC. 670224145Sdim // In this case, the class will become a non-POD class when we complete 671224145Sdim // the definition. 672218893Sdim ASTContext &Context = getASTContext(); 673218893Sdim QualType T = Context.getBaseElementType(Field->getType()); 674224145Sdim if (T->isObjCRetainableType() || T.isObjCGCStrong()) { 675234353Sdim if (!Context.getLangOpts().ObjCAutoRefCount || 676224145Sdim T.getObjCLifetime() != Qualifiers::OCL_ExplicitNone) 677224145Sdim setHasObjectMember(true); 678263508Sdim } else if (!T.isCXX98PODType(Context)) 679218893Sdim data().PlainOldData = false; 680224145Sdim 681221345Sdim if (T->isReferenceType()) { 682249423Sdim if (!Field->hasInClassInitializer()) 683249423Sdim data().HasUninitializedReferenceMember = true; 684221345Sdim 685221345Sdim // C++0x [class]p7: 686221345Sdim // A standard-layout class is a class that: 687221345Sdim // -- has no non-static data members of type [...] reference, 688221345Sdim data().IsStandardLayout = false; 689221345Sdim } 690221345Sdim 691234353Sdim // Record if this field is the first non-literal or volatile field or base. 692251662Sdim if (!T->isLiteralType(Context) || T.isVolatileQualified()) 693221345Sdim data().HasNonLiteralTypeFieldsOrBases = true; 694221345Sdim 695223017Sdim if (Field->hasInClassInitializer()) { 696239462Sdim data().HasInClassInitializer = true; 697239462Sdim 698239462Sdim // C++11 [class]p5: 699223017Sdim // A default constructor is trivial if [...] no non-static data member 700223017Sdim // of its class has a brace-or-equal-initializer. 701249423Sdim data().HasTrivialSpecialMembers &= ~SMF_DefaultConstructor; 702223017Sdim 703239462Sdim // C++11 [dcl.init.aggr]p1: 704223017Sdim // An aggregate is a [...] class with [...] no 705223017Sdim // brace-or-equal-initializers for non-static data members. 706251662Sdim // 707251662Sdim // This rule was removed in C++1y. 708251662Sdim if (!getASTContext().getLangOpts().CPlusPlus1y) 709251662Sdim data().Aggregate = false; 710223017Sdim 711239462Sdim // C++11 [class]p10: 712223017Sdim // A POD struct is [...] a trivial class. 713223017Sdim data().PlainOldData = false; 714223017Sdim } 715223017Sdim 716249423Sdim // C++11 [class.copy]p23: 717249423Sdim // A defaulted copy/move assignment operator for a class X is defined 718249423Sdim // as deleted if X has: 719249423Sdim // -- a non-static data member of reference type 720249423Sdim if (T->isReferenceType()) 721249423Sdim data().DefaultedMoveAssignmentIsDeleted = true; 722249423Sdim 723218893Sdim if (const RecordType *RecordTy = T->getAs<RecordType>()) { 724218893Sdim CXXRecordDecl* FieldRec = cast<CXXRecordDecl>(RecordTy->getDecl()); 725218893Sdim if (FieldRec->getDefinition()) { 726249423Sdim addedClassSubobject(FieldRec); 727249423Sdim 728263508Sdim // We may need to perform overload resolution to determine whether a 729263508Sdim // field can be moved if it's const or volatile qualified. 730263508Sdim if (T.getCVRQualifiers() & (Qualifiers::Const | Qualifiers::Volatile)) { 731263508Sdim data().NeedOverloadResolutionForMoveConstructor = true; 732263508Sdim data().NeedOverloadResolutionForMoveAssignment = true; 733263508Sdim } 734263508Sdim 735249423Sdim // C++11 [class.ctor]p5, C++11 [class.copy]p11: 736249423Sdim // A defaulted [special member] for a class X is defined as 737249423Sdim // deleted if: 738249423Sdim // -- X is a union-like class that has a variant member with a 739249423Sdim // non-trivial [corresponding special member] 740249423Sdim if (isUnion()) { 741249423Sdim if (FieldRec->hasNonTrivialMoveConstructor()) 742249423Sdim data().DefaultedMoveConstructorIsDeleted = true; 743249423Sdim if (FieldRec->hasNonTrivialMoveAssignment()) 744249423Sdim data().DefaultedMoveAssignmentIsDeleted = true; 745249423Sdim if (FieldRec->hasNonTrivialDestructor()) 746249423Sdim data().DefaultedDestructorIsDeleted = true; 747249423Sdim } 748249423Sdim 749223017Sdim // C++0x [class.ctor]p5: 750234353Sdim // A default constructor is trivial [...] if: 751223017Sdim // -- for all the non-static data members of its class that are of 752223017Sdim // class type (or array thereof), each such class has a trivial 753223017Sdim // default constructor. 754223017Sdim if (!FieldRec->hasTrivialDefaultConstructor()) 755249423Sdim data().HasTrivialSpecialMembers &= ~SMF_DefaultConstructor; 756221345Sdim 757221345Sdim // C++0x [class.copy]p13: 758221345Sdim // A copy/move constructor for class X is trivial if [...] 759221345Sdim // [...] 760221345Sdim // -- for each non-static data member of X that is of class type (or 761221345Sdim // an array thereof), the constructor selected to copy/move that 762221345Sdim // member is trivial; 763218893Sdim if (!FieldRec->hasTrivialCopyConstructor()) 764249423Sdim data().HasTrivialSpecialMembers &= ~SMF_CopyConstructor; 765249423Sdim // If the field doesn't have a simple move constructor, we'll eagerly 766249423Sdim // declare the move constructor for this class and we'll decide whether 767249423Sdim // it's trivial then. 768249423Sdim if (!FieldRec->hasTrivialMoveConstructor()) 769249423Sdim data().HasTrivialSpecialMembers &= ~SMF_MoveConstructor; 770221345Sdim 771221345Sdim // C++0x [class.copy]p27: 772221345Sdim // A copy/move assignment operator for class X is trivial if [...] 773221345Sdim // [...] 774221345Sdim // -- for each non-static data member of X that is of class type (or 775221345Sdim // an array thereof), the assignment operator selected to 776221345Sdim // copy/move that member is trivial; 777218893Sdim if (!FieldRec->hasTrivialCopyAssignment()) 778249423Sdim data().HasTrivialSpecialMembers &= ~SMF_CopyAssignment; 779249423Sdim // If the field doesn't have a simple move assignment, we'll eagerly 780249423Sdim // declare the move assignment for this class and we'll decide whether 781249423Sdim // it's trivial then. 782249423Sdim if (!FieldRec->hasTrivialMoveAssignment()) 783249423Sdim data().HasTrivialSpecialMembers &= ~SMF_MoveAssignment; 784221345Sdim 785218893Sdim if (!FieldRec->hasTrivialDestructor()) 786249423Sdim data().HasTrivialSpecialMembers &= ~SMF_Destructor; 787234353Sdim if (!FieldRec->hasIrrelevantDestructor()) 788234353Sdim data().HasIrrelevantDestructor = false; 789224145Sdim if (FieldRec->hasObjectMember()) 790224145Sdim setHasObjectMember(true); 791249423Sdim if (FieldRec->hasVolatileMember()) 792249423Sdim setHasVolatileMember(true); 793221345Sdim 794221345Sdim // C++0x [class]p7: 795221345Sdim // A standard-layout class is a class that: 796221345Sdim // -- has no non-static data members of type non-standard-layout 797221345Sdim // class (or array of such types) [...] 798221345Sdim if (!FieldRec->isStandardLayout()) 799221345Sdim data().IsStandardLayout = false; 800221345Sdim 801221345Sdim // C++0x [class]p7: 802221345Sdim // A standard-layout class is a class that: 803221345Sdim // [...] 804221345Sdim // -- has no base classes of the same type as the first non-static 805221345Sdim // data member. 806221345Sdim // We don't want to expend bits in the state of the record decl 807221345Sdim // tracking whether this is the first non-static data member so we 808221345Sdim // cheat a bit and use some of the existing state: the empty bit. 809221345Sdim // Virtual bases and virtual methods make a class non-empty, but they 810221345Sdim // also make it non-standard-layout so we needn't check here. 811221345Sdim // A non-empty base class may leave the class standard-layout, but not 812221345Sdim // if we have arrived here, and have at least on non-static data 813221345Sdim // member. If IsStandardLayout remains true, then the first non-static 814221345Sdim // data member must come through here with Empty still true, and Empty 815221345Sdim // will subsequently be set to false below. 816221345Sdim if (data().IsStandardLayout && data().Empty) { 817221345Sdim for (CXXRecordDecl::base_class_const_iterator BI = bases_begin(), 818221345Sdim BE = bases_end(); 819221345Sdim BI != BE; ++BI) { 820221345Sdim if (Context.hasSameUnqualifiedType(BI->getType(), T)) { 821221345Sdim data().IsStandardLayout = false; 822221345Sdim break; 823221345Sdim } 824221345Sdim } 825221345Sdim } 826223017Sdim 827223017Sdim // Keep track of the presence of mutable fields. 828223017Sdim if (FieldRec->hasMutableFields()) 829223017Sdim data().HasMutableFields = true; 830234353Sdim 831234353Sdim // C++11 [class.copy]p13: 832234353Sdim // If the implicitly-defined constructor would satisfy the 833234353Sdim // requirements of a constexpr constructor, the implicitly-defined 834234353Sdim // constructor is constexpr. 835234353Sdim // C++11 [dcl.constexpr]p4: 836234353Sdim // -- every constructor involved in initializing non-static data 837234353Sdim // members [...] shall be a constexpr constructor 838234353Sdim if (!Field->hasInClassInitializer() && 839239462Sdim !FieldRec->hasConstexprDefaultConstructor() && !isUnion()) 840234353Sdim // The standard requires any in-class initializer to be a constant 841234353Sdim // expression. We consider this to be a defect. 842234353Sdim data().DefaultedDefaultConstructorIsConstexpr = false; 843249423Sdim 844249423Sdim // C++11 [class.copy]p8: 845249423Sdim // The implicitly-declared copy constructor for a class X will have 846249423Sdim // the form 'X::X(const X&)' if [...] for all the non-static data 847249423Sdim // members of X that are of a class type M (or array thereof), each 848249423Sdim // such class type has a copy constructor whose first parameter is 849249423Sdim // of type 'const M&' or 'const volatile M&'. 850249423Sdim if (!FieldRec->hasCopyConstructorWithConstParam()) 851249423Sdim data().ImplicitCopyConstructorHasConstParam = false; 852249423Sdim 853249423Sdim // C++11 [class.copy]p18: 854249423Sdim // The implicitly-declared copy assignment oeprator for a class X will 855249423Sdim // have the form 'X& X::operator=(const X&)' if [...] for all the 856249423Sdim // non-static data members of X that are of a class type M (or array 857249423Sdim // thereof), each such class type has a copy assignment operator whose 858249423Sdim // parameter is of type 'const M&', 'const volatile M&' or 'M'. 859249423Sdim if (!FieldRec->hasCopyAssignmentWithConstParam()) 860249423Sdim data().ImplicitCopyAssignmentHasConstParam = false; 861249423Sdim 862249423Sdim if (FieldRec->hasUninitializedReferenceMember() && 863249423Sdim !Field->hasInClassInitializer()) 864249423Sdim data().HasUninitializedReferenceMember = true; 865218893Sdim } 866234353Sdim } else { 867234353Sdim // Base element type of field is a non-class type. 868251662Sdim if (!T->isLiteralType(Context) || 869239462Sdim (!Field->hasInClassInitializer() && !isUnion())) 870234353Sdim data().DefaultedDefaultConstructorIsConstexpr = false; 871249423Sdim 872249423Sdim // C++11 [class.copy]p23: 873249423Sdim // A defaulted copy/move assignment operator for a class X is defined 874249423Sdim // as deleted if X has: 875249423Sdim // -- a non-static data member of const non-class type (or array 876249423Sdim // thereof) 877249423Sdim if (T.isConstQualified()) 878249423Sdim data().DefaultedMoveAssignmentIsDeleted = true; 879218893Sdim } 880221345Sdim 881221345Sdim // C++0x [class]p7: 882221345Sdim // A standard-layout class is a class that: 883221345Sdim // [...] 884221345Sdim // -- either has no non-static data members in the most derived 885221345Sdim // class and at most one base class with non-static data members, 886221345Sdim // or has no base classes with non-static data members, and 887221345Sdim // At this point we know that we have a non-static data member, so the last 888221345Sdim // clause holds. 889221345Sdim if (!data().HasNoNonEmptyBases) 890221345Sdim data().IsStandardLayout = false; 891221345Sdim 892218893Sdim // If this is not a zero-length bit-field, then the class is not empty. 893218893Sdim if (data().Empty) { 894226633Sdim if (!Field->isBitField() || 895226633Sdim (!Field->getBitWidth()->isTypeDependent() && 896226633Sdim !Field->getBitWidth()->isValueDependent() && 897226633Sdim Field->getBitWidthValue(Context) != 0)) 898218893Sdim data().Empty = false; 899218893Sdim } 900218893Sdim } 901218893Sdim 902218893Sdim // Handle using declarations of conversion functions. 903263508Sdim if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(D)) { 904218893Sdim if (Shadow->getDeclName().getNameKind() 905263508Sdim == DeclarationName::CXXConversionFunctionName) { 906263508Sdim ASTContext &Ctx = getASTContext(); 907263508Sdim data().Conversions.get(Ctx).addDecl(Ctx, Shadow, Shadow->getAccess()); 908263508Sdim } 909263508Sdim } 910193326Sed} 911193326Sed 912249423Sdimvoid CXXRecordDecl::finishedDefaultedOrDeletedMember(CXXMethodDecl *D) { 913249423Sdim assert(!D->isImplicit() && !D->isUserProvided()); 914249423Sdim 915249423Sdim // The kind of special member this declaration is, if any. 916249423Sdim unsigned SMKind = 0; 917249423Sdim 918249423Sdim if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) { 919249423Sdim if (Constructor->isDefaultConstructor()) { 920249423Sdim SMKind |= SMF_DefaultConstructor; 921249423Sdim if (Constructor->isConstexpr()) 922249423Sdim data().HasConstexprDefaultConstructor = true; 923249423Sdim } 924249423Sdim if (Constructor->isCopyConstructor()) 925249423Sdim SMKind |= SMF_CopyConstructor; 926249423Sdim else if (Constructor->isMoveConstructor()) 927249423Sdim SMKind |= SMF_MoveConstructor; 928249423Sdim else if (Constructor->isConstexpr()) 929249423Sdim // We may now know that the constructor is constexpr. 930249423Sdim data().HasConstexprNonCopyMoveConstructor = true; 931249423Sdim } else if (isa<CXXDestructorDecl>(D)) 932249423Sdim SMKind |= SMF_Destructor; 933249423Sdim else if (D->isCopyAssignmentOperator()) 934249423Sdim SMKind |= SMF_CopyAssignment; 935249423Sdim else if (D->isMoveAssignmentOperator()) 936249423Sdim SMKind |= SMF_MoveAssignment; 937249423Sdim 938249423Sdim // Update which trivial / non-trivial special members we have. 939249423Sdim // addedMember will have skipped this step for this member. 940249423Sdim if (D->isTrivial()) 941249423Sdim data().HasTrivialSpecialMembers |= SMKind; 942249423Sdim else 943249423Sdim data().DeclaredNonTrivialSpecialMembers |= SMKind; 944249423Sdim} 945249423Sdim 946234353Sdimbool CXXRecordDecl::isCLike() const { 947243830Sdim if (getTagKind() == TTK_Class || getTagKind() == TTK_Interface || 948243830Sdim !TemplateOrInstantiation.isNull()) 949234353Sdim return false; 950234353Sdim if (!hasDefinition()) 951234353Sdim return true; 952234353Sdim 953234353Sdim return isPOD() && data().HasOnlyCMembers; 954234353Sdim} 955263508Sdim 956263508Sdimbool CXXRecordDecl::isGenericLambda() const { 957263508Sdim if (!isLambda()) return false; 958263508Sdim return getLambdaData().IsGenericLambda; 959263508Sdim} 960234353Sdim 961263508SdimCXXMethodDecl* CXXRecordDecl::getLambdaCallOperator() const { 962263508Sdim if (!isLambda()) return 0; 963263508Sdim DeclarationName Name = 964263508Sdim getASTContext().DeclarationNames.getCXXOperatorName(OO_Call); 965263508Sdim DeclContext::lookup_const_result Calls = lookup(Name); 966263508Sdim 967263508Sdim assert(!Calls.empty() && "Missing lambda call operator!"); 968263508Sdim assert(Calls.size() == 1 && "More than one lambda call operator!"); 969263508Sdim 970263508Sdim NamedDecl *CallOp = Calls.front(); 971263508Sdim if (FunctionTemplateDecl *CallOpTmpl = 972263508Sdim dyn_cast<FunctionTemplateDecl>(CallOp)) 973263508Sdim return cast<CXXMethodDecl>(CallOpTmpl->getTemplatedDecl()); 974263508Sdim 975263508Sdim return cast<CXXMethodDecl>(CallOp); 976263508Sdim} 977263508Sdim 978263508SdimCXXMethodDecl* CXXRecordDecl::getLambdaStaticInvoker() const { 979263508Sdim if (!isLambda()) return 0; 980263508Sdim DeclarationName Name = 981263508Sdim &getASTContext().Idents.get(getLambdaStaticInvokerName()); 982263508Sdim DeclContext::lookup_const_result Invoker = lookup(Name); 983263508Sdim if (Invoker.empty()) return 0; 984263508Sdim assert(Invoker.size() == 1 && "More than one static invoker operator!"); 985263508Sdim NamedDecl *InvokerFun = Invoker.front(); 986263508Sdim if (FunctionTemplateDecl *InvokerTemplate = 987263508Sdim dyn_cast<FunctionTemplateDecl>(InvokerFun)) 988263508Sdim return cast<CXXMethodDecl>(InvokerTemplate->getTemplatedDecl()); 989263508Sdim 990263508Sdim return cast<CXXMethodDecl>(InvokerFun); 991263508Sdim} 992263508Sdim 993234353Sdimvoid CXXRecordDecl::getCaptureFields( 994234353Sdim llvm::DenseMap<const VarDecl *, FieldDecl *> &Captures, 995234353Sdim FieldDecl *&ThisCapture) const { 996234353Sdim Captures.clear(); 997234353Sdim ThisCapture = 0; 998234353Sdim 999234353Sdim LambdaDefinitionData &Lambda = getLambdaData(); 1000234353Sdim RecordDecl::field_iterator Field = field_begin(); 1001234353Sdim for (LambdaExpr::Capture *C = Lambda.Captures, *CEnd = C + Lambda.NumCaptures; 1002234353Sdim C != CEnd; ++C, ++Field) { 1003263508Sdim if (C->capturesThis()) 1004234353Sdim ThisCapture = *Field; 1005263508Sdim else if (C->capturesVariable()) 1006263508Sdim Captures[C->getCapturedVar()] = *Field; 1007234353Sdim } 1008263508Sdim assert(Field == field_end()); 1009234353Sdim} 1010234353Sdim 1011263508SdimTemplateParameterList * 1012263508SdimCXXRecordDecl::getGenericLambdaTemplateParameterList() const { 1013263508Sdim if (!isLambda()) return 0; 1014263508Sdim CXXMethodDecl *CallOp = getLambdaCallOperator(); 1015263508Sdim if (FunctionTemplateDecl *Tmpl = CallOp->getDescribedFunctionTemplate()) 1016263508Sdim return Tmpl->getTemplateParameters(); 1017263508Sdim return 0; 1018263508Sdim} 1019234353Sdim 1020205219Srdivackystatic CanQualType GetConversionType(ASTContext &Context, NamedDecl *Conv) { 1021205219Srdivacky QualType T; 1022206084Srdivacky if (isa<UsingShadowDecl>(Conv)) 1023206084Srdivacky Conv = cast<UsingShadowDecl>(Conv)->getTargetDecl(); 1024205219Srdivacky if (FunctionTemplateDecl *ConvTemp = dyn_cast<FunctionTemplateDecl>(Conv)) 1025205219Srdivacky T = ConvTemp->getTemplatedDecl()->getResultType(); 1026205219Srdivacky else 1027205219Srdivacky T = cast<CXXConversionDecl>(Conv)->getConversionType(); 1028205219Srdivacky return Context.getCanonicalType(T); 1029198092Srdivacky} 1030198092Srdivacky 1031205219Srdivacky/// Collect the visible conversions of a base class. 1032205219Srdivacky/// 1033239462Sdim/// \param Record a base class of the class we're considering 1034205219Srdivacky/// \param InVirtual whether this base class is a virtual base (or a base 1035205219Srdivacky/// of a virtual base) 1036205219Srdivacky/// \param Access the access along the inheritance path to this base 1037205219Srdivacky/// \param ParentHiddenTypes the conversions provided by the inheritors 1038205219Srdivacky/// of this base 1039205219Srdivacky/// \param Output the set to which to add conversions from non-virtual bases 1040205219Srdivacky/// \param VOutput the set to which to add conversions from virtual bases 1041205219Srdivacky/// \param HiddenVBaseCs the set of conversions which were hidden in a 1042205219Srdivacky/// virtual base along some inheritance path 1043205219Srdivackystatic void CollectVisibleConversions(ASTContext &Context, 1044205219Srdivacky CXXRecordDecl *Record, 1045205219Srdivacky bool InVirtual, 1046205219Srdivacky AccessSpecifier Access, 1047205219Srdivacky const llvm::SmallPtrSet<CanQualType, 8> &ParentHiddenTypes, 1048249423Sdim ASTUnresolvedSet &Output, 1049205219Srdivacky UnresolvedSetImpl &VOutput, 1050205219Srdivacky llvm::SmallPtrSet<NamedDecl*, 8> &HiddenVBaseCs) { 1051205219Srdivacky // The set of types which have conversions in this class or its 1052205219Srdivacky // subclasses. As an optimization, we don't copy the derived set 1053205219Srdivacky // unless it might change. 1054205219Srdivacky const llvm::SmallPtrSet<CanQualType, 8> *HiddenTypes = &ParentHiddenTypes; 1055205219Srdivacky llvm::SmallPtrSet<CanQualType, 8> HiddenTypesBuffer; 1056205219Srdivacky 1057205219Srdivacky // Collect the direct conversions and figure out which conversions 1058205219Srdivacky // will be hidden in the subclasses. 1059249423Sdim CXXRecordDecl::conversion_iterator ConvI = Record->conversion_begin(); 1060249423Sdim CXXRecordDecl::conversion_iterator ConvE = Record->conversion_end(); 1061249423Sdim if (ConvI != ConvE) { 1062205219Srdivacky HiddenTypesBuffer = ParentHiddenTypes; 1063205219Srdivacky HiddenTypes = &HiddenTypesBuffer; 1064205219Srdivacky 1065249423Sdim for (CXXRecordDecl::conversion_iterator I = ConvI; I != ConvE; ++I) { 1066239462Sdim CanQualType ConvType(GetConversionType(Context, I.getDecl())); 1067239462Sdim bool Hidden = ParentHiddenTypes.count(ConvType); 1068239462Sdim if (!Hidden) 1069239462Sdim HiddenTypesBuffer.insert(ConvType); 1070205219Srdivacky 1071205219Srdivacky // If this conversion is hidden and we're in a virtual base, 1072205219Srdivacky // remember that it's hidden along some inheritance path. 1073205219Srdivacky if (Hidden && InVirtual) 1074205219Srdivacky HiddenVBaseCs.insert(cast<NamedDecl>(I.getDecl()->getCanonicalDecl())); 1075205219Srdivacky 1076205219Srdivacky // If this conversion isn't hidden, add it to the appropriate output. 1077205219Srdivacky else if (!Hidden) { 1078205219Srdivacky AccessSpecifier IAccess 1079205219Srdivacky = CXXRecordDecl::MergeAccess(Access, I.getAccess()); 1080205219Srdivacky 1081205219Srdivacky if (InVirtual) 1082205219Srdivacky VOutput.addDecl(I.getDecl(), IAccess); 1083198092Srdivacky else 1084249423Sdim Output.addDecl(Context, I.getDecl(), IAccess); 1085198092Srdivacky } 1086198092Srdivacky } 1087198092Srdivacky } 1088198893Srdivacky 1089205219Srdivacky // Collect information recursively from any base classes. 1090205219Srdivacky for (CXXRecordDecl::base_class_iterator 1091205219Srdivacky I = Record->bases_begin(), E = Record->bases_end(); I != E; ++I) { 1092205219Srdivacky const RecordType *RT = I->getType()->getAs<RecordType>(); 1093205219Srdivacky if (!RT) continue; 1094198893Srdivacky 1095205219Srdivacky AccessSpecifier BaseAccess 1096205219Srdivacky = CXXRecordDecl::MergeAccess(Access, I->getAccessSpecifier()); 1097205219Srdivacky bool BaseInVirtual = InVirtual || I->isVirtual(); 1098198893Srdivacky 1099205219Srdivacky CXXRecordDecl *Base = cast<CXXRecordDecl>(RT->getDecl()); 1100205219Srdivacky CollectVisibleConversions(Context, Base, BaseInVirtual, BaseAccess, 1101205219Srdivacky *HiddenTypes, Output, VOutput, HiddenVBaseCs); 1102198092Srdivacky } 1103205219Srdivacky} 1104198893Srdivacky 1105205219Srdivacky/// Collect the visible conversions of a class. 1106205219Srdivacky/// 1107205219Srdivacky/// This would be extremely straightforward if it weren't for virtual 1108205219Srdivacky/// bases. It might be worth special-casing that, really. 1109205219Srdivackystatic void CollectVisibleConversions(ASTContext &Context, 1110205219Srdivacky CXXRecordDecl *Record, 1111249423Sdim ASTUnresolvedSet &Output) { 1112205219Srdivacky // The collection of all conversions in virtual bases that we've 1113205219Srdivacky // found. These will be added to the output as long as they don't 1114205219Srdivacky // appear in the hidden-conversions set. 1115205219Srdivacky UnresolvedSet<8> VBaseCs; 1116205219Srdivacky 1117205219Srdivacky // The set of conversions in virtual bases that we've determined to 1118205219Srdivacky // be hidden. 1119205219Srdivacky llvm::SmallPtrSet<NamedDecl*, 8> HiddenVBaseCs; 1120205219Srdivacky 1121205219Srdivacky // The set of types hidden by classes derived from this one. 1122205219Srdivacky llvm::SmallPtrSet<CanQualType, 8> HiddenTypes; 1123205219Srdivacky 1124205219Srdivacky // Go ahead and collect the direct conversions and add them to the 1125205219Srdivacky // hidden-types set. 1126249423Sdim CXXRecordDecl::conversion_iterator ConvI = Record->conversion_begin(); 1127249423Sdim CXXRecordDecl::conversion_iterator ConvE = Record->conversion_end(); 1128249423Sdim Output.append(Context, ConvI, ConvE); 1129249423Sdim for (; ConvI != ConvE; ++ConvI) 1130249423Sdim HiddenTypes.insert(GetConversionType(Context, ConvI.getDecl())); 1131205219Srdivacky 1132205219Srdivacky // Recursively collect conversions from base classes. 1133205219Srdivacky for (CXXRecordDecl::base_class_iterator 1134205219Srdivacky I = Record->bases_begin(), E = Record->bases_end(); I != E; ++I) { 1135205219Srdivacky const RecordType *RT = I->getType()->getAs<RecordType>(); 1136205219Srdivacky if (!RT) continue; 1137205219Srdivacky 1138205219Srdivacky CollectVisibleConversions(Context, cast<CXXRecordDecl>(RT->getDecl()), 1139205219Srdivacky I->isVirtual(), I->getAccessSpecifier(), 1140205219Srdivacky HiddenTypes, Output, VBaseCs, HiddenVBaseCs); 1141198092Srdivacky } 1142205219Srdivacky 1143205219Srdivacky // Add any unhidden conversions provided by virtual bases. 1144205219Srdivacky for (UnresolvedSetIterator I = VBaseCs.begin(), E = VBaseCs.end(); 1145205219Srdivacky I != E; ++I) { 1146205219Srdivacky if (!HiddenVBaseCs.count(cast<NamedDecl>(I.getDecl()->getCanonicalDecl()))) 1147249423Sdim Output.addDecl(Context, I.getDecl(), I.getAccess()); 1148205219Srdivacky } 1149198092Srdivacky} 1150198092Srdivacky 1151198092Srdivacky/// getVisibleConversionFunctions - get all conversion functions visible 1152198092Srdivacky/// in current class; including conversion function templates. 1153249423Sdimstd::pair<CXXRecordDecl::conversion_iterator,CXXRecordDecl::conversion_iterator> 1154249423SdimCXXRecordDecl::getVisibleConversionFunctions() { 1155263508Sdim ASTContext &Ctx = getASTContext(); 1156263508Sdim 1157263508Sdim ASTUnresolvedSet *Set; 1158263508Sdim if (bases_begin() == bases_end()) { 1159263508Sdim // If root class, all conversions are visible. 1160263508Sdim Set = &data().Conversions.get(Ctx); 1161263508Sdim } else { 1162263508Sdim Set = &data().VisibleConversions.get(Ctx); 1163263508Sdim // If visible conversion list is not evaluated, evaluate it. 1164263508Sdim if (!data().ComputedVisibleConversions) { 1165263508Sdim CollectVisibleConversions(Ctx, this, *Set); 1166263508Sdim data().ComputedVisibleConversions = true; 1167263508Sdim } 1168249423Sdim } 1169263508Sdim return std::make_pair(Set->begin(), Set->end()); 1170198092Srdivacky} 1171198092Srdivacky 1172206084Srdivackyvoid CXXRecordDecl::removeConversion(const NamedDecl *ConvDecl) { 1173206084Srdivacky // This operation is O(N) but extremely rare. Sema only uses it to 1174206084Srdivacky // remove UsingShadowDecls in a class that were followed by a direct 1175206084Srdivacky // declaration, e.g.: 1176206084Srdivacky // class A : B { 1177206084Srdivacky // using B::operator int; 1178206084Srdivacky // operator int(); 1179206084Srdivacky // }; 1180206084Srdivacky // This is uncommon by itself and even more uncommon in conjunction 1181206084Srdivacky // with sufficiently large numbers of directly-declared conversions 1182206084Srdivacky // that asymptotic behavior matters. 1183206084Srdivacky 1184263508Sdim ASTUnresolvedSet &Convs = data().Conversions.get(getASTContext()); 1185206084Srdivacky for (unsigned I = 0, E = Convs.size(); I != E; ++I) { 1186206084Srdivacky if (Convs[I].getDecl() == ConvDecl) { 1187206084Srdivacky Convs.erase(I); 1188206084Srdivacky assert(std::find(Convs.begin(), Convs.end(), ConvDecl) == Convs.end() 1189206084Srdivacky && "conversion was found multiple times in unresolved set"); 1190206084Srdivacky return; 1191206084Srdivacky } 1192206084Srdivacky } 1193206084Srdivacky 1194206084Srdivacky llvm_unreachable("conversion not found in set!"); 1195198092Srdivacky} 1196194613Sed 1197198092SrdivackyCXXRecordDecl *CXXRecordDecl::getInstantiatedFromMemberClass() const { 1198198092Srdivacky if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo()) 1199198092Srdivacky return cast<CXXRecordDecl>(MSInfo->getInstantiatedFrom()); 1200198092Srdivacky 1201198092Srdivacky return 0; 1202198092Srdivacky} 1203198092Srdivacky 1204198092Srdivackyvoid 1205198092SrdivackyCXXRecordDecl::setInstantiationOfMemberClass(CXXRecordDecl *RD, 1206198092Srdivacky TemplateSpecializationKind TSK) { 1207198092Srdivacky assert(TemplateOrInstantiation.isNull() && 1208198092Srdivacky "Previous template or instantiation?"); 1209263508Sdim assert(!isa<ClassTemplatePartialSpecializationDecl>(this)); 1210198092Srdivacky TemplateOrInstantiation 1211198092Srdivacky = new (getASTContext()) MemberSpecializationInfo(RD, TSK); 1212198092Srdivacky} 1213198092Srdivacky 1214200583SrdivackyTemplateSpecializationKind CXXRecordDecl::getTemplateSpecializationKind() const{ 1215200583Srdivacky if (const ClassTemplateSpecializationDecl *Spec 1216198092Srdivacky = dyn_cast<ClassTemplateSpecializationDecl>(this)) 1217198092Srdivacky return Spec->getSpecializationKind(); 1218198092Srdivacky 1219198092Srdivacky if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo()) 1220198092Srdivacky return MSInfo->getTemplateSpecializationKind(); 1221198092Srdivacky 1222198092Srdivacky return TSK_Undeclared; 1223198092Srdivacky} 1224198092Srdivacky 1225198092Srdivackyvoid 1226198092SrdivackyCXXRecordDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) { 1227198092Srdivacky if (ClassTemplateSpecializationDecl *Spec 1228198092Srdivacky = dyn_cast<ClassTemplateSpecializationDecl>(this)) { 1229198092Srdivacky Spec->setSpecializationKind(TSK); 1230198092Srdivacky return; 1231198092Srdivacky } 1232198092Srdivacky 1233198092Srdivacky if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo()) { 1234198092Srdivacky MSInfo->setTemplateSpecializationKind(TSK); 1235198092Srdivacky return; 1236198092Srdivacky } 1237198092Srdivacky 1238226633Sdim llvm_unreachable("Not a class template or member class specialization"); 1239198092Srdivacky} 1240198092Srdivacky 1241210299SedCXXDestructorDecl *CXXRecordDecl::getDestructor() const { 1242210299Sed ASTContext &Context = getASTContext(); 1243193326Sed QualType ClassType = Context.getTypeDeclType(this); 1244193326Sed 1245198092Srdivacky DeclarationName Name 1246198092Srdivacky = Context.DeclarationNames.getCXXDestructorName( 1247198092Srdivacky Context.getCanonicalType(ClassType)); 1248198092Srdivacky 1249249423Sdim DeclContext::lookup_const_result R = lookup(Name); 1250249423Sdim if (R.empty()) 1251212904Sdim return 0; 1252198092Srdivacky 1253249423Sdim CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(R.front()); 1254193326Sed return Dtor; 1255193326Sed} 1256193326Sed 1257218893Sdimvoid CXXRecordDecl::completeDefinition() { 1258218893Sdim completeDefinition(0); 1259218893Sdim} 1260218893Sdim 1261218893Sdimvoid CXXRecordDecl::completeDefinition(CXXFinalOverriderMap *FinalOverriders) { 1262218893Sdim RecordDecl::completeDefinition(); 1263218893Sdim 1264234353Sdim if (hasObjectMember() && getASTContext().getLangOpts().ObjCAutoRefCount) { 1265224145Sdim // Objective-C Automatic Reference Counting: 1266224145Sdim // If a class has a non-static data member of Objective-C pointer 1267224145Sdim // type (or array thereof), it is a non-POD type and its 1268239462Sdim // default constructor (if any), copy constructor, move constructor, 1269239462Sdim // copy assignment operator, move assignment operator, and destructor are 1270239462Sdim // non-trivial. 1271224145Sdim struct DefinitionData &Data = data(); 1272224145Sdim Data.PlainOldData = false; 1273249423Sdim Data.HasTrivialSpecialMembers = 0; 1274234353Sdim Data.HasIrrelevantDestructor = false; 1275224145Sdim } 1276224145Sdim 1277218893Sdim // If the class may be abstract (but hasn't been marked as such), check for 1278218893Sdim // any pure final overriders. 1279218893Sdim if (mayBeAbstract()) { 1280218893Sdim CXXFinalOverriderMap MyFinalOverriders; 1281218893Sdim if (!FinalOverriders) { 1282218893Sdim getFinalOverriders(MyFinalOverriders); 1283218893Sdim FinalOverriders = &MyFinalOverriders; 1284218893Sdim } 1285218893Sdim 1286218893Sdim bool Done = false; 1287218893Sdim for (CXXFinalOverriderMap::iterator M = FinalOverriders->begin(), 1288218893Sdim MEnd = FinalOverriders->end(); 1289218893Sdim M != MEnd && !Done; ++M) { 1290218893Sdim for (OverridingMethods::iterator SO = M->second.begin(), 1291218893Sdim SOEnd = M->second.end(); 1292218893Sdim SO != SOEnd && !Done; ++SO) { 1293218893Sdim assert(SO->second.size() > 0 && 1294218893Sdim "All virtual functions have overridding virtual functions"); 1295218893Sdim 1296218893Sdim // C++ [class.abstract]p4: 1297218893Sdim // A class is abstract if it contains or inherits at least one 1298218893Sdim // pure virtual function for which the final overrider is pure 1299218893Sdim // virtual. 1300218893Sdim if (SO->second.front().Method->isPure()) { 1301218893Sdim data().Abstract = true; 1302218893Sdim Done = true; 1303218893Sdim break; 1304218893Sdim } 1305218893Sdim } 1306218893Sdim } 1307218893Sdim } 1308218893Sdim 1309218893Sdim // Set access bits correctly on the directly-declared conversions. 1310263508Sdim for (conversion_iterator I = conversion_begin(), E = conversion_end(); 1311218893Sdim I != E; ++I) 1312249423Sdim I.setAccess((*I)->getAccess()); 1313218893Sdim} 1314218893Sdim 1315218893Sdimbool CXXRecordDecl::mayBeAbstract() const { 1316218893Sdim if (data().Abstract || isInvalidDecl() || !data().Polymorphic || 1317218893Sdim isDependentContext()) 1318218893Sdim return false; 1319218893Sdim 1320218893Sdim for (CXXRecordDecl::base_class_const_iterator B = bases_begin(), 1321218893Sdim BEnd = bases_end(); 1322218893Sdim B != BEnd; ++B) { 1323218893Sdim CXXRecordDecl *BaseDecl 1324218893Sdim = cast<CXXRecordDecl>(B->getType()->getAs<RecordType>()->getDecl()); 1325218893Sdim if (BaseDecl->isAbstract()) 1326218893Sdim return true; 1327218893Sdim } 1328218893Sdim 1329218893Sdim return false; 1330218893Sdim} 1331218893Sdim 1332234353Sdimvoid CXXMethodDecl::anchor() { } 1333234353Sdim 1334249423Sdimbool CXXMethodDecl::isStatic() const { 1335251662Sdim const CXXMethodDecl *MD = getCanonicalDecl(); 1336249423Sdim 1337249423Sdim if (MD->getStorageClass() == SC_Static) 1338249423Sdim return true; 1339249423Sdim 1340263508Sdim OverloadedOperatorKind OOK = getDeclName().getCXXOverloadedOperator(); 1341263508Sdim return isStaticOverloadedOperator(OOK); 1342249423Sdim} 1343249423Sdim 1344239462Sdimstatic bool recursivelyOverrides(const CXXMethodDecl *DerivedMD, 1345239462Sdim const CXXMethodDecl *BaseMD) { 1346239462Sdim for (CXXMethodDecl::method_iterator I = DerivedMD->begin_overridden_methods(), 1347239462Sdim E = DerivedMD->end_overridden_methods(); I != E; ++I) { 1348239462Sdim const CXXMethodDecl *MD = *I; 1349239462Sdim if (MD->getCanonicalDecl() == BaseMD->getCanonicalDecl()) 1350239462Sdim return true; 1351239462Sdim if (recursivelyOverrides(MD, BaseMD)) 1352239462Sdim return true; 1353239462Sdim } 1354239462Sdim return false; 1355239462Sdim} 1356239462Sdim 1357193326SedCXXMethodDecl * 1358239462SdimCXXMethodDecl::getCorrespondingMethodInClass(const CXXRecordDecl *RD, 1359239462Sdim bool MayBeBase) { 1360239462Sdim if (this->getParent()->getCanonicalDecl() == RD->getCanonicalDecl()) 1361239462Sdim return this; 1362239462Sdim 1363239462Sdim // Lookup doesn't work for destructors, so handle them separately. 1364239462Sdim if (isa<CXXDestructorDecl>(this)) { 1365239462Sdim CXXMethodDecl *MD = RD->getDestructor(); 1366239462Sdim if (MD) { 1367239462Sdim if (recursivelyOverrides(MD, this)) 1368239462Sdim return MD; 1369239462Sdim if (MayBeBase && recursivelyOverrides(this, MD)) 1370239462Sdim return MD; 1371239462Sdim } 1372239462Sdim return NULL; 1373239462Sdim } 1374239462Sdim 1375239462Sdim lookup_const_result Candidates = RD->lookup(getDeclName()); 1376249423Sdim for (NamedDecl * const * I = Candidates.begin(); I != Candidates.end(); ++I) { 1377239462Sdim CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(*I); 1378239462Sdim if (!MD) 1379239462Sdim continue; 1380239462Sdim if (recursivelyOverrides(MD, this)) 1381239462Sdim return MD; 1382239462Sdim if (MayBeBase && recursivelyOverrides(this, MD)) 1383239462Sdim return MD; 1384239462Sdim } 1385239462Sdim 1386239462Sdim for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), 1387239462Sdim E = RD->bases_end(); I != E; ++I) { 1388239462Sdim const RecordType *RT = I->getType()->getAs<RecordType>(); 1389239462Sdim if (!RT) 1390239462Sdim continue; 1391239462Sdim const CXXRecordDecl *Base = cast<CXXRecordDecl>(RT->getDecl()); 1392239462Sdim CXXMethodDecl *T = this->getCorrespondingMethodInClass(Base); 1393239462Sdim if (T) 1394239462Sdim return T; 1395239462Sdim } 1396239462Sdim 1397239462Sdim return NULL; 1398239462Sdim} 1399239462Sdim 1400239462SdimCXXMethodDecl * 1401193326SedCXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD, 1402221345Sdim SourceLocation StartLoc, 1403212904Sdim const DeclarationNameInfo &NameInfo, 1404200583Srdivacky QualType T, TypeSourceInfo *TInfo, 1405249423Sdim StorageClass SC, bool isInline, 1406226633Sdim bool isConstexpr, SourceLocation EndLocation) { 1407221345Sdim return new (C) CXXMethodDecl(CXXMethod, RD, StartLoc, NameInfo, T, TInfo, 1408249423Sdim SC, isInline, isConstexpr, 1409226633Sdim EndLocation); 1410193326Sed} 1411193326Sed 1412234353SdimCXXMethodDecl *CXXMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) { 1413234353Sdim void *Mem = AllocateDeserializedDecl(C, ID, sizeof(CXXMethodDecl)); 1414234353Sdim return new (Mem) CXXMethodDecl(CXXMethod, 0, SourceLocation(), 1415234353Sdim DeclarationNameInfo(), QualType(), 1416249423Sdim 0, SC_None, false, false, 1417234353Sdim SourceLocation()); 1418234353Sdim} 1419234353Sdim 1420198092Srdivackybool CXXMethodDecl::isUsualDeallocationFunction() const { 1421198092Srdivacky if (getOverloadedOperator() != OO_Delete && 1422198092Srdivacky getOverloadedOperator() != OO_Array_Delete) 1423198092Srdivacky return false; 1424204643Srdivacky 1425198092Srdivacky // C++ [basic.stc.dynamic.deallocation]p2: 1426204643Srdivacky // A template instance is never a usual deallocation function, 1427204643Srdivacky // regardless of its signature. 1428204643Srdivacky if (getPrimaryTemplate()) 1429204643Srdivacky return false; 1430204643Srdivacky 1431204643Srdivacky // C++ [basic.stc.dynamic.deallocation]p2: 1432198092Srdivacky // If a class T has a member deallocation function named operator delete 1433198092Srdivacky // with exactly one parameter, then that function is a usual (non-placement) 1434198092Srdivacky // deallocation function. [...] 1435198092Srdivacky if (getNumParams() == 1) 1436198092Srdivacky return true; 1437198092Srdivacky 1438198092Srdivacky // C++ [basic.stc.dynamic.deallocation]p2: 1439198092Srdivacky // [...] If class T does not declare such an operator delete but does 1440198092Srdivacky // declare a member deallocation function named operator delete with 1441198092Srdivacky // exactly two parameters, the second of which has type std::size_t (18.1), 1442198092Srdivacky // then this function is a usual deallocation function. 1443198092Srdivacky ASTContext &Context = getASTContext(); 1444198092Srdivacky if (getNumParams() != 2 || 1445203955Srdivacky !Context.hasSameUnqualifiedType(getParamDecl(1)->getType(), 1446203955Srdivacky Context.getSizeType())) 1447198092Srdivacky return false; 1448198092Srdivacky 1449198092Srdivacky // This function is a usual deallocation function if there are no 1450198092Srdivacky // single-parameter deallocation functions of the same kind. 1451249423Sdim DeclContext::lookup_const_result R = getDeclContext()->lookup(getDeclName()); 1452249423Sdim for (DeclContext::lookup_const_result::iterator I = R.begin(), E = R.end(); 1453249423Sdim I != E; ++I) { 1454249423Sdim if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) 1455198092Srdivacky if (FD->getNumParams() == 1) 1456198092Srdivacky return false; 1457198092Srdivacky } 1458198092Srdivacky 1459198092Srdivacky return true; 1460198092Srdivacky} 1461193326Sed 1462207619Srdivackybool CXXMethodDecl::isCopyAssignmentOperator() const { 1463223017Sdim // C++0x [class.copy]p17: 1464207619Srdivacky // A user-declared copy assignment operator X::operator= is a non-static 1465207619Srdivacky // non-template member function of class X with exactly one parameter of 1466207619Srdivacky // type X, X&, const X&, volatile X& or const volatile X&. 1467207619Srdivacky if (/*operator=*/getOverloadedOperator() != OO_Equal || 1468207619Srdivacky /*non-static*/ isStatic() || 1469263508Sdim /*non-template*/getPrimaryTemplate() || getDescribedFunctionTemplate() || 1470263508Sdim getNumParams() != 1) 1471207619Srdivacky return false; 1472207619Srdivacky 1473207619Srdivacky QualType ParamType = getParamDecl(0)->getType(); 1474207619Srdivacky if (const LValueReferenceType *Ref = ParamType->getAs<LValueReferenceType>()) 1475207619Srdivacky ParamType = Ref->getPointeeType(); 1476207619Srdivacky 1477207619Srdivacky ASTContext &Context = getASTContext(); 1478207619Srdivacky QualType ClassType 1479207619Srdivacky = Context.getCanonicalType(Context.getTypeDeclType(getParent())); 1480207619Srdivacky return Context.hasSameUnqualifiedType(ClassType, ParamType); 1481207619Srdivacky} 1482207619Srdivacky 1483223017Sdimbool CXXMethodDecl::isMoveAssignmentOperator() const { 1484223017Sdim // C++0x [class.copy]p19: 1485223017Sdim // A user-declared move assignment operator X::operator= is a non-static 1486223017Sdim // non-template member function of class X with exactly one parameter of type 1487223017Sdim // X&&, const X&&, volatile X&&, or const volatile X&&. 1488223017Sdim if (getOverloadedOperator() != OO_Equal || isStatic() || 1489263508Sdim getPrimaryTemplate() || getDescribedFunctionTemplate() || 1490263508Sdim getNumParams() != 1) 1491223017Sdim return false; 1492223017Sdim 1493223017Sdim QualType ParamType = getParamDecl(0)->getType(); 1494223017Sdim if (!isa<RValueReferenceType>(ParamType)) 1495223017Sdim return false; 1496223017Sdim ParamType = ParamType->getPointeeType(); 1497223017Sdim 1498223017Sdim ASTContext &Context = getASTContext(); 1499223017Sdim QualType ClassType 1500223017Sdim = Context.getCanonicalType(Context.getTypeDeclType(getParent())); 1501223017Sdim return Context.hasSameUnqualifiedType(ClassType, ParamType); 1502223017Sdim} 1503223017Sdim 1504193326Sedvoid CXXMethodDecl::addOverriddenMethod(const CXXMethodDecl *MD) { 1505200583Srdivacky assert(MD->isCanonicalDecl() && "Method is not canonical!"); 1506203955Srdivacky assert(!MD->getParent()->isDependentContext() && 1507203955Srdivacky "Can't add an overridden method to a class template!"); 1508234353Sdim assert(MD->isVirtual() && "Method is not virtual!"); 1509203955Srdivacky 1510204643Srdivacky getASTContext().addOverriddenMethod(this, MD); 1511193326Sed} 1512193326Sed 1513193326SedCXXMethodDecl::method_iterator CXXMethodDecl::begin_overridden_methods() const { 1514234353Sdim if (isa<CXXConstructorDecl>(this)) return 0; 1515204643Srdivacky return getASTContext().overridden_methods_begin(this); 1516193326Sed} 1517193326Sed 1518193326SedCXXMethodDecl::method_iterator CXXMethodDecl::end_overridden_methods() const { 1519234353Sdim if (isa<CXXConstructorDecl>(this)) return 0; 1520204643Srdivacky return getASTContext().overridden_methods_end(this); 1521193326Sed} 1522193326Sed 1523210299Sedunsigned CXXMethodDecl::size_overridden_methods() const { 1524234353Sdim if (isa<CXXConstructorDecl>(this)) return 0; 1525210299Sed return getASTContext().overridden_methods_size(this); 1526210299Sed} 1527210299Sed 1528193326SedQualType CXXMethodDecl::getThisType(ASTContext &C) const { 1529193326Sed // C++ 9.3.2p1: The type of this in a member function of a class X is X*. 1530193326Sed // If the member function is declared const, the type of this is const X*, 1531193326Sed // if the member function is declared volatile, the type of this is 1532193326Sed // volatile X*, and if the member function is declared const volatile, 1533193326Sed // the type of this is const volatile X*. 1534193326Sed 1535193326Sed assert(isInstance() && "No 'this' for static methods!"); 1536194179Sed 1537204962Srdivacky QualType ClassTy = C.getTypeDeclType(getParent()); 1538198092Srdivacky ClassTy = C.getQualifiedType(ClassTy, 1539198092Srdivacky Qualifiers::fromCVRMask(getTypeQualifiers())); 1540198092Srdivacky return C.getPointerType(ClassTy); 1541193326Sed} 1542193326Sed 1543200583Srdivackybool CXXMethodDecl::hasInlineBody() const { 1544202379Srdivacky // If this function is a template instantiation, look at the template from 1545202379Srdivacky // which it was instantiated. 1546202379Srdivacky const FunctionDecl *CheckFn = getTemplateInstantiationPattern(); 1547202379Srdivacky if (!CheckFn) 1548202379Srdivacky CheckFn = this; 1549202379Srdivacky 1550200583Srdivacky const FunctionDecl *fn; 1551210299Sed return CheckFn->hasBody(fn) && !fn->isOutOfLine(); 1552200583Srdivacky} 1553200583Srdivacky 1554234353Sdimbool CXXMethodDecl::isLambdaStaticInvoker() const { 1555263508Sdim const CXXRecordDecl *P = getParent(); 1556263508Sdim if (P->isLambda()) { 1557263508Sdim if (const CXXMethodDecl *StaticInvoker = P->getLambdaStaticInvoker()) { 1558263508Sdim if (StaticInvoker == this) return true; 1559263508Sdim if (P->isGenericLambda() && this->isFunctionTemplateSpecialization()) 1560263508Sdim return StaticInvoker == this->getPrimaryTemplate()->getTemplatedDecl(); 1561263508Sdim } 1562263508Sdim } 1563263508Sdim return false; 1564234353Sdim} 1565234353Sdim 1566218893SdimCXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, 1567218893Sdim TypeSourceInfo *TInfo, bool IsVirtual, 1568218893Sdim SourceLocation L, Expr *Init, 1569218893Sdim SourceLocation R, 1570218893Sdim SourceLocation EllipsisLoc) 1571218893Sdim : Initializee(TInfo), MemberOrEllipsisLocation(EllipsisLoc), Init(Init), 1572234353Sdim LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(IsVirtual), 1573234353Sdim IsWritten(false), SourceOrderOrNumArrayIndices(0) 1574200583Srdivacky{ 1575193326Sed} 1576193326Sed 1577218893SdimCXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, 1578218893Sdim FieldDecl *Member, 1579218893Sdim SourceLocation MemberLoc, 1580218893Sdim SourceLocation L, Expr *Init, 1581218893Sdim SourceLocation R) 1582218893Sdim : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init), 1583234353Sdim LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false), 1584208600Srdivacky IsWritten(false), SourceOrderOrNumArrayIndices(0) 1585208600Srdivacky{ 1586208600Srdivacky} 1587208600Srdivacky 1588218893SdimCXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, 1589218893Sdim IndirectFieldDecl *Member, 1590218893Sdim SourceLocation MemberLoc, 1591218893Sdim SourceLocation L, Expr *Init, 1592218893Sdim SourceLocation R) 1593218893Sdim : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init), 1594234353Sdim LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false), 1595218893Sdim IsWritten(false), SourceOrderOrNumArrayIndices(0) 1596218893Sdim{ 1597218893Sdim} 1598218893Sdim 1599218893SdimCXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, 1600234353Sdim TypeSourceInfo *TInfo, 1601234353Sdim SourceLocation L, Expr *Init, 1602221345Sdim SourceLocation R) 1603234353Sdim : Initializee(TInfo), MemberOrEllipsisLocation(), Init(Init), 1604234353Sdim LParenLoc(L), RParenLoc(R), IsDelegating(true), IsVirtual(false), 1605221345Sdim IsWritten(false), SourceOrderOrNumArrayIndices(0) 1606221345Sdim{ 1607221345Sdim} 1608221345Sdim 1609221345SdimCXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, 1610218893Sdim FieldDecl *Member, 1611218893Sdim SourceLocation MemberLoc, 1612218893Sdim SourceLocation L, Expr *Init, 1613218893Sdim SourceLocation R, 1614218893Sdim VarDecl **Indices, 1615218893Sdim unsigned NumIndices) 1616218893Sdim : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init), 1617218893Sdim LParenLoc(L), RParenLoc(R), IsVirtual(false), 1618208600Srdivacky IsWritten(false), SourceOrderOrNumArrayIndices(NumIndices) 1619200583Srdivacky{ 1620208600Srdivacky VarDecl **MyIndices = reinterpret_cast<VarDecl **> (this + 1); 1621208600Srdivacky memcpy(MyIndices, Indices, NumIndices * sizeof(VarDecl *)); 1622193326Sed} 1623193326Sed 1624218893SdimCXXCtorInitializer *CXXCtorInitializer::Create(ASTContext &Context, 1625218893Sdim FieldDecl *Member, 1626218893Sdim SourceLocation MemberLoc, 1627218893Sdim SourceLocation L, Expr *Init, 1628218893Sdim SourceLocation R, 1629218893Sdim VarDecl **Indices, 1630218893Sdim unsigned NumIndices) { 1631218893Sdim void *Mem = Context.Allocate(sizeof(CXXCtorInitializer) + 1632208600Srdivacky sizeof(VarDecl *) * NumIndices, 1633218893Sdim llvm::alignOf<CXXCtorInitializer>()); 1634218893Sdim return new (Mem) CXXCtorInitializer(Context, Member, MemberLoc, L, Init, R, 1635218893Sdim Indices, NumIndices); 1636208600Srdivacky} 1637208600Srdivacky 1638218893SdimTypeLoc CXXCtorInitializer::getBaseClassLoc() const { 1639200583Srdivacky if (isBaseInitializer()) 1640218893Sdim return Initializee.get<TypeSourceInfo*>()->getTypeLoc(); 1641200583Srdivacky else 1642200583Srdivacky return TypeLoc(); 1643200583Srdivacky} 1644200583Srdivacky 1645218893Sdimconst Type *CXXCtorInitializer::getBaseClass() const { 1646200583Srdivacky if (isBaseInitializer()) 1647218893Sdim return Initializee.get<TypeSourceInfo*>()->getType().getTypePtr(); 1648200583Srdivacky else 1649200583Srdivacky return 0; 1650200583Srdivacky} 1651200583Srdivacky 1652218893SdimSourceLocation CXXCtorInitializer::getSourceLocation() const { 1653234353Sdim if (isAnyMemberInitializer()) 1654200583Srdivacky return getMemberLocation(); 1655223017Sdim 1656223017Sdim if (isInClassMemberInitializer()) 1657223017Sdim return getAnyMember()->getLocation(); 1658200583Srdivacky 1659234353Sdim if (TypeSourceInfo *TSInfo = Initializee.get<TypeSourceInfo*>()) 1660234353Sdim return TSInfo->getTypeLoc().getLocalSourceRange().getBegin(); 1661234353Sdim 1662234353Sdim return SourceLocation(); 1663200583Srdivacky} 1664200583Srdivacky 1665218893SdimSourceRange CXXCtorInitializer::getSourceRange() const { 1666223017Sdim if (isInClassMemberInitializer()) { 1667223017Sdim FieldDecl *D = getAnyMember(); 1668223017Sdim if (Expr *I = D->getInClassInitializer()) 1669223017Sdim return I->getSourceRange(); 1670223017Sdim return SourceRange(); 1671223017Sdim } 1672223017Sdim 1673200583Srdivacky return SourceRange(getSourceLocation(), getRParenLoc()); 1674200583Srdivacky} 1675200583Srdivacky 1676234353Sdimvoid CXXConstructorDecl::anchor() { } 1677234353Sdim 1678193326SedCXXConstructorDecl * 1679234353SdimCXXConstructorDecl::CreateDeserialized(ASTContext &C, unsigned ID) { 1680234353Sdim void *Mem = AllocateDeserializedDecl(C, ID, sizeof(CXXConstructorDecl)); 1681234353Sdim return new (Mem) CXXConstructorDecl(0, SourceLocation(),DeclarationNameInfo(), 1682234353Sdim QualType(), 0, false, false, false,false); 1683208600Srdivacky} 1684208600Srdivacky 1685208600SrdivackyCXXConstructorDecl * 1686193326SedCXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD, 1687221345Sdim SourceLocation StartLoc, 1688212904Sdim const DeclarationNameInfo &NameInfo, 1689200583Srdivacky QualType T, TypeSourceInfo *TInfo, 1690226633Sdim bool isExplicit, bool isInline, 1691226633Sdim bool isImplicitlyDeclared, bool isConstexpr) { 1692212904Sdim assert(NameInfo.getName().getNameKind() 1693212904Sdim == DeclarationName::CXXConstructorName && 1694193326Sed "Name must refer to a constructor"); 1695221345Sdim return new (C) CXXConstructorDecl(RD, StartLoc, NameInfo, T, TInfo, 1696226633Sdim isExplicit, isInline, isImplicitlyDeclared, 1697226633Sdim isConstexpr); 1698193326Sed} 1699193326Sed 1700234353SdimCXXConstructorDecl *CXXConstructorDecl::getTargetConstructor() const { 1701234353Sdim assert(isDelegatingConstructor() && "Not a delegating constructor!"); 1702234353Sdim Expr *E = (*init_begin())->getInit()->IgnoreImplicit(); 1703234353Sdim if (CXXConstructExpr *Construct = dyn_cast<CXXConstructExpr>(E)) 1704234353Sdim return Construct->getConstructor(); 1705234353Sdim 1706234353Sdim return 0; 1707234353Sdim} 1708234353Sdim 1709193326Sedbool CXXConstructorDecl::isDefaultConstructor() const { 1710193326Sed // C++ [class.ctor]p5: 1711193326Sed // A default constructor for a class X is a constructor of class 1712193326Sed // X that can be called without an argument. 1713193326Sed return (getNumParams() == 0) || 1714198092Srdivacky (getNumParams() > 0 && getParamDecl(0)->hasDefaultArg()); 1715193326Sed} 1716193326Sed 1717198092Srdivackybool 1718201361SrdivackyCXXConstructorDecl::isCopyConstructor(unsigned &TypeQuals) const { 1719218893Sdim return isCopyOrMoveConstructor(TypeQuals) && 1720218893Sdim getParamDecl(0)->getType()->isLValueReferenceType(); 1721218893Sdim} 1722218893Sdim 1723218893Sdimbool CXXConstructorDecl::isMoveConstructor(unsigned &TypeQuals) const { 1724218893Sdim return isCopyOrMoveConstructor(TypeQuals) && 1725218893Sdim getParamDecl(0)->getType()->isRValueReferenceType(); 1726218893Sdim} 1727218893Sdim 1728218893Sdim/// \brief Determine whether this is a copy or move constructor. 1729218893Sdimbool CXXConstructorDecl::isCopyOrMoveConstructor(unsigned &TypeQuals) const { 1730193326Sed // C++ [class.copy]p2: 1731193326Sed // A non-template constructor for class X is a copy constructor 1732193326Sed // if its first parameter is of type X&, const X&, volatile X& or 1733193326Sed // const volatile X&, and either there are no other parameters 1734193326Sed // or else all other parameters have default arguments (8.3.6). 1735218893Sdim // C++0x [class.copy]p3: 1736218893Sdim // A non-template constructor for class X is a move constructor if its 1737218893Sdim // first parameter is of type X&&, const X&&, volatile X&&, or 1738218893Sdim // const volatile X&&, and either there are no other parameters or else 1739218893Sdim // all other parameters have default arguments. 1740193326Sed if ((getNumParams() < 1) || 1741198092Srdivacky (getNumParams() > 1 && !getParamDecl(1)->hasDefaultArg()) || 1742198092Srdivacky (getPrimaryTemplate() != 0) || 1743198092Srdivacky (getDescribedFunctionTemplate() != 0)) 1744193326Sed return false; 1745218893Sdim 1746193326Sed const ParmVarDecl *Param = getParamDecl(0); 1747218893Sdim 1748218893Sdim // Do we have a reference type? 1749218893Sdim const ReferenceType *ParamRefType = Param->getType()->getAs<ReferenceType>(); 1750193326Sed if (!ParamRefType) 1751193326Sed return false; 1752218893Sdim 1753193326Sed // Is it a reference to our class type? 1754201361Srdivacky ASTContext &Context = getASTContext(); 1755201361Srdivacky 1756198092Srdivacky CanQualType PointeeType 1757193326Sed = Context.getCanonicalType(ParamRefType->getPointeeType()); 1758198092Srdivacky CanQualType ClassTy 1759198092Srdivacky = Context.getCanonicalType(Context.getTagDeclType(getParent())); 1760193326Sed if (PointeeType.getUnqualifiedType() != ClassTy) 1761193326Sed return false; 1762218893Sdim 1763198092Srdivacky // FIXME: other qualifiers? 1764218893Sdim 1765218893Sdim // We have a copy or move constructor. 1766193326Sed TypeQuals = PointeeType.getCVRQualifiers(); 1767218893Sdim return true; 1768193326Sed} 1769193326Sed 1770198092Srdivackybool CXXConstructorDecl::isConvertingConstructor(bool AllowExplicit) const { 1771193326Sed // C++ [class.conv.ctor]p1: 1772193326Sed // A constructor declared without the function-specifier explicit 1773193326Sed // that can be called with a single parameter specifies a 1774193326Sed // conversion from the type of its first parameter to the type of 1775193326Sed // its class. Such a constructor is called a converting 1776193326Sed // constructor. 1777198092Srdivacky if (isExplicit() && !AllowExplicit) 1778193326Sed return false; 1779193326Sed 1780198092Srdivacky return (getNumParams() == 0 && 1781198092Srdivacky getType()->getAs<FunctionProtoType>()->isVariadic()) || 1782193326Sed (getNumParams() == 1) || 1783239462Sdim (getNumParams() > 1 && 1784239462Sdim (getParamDecl(1)->hasDefaultArg() || 1785239462Sdim getParamDecl(1)->isParameterPack())); 1786193326Sed} 1787193326Sed 1788218893Sdimbool CXXConstructorDecl::isSpecializationCopyingObject() const { 1789199482Srdivacky if ((getNumParams() < 1) || 1790199482Srdivacky (getNumParams() > 1 && !getParamDecl(1)->hasDefaultArg()) || 1791199482Srdivacky (getPrimaryTemplate() == 0) || 1792199482Srdivacky (getDescribedFunctionTemplate() != 0)) 1793199482Srdivacky return false; 1794199482Srdivacky 1795199482Srdivacky const ParmVarDecl *Param = getParamDecl(0); 1796199482Srdivacky 1797199482Srdivacky ASTContext &Context = getASTContext(); 1798199482Srdivacky CanQualType ParamType = Context.getCanonicalType(Param->getType()); 1799199482Srdivacky 1800199482Srdivacky // Is it the same as our our class type? 1801199482Srdivacky CanQualType ClassTy 1802199482Srdivacky = Context.getCanonicalType(Context.getTagDeclType(getParent())); 1803199482Srdivacky if (ParamType.getUnqualifiedType() != ClassTy) 1804199482Srdivacky return false; 1805199482Srdivacky 1806199482Srdivacky return true; 1807199482Srdivacky} 1808199482Srdivacky 1809218893Sdimconst CXXConstructorDecl *CXXConstructorDecl::getInheritedConstructor() const { 1810218893Sdim // Hack: we store the inherited constructor in the overridden method table 1811234353Sdim method_iterator It = getASTContext().overridden_methods_begin(this); 1812234353Sdim if (It == getASTContext().overridden_methods_end(this)) 1813218893Sdim return 0; 1814218893Sdim 1815218893Sdim return cast<CXXConstructorDecl>(*It); 1816218893Sdim} 1817218893Sdim 1818218893Sdimvoid 1819218893SdimCXXConstructorDecl::setInheritedConstructor(const CXXConstructorDecl *BaseCtor){ 1820218893Sdim // Hack: we store the inherited constructor in the overridden method table 1821234353Sdim assert(getASTContext().overridden_methods_size(this) == 0 && 1822234353Sdim "Base ctor already set."); 1823234353Sdim getASTContext().addOverriddenMethod(this, BaseCtor); 1824218893Sdim} 1825218893Sdim 1826234353Sdimvoid CXXDestructorDecl::anchor() { } 1827234353Sdim 1828193326SedCXXDestructorDecl * 1829234353SdimCXXDestructorDecl::CreateDeserialized(ASTContext &C, unsigned ID) { 1830234353Sdim void *Mem = AllocateDeserializedDecl(C, ID, sizeof(CXXDestructorDecl)); 1831234353Sdim return new (Mem) CXXDestructorDecl(0, SourceLocation(), DeclarationNameInfo(), 1832218893Sdim QualType(), 0, false, false); 1833208600Srdivacky} 1834208600Srdivacky 1835208600SrdivackyCXXDestructorDecl * 1836193326SedCXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD, 1837221345Sdim SourceLocation StartLoc, 1838212904Sdim const DeclarationNameInfo &NameInfo, 1839218893Sdim QualType T, TypeSourceInfo *TInfo, 1840226633Sdim bool isInline, bool isImplicitlyDeclared) { 1841212904Sdim assert(NameInfo.getName().getNameKind() 1842212904Sdim == DeclarationName::CXXDestructorName && 1843193326Sed "Name must refer to a destructor"); 1844221345Sdim return new (C) CXXDestructorDecl(RD, StartLoc, NameInfo, T, TInfo, isInline, 1845212904Sdim isImplicitlyDeclared); 1846193326Sed} 1847193326Sed 1848234353Sdimvoid CXXConversionDecl::anchor() { } 1849234353Sdim 1850193326SedCXXConversionDecl * 1851234353SdimCXXConversionDecl::CreateDeserialized(ASTContext &C, unsigned ID) { 1852234353Sdim void *Mem = AllocateDeserializedDecl(C, ID, sizeof(CXXConversionDecl)); 1853234353Sdim return new (Mem) CXXConversionDecl(0, SourceLocation(), DeclarationNameInfo(), 1854234353Sdim QualType(), 0, false, false, false, 1855234353Sdim SourceLocation()); 1856208600Srdivacky} 1857208600Srdivacky 1858208600SrdivackyCXXConversionDecl * 1859193326SedCXXConversionDecl::Create(ASTContext &C, CXXRecordDecl *RD, 1860221345Sdim SourceLocation StartLoc, 1861212904Sdim const DeclarationNameInfo &NameInfo, 1862200583Srdivacky QualType T, TypeSourceInfo *TInfo, 1863221345Sdim bool isInline, bool isExplicit, 1864226633Sdim bool isConstexpr, SourceLocation EndLocation) { 1865212904Sdim assert(NameInfo.getName().getNameKind() 1866212904Sdim == DeclarationName::CXXConversionFunctionName && 1867193326Sed "Name must refer to a conversion function"); 1868221345Sdim return new (C) CXXConversionDecl(RD, StartLoc, NameInfo, T, TInfo, 1869226633Sdim isInline, isExplicit, isConstexpr, 1870226633Sdim EndLocation); 1871193326Sed} 1872193326Sed 1873234353Sdimbool CXXConversionDecl::isLambdaToBlockPointerConversion() const { 1874234353Sdim return isImplicit() && getParent()->isLambda() && 1875234353Sdim getConversionType()->isBlockPointerType(); 1876234353Sdim} 1877234353Sdim 1878234353Sdimvoid LinkageSpecDecl::anchor() { } 1879234353Sdim 1880193326SedLinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C, 1881198092Srdivacky DeclContext *DC, 1882221345Sdim SourceLocation ExternLoc, 1883221345Sdim SourceLocation LangLoc, 1884221345Sdim LanguageIDs Lang, 1885251662Sdim bool HasBraces) { 1886251662Sdim return new (C) LinkageSpecDecl(DC, ExternLoc, LangLoc, Lang, HasBraces); 1887193326Sed} 1888193326Sed 1889234353SdimLinkageSpecDecl *LinkageSpecDecl::CreateDeserialized(ASTContext &C, unsigned ID) { 1890234353Sdim void *Mem = AllocateDeserializedDecl(C, ID, sizeof(LinkageSpecDecl)); 1891234353Sdim return new (Mem) LinkageSpecDecl(0, SourceLocation(), SourceLocation(), 1892251662Sdim lang_c, false); 1893234353Sdim} 1894234353Sdim 1895234353Sdimvoid UsingDirectiveDecl::anchor() { } 1896234353Sdim 1897193326SedUsingDirectiveDecl *UsingDirectiveDecl::Create(ASTContext &C, DeclContext *DC, 1898193326Sed SourceLocation L, 1899193326Sed SourceLocation NamespaceLoc, 1900219077Sdim NestedNameSpecifierLoc QualifierLoc, 1901193326Sed SourceLocation IdentLoc, 1902199990Srdivacky NamedDecl *Used, 1903193326Sed DeclContext *CommonAncestor) { 1904199990Srdivacky if (NamespaceDecl *NS = dyn_cast_or_null<NamespaceDecl>(Used)) 1905199990Srdivacky Used = NS->getOriginalNamespace(); 1906219077Sdim return new (C) UsingDirectiveDecl(DC, L, NamespaceLoc, QualifierLoc, 1907219077Sdim IdentLoc, Used, CommonAncestor); 1908193326Sed} 1909193326Sed 1910234353SdimUsingDirectiveDecl * 1911234353SdimUsingDirectiveDecl::CreateDeserialized(ASTContext &C, unsigned ID) { 1912234353Sdim void *Mem = AllocateDeserializedDecl(C, ID, sizeof(UsingDirectiveDecl)); 1913234353Sdim return new (Mem) UsingDirectiveDecl(0, SourceLocation(), SourceLocation(), 1914234353Sdim NestedNameSpecifierLoc(), 1915234353Sdim SourceLocation(), 0, 0); 1916234353Sdim} 1917234353Sdim 1918199990SrdivackyNamespaceDecl *UsingDirectiveDecl::getNominatedNamespace() { 1919199990Srdivacky if (NamespaceAliasDecl *NA = 1920199990Srdivacky dyn_cast_or_null<NamespaceAliasDecl>(NominatedNamespace)) 1921199990Srdivacky return NA->getNamespace(); 1922199990Srdivacky return cast_or_null<NamespaceDecl>(NominatedNamespace); 1923199990Srdivacky} 1924199990Srdivacky 1925234353Sdimvoid NamespaceDecl::anchor() { } 1926234353Sdim 1927234353SdimNamespaceDecl::NamespaceDecl(DeclContext *DC, bool Inline, 1928234353Sdim SourceLocation StartLoc, 1929234353Sdim SourceLocation IdLoc, IdentifierInfo *Id, 1930234353Sdim NamespaceDecl *PrevDecl) 1931234353Sdim : NamedDecl(Namespace, DC, IdLoc, Id), DeclContext(Namespace), 1932234353Sdim LocStart(StartLoc), RBraceLoc(), AnonOrFirstNamespaceAndInline(0, Inline) 1933234353Sdim{ 1934263508Sdim setPreviousDecl(PrevDecl); 1935234353Sdim 1936234353Sdim if (PrevDecl) 1937234353Sdim AnonOrFirstNamespaceAndInline.setPointer(PrevDecl->getOriginalNamespace()); 1938234353Sdim} 1939234353Sdim 1940234353SdimNamespaceDecl *NamespaceDecl::Create(ASTContext &C, DeclContext *DC, 1941234353Sdim bool Inline, SourceLocation StartLoc, 1942234353Sdim SourceLocation IdLoc, IdentifierInfo *Id, 1943234353Sdim NamespaceDecl *PrevDecl) { 1944234353Sdim return new (C) NamespaceDecl(DC, Inline, StartLoc, IdLoc, Id, PrevDecl); 1945234353Sdim} 1946234353Sdim 1947234353SdimNamespaceDecl *NamespaceDecl::CreateDeserialized(ASTContext &C, unsigned ID) { 1948234353Sdim void *Mem = AllocateDeserializedDecl(C, ID, sizeof(NamespaceDecl)); 1949234353Sdim return new (Mem) NamespaceDecl(0, false, SourceLocation(), SourceLocation(), 1950234353Sdim 0, 0); 1951234353Sdim} 1952234353Sdim 1953234353Sdimvoid NamespaceAliasDecl::anchor() { } 1954234353Sdim 1955198092SrdivackyNamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC, 1956212904Sdim SourceLocation UsingLoc, 1957198092Srdivacky SourceLocation AliasLoc, 1958198092Srdivacky IdentifierInfo *Alias, 1959219077Sdim NestedNameSpecifierLoc QualifierLoc, 1960198092Srdivacky SourceLocation IdentLoc, 1961193326Sed NamedDecl *Namespace) { 1962199990Srdivacky if (NamespaceDecl *NS = dyn_cast_or_null<NamespaceDecl>(Namespace)) 1963199990Srdivacky Namespace = NS->getOriginalNamespace(); 1964219077Sdim return new (C) NamespaceAliasDecl(DC, UsingLoc, AliasLoc, Alias, 1965219077Sdim QualifierLoc, IdentLoc, Namespace); 1966193326Sed} 1967193326Sed 1968234353SdimNamespaceAliasDecl * 1969234353SdimNamespaceAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) { 1970234353Sdim void *Mem = AllocateDeserializedDecl(C, ID, sizeof(NamespaceAliasDecl)); 1971234353Sdim return new (Mem) NamespaceAliasDecl(0, SourceLocation(), SourceLocation(), 0, 1972234353Sdim NestedNameSpecifierLoc(), 1973234353Sdim SourceLocation(), 0); 1974234353Sdim} 1975234353Sdim 1976234353Sdimvoid UsingShadowDecl::anchor() { } 1977234353Sdim 1978234353SdimUsingShadowDecl * 1979234353SdimUsingShadowDecl::CreateDeserialized(ASTContext &C, unsigned ID) { 1980234353Sdim void *Mem = AllocateDeserializedDecl(C, ID, sizeof(UsingShadowDecl)); 1981234353Sdim return new (Mem) UsingShadowDecl(0, SourceLocation(), 0, 0); 1982234353Sdim} 1983234353Sdim 1984218893SdimUsingDecl *UsingShadowDecl::getUsingDecl() const { 1985218893Sdim const UsingShadowDecl *Shadow = this; 1986218893Sdim while (const UsingShadowDecl *NextShadow = 1987218893Sdim dyn_cast<UsingShadowDecl>(Shadow->UsingOrNextShadow)) 1988218893Sdim Shadow = NextShadow; 1989218893Sdim return cast<UsingDecl>(Shadow->UsingOrNextShadow); 1990218893Sdim} 1991218893Sdim 1992234353Sdimvoid UsingDecl::anchor() { } 1993234353Sdim 1994218893Sdimvoid UsingDecl::addShadowDecl(UsingShadowDecl *S) { 1995218893Sdim assert(std::find(shadow_begin(), shadow_end(), S) == shadow_end() && 1996218893Sdim "declaration already in set"); 1997218893Sdim assert(S->getUsingDecl() == this); 1998218893Sdim 1999234353Sdim if (FirstUsingShadow.getPointer()) 2000234353Sdim S->UsingOrNextShadow = FirstUsingShadow.getPointer(); 2001234353Sdim FirstUsingShadow.setPointer(S); 2002218893Sdim} 2003218893Sdim 2004218893Sdimvoid UsingDecl::removeShadowDecl(UsingShadowDecl *S) { 2005218893Sdim assert(std::find(shadow_begin(), shadow_end(), S) != shadow_end() && 2006218893Sdim "declaration not in set"); 2007218893Sdim assert(S->getUsingDecl() == this); 2008218893Sdim 2009218893Sdim // Remove S from the shadow decl chain. This is O(n) but hopefully rare. 2010218893Sdim 2011234353Sdim if (FirstUsingShadow.getPointer() == S) { 2012234353Sdim FirstUsingShadow.setPointer( 2013234353Sdim dyn_cast<UsingShadowDecl>(S->UsingOrNextShadow)); 2014218893Sdim S->UsingOrNextShadow = this; 2015218893Sdim return; 2016218893Sdim } 2017218893Sdim 2018234353Sdim UsingShadowDecl *Prev = FirstUsingShadow.getPointer(); 2019218893Sdim while (Prev->UsingOrNextShadow != S) 2020218893Sdim Prev = cast<UsingShadowDecl>(Prev->UsingOrNextShadow); 2021218893Sdim Prev->UsingOrNextShadow = S->UsingOrNextShadow; 2022218893Sdim S->UsingOrNextShadow = this; 2023218893Sdim} 2024218893Sdim 2025219077SdimUsingDecl *UsingDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation UL, 2026219077Sdim NestedNameSpecifierLoc QualifierLoc, 2027212904Sdim const DeclarationNameInfo &NameInfo, 2028263508Sdim bool HasTypename) { 2029263508Sdim return new (C) UsingDecl(DC, UL, QualifierLoc, NameInfo, HasTypename); 2030194613Sed} 2031194613Sed 2032234353SdimUsingDecl *UsingDecl::CreateDeserialized(ASTContext &C, unsigned ID) { 2033234353Sdim void *Mem = AllocateDeserializedDecl(C, ID, sizeof(UsingDecl)); 2034234353Sdim return new (Mem) UsingDecl(0, SourceLocation(), NestedNameSpecifierLoc(), 2035234353Sdim DeclarationNameInfo(), false); 2036234353Sdim} 2037234353Sdim 2038263508SdimSourceRange UsingDecl::getSourceRange() const { 2039263508Sdim SourceLocation Begin = isAccessDeclaration() 2040263508Sdim ? getQualifierLoc().getBeginLoc() : UsingLocation; 2041263508Sdim return SourceRange(Begin, getNameInfo().getEndLoc()); 2042263508Sdim} 2043263508Sdim 2044234353Sdimvoid UnresolvedUsingValueDecl::anchor() { } 2045234353Sdim 2046199482SrdivackyUnresolvedUsingValueDecl * 2047199482SrdivackyUnresolvedUsingValueDecl::Create(ASTContext &C, DeclContext *DC, 2048199482Srdivacky SourceLocation UsingLoc, 2049219077Sdim NestedNameSpecifierLoc QualifierLoc, 2050212904Sdim const DeclarationNameInfo &NameInfo) { 2051199482Srdivacky return new (C) UnresolvedUsingValueDecl(DC, C.DependentTy, UsingLoc, 2052219077Sdim QualifierLoc, NameInfo); 2053198092Srdivacky} 2054198092Srdivacky 2055234353SdimUnresolvedUsingValueDecl * 2056234353SdimUnresolvedUsingValueDecl::CreateDeserialized(ASTContext &C, unsigned ID) { 2057234353Sdim void *Mem = AllocateDeserializedDecl(C, ID, sizeof(UnresolvedUsingValueDecl)); 2058234353Sdim return new (Mem) UnresolvedUsingValueDecl(0, QualType(), SourceLocation(), 2059234353Sdim NestedNameSpecifierLoc(), 2060234353Sdim DeclarationNameInfo()); 2061234353Sdim} 2062234353Sdim 2063263508SdimSourceRange UnresolvedUsingValueDecl::getSourceRange() const { 2064263508Sdim SourceLocation Begin = isAccessDeclaration() 2065263508Sdim ? getQualifierLoc().getBeginLoc() : UsingLocation; 2066263508Sdim return SourceRange(Begin, getNameInfo().getEndLoc()); 2067263508Sdim} 2068263508Sdim 2069234353Sdimvoid UnresolvedUsingTypenameDecl::anchor() { } 2070234353Sdim 2071199482SrdivackyUnresolvedUsingTypenameDecl * 2072199482SrdivackyUnresolvedUsingTypenameDecl::Create(ASTContext &C, DeclContext *DC, 2073199482Srdivacky SourceLocation UsingLoc, 2074199482Srdivacky SourceLocation TypenameLoc, 2075219077Sdim NestedNameSpecifierLoc QualifierLoc, 2076199482Srdivacky SourceLocation TargetNameLoc, 2077199482Srdivacky DeclarationName TargetName) { 2078199482Srdivacky return new (C) UnresolvedUsingTypenameDecl(DC, UsingLoc, TypenameLoc, 2079219077Sdim QualifierLoc, TargetNameLoc, 2080199482Srdivacky TargetName.getAsIdentifierInfo()); 2081199482Srdivacky} 2082199482Srdivacky 2083234353SdimUnresolvedUsingTypenameDecl * 2084234353SdimUnresolvedUsingTypenameDecl::CreateDeserialized(ASTContext &C, unsigned ID) { 2085234353Sdim void *Mem = AllocateDeserializedDecl(C, ID, 2086234353Sdim sizeof(UnresolvedUsingTypenameDecl)); 2087234353Sdim return new (Mem) UnresolvedUsingTypenameDecl(0, SourceLocation(), 2088234353Sdim SourceLocation(), 2089234353Sdim NestedNameSpecifierLoc(), 2090234353Sdim SourceLocation(), 2091234353Sdim 0); 2092234353Sdim} 2093234353Sdim 2094234353Sdimvoid StaticAssertDecl::anchor() { } 2095234353Sdim 2096193326SedStaticAssertDecl *StaticAssertDecl::Create(ASTContext &C, DeclContext *DC, 2097221345Sdim SourceLocation StaticAssertLoc, 2098221345Sdim Expr *AssertExpr, 2099221345Sdim StringLiteral *Message, 2100239462Sdim SourceLocation RParenLoc, 2101239462Sdim bool Failed) { 2102221345Sdim return new (C) StaticAssertDecl(DC, StaticAssertLoc, AssertExpr, Message, 2103239462Sdim RParenLoc, Failed); 2104193326Sed} 2105193326Sed 2106234353SdimStaticAssertDecl *StaticAssertDecl::CreateDeserialized(ASTContext &C, 2107234353Sdim unsigned ID) { 2108234353Sdim void *Mem = AllocateDeserializedDecl(C, ID, sizeof(StaticAssertDecl)); 2109239462Sdim return new (Mem) StaticAssertDecl(0, SourceLocation(), 0, 0, 2110239462Sdim SourceLocation(), false); 2111234353Sdim} 2112234353Sdim 2113193326Sedstatic const char *getAccessName(AccessSpecifier AS) { 2114193326Sed switch (AS) { 2115193326Sed case AS_none: 2116226633Sdim llvm_unreachable("Invalid access specifier!"); 2117193326Sed case AS_public: 2118193326Sed return "public"; 2119193326Sed case AS_private: 2120193326Sed return "private"; 2121193326Sed case AS_protected: 2122193326Sed return "protected"; 2123193326Sed } 2124234353Sdim llvm_unreachable("Invalid access specifier!"); 2125193326Sed} 2126193326Sed 2127193326Sedconst DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, 2128193326Sed AccessSpecifier AS) { 2129193326Sed return DB << getAccessName(AS); 2130193326Sed} 2131234353Sdim 2132234353Sdimconst PartialDiagnostic &clang::operator<<(const PartialDiagnostic &DB, 2133234353Sdim AccessSpecifier AS) { 2134234353Sdim return DB << getAccessName(AS); 2135234353Sdim} 2136