1*f4a2713aSLionel Sambuc //===---- SemaAccess.cpp - C++ Access Control -------------------*- C++ -*-===// 2*f4a2713aSLionel Sambuc // 3*f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure 4*f4a2713aSLionel Sambuc // 5*f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source 6*f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details. 7*f4a2713aSLionel Sambuc // 8*f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===// 9*f4a2713aSLionel Sambuc // 10*f4a2713aSLionel Sambuc // This file provides Sema routines for C++ access control semantics. 11*f4a2713aSLionel Sambuc // 12*f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===// 13*f4a2713aSLionel Sambuc 14*f4a2713aSLionel Sambuc #include "clang/Sema/SemaInternal.h" 15*f4a2713aSLionel Sambuc #include "clang/AST/ASTContext.h" 16*f4a2713aSLionel Sambuc #include "clang/AST/CXXInheritance.h" 17*f4a2713aSLionel Sambuc #include "clang/AST/DeclCXX.h" 18*f4a2713aSLionel Sambuc #include "clang/AST/DeclFriend.h" 19*f4a2713aSLionel Sambuc #include "clang/AST/DeclObjC.h" 20*f4a2713aSLionel Sambuc #include "clang/AST/DependentDiagnostic.h" 21*f4a2713aSLionel Sambuc #include "clang/AST/ExprCXX.h" 22*f4a2713aSLionel Sambuc #include "clang/Sema/DelayedDiagnostic.h" 23*f4a2713aSLionel Sambuc #include "clang/Sema/Initialization.h" 24*f4a2713aSLionel Sambuc #include "clang/Sema/Lookup.h" 25*f4a2713aSLionel Sambuc 26*f4a2713aSLionel Sambuc using namespace clang; 27*f4a2713aSLionel Sambuc using namespace sema; 28*f4a2713aSLionel Sambuc 29*f4a2713aSLionel Sambuc /// A copy of Sema's enum without AR_delayed. 30*f4a2713aSLionel Sambuc enum AccessResult { 31*f4a2713aSLionel Sambuc AR_accessible, 32*f4a2713aSLionel Sambuc AR_inaccessible, 33*f4a2713aSLionel Sambuc AR_dependent 34*f4a2713aSLionel Sambuc }; 35*f4a2713aSLionel Sambuc 36*f4a2713aSLionel Sambuc /// SetMemberAccessSpecifier - Set the access specifier of a member. 37*f4a2713aSLionel Sambuc /// Returns true on error (when the previous member decl access specifier 38*f4a2713aSLionel Sambuc /// is different from the new member decl access specifier). 39*f4a2713aSLionel Sambuc bool Sema::SetMemberAccessSpecifier(NamedDecl *MemberDecl, 40*f4a2713aSLionel Sambuc NamedDecl *PrevMemberDecl, 41*f4a2713aSLionel Sambuc AccessSpecifier LexicalAS) { 42*f4a2713aSLionel Sambuc if (!PrevMemberDecl) { 43*f4a2713aSLionel Sambuc // Use the lexical access specifier. 44*f4a2713aSLionel Sambuc MemberDecl->setAccess(LexicalAS); 45*f4a2713aSLionel Sambuc return false; 46*f4a2713aSLionel Sambuc } 47*f4a2713aSLionel Sambuc 48*f4a2713aSLionel Sambuc // C++ [class.access.spec]p3: When a member is redeclared its access 49*f4a2713aSLionel Sambuc // specifier must be same as its initial declaration. 50*f4a2713aSLionel Sambuc if (LexicalAS != AS_none && LexicalAS != PrevMemberDecl->getAccess()) { 51*f4a2713aSLionel Sambuc Diag(MemberDecl->getLocation(), 52*f4a2713aSLionel Sambuc diag::err_class_redeclared_with_different_access) 53*f4a2713aSLionel Sambuc << MemberDecl << LexicalAS; 54*f4a2713aSLionel Sambuc Diag(PrevMemberDecl->getLocation(), diag::note_previous_access_declaration) 55*f4a2713aSLionel Sambuc << PrevMemberDecl << PrevMemberDecl->getAccess(); 56*f4a2713aSLionel Sambuc 57*f4a2713aSLionel Sambuc MemberDecl->setAccess(LexicalAS); 58*f4a2713aSLionel Sambuc return true; 59*f4a2713aSLionel Sambuc } 60*f4a2713aSLionel Sambuc 61*f4a2713aSLionel Sambuc MemberDecl->setAccess(PrevMemberDecl->getAccess()); 62*f4a2713aSLionel Sambuc return false; 63*f4a2713aSLionel Sambuc } 64*f4a2713aSLionel Sambuc 65*f4a2713aSLionel Sambuc static CXXRecordDecl *FindDeclaringClass(NamedDecl *D) { 66*f4a2713aSLionel Sambuc DeclContext *DC = D->getDeclContext(); 67*f4a2713aSLionel Sambuc 68*f4a2713aSLionel Sambuc // This can only happen at top: enum decls only "publish" their 69*f4a2713aSLionel Sambuc // immediate members. 70*f4a2713aSLionel Sambuc if (isa<EnumDecl>(DC)) 71*f4a2713aSLionel Sambuc DC = cast<EnumDecl>(DC)->getDeclContext(); 72*f4a2713aSLionel Sambuc 73*f4a2713aSLionel Sambuc CXXRecordDecl *DeclaringClass = cast<CXXRecordDecl>(DC); 74*f4a2713aSLionel Sambuc while (DeclaringClass->isAnonymousStructOrUnion()) 75*f4a2713aSLionel Sambuc DeclaringClass = cast<CXXRecordDecl>(DeclaringClass->getDeclContext()); 76*f4a2713aSLionel Sambuc return DeclaringClass; 77*f4a2713aSLionel Sambuc } 78*f4a2713aSLionel Sambuc 79*f4a2713aSLionel Sambuc namespace { 80*f4a2713aSLionel Sambuc struct EffectiveContext { 81*f4a2713aSLionel Sambuc EffectiveContext() : Inner(0), Dependent(false) {} 82*f4a2713aSLionel Sambuc 83*f4a2713aSLionel Sambuc explicit EffectiveContext(DeclContext *DC) 84*f4a2713aSLionel Sambuc : Inner(DC), 85*f4a2713aSLionel Sambuc Dependent(DC->isDependentContext()) { 86*f4a2713aSLionel Sambuc 87*f4a2713aSLionel Sambuc // C++11 [class.access.nest]p1: 88*f4a2713aSLionel Sambuc // A nested class is a member and as such has the same access 89*f4a2713aSLionel Sambuc // rights as any other member. 90*f4a2713aSLionel Sambuc // C++11 [class.access]p2: 91*f4a2713aSLionel Sambuc // A member of a class can also access all the names to which 92*f4a2713aSLionel Sambuc // the class has access. A local class of a member function 93*f4a2713aSLionel Sambuc // may access the same names that the member function itself 94*f4a2713aSLionel Sambuc // may access. 95*f4a2713aSLionel Sambuc // This almost implies that the privileges of nesting are transitive. 96*f4a2713aSLionel Sambuc // Technically it says nothing about the local classes of non-member 97*f4a2713aSLionel Sambuc // functions (which can gain privileges through friendship), but we 98*f4a2713aSLionel Sambuc // take that as an oversight. 99*f4a2713aSLionel Sambuc while (true) { 100*f4a2713aSLionel Sambuc // We want to add canonical declarations to the EC lists for 101*f4a2713aSLionel Sambuc // simplicity of checking, but we need to walk up through the 102*f4a2713aSLionel Sambuc // actual current DC chain. Otherwise, something like a local 103*f4a2713aSLionel Sambuc // extern or friend which happens to be the canonical 104*f4a2713aSLionel Sambuc // declaration will really mess us up. 105*f4a2713aSLionel Sambuc 106*f4a2713aSLionel Sambuc if (isa<CXXRecordDecl>(DC)) { 107*f4a2713aSLionel Sambuc CXXRecordDecl *Record = cast<CXXRecordDecl>(DC); 108*f4a2713aSLionel Sambuc Records.push_back(Record->getCanonicalDecl()); 109*f4a2713aSLionel Sambuc DC = Record->getDeclContext(); 110*f4a2713aSLionel Sambuc } else if (isa<FunctionDecl>(DC)) { 111*f4a2713aSLionel Sambuc FunctionDecl *Function = cast<FunctionDecl>(DC); 112*f4a2713aSLionel Sambuc Functions.push_back(Function->getCanonicalDecl()); 113*f4a2713aSLionel Sambuc if (Function->getFriendObjectKind()) 114*f4a2713aSLionel Sambuc DC = Function->getLexicalDeclContext(); 115*f4a2713aSLionel Sambuc else 116*f4a2713aSLionel Sambuc DC = Function->getDeclContext(); 117*f4a2713aSLionel Sambuc } else if (DC->isFileContext()) { 118*f4a2713aSLionel Sambuc break; 119*f4a2713aSLionel Sambuc } else { 120*f4a2713aSLionel Sambuc DC = DC->getParent(); 121*f4a2713aSLionel Sambuc } 122*f4a2713aSLionel Sambuc } 123*f4a2713aSLionel Sambuc } 124*f4a2713aSLionel Sambuc 125*f4a2713aSLionel Sambuc bool isDependent() const { return Dependent; } 126*f4a2713aSLionel Sambuc 127*f4a2713aSLionel Sambuc bool includesClass(const CXXRecordDecl *R) const { 128*f4a2713aSLionel Sambuc R = R->getCanonicalDecl(); 129*f4a2713aSLionel Sambuc return std::find(Records.begin(), Records.end(), R) 130*f4a2713aSLionel Sambuc != Records.end(); 131*f4a2713aSLionel Sambuc } 132*f4a2713aSLionel Sambuc 133*f4a2713aSLionel Sambuc /// Retrieves the innermost "useful" context. Can be null if we're 134*f4a2713aSLionel Sambuc /// doing access-control without privileges. 135*f4a2713aSLionel Sambuc DeclContext *getInnerContext() const { 136*f4a2713aSLionel Sambuc return Inner; 137*f4a2713aSLionel Sambuc } 138*f4a2713aSLionel Sambuc 139*f4a2713aSLionel Sambuc typedef SmallVectorImpl<CXXRecordDecl*>::const_iterator record_iterator; 140*f4a2713aSLionel Sambuc 141*f4a2713aSLionel Sambuc DeclContext *Inner; 142*f4a2713aSLionel Sambuc SmallVector<FunctionDecl*, 4> Functions; 143*f4a2713aSLionel Sambuc SmallVector<CXXRecordDecl*, 4> Records; 144*f4a2713aSLionel Sambuc bool Dependent; 145*f4a2713aSLionel Sambuc }; 146*f4a2713aSLionel Sambuc 147*f4a2713aSLionel Sambuc /// Like sema::AccessedEntity, but kindly lets us scribble all over 148*f4a2713aSLionel Sambuc /// it. 149*f4a2713aSLionel Sambuc struct AccessTarget : public AccessedEntity { 150*f4a2713aSLionel Sambuc AccessTarget(const AccessedEntity &Entity) 151*f4a2713aSLionel Sambuc : AccessedEntity(Entity) { 152*f4a2713aSLionel Sambuc initialize(); 153*f4a2713aSLionel Sambuc } 154*f4a2713aSLionel Sambuc 155*f4a2713aSLionel Sambuc AccessTarget(ASTContext &Context, 156*f4a2713aSLionel Sambuc MemberNonce _, 157*f4a2713aSLionel Sambuc CXXRecordDecl *NamingClass, 158*f4a2713aSLionel Sambuc DeclAccessPair FoundDecl, 159*f4a2713aSLionel Sambuc QualType BaseObjectType) 160*f4a2713aSLionel Sambuc : AccessedEntity(Context.getDiagAllocator(), Member, NamingClass, 161*f4a2713aSLionel Sambuc FoundDecl, BaseObjectType) { 162*f4a2713aSLionel Sambuc initialize(); 163*f4a2713aSLionel Sambuc } 164*f4a2713aSLionel Sambuc 165*f4a2713aSLionel Sambuc AccessTarget(ASTContext &Context, 166*f4a2713aSLionel Sambuc BaseNonce _, 167*f4a2713aSLionel Sambuc CXXRecordDecl *BaseClass, 168*f4a2713aSLionel Sambuc CXXRecordDecl *DerivedClass, 169*f4a2713aSLionel Sambuc AccessSpecifier Access) 170*f4a2713aSLionel Sambuc : AccessedEntity(Context.getDiagAllocator(), Base, BaseClass, DerivedClass, 171*f4a2713aSLionel Sambuc Access) { 172*f4a2713aSLionel Sambuc initialize(); 173*f4a2713aSLionel Sambuc } 174*f4a2713aSLionel Sambuc 175*f4a2713aSLionel Sambuc bool isInstanceMember() const { 176*f4a2713aSLionel Sambuc return (isMemberAccess() && getTargetDecl()->isCXXInstanceMember()); 177*f4a2713aSLionel Sambuc } 178*f4a2713aSLionel Sambuc 179*f4a2713aSLionel Sambuc bool hasInstanceContext() const { 180*f4a2713aSLionel Sambuc return HasInstanceContext; 181*f4a2713aSLionel Sambuc } 182*f4a2713aSLionel Sambuc 183*f4a2713aSLionel Sambuc class SavedInstanceContext { 184*f4a2713aSLionel Sambuc public: 185*f4a2713aSLionel Sambuc ~SavedInstanceContext() { 186*f4a2713aSLionel Sambuc Target.HasInstanceContext = Has; 187*f4a2713aSLionel Sambuc } 188*f4a2713aSLionel Sambuc 189*f4a2713aSLionel Sambuc private: 190*f4a2713aSLionel Sambuc friend struct AccessTarget; 191*f4a2713aSLionel Sambuc explicit SavedInstanceContext(AccessTarget &Target) 192*f4a2713aSLionel Sambuc : Target(Target), Has(Target.HasInstanceContext) {} 193*f4a2713aSLionel Sambuc AccessTarget &Target; 194*f4a2713aSLionel Sambuc bool Has; 195*f4a2713aSLionel Sambuc }; 196*f4a2713aSLionel Sambuc 197*f4a2713aSLionel Sambuc SavedInstanceContext saveInstanceContext() { 198*f4a2713aSLionel Sambuc return SavedInstanceContext(*this); 199*f4a2713aSLionel Sambuc } 200*f4a2713aSLionel Sambuc 201*f4a2713aSLionel Sambuc void suppressInstanceContext() { 202*f4a2713aSLionel Sambuc HasInstanceContext = false; 203*f4a2713aSLionel Sambuc } 204*f4a2713aSLionel Sambuc 205*f4a2713aSLionel Sambuc const CXXRecordDecl *resolveInstanceContext(Sema &S) const { 206*f4a2713aSLionel Sambuc assert(HasInstanceContext); 207*f4a2713aSLionel Sambuc if (CalculatedInstanceContext) 208*f4a2713aSLionel Sambuc return InstanceContext; 209*f4a2713aSLionel Sambuc 210*f4a2713aSLionel Sambuc CalculatedInstanceContext = true; 211*f4a2713aSLionel Sambuc DeclContext *IC = S.computeDeclContext(getBaseObjectType()); 212*f4a2713aSLionel Sambuc InstanceContext = (IC ? cast<CXXRecordDecl>(IC)->getCanonicalDecl() : 0); 213*f4a2713aSLionel Sambuc return InstanceContext; 214*f4a2713aSLionel Sambuc } 215*f4a2713aSLionel Sambuc 216*f4a2713aSLionel Sambuc const CXXRecordDecl *getDeclaringClass() const { 217*f4a2713aSLionel Sambuc return DeclaringClass; 218*f4a2713aSLionel Sambuc } 219*f4a2713aSLionel Sambuc 220*f4a2713aSLionel Sambuc /// The "effective" naming class is the canonical non-anonymous 221*f4a2713aSLionel Sambuc /// class containing the actual naming class. 222*f4a2713aSLionel Sambuc const CXXRecordDecl *getEffectiveNamingClass() const { 223*f4a2713aSLionel Sambuc const CXXRecordDecl *namingClass = getNamingClass(); 224*f4a2713aSLionel Sambuc while (namingClass->isAnonymousStructOrUnion()) 225*f4a2713aSLionel Sambuc namingClass = cast<CXXRecordDecl>(namingClass->getParent()); 226*f4a2713aSLionel Sambuc return namingClass->getCanonicalDecl(); 227*f4a2713aSLionel Sambuc } 228*f4a2713aSLionel Sambuc 229*f4a2713aSLionel Sambuc private: 230*f4a2713aSLionel Sambuc void initialize() { 231*f4a2713aSLionel Sambuc HasInstanceContext = (isMemberAccess() && 232*f4a2713aSLionel Sambuc !getBaseObjectType().isNull() && 233*f4a2713aSLionel Sambuc getTargetDecl()->isCXXInstanceMember()); 234*f4a2713aSLionel Sambuc CalculatedInstanceContext = false; 235*f4a2713aSLionel Sambuc InstanceContext = 0; 236*f4a2713aSLionel Sambuc 237*f4a2713aSLionel Sambuc if (isMemberAccess()) 238*f4a2713aSLionel Sambuc DeclaringClass = FindDeclaringClass(getTargetDecl()); 239*f4a2713aSLionel Sambuc else 240*f4a2713aSLionel Sambuc DeclaringClass = getBaseClass(); 241*f4a2713aSLionel Sambuc DeclaringClass = DeclaringClass->getCanonicalDecl(); 242*f4a2713aSLionel Sambuc } 243*f4a2713aSLionel Sambuc 244*f4a2713aSLionel Sambuc bool HasInstanceContext : 1; 245*f4a2713aSLionel Sambuc mutable bool CalculatedInstanceContext : 1; 246*f4a2713aSLionel Sambuc mutable const CXXRecordDecl *InstanceContext; 247*f4a2713aSLionel Sambuc const CXXRecordDecl *DeclaringClass; 248*f4a2713aSLionel Sambuc }; 249*f4a2713aSLionel Sambuc 250*f4a2713aSLionel Sambuc } 251*f4a2713aSLionel Sambuc 252*f4a2713aSLionel Sambuc /// Checks whether one class might instantiate to the other. 253*f4a2713aSLionel Sambuc static bool MightInstantiateTo(const CXXRecordDecl *From, 254*f4a2713aSLionel Sambuc const CXXRecordDecl *To) { 255*f4a2713aSLionel Sambuc // Declaration names are always preserved by instantiation. 256*f4a2713aSLionel Sambuc if (From->getDeclName() != To->getDeclName()) 257*f4a2713aSLionel Sambuc return false; 258*f4a2713aSLionel Sambuc 259*f4a2713aSLionel Sambuc const DeclContext *FromDC = From->getDeclContext()->getPrimaryContext(); 260*f4a2713aSLionel Sambuc const DeclContext *ToDC = To->getDeclContext()->getPrimaryContext(); 261*f4a2713aSLionel Sambuc if (FromDC == ToDC) return true; 262*f4a2713aSLionel Sambuc if (FromDC->isFileContext() || ToDC->isFileContext()) return false; 263*f4a2713aSLionel Sambuc 264*f4a2713aSLionel Sambuc // Be conservative. 265*f4a2713aSLionel Sambuc return true; 266*f4a2713aSLionel Sambuc } 267*f4a2713aSLionel Sambuc 268*f4a2713aSLionel Sambuc /// Checks whether one class is derived from another, inclusively. 269*f4a2713aSLionel Sambuc /// Properly indicates when it couldn't be determined due to 270*f4a2713aSLionel Sambuc /// dependence. 271*f4a2713aSLionel Sambuc /// 272*f4a2713aSLionel Sambuc /// This should probably be donated to AST or at least Sema. 273*f4a2713aSLionel Sambuc static AccessResult IsDerivedFromInclusive(const CXXRecordDecl *Derived, 274*f4a2713aSLionel Sambuc const CXXRecordDecl *Target) { 275*f4a2713aSLionel Sambuc assert(Derived->getCanonicalDecl() == Derived); 276*f4a2713aSLionel Sambuc assert(Target->getCanonicalDecl() == Target); 277*f4a2713aSLionel Sambuc 278*f4a2713aSLionel Sambuc if (Derived == Target) return AR_accessible; 279*f4a2713aSLionel Sambuc 280*f4a2713aSLionel Sambuc bool CheckDependent = Derived->isDependentContext(); 281*f4a2713aSLionel Sambuc if (CheckDependent && MightInstantiateTo(Derived, Target)) 282*f4a2713aSLionel Sambuc return AR_dependent; 283*f4a2713aSLionel Sambuc 284*f4a2713aSLionel Sambuc AccessResult OnFailure = AR_inaccessible; 285*f4a2713aSLionel Sambuc SmallVector<const CXXRecordDecl*, 8> Queue; // actually a stack 286*f4a2713aSLionel Sambuc 287*f4a2713aSLionel Sambuc while (true) { 288*f4a2713aSLionel Sambuc if (Derived->isDependentContext() && !Derived->hasDefinition()) 289*f4a2713aSLionel Sambuc return AR_dependent; 290*f4a2713aSLionel Sambuc 291*f4a2713aSLionel Sambuc for (CXXRecordDecl::base_class_const_iterator 292*f4a2713aSLionel Sambuc I = Derived->bases_begin(), E = Derived->bases_end(); I != E; ++I) { 293*f4a2713aSLionel Sambuc 294*f4a2713aSLionel Sambuc const CXXRecordDecl *RD; 295*f4a2713aSLionel Sambuc 296*f4a2713aSLionel Sambuc QualType T = I->getType(); 297*f4a2713aSLionel Sambuc if (const RecordType *RT = T->getAs<RecordType>()) { 298*f4a2713aSLionel Sambuc RD = cast<CXXRecordDecl>(RT->getDecl()); 299*f4a2713aSLionel Sambuc } else if (const InjectedClassNameType *IT 300*f4a2713aSLionel Sambuc = T->getAs<InjectedClassNameType>()) { 301*f4a2713aSLionel Sambuc RD = IT->getDecl(); 302*f4a2713aSLionel Sambuc } else { 303*f4a2713aSLionel Sambuc assert(T->isDependentType() && "non-dependent base wasn't a record?"); 304*f4a2713aSLionel Sambuc OnFailure = AR_dependent; 305*f4a2713aSLionel Sambuc continue; 306*f4a2713aSLionel Sambuc } 307*f4a2713aSLionel Sambuc 308*f4a2713aSLionel Sambuc RD = RD->getCanonicalDecl(); 309*f4a2713aSLionel Sambuc if (RD == Target) return AR_accessible; 310*f4a2713aSLionel Sambuc if (CheckDependent && MightInstantiateTo(RD, Target)) 311*f4a2713aSLionel Sambuc OnFailure = AR_dependent; 312*f4a2713aSLionel Sambuc 313*f4a2713aSLionel Sambuc Queue.push_back(RD); 314*f4a2713aSLionel Sambuc } 315*f4a2713aSLionel Sambuc 316*f4a2713aSLionel Sambuc if (Queue.empty()) break; 317*f4a2713aSLionel Sambuc 318*f4a2713aSLionel Sambuc Derived = Queue.pop_back_val(); 319*f4a2713aSLionel Sambuc } 320*f4a2713aSLionel Sambuc 321*f4a2713aSLionel Sambuc return OnFailure; 322*f4a2713aSLionel Sambuc } 323*f4a2713aSLionel Sambuc 324*f4a2713aSLionel Sambuc 325*f4a2713aSLionel Sambuc static bool MightInstantiateTo(Sema &S, DeclContext *Context, 326*f4a2713aSLionel Sambuc DeclContext *Friend) { 327*f4a2713aSLionel Sambuc if (Friend == Context) 328*f4a2713aSLionel Sambuc return true; 329*f4a2713aSLionel Sambuc 330*f4a2713aSLionel Sambuc assert(!Friend->isDependentContext() && 331*f4a2713aSLionel Sambuc "can't handle friends with dependent contexts here"); 332*f4a2713aSLionel Sambuc 333*f4a2713aSLionel Sambuc if (!Context->isDependentContext()) 334*f4a2713aSLionel Sambuc return false; 335*f4a2713aSLionel Sambuc 336*f4a2713aSLionel Sambuc if (Friend->isFileContext()) 337*f4a2713aSLionel Sambuc return false; 338*f4a2713aSLionel Sambuc 339*f4a2713aSLionel Sambuc // TODO: this is very conservative 340*f4a2713aSLionel Sambuc return true; 341*f4a2713aSLionel Sambuc } 342*f4a2713aSLionel Sambuc 343*f4a2713aSLionel Sambuc // Asks whether the type in 'context' can ever instantiate to the type 344*f4a2713aSLionel Sambuc // in 'friend'. 345*f4a2713aSLionel Sambuc static bool MightInstantiateTo(Sema &S, CanQualType Context, CanQualType Friend) { 346*f4a2713aSLionel Sambuc if (Friend == Context) 347*f4a2713aSLionel Sambuc return true; 348*f4a2713aSLionel Sambuc 349*f4a2713aSLionel Sambuc if (!Friend->isDependentType() && !Context->isDependentType()) 350*f4a2713aSLionel Sambuc return false; 351*f4a2713aSLionel Sambuc 352*f4a2713aSLionel Sambuc // TODO: this is very conservative. 353*f4a2713aSLionel Sambuc return true; 354*f4a2713aSLionel Sambuc } 355*f4a2713aSLionel Sambuc 356*f4a2713aSLionel Sambuc static bool MightInstantiateTo(Sema &S, 357*f4a2713aSLionel Sambuc FunctionDecl *Context, 358*f4a2713aSLionel Sambuc FunctionDecl *Friend) { 359*f4a2713aSLionel Sambuc if (Context->getDeclName() != Friend->getDeclName()) 360*f4a2713aSLionel Sambuc return false; 361*f4a2713aSLionel Sambuc 362*f4a2713aSLionel Sambuc if (!MightInstantiateTo(S, 363*f4a2713aSLionel Sambuc Context->getDeclContext(), 364*f4a2713aSLionel Sambuc Friend->getDeclContext())) 365*f4a2713aSLionel Sambuc return false; 366*f4a2713aSLionel Sambuc 367*f4a2713aSLionel Sambuc CanQual<FunctionProtoType> FriendTy 368*f4a2713aSLionel Sambuc = S.Context.getCanonicalType(Friend->getType()) 369*f4a2713aSLionel Sambuc ->getAs<FunctionProtoType>(); 370*f4a2713aSLionel Sambuc CanQual<FunctionProtoType> ContextTy 371*f4a2713aSLionel Sambuc = S.Context.getCanonicalType(Context->getType()) 372*f4a2713aSLionel Sambuc ->getAs<FunctionProtoType>(); 373*f4a2713aSLionel Sambuc 374*f4a2713aSLionel Sambuc // There isn't any way that I know of to add qualifiers 375*f4a2713aSLionel Sambuc // during instantiation. 376*f4a2713aSLionel Sambuc if (FriendTy.getQualifiers() != ContextTy.getQualifiers()) 377*f4a2713aSLionel Sambuc return false; 378*f4a2713aSLionel Sambuc 379*f4a2713aSLionel Sambuc if (FriendTy->getNumArgs() != ContextTy->getNumArgs()) 380*f4a2713aSLionel Sambuc return false; 381*f4a2713aSLionel Sambuc 382*f4a2713aSLionel Sambuc if (!MightInstantiateTo(S, 383*f4a2713aSLionel Sambuc ContextTy->getResultType(), 384*f4a2713aSLionel Sambuc FriendTy->getResultType())) 385*f4a2713aSLionel Sambuc return false; 386*f4a2713aSLionel Sambuc 387*f4a2713aSLionel Sambuc for (unsigned I = 0, E = FriendTy->getNumArgs(); I != E; ++I) 388*f4a2713aSLionel Sambuc if (!MightInstantiateTo(S, 389*f4a2713aSLionel Sambuc ContextTy->getArgType(I), 390*f4a2713aSLionel Sambuc FriendTy->getArgType(I))) 391*f4a2713aSLionel Sambuc return false; 392*f4a2713aSLionel Sambuc 393*f4a2713aSLionel Sambuc return true; 394*f4a2713aSLionel Sambuc } 395*f4a2713aSLionel Sambuc 396*f4a2713aSLionel Sambuc static bool MightInstantiateTo(Sema &S, 397*f4a2713aSLionel Sambuc FunctionTemplateDecl *Context, 398*f4a2713aSLionel Sambuc FunctionTemplateDecl *Friend) { 399*f4a2713aSLionel Sambuc return MightInstantiateTo(S, 400*f4a2713aSLionel Sambuc Context->getTemplatedDecl(), 401*f4a2713aSLionel Sambuc Friend->getTemplatedDecl()); 402*f4a2713aSLionel Sambuc } 403*f4a2713aSLionel Sambuc 404*f4a2713aSLionel Sambuc static AccessResult MatchesFriend(Sema &S, 405*f4a2713aSLionel Sambuc const EffectiveContext &EC, 406*f4a2713aSLionel Sambuc const CXXRecordDecl *Friend) { 407*f4a2713aSLionel Sambuc if (EC.includesClass(Friend)) 408*f4a2713aSLionel Sambuc return AR_accessible; 409*f4a2713aSLionel Sambuc 410*f4a2713aSLionel Sambuc if (EC.isDependent()) { 411*f4a2713aSLionel Sambuc CanQualType FriendTy 412*f4a2713aSLionel Sambuc = S.Context.getCanonicalType(S.Context.getTypeDeclType(Friend)); 413*f4a2713aSLionel Sambuc 414*f4a2713aSLionel Sambuc for (EffectiveContext::record_iterator 415*f4a2713aSLionel Sambuc I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { 416*f4a2713aSLionel Sambuc CanQualType ContextTy 417*f4a2713aSLionel Sambuc = S.Context.getCanonicalType(S.Context.getTypeDeclType(*I)); 418*f4a2713aSLionel Sambuc if (MightInstantiateTo(S, ContextTy, FriendTy)) 419*f4a2713aSLionel Sambuc return AR_dependent; 420*f4a2713aSLionel Sambuc } 421*f4a2713aSLionel Sambuc } 422*f4a2713aSLionel Sambuc 423*f4a2713aSLionel Sambuc return AR_inaccessible; 424*f4a2713aSLionel Sambuc } 425*f4a2713aSLionel Sambuc 426*f4a2713aSLionel Sambuc static AccessResult MatchesFriend(Sema &S, 427*f4a2713aSLionel Sambuc const EffectiveContext &EC, 428*f4a2713aSLionel Sambuc CanQualType Friend) { 429*f4a2713aSLionel Sambuc if (const RecordType *RT = Friend->getAs<RecordType>()) 430*f4a2713aSLionel Sambuc return MatchesFriend(S, EC, cast<CXXRecordDecl>(RT->getDecl())); 431*f4a2713aSLionel Sambuc 432*f4a2713aSLionel Sambuc // TODO: we can do better than this 433*f4a2713aSLionel Sambuc if (Friend->isDependentType()) 434*f4a2713aSLionel Sambuc return AR_dependent; 435*f4a2713aSLionel Sambuc 436*f4a2713aSLionel Sambuc return AR_inaccessible; 437*f4a2713aSLionel Sambuc } 438*f4a2713aSLionel Sambuc 439*f4a2713aSLionel Sambuc /// Determines whether the given friend class template matches 440*f4a2713aSLionel Sambuc /// anything in the effective context. 441*f4a2713aSLionel Sambuc static AccessResult MatchesFriend(Sema &S, 442*f4a2713aSLionel Sambuc const EffectiveContext &EC, 443*f4a2713aSLionel Sambuc ClassTemplateDecl *Friend) { 444*f4a2713aSLionel Sambuc AccessResult OnFailure = AR_inaccessible; 445*f4a2713aSLionel Sambuc 446*f4a2713aSLionel Sambuc // Check whether the friend is the template of a class in the 447*f4a2713aSLionel Sambuc // context chain. 448*f4a2713aSLionel Sambuc for (SmallVectorImpl<CXXRecordDecl*>::const_iterator 449*f4a2713aSLionel Sambuc I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { 450*f4a2713aSLionel Sambuc CXXRecordDecl *Record = *I; 451*f4a2713aSLionel Sambuc 452*f4a2713aSLionel Sambuc // Figure out whether the current class has a template: 453*f4a2713aSLionel Sambuc ClassTemplateDecl *CTD; 454*f4a2713aSLionel Sambuc 455*f4a2713aSLionel Sambuc // A specialization of the template... 456*f4a2713aSLionel Sambuc if (isa<ClassTemplateSpecializationDecl>(Record)) { 457*f4a2713aSLionel Sambuc CTD = cast<ClassTemplateSpecializationDecl>(Record) 458*f4a2713aSLionel Sambuc ->getSpecializedTemplate(); 459*f4a2713aSLionel Sambuc 460*f4a2713aSLionel Sambuc // ... or the template pattern itself. 461*f4a2713aSLionel Sambuc } else { 462*f4a2713aSLionel Sambuc CTD = Record->getDescribedClassTemplate(); 463*f4a2713aSLionel Sambuc if (!CTD) continue; 464*f4a2713aSLionel Sambuc } 465*f4a2713aSLionel Sambuc 466*f4a2713aSLionel Sambuc // It's a match. 467*f4a2713aSLionel Sambuc if (Friend == CTD->getCanonicalDecl()) 468*f4a2713aSLionel Sambuc return AR_accessible; 469*f4a2713aSLionel Sambuc 470*f4a2713aSLionel Sambuc // If the context isn't dependent, it can't be a dependent match. 471*f4a2713aSLionel Sambuc if (!EC.isDependent()) 472*f4a2713aSLionel Sambuc continue; 473*f4a2713aSLionel Sambuc 474*f4a2713aSLionel Sambuc // If the template names don't match, it can't be a dependent 475*f4a2713aSLionel Sambuc // match. 476*f4a2713aSLionel Sambuc if (CTD->getDeclName() != Friend->getDeclName()) 477*f4a2713aSLionel Sambuc continue; 478*f4a2713aSLionel Sambuc 479*f4a2713aSLionel Sambuc // If the class's context can't instantiate to the friend's 480*f4a2713aSLionel Sambuc // context, it can't be a dependent match. 481*f4a2713aSLionel Sambuc if (!MightInstantiateTo(S, CTD->getDeclContext(), 482*f4a2713aSLionel Sambuc Friend->getDeclContext())) 483*f4a2713aSLionel Sambuc continue; 484*f4a2713aSLionel Sambuc 485*f4a2713aSLionel Sambuc // Otherwise, it's a dependent match. 486*f4a2713aSLionel Sambuc OnFailure = AR_dependent; 487*f4a2713aSLionel Sambuc } 488*f4a2713aSLionel Sambuc 489*f4a2713aSLionel Sambuc return OnFailure; 490*f4a2713aSLionel Sambuc } 491*f4a2713aSLionel Sambuc 492*f4a2713aSLionel Sambuc /// Determines whether the given friend function matches anything in 493*f4a2713aSLionel Sambuc /// the effective context. 494*f4a2713aSLionel Sambuc static AccessResult MatchesFriend(Sema &S, 495*f4a2713aSLionel Sambuc const EffectiveContext &EC, 496*f4a2713aSLionel Sambuc FunctionDecl *Friend) { 497*f4a2713aSLionel Sambuc AccessResult OnFailure = AR_inaccessible; 498*f4a2713aSLionel Sambuc 499*f4a2713aSLionel Sambuc for (SmallVectorImpl<FunctionDecl*>::const_iterator 500*f4a2713aSLionel Sambuc I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) { 501*f4a2713aSLionel Sambuc if (Friend == *I) 502*f4a2713aSLionel Sambuc return AR_accessible; 503*f4a2713aSLionel Sambuc 504*f4a2713aSLionel Sambuc if (EC.isDependent() && MightInstantiateTo(S, *I, Friend)) 505*f4a2713aSLionel Sambuc OnFailure = AR_dependent; 506*f4a2713aSLionel Sambuc } 507*f4a2713aSLionel Sambuc 508*f4a2713aSLionel Sambuc return OnFailure; 509*f4a2713aSLionel Sambuc } 510*f4a2713aSLionel Sambuc 511*f4a2713aSLionel Sambuc /// Determines whether the given friend function template matches 512*f4a2713aSLionel Sambuc /// anything in the effective context. 513*f4a2713aSLionel Sambuc static AccessResult MatchesFriend(Sema &S, 514*f4a2713aSLionel Sambuc const EffectiveContext &EC, 515*f4a2713aSLionel Sambuc FunctionTemplateDecl *Friend) { 516*f4a2713aSLionel Sambuc if (EC.Functions.empty()) return AR_inaccessible; 517*f4a2713aSLionel Sambuc 518*f4a2713aSLionel Sambuc AccessResult OnFailure = AR_inaccessible; 519*f4a2713aSLionel Sambuc 520*f4a2713aSLionel Sambuc for (SmallVectorImpl<FunctionDecl*>::const_iterator 521*f4a2713aSLionel Sambuc I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) { 522*f4a2713aSLionel Sambuc 523*f4a2713aSLionel Sambuc FunctionTemplateDecl *FTD = (*I)->getPrimaryTemplate(); 524*f4a2713aSLionel Sambuc if (!FTD) 525*f4a2713aSLionel Sambuc FTD = (*I)->getDescribedFunctionTemplate(); 526*f4a2713aSLionel Sambuc if (!FTD) 527*f4a2713aSLionel Sambuc continue; 528*f4a2713aSLionel Sambuc 529*f4a2713aSLionel Sambuc FTD = FTD->getCanonicalDecl(); 530*f4a2713aSLionel Sambuc 531*f4a2713aSLionel Sambuc if (Friend == FTD) 532*f4a2713aSLionel Sambuc return AR_accessible; 533*f4a2713aSLionel Sambuc 534*f4a2713aSLionel Sambuc if (EC.isDependent() && MightInstantiateTo(S, FTD, Friend)) 535*f4a2713aSLionel Sambuc OnFailure = AR_dependent; 536*f4a2713aSLionel Sambuc } 537*f4a2713aSLionel Sambuc 538*f4a2713aSLionel Sambuc return OnFailure; 539*f4a2713aSLionel Sambuc } 540*f4a2713aSLionel Sambuc 541*f4a2713aSLionel Sambuc /// Determines whether the given friend declaration matches anything 542*f4a2713aSLionel Sambuc /// in the effective context. 543*f4a2713aSLionel Sambuc static AccessResult MatchesFriend(Sema &S, 544*f4a2713aSLionel Sambuc const EffectiveContext &EC, 545*f4a2713aSLionel Sambuc FriendDecl *FriendD) { 546*f4a2713aSLionel Sambuc // Whitelist accesses if there's an invalid or unsupported friend 547*f4a2713aSLionel Sambuc // declaration. 548*f4a2713aSLionel Sambuc if (FriendD->isInvalidDecl() || FriendD->isUnsupportedFriend()) 549*f4a2713aSLionel Sambuc return AR_accessible; 550*f4a2713aSLionel Sambuc 551*f4a2713aSLionel Sambuc if (TypeSourceInfo *T = FriendD->getFriendType()) 552*f4a2713aSLionel Sambuc return MatchesFriend(S, EC, T->getType()->getCanonicalTypeUnqualified()); 553*f4a2713aSLionel Sambuc 554*f4a2713aSLionel Sambuc NamedDecl *Friend 555*f4a2713aSLionel Sambuc = cast<NamedDecl>(FriendD->getFriendDecl()->getCanonicalDecl()); 556*f4a2713aSLionel Sambuc 557*f4a2713aSLionel Sambuc // FIXME: declarations with dependent or templated scope. 558*f4a2713aSLionel Sambuc 559*f4a2713aSLionel Sambuc if (isa<ClassTemplateDecl>(Friend)) 560*f4a2713aSLionel Sambuc return MatchesFriend(S, EC, cast<ClassTemplateDecl>(Friend)); 561*f4a2713aSLionel Sambuc 562*f4a2713aSLionel Sambuc if (isa<FunctionTemplateDecl>(Friend)) 563*f4a2713aSLionel Sambuc return MatchesFriend(S, EC, cast<FunctionTemplateDecl>(Friend)); 564*f4a2713aSLionel Sambuc 565*f4a2713aSLionel Sambuc if (isa<CXXRecordDecl>(Friend)) 566*f4a2713aSLionel Sambuc return MatchesFriend(S, EC, cast<CXXRecordDecl>(Friend)); 567*f4a2713aSLionel Sambuc 568*f4a2713aSLionel Sambuc assert(isa<FunctionDecl>(Friend) && "unknown friend decl kind"); 569*f4a2713aSLionel Sambuc return MatchesFriend(S, EC, cast<FunctionDecl>(Friend)); 570*f4a2713aSLionel Sambuc } 571*f4a2713aSLionel Sambuc 572*f4a2713aSLionel Sambuc static AccessResult GetFriendKind(Sema &S, 573*f4a2713aSLionel Sambuc const EffectiveContext &EC, 574*f4a2713aSLionel Sambuc const CXXRecordDecl *Class) { 575*f4a2713aSLionel Sambuc AccessResult OnFailure = AR_inaccessible; 576*f4a2713aSLionel Sambuc 577*f4a2713aSLionel Sambuc // Okay, check friends. 578*f4a2713aSLionel Sambuc for (CXXRecordDecl::friend_iterator I = Class->friend_begin(), 579*f4a2713aSLionel Sambuc E = Class->friend_end(); I != E; ++I) { 580*f4a2713aSLionel Sambuc FriendDecl *Friend = *I; 581*f4a2713aSLionel Sambuc 582*f4a2713aSLionel Sambuc switch (MatchesFriend(S, EC, Friend)) { 583*f4a2713aSLionel Sambuc case AR_accessible: 584*f4a2713aSLionel Sambuc return AR_accessible; 585*f4a2713aSLionel Sambuc 586*f4a2713aSLionel Sambuc case AR_inaccessible: 587*f4a2713aSLionel Sambuc continue; 588*f4a2713aSLionel Sambuc 589*f4a2713aSLionel Sambuc case AR_dependent: 590*f4a2713aSLionel Sambuc OnFailure = AR_dependent; 591*f4a2713aSLionel Sambuc break; 592*f4a2713aSLionel Sambuc } 593*f4a2713aSLionel Sambuc } 594*f4a2713aSLionel Sambuc 595*f4a2713aSLionel Sambuc // That's it, give up. 596*f4a2713aSLionel Sambuc return OnFailure; 597*f4a2713aSLionel Sambuc } 598*f4a2713aSLionel Sambuc 599*f4a2713aSLionel Sambuc namespace { 600*f4a2713aSLionel Sambuc 601*f4a2713aSLionel Sambuc /// A helper class for checking for a friend which will grant access 602*f4a2713aSLionel Sambuc /// to a protected instance member. 603*f4a2713aSLionel Sambuc struct ProtectedFriendContext { 604*f4a2713aSLionel Sambuc Sema &S; 605*f4a2713aSLionel Sambuc const EffectiveContext &EC; 606*f4a2713aSLionel Sambuc const CXXRecordDecl *NamingClass; 607*f4a2713aSLionel Sambuc bool CheckDependent; 608*f4a2713aSLionel Sambuc bool EverDependent; 609*f4a2713aSLionel Sambuc 610*f4a2713aSLionel Sambuc /// The path down to the current base class. 611*f4a2713aSLionel Sambuc SmallVector<const CXXRecordDecl*, 20> CurPath; 612*f4a2713aSLionel Sambuc 613*f4a2713aSLionel Sambuc ProtectedFriendContext(Sema &S, const EffectiveContext &EC, 614*f4a2713aSLionel Sambuc const CXXRecordDecl *InstanceContext, 615*f4a2713aSLionel Sambuc const CXXRecordDecl *NamingClass) 616*f4a2713aSLionel Sambuc : S(S), EC(EC), NamingClass(NamingClass), 617*f4a2713aSLionel Sambuc CheckDependent(InstanceContext->isDependentContext() || 618*f4a2713aSLionel Sambuc NamingClass->isDependentContext()), 619*f4a2713aSLionel Sambuc EverDependent(false) {} 620*f4a2713aSLionel Sambuc 621*f4a2713aSLionel Sambuc /// Check classes in the current path for friendship, starting at 622*f4a2713aSLionel Sambuc /// the given index. 623*f4a2713aSLionel Sambuc bool checkFriendshipAlongPath(unsigned I) { 624*f4a2713aSLionel Sambuc assert(I < CurPath.size()); 625*f4a2713aSLionel Sambuc for (unsigned E = CurPath.size(); I != E; ++I) { 626*f4a2713aSLionel Sambuc switch (GetFriendKind(S, EC, CurPath[I])) { 627*f4a2713aSLionel Sambuc case AR_accessible: return true; 628*f4a2713aSLionel Sambuc case AR_inaccessible: continue; 629*f4a2713aSLionel Sambuc case AR_dependent: EverDependent = true; continue; 630*f4a2713aSLionel Sambuc } 631*f4a2713aSLionel Sambuc } 632*f4a2713aSLionel Sambuc return false; 633*f4a2713aSLionel Sambuc } 634*f4a2713aSLionel Sambuc 635*f4a2713aSLionel Sambuc /// Perform a search starting at the given class. 636*f4a2713aSLionel Sambuc /// 637*f4a2713aSLionel Sambuc /// PrivateDepth is the index of the last (least derived) class 638*f4a2713aSLionel Sambuc /// along the current path such that a notional public member of 639*f4a2713aSLionel Sambuc /// the final class in the path would have access in that class. 640*f4a2713aSLionel Sambuc bool findFriendship(const CXXRecordDecl *Cur, unsigned PrivateDepth) { 641*f4a2713aSLionel Sambuc // If we ever reach the naming class, check the current path for 642*f4a2713aSLionel Sambuc // friendship. We can also stop recursing because we obviously 643*f4a2713aSLionel Sambuc // won't find the naming class there again. 644*f4a2713aSLionel Sambuc if (Cur == NamingClass) 645*f4a2713aSLionel Sambuc return checkFriendshipAlongPath(PrivateDepth); 646*f4a2713aSLionel Sambuc 647*f4a2713aSLionel Sambuc if (CheckDependent && MightInstantiateTo(Cur, NamingClass)) 648*f4a2713aSLionel Sambuc EverDependent = true; 649*f4a2713aSLionel Sambuc 650*f4a2713aSLionel Sambuc // Recurse into the base classes. 651*f4a2713aSLionel Sambuc for (CXXRecordDecl::base_class_const_iterator 652*f4a2713aSLionel Sambuc I = Cur->bases_begin(), E = Cur->bases_end(); I != E; ++I) { 653*f4a2713aSLionel Sambuc 654*f4a2713aSLionel Sambuc // If this is private inheritance, then a public member of the 655*f4a2713aSLionel Sambuc // base will not have any access in classes derived from Cur. 656*f4a2713aSLionel Sambuc unsigned BasePrivateDepth = PrivateDepth; 657*f4a2713aSLionel Sambuc if (I->getAccessSpecifier() == AS_private) 658*f4a2713aSLionel Sambuc BasePrivateDepth = CurPath.size() - 1; 659*f4a2713aSLionel Sambuc 660*f4a2713aSLionel Sambuc const CXXRecordDecl *RD; 661*f4a2713aSLionel Sambuc 662*f4a2713aSLionel Sambuc QualType T = I->getType(); 663*f4a2713aSLionel Sambuc if (const RecordType *RT = T->getAs<RecordType>()) { 664*f4a2713aSLionel Sambuc RD = cast<CXXRecordDecl>(RT->getDecl()); 665*f4a2713aSLionel Sambuc } else if (const InjectedClassNameType *IT 666*f4a2713aSLionel Sambuc = T->getAs<InjectedClassNameType>()) { 667*f4a2713aSLionel Sambuc RD = IT->getDecl(); 668*f4a2713aSLionel Sambuc } else { 669*f4a2713aSLionel Sambuc assert(T->isDependentType() && "non-dependent base wasn't a record?"); 670*f4a2713aSLionel Sambuc EverDependent = true; 671*f4a2713aSLionel Sambuc continue; 672*f4a2713aSLionel Sambuc } 673*f4a2713aSLionel Sambuc 674*f4a2713aSLionel Sambuc // Recurse. We don't need to clean up if this returns true. 675*f4a2713aSLionel Sambuc CurPath.push_back(RD); 676*f4a2713aSLionel Sambuc if (findFriendship(RD->getCanonicalDecl(), BasePrivateDepth)) 677*f4a2713aSLionel Sambuc return true; 678*f4a2713aSLionel Sambuc CurPath.pop_back(); 679*f4a2713aSLionel Sambuc } 680*f4a2713aSLionel Sambuc 681*f4a2713aSLionel Sambuc return false; 682*f4a2713aSLionel Sambuc } 683*f4a2713aSLionel Sambuc 684*f4a2713aSLionel Sambuc bool findFriendship(const CXXRecordDecl *Cur) { 685*f4a2713aSLionel Sambuc assert(CurPath.empty()); 686*f4a2713aSLionel Sambuc CurPath.push_back(Cur); 687*f4a2713aSLionel Sambuc return findFriendship(Cur, 0); 688*f4a2713aSLionel Sambuc } 689*f4a2713aSLionel Sambuc }; 690*f4a2713aSLionel Sambuc } 691*f4a2713aSLionel Sambuc 692*f4a2713aSLionel Sambuc /// Search for a class P that EC is a friend of, under the constraint 693*f4a2713aSLionel Sambuc /// InstanceContext <= P 694*f4a2713aSLionel Sambuc /// if InstanceContext exists, or else 695*f4a2713aSLionel Sambuc /// NamingClass <= P 696*f4a2713aSLionel Sambuc /// and with the additional restriction that a protected member of 697*f4a2713aSLionel Sambuc /// NamingClass would have some natural access in P, which implicitly 698*f4a2713aSLionel Sambuc /// imposes the constraint that P <= NamingClass. 699*f4a2713aSLionel Sambuc /// 700*f4a2713aSLionel Sambuc /// This isn't quite the condition laid out in the standard. 701*f4a2713aSLionel Sambuc /// Instead of saying that a notional protected member of NamingClass 702*f4a2713aSLionel Sambuc /// would have to have some natural access in P, it says the actual 703*f4a2713aSLionel Sambuc /// target has to have some natural access in P, which opens up the 704*f4a2713aSLionel Sambuc /// possibility that the target (which is not necessarily a member 705*f4a2713aSLionel Sambuc /// of NamingClass) might be more accessible along some path not 706*f4a2713aSLionel Sambuc /// passing through it. That's really a bad idea, though, because it 707*f4a2713aSLionel Sambuc /// introduces two problems: 708*f4a2713aSLionel Sambuc /// - Most importantly, it breaks encapsulation because you can 709*f4a2713aSLionel Sambuc /// access a forbidden base class's members by directly subclassing 710*f4a2713aSLionel Sambuc /// it elsewhere. 711*f4a2713aSLionel Sambuc /// - It also makes access substantially harder to compute because it 712*f4a2713aSLionel Sambuc /// breaks the hill-climbing algorithm: knowing that the target is 713*f4a2713aSLionel Sambuc /// accessible in some base class would no longer let you change 714*f4a2713aSLionel Sambuc /// the question solely to whether the base class is accessible, 715*f4a2713aSLionel Sambuc /// because the original target might have been more accessible 716*f4a2713aSLionel Sambuc /// because of crazy subclassing. 717*f4a2713aSLionel Sambuc /// So we don't implement that. 718*f4a2713aSLionel Sambuc static AccessResult GetProtectedFriendKind(Sema &S, const EffectiveContext &EC, 719*f4a2713aSLionel Sambuc const CXXRecordDecl *InstanceContext, 720*f4a2713aSLionel Sambuc const CXXRecordDecl *NamingClass) { 721*f4a2713aSLionel Sambuc assert(InstanceContext == 0 || 722*f4a2713aSLionel Sambuc InstanceContext->getCanonicalDecl() == InstanceContext); 723*f4a2713aSLionel Sambuc assert(NamingClass->getCanonicalDecl() == NamingClass); 724*f4a2713aSLionel Sambuc 725*f4a2713aSLionel Sambuc // If we don't have an instance context, our constraints give us 726*f4a2713aSLionel Sambuc // that NamingClass <= P <= NamingClass, i.e. P == NamingClass. 727*f4a2713aSLionel Sambuc // This is just the usual friendship check. 728*f4a2713aSLionel Sambuc if (!InstanceContext) return GetFriendKind(S, EC, NamingClass); 729*f4a2713aSLionel Sambuc 730*f4a2713aSLionel Sambuc ProtectedFriendContext PRC(S, EC, InstanceContext, NamingClass); 731*f4a2713aSLionel Sambuc if (PRC.findFriendship(InstanceContext)) return AR_accessible; 732*f4a2713aSLionel Sambuc if (PRC.EverDependent) return AR_dependent; 733*f4a2713aSLionel Sambuc return AR_inaccessible; 734*f4a2713aSLionel Sambuc } 735*f4a2713aSLionel Sambuc 736*f4a2713aSLionel Sambuc static AccessResult HasAccess(Sema &S, 737*f4a2713aSLionel Sambuc const EffectiveContext &EC, 738*f4a2713aSLionel Sambuc const CXXRecordDecl *NamingClass, 739*f4a2713aSLionel Sambuc AccessSpecifier Access, 740*f4a2713aSLionel Sambuc const AccessTarget &Target) { 741*f4a2713aSLionel Sambuc assert(NamingClass->getCanonicalDecl() == NamingClass && 742*f4a2713aSLionel Sambuc "declaration should be canonicalized before being passed here"); 743*f4a2713aSLionel Sambuc 744*f4a2713aSLionel Sambuc if (Access == AS_public) return AR_accessible; 745*f4a2713aSLionel Sambuc assert(Access == AS_private || Access == AS_protected); 746*f4a2713aSLionel Sambuc 747*f4a2713aSLionel Sambuc AccessResult OnFailure = AR_inaccessible; 748*f4a2713aSLionel Sambuc 749*f4a2713aSLionel Sambuc for (EffectiveContext::record_iterator 750*f4a2713aSLionel Sambuc I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { 751*f4a2713aSLionel Sambuc // All the declarations in EC have been canonicalized, so pointer 752*f4a2713aSLionel Sambuc // equality from this point on will work fine. 753*f4a2713aSLionel Sambuc const CXXRecordDecl *ECRecord = *I; 754*f4a2713aSLionel Sambuc 755*f4a2713aSLionel Sambuc // [B2] and [M2] 756*f4a2713aSLionel Sambuc if (Access == AS_private) { 757*f4a2713aSLionel Sambuc if (ECRecord == NamingClass) 758*f4a2713aSLionel Sambuc return AR_accessible; 759*f4a2713aSLionel Sambuc 760*f4a2713aSLionel Sambuc if (EC.isDependent() && MightInstantiateTo(ECRecord, NamingClass)) 761*f4a2713aSLionel Sambuc OnFailure = AR_dependent; 762*f4a2713aSLionel Sambuc 763*f4a2713aSLionel Sambuc // [B3] and [M3] 764*f4a2713aSLionel Sambuc } else { 765*f4a2713aSLionel Sambuc assert(Access == AS_protected); 766*f4a2713aSLionel Sambuc switch (IsDerivedFromInclusive(ECRecord, NamingClass)) { 767*f4a2713aSLionel Sambuc case AR_accessible: break; 768*f4a2713aSLionel Sambuc case AR_inaccessible: continue; 769*f4a2713aSLionel Sambuc case AR_dependent: OnFailure = AR_dependent; continue; 770*f4a2713aSLionel Sambuc } 771*f4a2713aSLionel Sambuc 772*f4a2713aSLionel Sambuc // C++ [class.protected]p1: 773*f4a2713aSLionel Sambuc // An additional access check beyond those described earlier in 774*f4a2713aSLionel Sambuc // [class.access] is applied when a non-static data member or 775*f4a2713aSLionel Sambuc // non-static member function is a protected member of its naming 776*f4a2713aSLionel Sambuc // class. As described earlier, access to a protected member is 777*f4a2713aSLionel Sambuc // granted because the reference occurs in a friend or member of 778*f4a2713aSLionel Sambuc // some class C. If the access is to form a pointer to member, 779*f4a2713aSLionel Sambuc // the nested-name-specifier shall name C or a class derived from 780*f4a2713aSLionel Sambuc // C. All other accesses involve a (possibly implicit) object 781*f4a2713aSLionel Sambuc // expression. In this case, the class of the object expression 782*f4a2713aSLionel Sambuc // shall be C or a class derived from C. 783*f4a2713aSLionel Sambuc // 784*f4a2713aSLionel Sambuc // We interpret this as a restriction on [M3]. 785*f4a2713aSLionel Sambuc 786*f4a2713aSLionel Sambuc // In this part of the code, 'C' is just our context class ECRecord. 787*f4a2713aSLionel Sambuc 788*f4a2713aSLionel Sambuc // These rules are different if we don't have an instance context. 789*f4a2713aSLionel Sambuc if (!Target.hasInstanceContext()) { 790*f4a2713aSLionel Sambuc // If it's not an instance member, these restrictions don't apply. 791*f4a2713aSLionel Sambuc if (!Target.isInstanceMember()) return AR_accessible; 792*f4a2713aSLionel Sambuc 793*f4a2713aSLionel Sambuc // If it's an instance member, use the pointer-to-member rule 794*f4a2713aSLionel Sambuc // that the naming class has to be derived from the effective 795*f4a2713aSLionel Sambuc // context. 796*f4a2713aSLionel Sambuc 797*f4a2713aSLionel Sambuc // Emulate a MSVC bug where the creation of pointer-to-member 798*f4a2713aSLionel Sambuc // to protected member of base class is allowed but only from 799*f4a2713aSLionel Sambuc // static member functions. 800*f4a2713aSLionel Sambuc if (S.getLangOpts().MicrosoftMode && !EC.Functions.empty()) 801*f4a2713aSLionel Sambuc if (CXXMethodDecl* MD = dyn_cast<CXXMethodDecl>(EC.Functions.front())) 802*f4a2713aSLionel Sambuc if (MD->isStatic()) return AR_accessible; 803*f4a2713aSLionel Sambuc 804*f4a2713aSLionel Sambuc // Despite the standard's confident wording, there is a case 805*f4a2713aSLionel Sambuc // where you can have an instance member that's neither in a 806*f4a2713aSLionel Sambuc // pointer-to-member expression nor in a member access: when 807*f4a2713aSLionel Sambuc // it names a field in an unevaluated context that can't be an 808*f4a2713aSLionel Sambuc // implicit member. Pending clarification, we just apply the 809*f4a2713aSLionel Sambuc // same naming-class restriction here. 810*f4a2713aSLionel Sambuc // FIXME: we're probably not correctly adding the 811*f4a2713aSLionel Sambuc // protected-member restriction when we retroactively convert 812*f4a2713aSLionel Sambuc // an expression to being evaluated. 813*f4a2713aSLionel Sambuc 814*f4a2713aSLionel Sambuc // We know that ECRecord derives from NamingClass. The 815*f4a2713aSLionel Sambuc // restriction says to check whether NamingClass derives from 816*f4a2713aSLionel Sambuc // ECRecord, but that's not really necessary: two distinct 817*f4a2713aSLionel Sambuc // classes can't be recursively derived from each other. So 818*f4a2713aSLionel Sambuc // along this path, we just need to check whether the classes 819*f4a2713aSLionel Sambuc // are equal. 820*f4a2713aSLionel Sambuc if (NamingClass == ECRecord) return AR_accessible; 821*f4a2713aSLionel Sambuc 822*f4a2713aSLionel Sambuc // Otherwise, this context class tells us nothing; on to the next. 823*f4a2713aSLionel Sambuc continue; 824*f4a2713aSLionel Sambuc } 825*f4a2713aSLionel Sambuc 826*f4a2713aSLionel Sambuc assert(Target.isInstanceMember()); 827*f4a2713aSLionel Sambuc 828*f4a2713aSLionel Sambuc const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S); 829*f4a2713aSLionel Sambuc if (!InstanceContext) { 830*f4a2713aSLionel Sambuc OnFailure = AR_dependent; 831*f4a2713aSLionel Sambuc continue; 832*f4a2713aSLionel Sambuc } 833*f4a2713aSLionel Sambuc 834*f4a2713aSLionel Sambuc switch (IsDerivedFromInclusive(InstanceContext, ECRecord)) { 835*f4a2713aSLionel Sambuc case AR_accessible: return AR_accessible; 836*f4a2713aSLionel Sambuc case AR_inaccessible: continue; 837*f4a2713aSLionel Sambuc case AR_dependent: OnFailure = AR_dependent; continue; 838*f4a2713aSLionel Sambuc } 839*f4a2713aSLionel Sambuc } 840*f4a2713aSLionel Sambuc } 841*f4a2713aSLionel Sambuc 842*f4a2713aSLionel Sambuc // [M3] and [B3] say that, if the target is protected in N, we grant 843*f4a2713aSLionel Sambuc // access if the access occurs in a friend or member of some class P 844*f4a2713aSLionel Sambuc // that's a subclass of N and where the target has some natural 845*f4a2713aSLionel Sambuc // access in P. The 'member' aspect is easy to handle because P 846*f4a2713aSLionel Sambuc // would necessarily be one of the effective-context records, and we 847*f4a2713aSLionel Sambuc // address that above. The 'friend' aspect is completely ridiculous 848*f4a2713aSLionel Sambuc // to implement because there are no restrictions at all on P 849*f4a2713aSLionel Sambuc // *unless* the [class.protected] restriction applies. If it does, 850*f4a2713aSLionel Sambuc // however, we should ignore whether the naming class is a friend, 851*f4a2713aSLionel Sambuc // and instead rely on whether any potential P is a friend. 852*f4a2713aSLionel Sambuc if (Access == AS_protected && Target.isInstanceMember()) { 853*f4a2713aSLionel Sambuc // Compute the instance context if possible. 854*f4a2713aSLionel Sambuc const CXXRecordDecl *InstanceContext = 0; 855*f4a2713aSLionel Sambuc if (Target.hasInstanceContext()) { 856*f4a2713aSLionel Sambuc InstanceContext = Target.resolveInstanceContext(S); 857*f4a2713aSLionel Sambuc if (!InstanceContext) return AR_dependent; 858*f4a2713aSLionel Sambuc } 859*f4a2713aSLionel Sambuc 860*f4a2713aSLionel Sambuc switch (GetProtectedFriendKind(S, EC, InstanceContext, NamingClass)) { 861*f4a2713aSLionel Sambuc case AR_accessible: return AR_accessible; 862*f4a2713aSLionel Sambuc case AR_inaccessible: return OnFailure; 863*f4a2713aSLionel Sambuc case AR_dependent: return AR_dependent; 864*f4a2713aSLionel Sambuc } 865*f4a2713aSLionel Sambuc llvm_unreachable("impossible friendship kind"); 866*f4a2713aSLionel Sambuc } 867*f4a2713aSLionel Sambuc 868*f4a2713aSLionel Sambuc switch (GetFriendKind(S, EC, NamingClass)) { 869*f4a2713aSLionel Sambuc case AR_accessible: return AR_accessible; 870*f4a2713aSLionel Sambuc case AR_inaccessible: return OnFailure; 871*f4a2713aSLionel Sambuc case AR_dependent: return AR_dependent; 872*f4a2713aSLionel Sambuc } 873*f4a2713aSLionel Sambuc 874*f4a2713aSLionel Sambuc // Silence bogus warnings 875*f4a2713aSLionel Sambuc llvm_unreachable("impossible friendship kind"); 876*f4a2713aSLionel Sambuc } 877*f4a2713aSLionel Sambuc 878*f4a2713aSLionel Sambuc /// Finds the best path from the naming class to the declaring class, 879*f4a2713aSLionel Sambuc /// taking friend declarations into account. 880*f4a2713aSLionel Sambuc /// 881*f4a2713aSLionel Sambuc /// C++0x [class.access.base]p5: 882*f4a2713aSLionel Sambuc /// A member m is accessible at the point R when named in class N if 883*f4a2713aSLionel Sambuc /// [M1] m as a member of N is public, or 884*f4a2713aSLionel Sambuc /// [M2] m as a member of N is private, and R occurs in a member or 885*f4a2713aSLionel Sambuc /// friend of class N, or 886*f4a2713aSLionel Sambuc /// [M3] m as a member of N is protected, and R occurs in a member or 887*f4a2713aSLionel Sambuc /// friend of class N, or in a member or friend of a class P 888*f4a2713aSLionel Sambuc /// derived from N, where m as a member of P is public, private, 889*f4a2713aSLionel Sambuc /// or protected, or 890*f4a2713aSLionel Sambuc /// [M4] there exists a base class B of N that is accessible at R, and 891*f4a2713aSLionel Sambuc /// m is accessible at R when named in class B. 892*f4a2713aSLionel Sambuc /// 893*f4a2713aSLionel Sambuc /// C++0x [class.access.base]p4: 894*f4a2713aSLionel Sambuc /// A base class B of N is accessible at R, if 895*f4a2713aSLionel Sambuc /// [B1] an invented public member of B would be a public member of N, or 896*f4a2713aSLionel Sambuc /// [B2] R occurs in a member or friend of class N, and an invented public 897*f4a2713aSLionel Sambuc /// member of B would be a private or protected member of N, or 898*f4a2713aSLionel Sambuc /// [B3] R occurs in a member or friend of a class P derived from N, and an 899*f4a2713aSLionel Sambuc /// invented public member of B would be a private or protected member 900*f4a2713aSLionel Sambuc /// of P, or 901*f4a2713aSLionel Sambuc /// [B4] there exists a class S such that B is a base class of S accessible 902*f4a2713aSLionel Sambuc /// at R and S is a base class of N accessible at R. 903*f4a2713aSLionel Sambuc /// 904*f4a2713aSLionel Sambuc /// Along a single inheritance path we can restate both of these 905*f4a2713aSLionel Sambuc /// iteratively: 906*f4a2713aSLionel Sambuc /// 907*f4a2713aSLionel Sambuc /// First, we note that M1-4 are equivalent to B1-4 if the member is 908*f4a2713aSLionel Sambuc /// treated as a notional base of its declaring class with inheritance 909*f4a2713aSLionel Sambuc /// access equivalent to the member's access. Therefore we need only 910*f4a2713aSLionel Sambuc /// ask whether a class B is accessible from a class N in context R. 911*f4a2713aSLionel Sambuc /// 912*f4a2713aSLionel Sambuc /// Let B_1 .. B_n be the inheritance path in question (i.e. where 913*f4a2713aSLionel Sambuc /// B_1 = N, B_n = B, and for all i, B_{i+1} is a direct base class of 914*f4a2713aSLionel Sambuc /// B_i). For i in 1..n, we will calculate ACAB(i), the access to the 915*f4a2713aSLionel Sambuc /// closest accessible base in the path: 916*f4a2713aSLionel Sambuc /// Access(a, b) = (* access on the base specifier from a to b *) 917*f4a2713aSLionel Sambuc /// Merge(a, forbidden) = forbidden 918*f4a2713aSLionel Sambuc /// Merge(a, private) = forbidden 919*f4a2713aSLionel Sambuc /// Merge(a, b) = min(a,b) 920*f4a2713aSLionel Sambuc /// Accessible(c, forbidden) = false 921*f4a2713aSLionel Sambuc /// Accessible(c, private) = (R is c) || IsFriend(c, R) 922*f4a2713aSLionel Sambuc /// Accessible(c, protected) = (R derived from c) || IsFriend(c, R) 923*f4a2713aSLionel Sambuc /// Accessible(c, public) = true 924*f4a2713aSLionel Sambuc /// ACAB(n) = public 925*f4a2713aSLionel Sambuc /// ACAB(i) = 926*f4a2713aSLionel Sambuc /// let AccessToBase = Merge(Access(B_i, B_{i+1}), ACAB(i+1)) in 927*f4a2713aSLionel Sambuc /// if Accessible(B_i, AccessToBase) then public else AccessToBase 928*f4a2713aSLionel Sambuc /// 929*f4a2713aSLionel Sambuc /// B is an accessible base of N at R iff ACAB(1) = public. 930*f4a2713aSLionel Sambuc /// 931*f4a2713aSLionel Sambuc /// \param FinalAccess the access of the "final step", or AS_public if 932*f4a2713aSLionel Sambuc /// there is no final step. 933*f4a2713aSLionel Sambuc /// \return null if friendship is dependent 934*f4a2713aSLionel Sambuc static CXXBasePath *FindBestPath(Sema &S, 935*f4a2713aSLionel Sambuc const EffectiveContext &EC, 936*f4a2713aSLionel Sambuc AccessTarget &Target, 937*f4a2713aSLionel Sambuc AccessSpecifier FinalAccess, 938*f4a2713aSLionel Sambuc CXXBasePaths &Paths) { 939*f4a2713aSLionel Sambuc // Derive the paths to the desired base. 940*f4a2713aSLionel Sambuc const CXXRecordDecl *Derived = Target.getNamingClass(); 941*f4a2713aSLionel Sambuc const CXXRecordDecl *Base = Target.getDeclaringClass(); 942*f4a2713aSLionel Sambuc 943*f4a2713aSLionel Sambuc // FIXME: fail correctly when there are dependent paths. 944*f4a2713aSLionel Sambuc bool isDerived = Derived->isDerivedFrom(const_cast<CXXRecordDecl*>(Base), 945*f4a2713aSLionel Sambuc Paths); 946*f4a2713aSLionel Sambuc assert(isDerived && "derived class not actually derived from base"); 947*f4a2713aSLionel Sambuc (void) isDerived; 948*f4a2713aSLionel Sambuc 949*f4a2713aSLionel Sambuc CXXBasePath *BestPath = 0; 950*f4a2713aSLionel Sambuc 951*f4a2713aSLionel Sambuc assert(FinalAccess != AS_none && "forbidden access after declaring class"); 952*f4a2713aSLionel Sambuc 953*f4a2713aSLionel Sambuc bool AnyDependent = false; 954*f4a2713aSLionel Sambuc 955*f4a2713aSLionel Sambuc // Derive the friend-modified access along each path. 956*f4a2713aSLionel Sambuc for (CXXBasePaths::paths_iterator PI = Paths.begin(), PE = Paths.end(); 957*f4a2713aSLionel Sambuc PI != PE; ++PI) { 958*f4a2713aSLionel Sambuc AccessTarget::SavedInstanceContext _ = Target.saveInstanceContext(); 959*f4a2713aSLionel Sambuc 960*f4a2713aSLionel Sambuc // Walk through the path backwards. 961*f4a2713aSLionel Sambuc AccessSpecifier PathAccess = FinalAccess; 962*f4a2713aSLionel Sambuc CXXBasePath::iterator I = PI->end(), E = PI->begin(); 963*f4a2713aSLionel Sambuc while (I != E) { 964*f4a2713aSLionel Sambuc --I; 965*f4a2713aSLionel Sambuc 966*f4a2713aSLionel Sambuc assert(PathAccess != AS_none); 967*f4a2713aSLionel Sambuc 968*f4a2713aSLionel Sambuc // If the declaration is a private member of a base class, there 969*f4a2713aSLionel Sambuc // is no level of friendship in derived classes that can make it 970*f4a2713aSLionel Sambuc // accessible. 971*f4a2713aSLionel Sambuc if (PathAccess == AS_private) { 972*f4a2713aSLionel Sambuc PathAccess = AS_none; 973*f4a2713aSLionel Sambuc break; 974*f4a2713aSLionel Sambuc } 975*f4a2713aSLionel Sambuc 976*f4a2713aSLionel Sambuc const CXXRecordDecl *NC = I->Class->getCanonicalDecl(); 977*f4a2713aSLionel Sambuc 978*f4a2713aSLionel Sambuc AccessSpecifier BaseAccess = I->Base->getAccessSpecifier(); 979*f4a2713aSLionel Sambuc PathAccess = std::max(PathAccess, BaseAccess); 980*f4a2713aSLionel Sambuc 981*f4a2713aSLionel Sambuc switch (HasAccess(S, EC, NC, PathAccess, Target)) { 982*f4a2713aSLionel Sambuc case AR_inaccessible: break; 983*f4a2713aSLionel Sambuc case AR_accessible: 984*f4a2713aSLionel Sambuc PathAccess = AS_public; 985*f4a2713aSLionel Sambuc 986*f4a2713aSLionel Sambuc // Future tests are not against members and so do not have 987*f4a2713aSLionel Sambuc // instance context. 988*f4a2713aSLionel Sambuc Target.suppressInstanceContext(); 989*f4a2713aSLionel Sambuc break; 990*f4a2713aSLionel Sambuc case AR_dependent: 991*f4a2713aSLionel Sambuc AnyDependent = true; 992*f4a2713aSLionel Sambuc goto Next; 993*f4a2713aSLionel Sambuc } 994*f4a2713aSLionel Sambuc } 995*f4a2713aSLionel Sambuc 996*f4a2713aSLionel Sambuc // Note that we modify the path's Access field to the 997*f4a2713aSLionel Sambuc // friend-modified access. 998*f4a2713aSLionel Sambuc if (BestPath == 0 || PathAccess < BestPath->Access) { 999*f4a2713aSLionel Sambuc BestPath = &*PI; 1000*f4a2713aSLionel Sambuc BestPath->Access = PathAccess; 1001*f4a2713aSLionel Sambuc 1002*f4a2713aSLionel Sambuc // Short-circuit if we found a public path. 1003*f4a2713aSLionel Sambuc if (BestPath->Access == AS_public) 1004*f4a2713aSLionel Sambuc return BestPath; 1005*f4a2713aSLionel Sambuc } 1006*f4a2713aSLionel Sambuc 1007*f4a2713aSLionel Sambuc Next: ; 1008*f4a2713aSLionel Sambuc } 1009*f4a2713aSLionel Sambuc 1010*f4a2713aSLionel Sambuc assert((!BestPath || BestPath->Access != AS_public) && 1011*f4a2713aSLionel Sambuc "fell out of loop with public path"); 1012*f4a2713aSLionel Sambuc 1013*f4a2713aSLionel Sambuc // We didn't find a public path, but at least one path was subject 1014*f4a2713aSLionel Sambuc // to dependent friendship, so delay the check. 1015*f4a2713aSLionel Sambuc if (AnyDependent) 1016*f4a2713aSLionel Sambuc return 0; 1017*f4a2713aSLionel Sambuc 1018*f4a2713aSLionel Sambuc return BestPath; 1019*f4a2713aSLionel Sambuc } 1020*f4a2713aSLionel Sambuc 1021*f4a2713aSLionel Sambuc /// Given that an entity has protected natural access, check whether 1022*f4a2713aSLionel Sambuc /// access might be denied because of the protected member access 1023*f4a2713aSLionel Sambuc /// restriction. 1024*f4a2713aSLionel Sambuc /// 1025*f4a2713aSLionel Sambuc /// \return true if a note was emitted 1026*f4a2713aSLionel Sambuc static bool TryDiagnoseProtectedAccess(Sema &S, const EffectiveContext &EC, 1027*f4a2713aSLionel Sambuc AccessTarget &Target) { 1028*f4a2713aSLionel Sambuc // Only applies to instance accesses. 1029*f4a2713aSLionel Sambuc if (!Target.isInstanceMember()) 1030*f4a2713aSLionel Sambuc return false; 1031*f4a2713aSLionel Sambuc 1032*f4a2713aSLionel Sambuc assert(Target.isMemberAccess()); 1033*f4a2713aSLionel Sambuc 1034*f4a2713aSLionel Sambuc const CXXRecordDecl *NamingClass = Target.getEffectiveNamingClass(); 1035*f4a2713aSLionel Sambuc 1036*f4a2713aSLionel Sambuc for (EffectiveContext::record_iterator 1037*f4a2713aSLionel Sambuc I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { 1038*f4a2713aSLionel Sambuc const CXXRecordDecl *ECRecord = *I; 1039*f4a2713aSLionel Sambuc switch (IsDerivedFromInclusive(ECRecord, NamingClass)) { 1040*f4a2713aSLionel Sambuc case AR_accessible: break; 1041*f4a2713aSLionel Sambuc case AR_inaccessible: continue; 1042*f4a2713aSLionel Sambuc case AR_dependent: continue; 1043*f4a2713aSLionel Sambuc } 1044*f4a2713aSLionel Sambuc 1045*f4a2713aSLionel Sambuc // The effective context is a subclass of the declaring class. 1046*f4a2713aSLionel Sambuc // Check whether the [class.protected] restriction is limiting 1047*f4a2713aSLionel Sambuc // access. 1048*f4a2713aSLionel Sambuc 1049*f4a2713aSLionel Sambuc // To get this exactly right, this might need to be checked more 1050*f4a2713aSLionel Sambuc // holistically; it's not necessarily the case that gaining 1051*f4a2713aSLionel Sambuc // access here would grant us access overall. 1052*f4a2713aSLionel Sambuc 1053*f4a2713aSLionel Sambuc NamedDecl *D = Target.getTargetDecl(); 1054*f4a2713aSLionel Sambuc 1055*f4a2713aSLionel Sambuc // If we don't have an instance context, [class.protected] says the 1056*f4a2713aSLionel Sambuc // naming class has to equal the context class. 1057*f4a2713aSLionel Sambuc if (!Target.hasInstanceContext()) { 1058*f4a2713aSLionel Sambuc // If it does, the restriction doesn't apply. 1059*f4a2713aSLionel Sambuc if (NamingClass == ECRecord) continue; 1060*f4a2713aSLionel Sambuc 1061*f4a2713aSLionel Sambuc // TODO: it would be great to have a fixit here, since this is 1062*f4a2713aSLionel Sambuc // such an obvious error. 1063*f4a2713aSLionel Sambuc S.Diag(D->getLocation(), diag::note_access_protected_restricted_noobject) 1064*f4a2713aSLionel Sambuc << S.Context.getTypeDeclType(ECRecord); 1065*f4a2713aSLionel Sambuc return true; 1066*f4a2713aSLionel Sambuc } 1067*f4a2713aSLionel Sambuc 1068*f4a2713aSLionel Sambuc const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S); 1069*f4a2713aSLionel Sambuc assert(InstanceContext && "diagnosing dependent access"); 1070*f4a2713aSLionel Sambuc 1071*f4a2713aSLionel Sambuc switch (IsDerivedFromInclusive(InstanceContext, ECRecord)) { 1072*f4a2713aSLionel Sambuc case AR_accessible: continue; 1073*f4a2713aSLionel Sambuc case AR_dependent: continue; 1074*f4a2713aSLionel Sambuc case AR_inaccessible: 1075*f4a2713aSLionel Sambuc break; 1076*f4a2713aSLionel Sambuc } 1077*f4a2713aSLionel Sambuc 1078*f4a2713aSLionel Sambuc // Okay, the restriction seems to be what's limiting us. 1079*f4a2713aSLionel Sambuc 1080*f4a2713aSLionel Sambuc // Use a special diagnostic for constructors and destructors. 1081*f4a2713aSLionel Sambuc if (isa<CXXConstructorDecl>(D) || isa<CXXDestructorDecl>(D) || 1082*f4a2713aSLionel Sambuc (isa<FunctionTemplateDecl>(D) && 1083*f4a2713aSLionel Sambuc isa<CXXConstructorDecl>( 1084*f4a2713aSLionel Sambuc cast<FunctionTemplateDecl>(D)->getTemplatedDecl()))) { 1085*f4a2713aSLionel Sambuc S.Diag(D->getLocation(), diag::note_access_protected_restricted_ctordtor) 1086*f4a2713aSLionel Sambuc << isa<CXXDestructorDecl>(D); 1087*f4a2713aSLionel Sambuc return true; 1088*f4a2713aSLionel Sambuc } 1089*f4a2713aSLionel Sambuc 1090*f4a2713aSLionel Sambuc // Otherwise, use the generic diagnostic. 1091*f4a2713aSLionel Sambuc S.Diag(D->getLocation(), diag::note_access_protected_restricted_object) 1092*f4a2713aSLionel Sambuc << S.Context.getTypeDeclType(ECRecord); 1093*f4a2713aSLionel Sambuc return true; 1094*f4a2713aSLionel Sambuc } 1095*f4a2713aSLionel Sambuc 1096*f4a2713aSLionel Sambuc return false; 1097*f4a2713aSLionel Sambuc } 1098*f4a2713aSLionel Sambuc 1099*f4a2713aSLionel Sambuc /// We are unable to access a given declaration due to its direct 1100*f4a2713aSLionel Sambuc /// access control; diagnose that. 1101*f4a2713aSLionel Sambuc static void diagnoseBadDirectAccess(Sema &S, 1102*f4a2713aSLionel Sambuc const EffectiveContext &EC, 1103*f4a2713aSLionel Sambuc AccessTarget &entity) { 1104*f4a2713aSLionel Sambuc assert(entity.isMemberAccess()); 1105*f4a2713aSLionel Sambuc NamedDecl *D = entity.getTargetDecl(); 1106*f4a2713aSLionel Sambuc 1107*f4a2713aSLionel Sambuc if (D->getAccess() == AS_protected && 1108*f4a2713aSLionel Sambuc TryDiagnoseProtectedAccess(S, EC, entity)) 1109*f4a2713aSLionel Sambuc return; 1110*f4a2713aSLionel Sambuc 1111*f4a2713aSLionel Sambuc // Find an original declaration. 1112*f4a2713aSLionel Sambuc while (D->isOutOfLine()) { 1113*f4a2713aSLionel Sambuc NamedDecl *PrevDecl = 0; 1114*f4a2713aSLionel Sambuc if (VarDecl *VD = dyn_cast<VarDecl>(D)) 1115*f4a2713aSLionel Sambuc PrevDecl = VD->getPreviousDecl(); 1116*f4a2713aSLionel Sambuc else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) 1117*f4a2713aSLionel Sambuc PrevDecl = FD->getPreviousDecl(); 1118*f4a2713aSLionel Sambuc else if (TypedefNameDecl *TND = dyn_cast<TypedefNameDecl>(D)) 1119*f4a2713aSLionel Sambuc PrevDecl = TND->getPreviousDecl(); 1120*f4a2713aSLionel Sambuc else if (TagDecl *TD = dyn_cast<TagDecl>(D)) { 1121*f4a2713aSLionel Sambuc if (isa<RecordDecl>(D) && cast<RecordDecl>(D)->isInjectedClassName()) 1122*f4a2713aSLionel Sambuc break; 1123*f4a2713aSLionel Sambuc PrevDecl = TD->getPreviousDecl(); 1124*f4a2713aSLionel Sambuc } 1125*f4a2713aSLionel Sambuc if (!PrevDecl) break; 1126*f4a2713aSLionel Sambuc D = PrevDecl; 1127*f4a2713aSLionel Sambuc } 1128*f4a2713aSLionel Sambuc 1129*f4a2713aSLionel Sambuc CXXRecordDecl *DeclaringClass = FindDeclaringClass(D); 1130*f4a2713aSLionel Sambuc Decl *ImmediateChild; 1131*f4a2713aSLionel Sambuc if (D->getDeclContext() == DeclaringClass) 1132*f4a2713aSLionel Sambuc ImmediateChild = D; 1133*f4a2713aSLionel Sambuc else { 1134*f4a2713aSLionel Sambuc DeclContext *DC = D->getDeclContext(); 1135*f4a2713aSLionel Sambuc while (DC->getParent() != DeclaringClass) 1136*f4a2713aSLionel Sambuc DC = DC->getParent(); 1137*f4a2713aSLionel Sambuc ImmediateChild = cast<Decl>(DC); 1138*f4a2713aSLionel Sambuc } 1139*f4a2713aSLionel Sambuc 1140*f4a2713aSLionel Sambuc // Check whether there's an AccessSpecDecl preceding this in the 1141*f4a2713aSLionel Sambuc // chain of the DeclContext. 1142*f4a2713aSLionel Sambuc bool isImplicit = true; 1143*f4a2713aSLionel Sambuc for (CXXRecordDecl::decl_iterator 1144*f4a2713aSLionel Sambuc I = DeclaringClass->decls_begin(), E = DeclaringClass->decls_end(); 1145*f4a2713aSLionel Sambuc I != E; ++I) { 1146*f4a2713aSLionel Sambuc if (*I == ImmediateChild) break; 1147*f4a2713aSLionel Sambuc if (isa<AccessSpecDecl>(*I)) { 1148*f4a2713aSLionel Sambuc isImplicit = false; 1149*f4a2713aSLionel Sambuc break; 1150*f4a2713aSLionel Sambuc } 1151*f4a2713aSLionel Sambuc } 1152*f4a2713aSLionel Sambuc 1153*f4a2713aSLionel Sambuc S.Diag(D->getLocation(), diag::note_access_natural) 1154*f4a2713aSLionel Sambuc << (unsigned) (D->getAccess() == AS_protected) 1155*f4a2713aSLionel Sambuc << isImplicit; 1156*f4a2713aSLionel Sambuc } 1157*f4a2713aSLionel Sambuc 1158*f4a2713aSLionel Sambuc /// Diagnose the path which caused the given declaration or base class 1159*f4a2713aSLionel Sambuc /// to become inaccessible. 1160*f4a2713aSLionel Sambuc static void DiagnoseAccessPath(Sema &S, 1161*f4a2713aSLionel Sambuc const EffectiveContext &EC, 1162*f4a2713aSLionel Sambuc AccessTarget &entity) { 1163*f4a2713aSLionel Sambuc // Save the instance context to preserve invariants. 1164*f4a2713aSLionel Sambuc AccessTarget::SavedInstanceContext _ = entity.saveInstanceContext(); 1165*f4a2713aSLionel Sambuc 1166*f4a2713aSLionel Sambuc // This basically repeats the main algorithm but keeps some more 1167*f4a2713aSLionel Sambuc // information. 1168*f4a2713aSLionel Sambuc 1169*f4a2713aSLionel Sambuc // The natural access so far. 1170*f4a2713aSLionel Sambuc AccessSpecifier accessSoFar = AS_public; 1171*f4a2713aSLionel Sambuc 1172*f4a2713aSLionel Sambuc // Check whether we have special rights to the declaring class. 1173*f4a2713aSLionel Sambuc if (entity.isMemberAccess()) { 1174*f4a2713aSLionel Sambuc NamedDecl *D = entity.getTargetDecl(); 1175*f4a2713aSLionel Sambuc accessSoFar = D->getAccess(); 1176*f4a2713aSLionel Sambuc const CXXRecordDecl *declaringClass = entity.getDeclaringClass(); 1177*f4a2713aSLionel Sambuc 1178*f4a2713aSLionel Sambuc switch (HasAccess(S, EC, declaringClass, accessSoFar, entity)) { 1179*f4a2713aSLionel Sambuc // If the declaration is accessible when named in its declaring 1180*f4a2713aSLionel Sambuc // class, then we must be constrained by the path. 1181*f4a2713aSLionel Sambuc case AR_accessible: 1182*f4a2713aSLionel Sambuc accessSoFar = AS_public; 1183*f4a2713aSLionel Sambuc entity.suppressInstanceContext(); 1184*f4a2713aSLionel Sambuc break; 1185*f4a2713aSLionel Sambuc 1186*f4a2713aSLionel Sambuc case AR_inaccessible: 1187*f4a2713aSLionel Sambuc if (accessSoFar == AS_private || 1188*f4a2713aSLionel Sambuc declaringClass == entity.getEffectiveNamingClass()) 1189*f4a2713aSLionel Sambuc return diagnoseBadDirectAccess(S, EC, entity); 1190*f4a2713aSLionel Sambuc break; 1191*f4a2713aSLionel Sambuc 1192*f4a2713aSLionel Sambuc case AR_dependent: 1193*f4a2713aSLionel Sambuc llvm_unreachable("cannot diagnose dependent access"); 1194*f4a2713aSLionel Sambuc } 1195*f4a2713aSLionel Sambuc } 1196*f4a2713aSLionel Sambuc 1197*f4a2713aSLionel Sambuc CXXBasePaths paths; 1198*f4a2713aSLionel Sambuc CXXBasePath &path = *FindBestPath(S, EC, entity, accessSoFar, paths); 1199*f4a2713aSLionel Sambuc assert(path.Access != AS_public); 1200*f4a2713aSLionel Sambuc 1201*f4a2713aSLionel Sambuc CXXBasePath::iterator i = path.end(), e = path.begin(); 1202*f4a2713aSLionel Sambuc CXXBasePath::iterator constrainingBase = i; 1203*f4a2713aSLionel Sambuc while (i != e) { 1204*f4a2713aSLionel Sambuc --i; 1205*f4a2713aSLionel Sambuc 1206*f4a2713aSLionel Sambuc assert(accessSoFar != AS_none && accessSoFar != AS_private); 1207*f4a2713aSLionel Sambuc 1208*f4a2713aSLionel Sambuc // Is the entity accessible when named in the deriving class, as 1209*f4a2713aSLionel Sambuc // modified by the base specifier? 1210*f4a2713aSLionel Sambuc const CXXRecordDecl *derivingClass = i->Class->getCanonicalDecl(); 1211*f4a2713aSLionel Sambuc const CXXBaseSpecifier *base = i->Base; 1212*f4a2713aSLionel Sambuc 1213*f4a2713aSLionel Sambuc // If the access to this base is worse than the access we have to 1214*f4a2713aSLionel Sambuc // the declaration, remember it. 1215*f4a2713aSLionel Sambuc AccessSpecifier baseAccess = base->getAccessSpecifier(); 1216*f4a2713aSLionel Sambuc if (baseAccess > accessSoFar) { 1217*f4a2713aSLionel Sambuc constrainingBase = i; 1218*f4a2713aSLionel Sambuc accessSoFar = baseAccess; 1219*f4a2713aSLionel Sambuc } 1220*f4a2713aSLionel Sambuc 1221*f4a2713aSLionel Sambuc switch (HasAccess(S, EC, derivingClass, accessSoFar, entity)) { 1222*f4a2713aSLionel Sambuc case AR_inaccessible: break; 1223*f4a2713aSLionel Sambuc case AR_accessible: 1224*f4a2713aSLionel Sambuc accessSoFar = AS_public; 1225*f4a2713aSLionel Sambuc entity.suppressInstanceContext(); 1226*f4a2713aSLionel Sambuc constrainingBase = 0; 1227*f4a2713aSLionel Sambuc break; 1228*f4a2713aSLionel Sambuc case AR_dependent: 1229*f4a2713aSLionel Sambuc llvm_unreachable("cannot diagnose dependent access"); 1230*f4a2713aSLionel Sambuc } 1231*f4a2713aSLionel Sambuc 1232*f4a2713aSLionel Sambuc // If this was private inheritance, but we don't have access to 1233*f4a2713aSLionel Sambuc // the deriving class, we're done. 1234*f4a2713aSLionel Sambuc if (accessSoFar == AS_private) { 1235*f4a2713aSLionel Sambuc assert(baseAccess == AS_private); 1236*f4a2713aSLionel Sambuc assert(constrainingBase == i); 1237*f4a2713aSLionel Sambuc break; 1238*f4a2713aSLionel Sambuc } 1239*f4a2713aSLionel Sambuc } 1240*f4a2713aSLionel Sambuc 1241*f4a2713aSLionel Sambuc // If we don't have a constraining base, the access failure must be 1242*f4a2713aSLionel Sambuc // due to the original declaration. 1243*f4a2713aSLionel Sambuc if (constrainingBase == path.end()) 1244*f4a2713aSLionel Sambuc return diagnoseBadDirectAccess(S, EC, entity); 1245*f4a2713aSLionel Sambuc 1246*f4a2713aSLionel Sambuc // We're constrained by inheritance, but we want to say 1247*f4a2713aSLionel Sambuc // "declared private here" if we're diagnosing a hierarchy 1248*f4a2713aSLionel Sambuc // conversion and this is the final step. 1249*f4a2713aSLionel Sambuc unsigned diagnostic; 1250*f4a2713aSLionel Sambuc if (entity.isMemberAccess() || 1251*f4a2713aSLionel Sambuc constrainingBase + 1 != path.end()) { 1252*f4a2713aSLionel Sambuc diagnostic = diag::note_access_constrained_by_path; 1253*f4a2713aSLionel Sambuc } else { 1254*f4a2713aSLionel Sambuc diagnostic = diag::note_access_natural; 1255*f4a2713aSLionel Sambuc } 1256*f4a2713aSLionel Sambuc 1257*f4a2713aSLionel Sambuc const CXXBaseSpecifier *base = constrainingBase->Base; 1258*f4a2713aSLionel Sambuc 1259*f4a2713aSLionel Sambuc S.Diag(base->getSourceRange().getBegin(), diagnostic) 1260*f4a2713aSLionel Sambuc << base->getSourceRange() 1261*f4a2713aSLionel Sambuc << (base->getAccessSpecifier() == AS_protected) 1262*f4a2713aSLionel Sambuc << (base->getAccessSpecifierAsWritten() == AS_none); 1263*f4a2713aSLionel Sambuc 1264*f4a2713aSLionel Sambuc if (entity.isMemberAccess()) 1265*f4a2713aSLionel Sambuc S.Diag(entity.getTargetDecl()->getLocation(), diag::note_field_decl); 1266*f4a2713aSLionel Sambuc } 1267*f4a2713aSLionel Sambuc 1268*f4a2713aSLionel Sambuc static void DiagnoseBadAccess(Sema &S, SourceLocation Loc, 1269*f4a2713aSLionel Sambuc const EffectiveContext &EC, 1270*f4a2713aSLionel Sambuc AccessTarget &Entity) { 1271*f4a2713aSLionel Sambuc const CXXRecordDecl *NamingClass = Entity.getNamingClass(); 1272*f4a2713aSLionel Sambuc const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass(); 1273*f4a2713aSLionel Sambuc NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : 0); 1274*f4a2713aSLionel Sambuc 1275*f4a2713aSLionel Sambuc S.Diag(Loc, Entity.getDiag()) 1276*f4a2713aSLionel Sambuc << (Entity.getAccess() == AS_protected) 1277*f4a2713aSLionel Sambuc << (D ? D->getDeclName() : DeclarationName()) 1278*f4a2713aSLionel Sambuc << S.Context.getTypeDeclType(NamingClass) 1279*f4a2713aSLionel Sambuc << S.Context.getTypeDeclType(DeclaringClass); 1280*f4a2713aSLionel Sambuc DiagnoseAccessPath(S, EC, Entity); 1281*f4a2713aSLionel Sambuc } 1282*f4a2713aSLionel Sambuc 1283*f4a2713aSLionel Sambuc /// MSVC has a bug where if during an using declaration name lookup, 1284*f4a2713aSLionel Sambuc /// the declaration found is unaccessible (private) and that declaration 1285*f4a2713aSLionel Sambuc /// was bring into scope via another using declaration whose target 1286*f4a2713aSLionel Sambuc /// declaration is accessible (public) then no error is generated. 1287*f4a2713aSLionel Sambuc /// Example: 1288*f4a2713aSLionel Sambuc /// class A { 1289*f4a2713aSLionel Sambuc /// public: 1290*f4a2713aSLionel Sambuc /// int f(); 1291*f4a2713aSLionel Sambuc /// }; 1292*f4a2713aSLionel Sambuc /// class B : public A { 1293*f4a2713aSLionel Sambuc /// private: 1294*f4a2713aSLionel Sambuc /// using A::f; 1295*f4a2713aSLionel Sambuc /// }; 1296*f4a2713aSLionel Sambuc /// class C : public B { 1297*f4a2713aSLionel Sambuc /// private: 1298*f4a2713aSLionel Sambuc /// using B::f; 1299*f4a2713aSLionel Sambuc /// }; 1300*f4a2713aSLionel Sambuc /// 1301*f4a2713aSLionel Sambuc /// Here, B::f is private so this should fail in Standard C++, but 1302*f4a2713aSLionel Sambuc /// because B::f refers to A::f which is public MSVC accepts it. 1303*f4a2713aSLionel Sambuc static bool IsMicrosoftUsingDeclarationAccessBug(Sema& S, 1304*f4a2713aSLionel Sambuc SourceLocation AccessLoc, 1305*f4a2713aSLionel Sambuc AccessTarget &Entity) { 1306*f4a2713aSLionel Sambuc if (UsingShadowDecl *Shadow = 1307*f4a2713aSLionel Sambuc dyn_cast<UsingShadowDecl>(Entity.getTargetDecl())) { 1308*f4a2713aSLionel Sambuc const NamedDecl *OrigDecl = Entity.getTargetDecl()->getUnderlyingDecl(); 1309*f4a2713aSLionel Sambuc if (Entity.getTargetDecl()->getAccess() == AS_private && 1310*f4a2713aSLionel Sambuc (OrigDecl->getAccess() == AS_public || 1311*f4a2713aSLionel Sambuc OrigDecl->getAccess() == AS_protected)) { 1312*f4a2713aSLionel Sambuc S.Diag(AccessLoc, diag::ext_ms_using_declaration_inaccessible) 1313*f4a2713aSLionel Sambuc << Shadow->getUsingDecl()->getQualifiedNameAsString() 1314*f4a2713aSLionel Sambuc << OrigDecl->getQualifiedNameAsString(); 1315*f4a2713aSLionel Sambuc return true; 1316*f4a2713aSLionel Sambuc } 1317*f4a2713aSLionel Sambuc } 1318*f4a2713aSLionel Sambuc return false; 1319*f4a2713aSLionel Sambuc } 1320*f4a2713aSLionel Sambuc 1321*f4a2713aSLionel Sambuc /// Determines whether the accessed entity is accessible. Public members 1322*f4a2713aSLionel Sambuc /// have been weeded out by this point. 1323*f4a2713aSLionel Sambuc static AccessResult IsAccessible(Sema &S, 1324*f4a2713aSLionel Sambuc const EffectiveContext &EC, 1325*f4a2713aSLionel Sambuc AccessTarget &Entity) { 1326*f4a2713aSLionel Sambuc // Determine the actual naming class. 1327*f4a2713aSLionel Sambuc const CXXRecordDecl *NamingClass = Entity.getEffectiveNamingClass(); 1328*f4a2713aSLionel Sambuc 1329*f4a2713aSLionel Sambuc AccessSpecifier UnprivilegedAccess = Entity.getAccess(); 1330*f4a2713aSLionel Sambuc assert(UnprivilegedAccess != AS_public && "public access not weeded out"); 1331*f4a2713aSLionel Sambuc 1332*f4a2713aSLionel Sambuc // Before we try to recalculate access paths, try to white-list 1333*f4a2713aSLionel Sambuc // accesses which just trade in on the final step, i.e. accesses 1334*f4a2713aSLionel Sambuc // which don't require [M4] or [B4]. These are by far the most 1335*f4a2713aSLionel Sambuc // common forms of privileged access. 1336*f4a2713aSLionel Sambuc if (UnprivilegedAccess != AS_none) { 1337*f4a2713aSLionel Sambuc switch (HasAccess(S, EC, NamingClass, UnprivilegedAccess, Entity)) { 1338*f4a2713aSLionel Sambuc case AR_dependent: 1339*f4a2713aSLionel Sambuc // This is actually an interesting policy decision. We don't 1340*f4a2713aSLionel Sambuc // *have* to delay immediately here: we can do the full access 1341*f4a2713aSLionel Sambuc // calculation in the hope that friendship on some intermediate 1342*f4a2713aSLionel Sambuc // class will make the declaration accessible non-dependently. 1343*f4a2713aSLionel Sambuc // But that's not cheap, and odds are very good (note: assertion 1344*f4a2713aSLionel Sambuc // made without data) that the friend declaration will determine 1345*f4a2713aSLionel Sambuc // access. 1346*f4a2713aSLionel Sambuc return AR_dependent; 1347*f4a2713aSLionel Sambuc 1348*f4a2713aSLionel Sambuc case AR_accessible: return AR_accessible; 1349*f4a2713aSLionel Sambuc case AR_inaccessible: break; 1350*f4a2713aSLionel Sambuc } 1351*f4a2713aSLionel Sambuc } 1352*f4a2713aSLionel Sambuc 1353*f4a2713aSLionel Sambuc AccessTarget::SavedInstanceContext _ = Entity.saveInstanceContext(); 1354*f4a2713aSLionel Sambuc 1355*f4a2713aSLionel Sambuc // We lower member accesses to base accesses by pretending that the 1356*f4a2713aSLionel Sambuc // member is a base class of its declaring class. 1357*f4a2713aSLionel Sambuc AccessSpecifier FinalAccess; 1358*f4a2713aSLionel Sambuc 1359*f4a2713aSLionel Sambuc if (Entity.isMemberAccess()) { 1360*f4a2713aSLionel Sambuc // Determine if the declaration is accessible from EC when named 1361*f4a2713aSLionel Sambuc // in its declaring class. 1362*f4a2713aSLionel Sambuc NamedDecl *Target = Entity.getTargetDecl(); 1363*f4a2713aSLionel Sambuc const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass(); 1364*f4a2713aSLionel Sambuc 1365*f4a2713aSLionel Sambuc FinalAccess = Target->getAccess(); 1366*f4a2713aSLionel Sambuc switch (HasAccess(S, EC, DeclaringClass, FinalAccess, Entity)) { 1367*f4a2713aSLionel Sambuc case AR_accessible: 1368*f4a2713aSLionel Sambuc // Target is accessible at EC when named in its declaring class. 1369*f4a2713aSLionel Sambuc // We can now hill-climb and simply check whether the declaring 1370*f4a2713aSLionel Sambuc // class is accessible as a base of the naming class. This is 1371*f4a2713aSLionel Sambuc // equivalent to checking the access of a notional public 1372*f4a2713aSLionel Sambuc // member with no instance context. 1373*f4a2713aSLionel Sambuc FinalAccess = AS_public; 1374*f4a2713aSLionel Sambuc Entity.suppressInstanceContext(); 1375*f4a2713aSLionel Sambuc break; 1376*f4a2713aSLionel Sambuc case AR_inaccessible: break; 1377*f4a2713aSLionel Sambuc case AR_dependent: return AR_dependent; // see above 1378*f4a2713aSLionel Sambuc } 1379*f4a2713aSLionel Sambuc 1380*f4a2713aSLionel Sambuc if (DeclaringClass == NamingClass) 1381*f4a2713aSLionel Sambuc return (FinalAccess == AS_public ? AR_accessible : AR_inaccessible); 1382*f4a2713aSLionel Sambuc } else { 1383*f4a2713aSLionel Sambuc FinalAccess = AS_public; 1384*f4a2713aSLionel Sambuc } 1385*f4a2713aSLionel Sambuc 1386*f4a2713aSLionel Sambuc assert(Entity.getDeclaringClass() != NamingClass); 1387*f4a2713aSLionel Sambuc 1388*f4a2713aSLionel Sambuc // Append the declaration's access if applicable. 1389*f4a2713aSLionel Sambuc CXXBasePaths Paths; 1390*f4a2713aSLionel Sambuc CXXBasePath *Path = FindBestPath(S, EC, Entity, FinalAccess, Paths); 1391*f4a2713aSLionel Sambuc if (!Path) 1392*f4a2713aSLionel Sambuc return AR_dependent; 1393*f4a2713aSLionel Sambuc 1394*f4a2713aSLionel Sambuc assert(Path->Access <= UnprivilegedAccess && 1395*f4a2713aSLionel Sambuc "access along best path worse than direct?"); 1396*f4a2713aSLionel Sambuc if (Path->Access == AS_public) 1397*f4a2713aSLionel Sambuc return AR_accessible; 1398*f4a2713aSLionel Sambuc return AR_inaccessible; 1399*f4a2713aSLionel Sambuc } 1400*f4a2713aSLionel Sambuc 1401*f4a2713aSLionel Sambuc static void DelayDependentAccess(Sema &S, 1402*f4a2713aSLionel Sambuc const EffectiveContext &EC, 1403*f4a2713aSLionel Sambuc SourceLocation Loc, 1404*f4a2713aSLionel Sambuc const AccessTarget &Entity) { 1405*f4a2713aSLionel Sambuc assert(EC.isDependent() && "delaying non-dependent access"); 1406*f4a2713aSLionel Sambuc DeclContext *DC = EC.getInnerContext(); 1407*f4a2713aSLionel Sambuc assert(DC->isDependentContext() && "delaying non-dependent access"); 1408*f4a2713aSLionel Sambuc DependentDiagnostic::Create(S.Context, DC, DependentDiagnostic::Access, 1409*f4a2713aSLionel Sambuc Loc, 1410*f4a2713aSLionel Sambuc Entity.isMemberAccess(), 1411*f4a2713aSLionel Sambuc Entity.getAccess(), 1412*f4a2713aSLionel Sambuc Entity.getTargetDecl(), 1413*f4a2713aSLionel Sambuc Entity.getNamingClass(), 1414*f4a2713aSLionel Sambuc Entity.getBaseObjectType(), 1415*f4a2713aSLionel Sambuc Entity.getDiag()); 1416*f4a2713aSLionel Sambuc } 1417*f4a2713aSLionel Sambuc 1418*f4a2713aSLionel Sambuc /// Checks access to an entity from the given effective context. 1419*f4a2713aSLionel Sambuc static AccessResult CheckEffectiveAccess(Sema &S, 1420*f4a2713aSLionel Sambuc const EffectiveContext &EC, 1421*f4a2713aSLionel Sambuc SourceLocation Loc, 1422*f4a2713aSLionel Sambuc AccessTarget &Entity) { 1423*f4a2713aSLionel Sambuc assert(Entity.getAccess() != AS_public && "called for public access!"); 1424*f4a2713aSLionel Sambuc 1425*f4a2713aSLionel Sambuc if (S.getLangOpts().MicrosoftMode && 1426*f4a2713aSLionel Sambuc IsMicrosoftUsingDeclarationAccessBug(S, Loc, Entity)) 1427*f4a2713aSLionel Sambuc return AR_accessible; 1428*f4a2713aSLionel Sambuc 1429*f4a2713aSLionel Sambuc switch (IsAccessible(S, EC, Entity)) { 1430*f4a2713aSLionel Sambuc case AR_dependent: 1431*f4a2713aSLionel Sambuc DelayDependentAccess(S, EC, Loc, Entity); 1432*f4a2713aSLionel Sambuc return AR_dependent; 1433*f4a2713aSLionel Sambuc 1434*f4a2713aSLionel Sambuc case AR_inaccessible: 1435*f4a2713aSLionel Sambuc if (!Entity.isQuiet()) 1436*f4a2713aSLionel Sambuc DiagnoseBadAccess(S, Loc, EC, Entity); 1437*f4a2713aSLionel Sambuc return AR_inaccessible; 1438*f4a2713aSLionel Sambuc 1439*f4a2713aSLionel Sambuc case AR_accessible: 1440*f4a2713aSLionel Sambuc return AR_accessible; 1441*f4a2713aSLionel Sambuc } 1442*f4a2713aSLionel Sambuc 1443*f4a2713aSLionel Sambuc // silence unnecessary warning 1444*f4a2713aSLionel Sambuc llvm_unreachable("invalid access result"); 1445*f4a2713aSLionel Sambuc } 1446*f4a2713aSLionel Sambuc 1447*f4a2713aSLionel Sambuc static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc, 1448*f4a2713aSLionel Sambuc AccessTarget &Entity) { 1449*f4a2713aSLionel Sambuc // If the access path is public, it's accessible everywhere. 1450*f4a2713aSLionel Sambuc if (Entity.getAccess() == AS_public) 1451*f4a2713aSLionel Sambuc return Sema::AR_accessible; 1452*f4a2713aSLionel Sambuc 1453*f4a2713aSLionel Sambuc // If we're currently parsing a declaration, we may need to delay 1454*f4a2713aSLionel Sambuc // access control checking, because our effective context might be 1455*f4a2713aSLionel Sambuc // different based on what the declaration comes out as. 1456*f4a2713aSLionel Sambuc // 1457*f4a2713aSLionel Sambuc // For example, we might be parsing a declaration with a scope 1458*f4a2713aSLionel Sambuc // specifier, like this: 1459*f4a2713aSLionel Sambuc // A::private_type A::foo() { ... } 1460*f4a2713aSLionel Sambuc // 1461*f4a2713aSLionel Sambuc // Or we might be parsing something that will turn out to be a friend: 1462*f4a2713aSLionel Sambuc // void foo(A::private_type); 1463*f4a2713aSLionel Sambuc // void B::foo(A::private_type); 1464*f4a2713aSLionel Sambuc if (S.DelayedDiagnostics.shouldDelayDiagnostics()) { 1465*f4a2713aSLionel Sambuc S.DelayedDiagnostics.add(DelayedDiagnostic::makeAccess(Loc, Entity)); 1466*f4a2713aSLionel Sambuc return Sema::AR_delayed; 1467*f4a2713aSLionel Sambuc } 1468*f4a2713aSLionel Sambuc 1469*f4a2713aSLionel Sambuc EffectiveContext EC(S.CurContext); 1470*f4a2713aSLionel Sambuc switch (CheckEffectiveAccess(S, EC, Loc, Entity)) { 1471*f4a2713aSLionel Sambuc case AR_accessible: return Sema::AR_accessible; 1472*f4a2713aSLionel Sambuc case AR_inaccessible: return Sema::AR_inaccessible; 1473*f4a2713aSLionel Sambuc case AR_dependent: return Sema::AR_dependent; 1474*f4a2713aSLionel Sambuc } 1475*f4a2713aSLionel Sambuc llvm_unreachable("falling off end"); 1476*f4a2713aSLionel Sambuc } 1477*f4a2713aSLionel Sambuc 1478*f4a2713aSLionel Sambuc void Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *D) { 1479*f4a2713aSLionel Sambuc // Access control for names used in the declarations of functions 1480*f4a2713aSLionel Sambuc // and function templates should normally be evaluated in the context 1481*f4a2713aSLionel Sambuc // of the declaration, just in case it's a friend of something. 1482*f4a2713aSLionel Sambuc // However, this does not apply to local extern declarations. 1483*f4a2713aSLionel Sambuc 1484*f4a2713aSLionel Sambuc DeclContext *DC = D->getDeclContext(); 1485*f4a2713aSLionel Sambuc if (FunctionDecl *FN = dyn_cast<FunctionDecl>(D)) { 1486*f4a2713aSLionel Sambuc if (D->getLexicalDeclContext()->isFunctionOrMethod()) 1487*f4a2713aSLionel Sambuc DC = D->getLexicalDeclContext(); 1488*f4a2713aSLionel Sambuc else 1489*f4a2713aSLionel Sambuc DC = FN; 1490*f4a2713aSLionel Sambuc } else if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D)) { 1491*f4a2713aSLionel Sambuc DC = cast<DeclContext>(TD->getTemplatedDecl()); 1492*f4a2713aSLionel Sambuc } 1493*f4a2713aSLionel Sambuc 1494*f4a2713aSLionel Sambuc EffectiveContext EC(DC); 1495*f4a2713aSLionel Sambuc 1496*f4a2713aSLionel Sambuc AccessTarget Target(DD.getAccessData()); 1497*f4a2713aSLionel Sambuc 1498*f4a2713aSLionel Sambuc if (CheckEffectiveAccess(*this, EC, DD.Loc, Target) == ::AR_inaccessible) 1499*f4a2713aSLionel Sambuc DD.Triggered = true; 1500*f4a2713aSLionel Sambuc } 1501*f4a2713aSLionel Sambuc 1502*f4a2713aSLionel Sambuc void Sema::HandleDependentAccessCheck(const DependentDiagnostic &DD, 1503*f4a2713aSLionel Sambuc const MultiLevelTemplateArgumentList &TemplateArgs) { 1504*f4a2713aSLionel Sambuc SourceLocation Loc = DD.getAccessLoc(); 1505*f4a2713aSLionel Sambuc AccessSpecifier Access = DD.getAccess(); 1506*f4a2713aSLionel Sambuc 1507*f4a2713aSLionel Sambuc Decl *NamingD = FindInstantiatedDecl(Loc, DD.getAccessNamingClass(), 1508*f4a2713aSLionel Sambuc TemplateArgs); 1509*f4a2713aSLionel Sambuc if (!NamingD) return; 1510*f4a2713aSLionel Sambuc Decl *TargetD = FindInstantiatedDecl(Loc, DD.getAccessTarget(), 1511*f4a2713aSLionel Sambuc TemplateArgs); 1512*f4a2713aSLionel Sambuc if (!TargetD) return; 1513*f4a2713aSLionel Sambuc 1514*f4a2713aSLionel Sambuc if (DD.isAccessToMember()) { 1515*f4a2713aSLionel Sambuc CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(NamingD); 1516*f4a2713aSLionel Sambuc NamedDecl *TargetDecl = cast<NamedDecl>(TargetD); 1517*f4a2713aSLionel Sambuc QualType BaseObjectType = DD.getAccessBaseObjectType(); 1518*f4a2713aSLionel Sambuc if (!BaseObjectType.isNull()) { 1519*f4a2713aSLionel Sambuc BaseObjectType = SubstType(BaseObjectType, TemplateArgs, Loc, 1520*f4a2713aSLionel Sambuc DeclarationName()); 1521*f4a2713aSLionel Sambuc if (BaseObjectType.isNull()) return; 1522*f4a2713aSLionel Sambuc } 1523*f4a2713aSLionel Sambuc 1524*f4a2713aSLionel Sambuc AccessTarget Entity(Context, 1525*f4a2713aSLionel Sambuc AccessTarget::Member, 1526*f4a2713aSLionel Sambuc NamingClass, 1527*f4a2713aSLionel Sambuc DeclAccessPair::make(TargetDecl, Access), 1528*f4a2713aSLionel Sambuc BaseObjectType); 1529*f4a2713aSLionel Sambuc Entity.setDiag(DD.getDiagnostic()); 1530*f4a2713aSLionel Sambuc CheckAccess(*this, Loc, Entity); 1531*f4a2713aSLionel Sambuc } else { 1532*f4a2713aSLionel Sambuc AccessTarget Entity(Context, 1533*f4a2713aSLionel Sambuc AccessTarget::Base, 1534*f4a2713aSLionel Sambuc cast<CXXRecordDecl>(TargetD), 1535*f4a2713aSLionel Sambuc cast<CXXRecordDecl>(NamingD), 1536*f4a2713aSLionel Sambuc Access); 1537*f4a2713aSLionel Sambuc Entity.setDiag(DD.getDiagnostic()); 1538*f4a2713aSLionel Sambuc CheckAccess(*this, Loc, Entity); 1539*f4a2713aSLionel Sambuc } 1540*f4a2713aSLionel Sambuc } 1541*f4a2713aSLionel Sambuc 1542*f4a2713aSLionel Sambuc Sema::AccessResult Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E, 1543*f4a2713aSLionel Sambuc DeclAccessPair Found) { 1544*f4a2713aSLionel Sambuc if (!getLangOpts().AccessControl || 1545*f4a2713aSLionel Sambuc !E->getNamingClass() || 1546*f4a2713aSLionel Sambuc Found.getAccess() == AS_public) 1547*f4a2713aSLionel Sambuc return AR_accessible; 1548*f4a2713aSLionel Sambuc 1549*f4a2713aSLionel Sambuc AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(), 1550*f4a2713aSLionel Sambuc Found, QualType()); 1551*f4a2713aSLionel Sambuc Entity.setDiag(diag::err_access) << E->getSourceRange(); 1552*f4a2713aSLionel Sambuc 1553*f4a2713aSLionel Sambuc return CheckAccess(*this, E->getNameLoc(), Entity); 1554*f4a2713aSLionel Sambuc } 1555*f4a2713aSLionel Sambuc 1556*f4a2713aSLionel Sambuc /// Perform access-control checking on a previously-unresolved member 1557*f4a2713aSLionel Sambuc /// access which has now been resolved to a member. 1558*f4a2713aSLionel Sambuc Sema::AccessResult Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E, 1559*f4a2713aSLionel Sambuc DeclAccessPair Found) { 1560*f4a2713aSLionel Sambuc if (!getLangOpts().AccessControl || 1561*f4a2713aSLionel Sambuc Found.getAccess() == AS_public) 1562*f4a2713aSLionel Sambuc return AR_accessible; 1563*f4a2713aSLionel Sambuc 1564*f4a2713aSLionel Sambuc QualType BaseType = E->getBaseType(); 1565*f4a2713aSLionel Sambuc if (E->isArrow()) 1566*f4a2713aSLionel Sambuc BaseType = BaseType->getAs<PointerType>()->getPointeeType(); 1567*f4a2713aSLionel Sambuc 1568*f4a2713aSLionel Sambuc AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(), 1569*f4a2713aSLionel Sambuc Found, BaseType); 1570*f4a2713aSLionel Sambuc Entity.setDiag(diag::err_access) << E->getSourceRange(); 1571*f4a2713aSLionel Sambuc 1572*f4a2713aSLionel Sambuc return CheckAccess(*this, E->getMemberLoc(), Entity); 1573*f4a2713aSLionel Sambuc } 1574*f4a2713aSLionel Sambuc 1575*f4a2713aSLionel Sambuc /// Is the given special member function accessible for the purposes of 1576*f4a2713aSLionel Sambuc /// deciding whether to define a special member function as deleted? 1577*f4a2713aSLionel Sambuc bool Sema::isSpecialMemberAccessibleForDeletion(CXXMethodDecl *decl, 1578*f4a2713aSLionel Sambuc AccessSpecifier access, 1579*f4a2713aSLionel Sambuc QualType objectType) { 1580*f4a2713aSLionel Sambuc // Fast path. 1581*f4a2713aSLionel Sambuc if (access == AS_public || !getLangOpts().AccessControl) return true; 1582*f4a2713aSLionel Sambuc 1583*f4a2713aSLionel Sambuc AccessTarget entity(Context, AccessTarget::Member, decl->getParent(), 1584*f4a2713aSLionel Sambuc DeclAccessPair::make(decl, access), objectType); 1585*f4a2713aSLionel Sambuc 1586*f4a2713aSLionel Sambuc // Suppress diagnostics. 1587*f4a2713aSLionel Sambuc entity.setDiag(PDiag()); 1588*f4a2713aSLionel Sambuc 1589*f4a2713aSLionel Sambuc switch (CheckAccess(*this, SourceLocation(), entity)) { 1590*f4a2713aSLionel Sambuc case AR_accessible: return true; 1591*f4a2713aSLionel Sambuc case AR_inaccessible: return false; 1592*f4a2713aSLionel Sambuc case AR_dependent: llvm_unreachable("dependent for =delete computation"); 1593*f4a2713aSLionel Sambuc case AR_delayed: llvm_unreachable("cannot delay =delete computation"); 1594*f4a2713aSLionel Sambuc } 1595*f4a2713aSLionel Sambuc llvm_unreachable("bad access result"); 1596*f4a2713aSLionel Sambuc } 1597*f4a2713aSLionel Sambuc 1598*f4a2713aSLionel Sambuc Sema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc, 1599*f4a2713aSLionel Sambuc CXXDestructorDecl *Dtor, 1600*f4a2713aSLionel Sambuc const PartialDiagnostic &PDiag, 1601*f4a2713aSLionel Sambuc QualType ObjectTy) { 1602*f4a2713aSLionel Sambuc if (!getLangOpts().AccessControl) 1603*f4a2713aSLionel Sambuc return AR_accessible; 1604*f4a2713aSLionel Sambuc 1605*f4a2713aSLionel Sambuc // There's never a path involved when checking implicit destructor access. 1606*f4a2713aSLionel Sambuc AccessSpecifier Access = Dtor->getAccess(); 1607*f4a2713aSLionel Sambuc if (Access == AS_public) 1608*f4a2713aSLionel Sambuc return AR_accessible; 1609*f4a2713aSLionel Sambuc 1610*f4a2713aSLionel Sambuc CXXRecordDecl *NamingClass = Dtor->getParent(); 1611*f4a2713aSLionel Sambuc if (ObjectTy.isNull()) ObjectTy = Context.getTypeDeclType(NamingClass); 1612*f4a2713aSLionel Sambuc 1613*f4a2713aSLionel Sambuc AccessTarget Entity(Context, AccessTarget::Member, NamingClass, 1614*f4a2713aSLionel Sambuc DeclAccessPair::make(Dtor, Access), 1615*f4a2713aSLionel Sambuc ObjectTy); 1616*f4a2713aSLionel Sambuc Entity.setDiag(PDiag); // TODO: avoid copy 1617*f4a2713aSLionel Sambuc 1618*f4a2713aSLionel Sambuc return CheckAccess(*this, Loc, Entity); 1619*f4a2713aSLionel Sambuc } 1620*f4a2713aSLionel Sambuc 1621*f4a2713aSLionel Sambuc /// Checks access to a constructor. 1622*f4a2713aSLionel Sambuc Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc, 1623*f4a2713aSLionel Sambuc CXXConstructorDecl *Constructor, 1624*f4a2713aSLionel Sambuc const InitializedEntity &Entity, 1625*f4a2713aSLionel Sambuc AccessSpecifier Access, 1626*f4a2713aSLionel Sambuc bool IsCopyBindingRefToTemp) { 1627*f4a2713aSLionel Sambuc if (!getLangOpts().AccessControl || Access == AS_public) 1628*f4a2713aSLionel Sambuc return AR_accessible; 1629*f4a2713aSLionel Sambuc 1630*f4a2713aSLionel Sambuc PartialDiagnostic PD(PDiag()); 1631*f4a2713aSLionel Sambuc switch (Entity.getKind()) { 1632*f4a2713aSLionel Sambuc default: 1633*f4a2713aSLionel Sambuc PD = PDiag(IsCopyBindingRefToTemp 1634*f4a2713aSLionel Sambuc ? diag::ext_rvalue_to_reference_access_ctor 1635*f4a2713aSLionel Sambuc : diag::err_access_ctor); 1636*f4a2713aSLionel Sambuc 1637*f4a2713aSLionel Sambuc break; 1638*f4a2713aSLionel Sambuc 1639*f4a2713aSLionel Sambuc case InitializedEntity::EK_Base: 1640*f4a2713aSLionel Sambuc PD = PDiag(diag::err_access_base_ctor); 1641*f4a2713aSLionel Sambuc PD << Entity.isInheritedVirtualBase() 1642*f4a2713aSLionel Sambuc << Entity.getBaseSpecifier()->getType() << getSpecialMember(Constructor); 1643*f4a2713aSLionel Sambuc break; 1644*f4a2713aSLionel Sambuc 1645*f4a2713aSLionel Sambuc case InitializedEntity::EK_Member: { 1646*f4a2713aSLionel Sambuc const FieldDecl *Field = cast<FieldDecl>(Entity.getDecl()); 1647*f4a2713aSLionel Sambuc PD = PDiag(diag::err_access_field_ctor); 1648*f4a2713aSLionel Sambuc PD << Field->getType() << getSpecialMember(Constructor); 1649*f4a2713aSLionel Sambuc break; 1650*f4a2713aSLionel Sambuc } 1651*f4a2713aSLionel Sambuc 1652*f4a2713aSLionel Sambuc case InitializedEntity::EK_LambdaCapture: { 1653*f4a2713aSLionel Sambuc const VarDecl *Var = Entity.getCapturedVar(); 1654*f4a2713aSLionel Sambuc PD = PDiag(diag::err_access_lambda_capture); 1655*f4a2713aSLionel Sambuc PD << Var->getName() << Entity.getType() << getSpecialMember(Constructor); 1656*f4a2713aSLionel Sambuc break; 1657*f4a2713aSLionel Sambuc } 1658*f4a2713aSLionel Sambuc 1659*f4a2713aSLionel Sambuc } 1660*f4a2713aSLionel Sambuc 1661*f4a2713aSLionel Sambuc return CheckConstructorAccess(UseLoc, Constructor, Entity, Access, PD); 1662*f4a2713aSLionel Sambuc } 1663*f4a2713aSLionel Sambuc 1664*f4a2713aSLionel Sambuc /// Checks access to a constructor. 1665*f4a2713aSLionel Sambuc Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc, 1666*f4a2713aSLionel Sambuc CXXConstructorDecl *Constructor, 1667*f4a2713aSLionel Sambuc const InitializedEntity &Entity, 1668*f4a2713aSLionel Sambuc AccessSpecifier Access, 1669*f4a2713aSLionel Sambuc const PartialDiagnostic &PD) { 1670*f4a2713aSLionel Sambuc if (!getLangOpts().AccessControl || 1671*f4a2713aSLionel Sambuc Access == AS_public) 1672*f4a2713aSLionel Sambuc return AR_accessible; 1673*f4a2713aSLionel Sambuc 1674*f4a2713aSLionel Sambuc CXXRecordDecl *NamingClass = Constructor->getParent(); 1675*f4a2713aSLionel Sambuc 1676*f4a2713aSLionel Sambuc // Initializing a base sub-object is an instance method call on an 1677*f4a2713aSLionel Sambuc // object of the derived class. Otherwise, we have an instance method 1678*f4a2713aSLionel Sambuc // call on an object of the constructed type. 1679*f4a2713aSLionel Sambuc CXXRecordDecl *ObjectClass; 1680*f4a2713aSLionel Sambuc if (Entity.getKind() == InitializedEntity::EK_Base) { 1681*f4a2713aSLionel Sambuc ObjectClass = cast<CXXConstructorDecl>(CurContext)->getParent(); 1682*f4a2713aSLionel Sambuc } else { 1683*f4a2713aSLionel Sambuc ObjectClass = NamingClass; 1684*f4a2713aSLionel Sambuc } 1685*f4a2713aSLionel Sambuc 1686*f4a2713aSLionel Sambuc AccessTarget AccessEntity(Context, AccessTarget::Member, NamingClass, 1687*f4a2713aSLionel Sambuc DeclAccessPair::make(Constructor, Access), 1688*f4a2713aSLionel Sambuc Context.getTypeDeclType(ObjectClass)); 1689*f4a2713aSLionel Sambuc AccessEntity.setDiag(PD); 1690*f4a2713aSLionel Sambuc 1691*f4a2713aSLionel Sambuc return CheckAccess(*this, UseLoc, AccessEntity); 1692*f4a2713aSLionel Sambuc } 1693*f4a2713aSLionel Sambuc 1694*f4a2713aSLionel Sambuc /// Checks access to an overloaded operator new or delete. 1695*f4a2713aSLionel Sambuc Sema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc, 1696*f4a2713aSLionel Sambuc SourceRange PlacementRange, 1697*f4a2713aSLionel Sambuc CXXRecordDecl *NamingClass, 1698*f4a2713aSLionel Sambuc DeclAccessPair Found, 1699*f4a2713aSLionel Sambuc bool Diagnose) { 1700*f4a2713aSLionel Sambuc if (!getLangOpts().AccessControl || 1701*f4a2713aSLionel Sambuc !NamingClass || 1702*f4a2713aSLionel Sambuc Found.getAccess() == AS_public) 1703*f4a2713aSLionel Sambuc return AR_accessible; 1704*f4a2713aSLionel Sambuc 1705*f4a2713aSLionel Sambuc AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found, 1706*f4a2713aSLionel Sambuc QualType()); 1707*f4a2713aSLionel Sambuc if (Diagnose) 1708*f4a2713aSLionel Sambuc Entity.setDiag(diag::err_access) 1709*f4a2713aSLionel Sambuc << PlacementRange; 1710*f4a2713aSLionel Sambuc 1711*f4a2713aSLionel Sambuc return CheckAccess(*this, OpLoc, Entity); 1712*f4a2713aSLionel Sambuc } 1713*f4a2713aSLionel Sambuc 1714*f4a2713aSLionel Sambuc /// \brief Checks access to a member. 1715*f4a2713aSLionel Sambuc Sema::AccessResult Sema::CheckMemberAccess(SourceLocation UseLoc, 1716*f4a2713aSLionel Sambuc CXXRecordDecl *NamingClass, 1717*f4a2713aSLionel Sambuc DeclAccessPair Found) { 1718*f4a2713aSLionel Sambuc if (!getLangOpts().AccessControl || 1719*f4a2713aSLionel Sambuc !NamingClass || 1720*f4a2713aSLionel Sambuc Found.getAccess() == AS_public) 1721*f4a2713aSLionel Sambuc return AR_accessible; 1722*f4a2713aSLionel Sambuc 1723*f4a2713aSLionel Sambuc AccessTarget Entity(Context, AccessTarget::Member, NamingClass, 1724*f4a2713aSLionel Sambuc Found, QualType()); 1725*f4a2713aSLionel Sambuc 1726*f4a2713aSLionel Sambuc return CheckAccess(*this, UseLoc, Entity); 1727*f4a2713aSLionel Sambuc } 1728*f4a2713aSLionel Sambuc 1729*f4a2713aSLionel Sambuc /// Checks access to an overloaded member operator, including 1730*f4a2713aSLionel Sambuc /// conversion operators. 1731*f4a2713aSLionel Sambuc Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc, 1732*f4a2713aSLionel Sambuc Expr *ObjectExpr, 1733*f4a2713aSLionel Sambuc Expr *ArgExpr, 1734*f4a2713aSLionel Sambuc DeclAccessPair Found) { 1735*f4a2713aSLionel Sambuc if (!getLangOpts().AccessControl || 1736*f4a2713aSLionel Sambuc Found.getAccess() == AS_public) 1737*f4a2713aSLionel Sambuc return AR_accessible; 1738*f4a2713aSLionel Sambuc 1739*f4a2713aSLionel Sambuc const RecordType *RT = ObjectExpr->getType()->castAs<RecordType>(); 1740*f4a2713aSLionel Sambuc CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(RT->getDecl()); 1741*f4a2713aSLionel Sambuc 1742*f4a2713aSLionel Sambuc AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found, 1743*f4a2713aSLionel Sambuc ObjectExpr->getType()); 1744*f4a2713aSLionel Sambuc Entity.setDiag(diag::err_access) 1745*f4a2713aSLionel Sambuc << ObjectExpr->getSourceRange() 1746*f4a2713aSLionel Sambuc << (ArgExpr ? ArgExpr->getSourceRange() : SourceRange()); 1747*f4a2713aSLionel Sambuc 1748*f4a2713aSLionel Sambuc return CheckAccess(*this, OpLoc, Entity); 1749*f4a2713aSLionel Sambuc } 1750*f4a2713aSLionel Sambuc 1751*f4a2713aSLionel Sambuc /// Checks access to the target of a friend declaration. 1752*f4a2713aSLionel Sambuc Sema::AccessResult Sema::CheckFriendAccess(NamedDecl *target) { 1753*f4a2713aSLionel Sambuc assert(isa<CXXMethodDecl>(target) || 1754*f4a2713aSLionel Sambuc (isa<FunctionTemplateDecl>(target) && 1755*f4a2713aSLionel Sambuc isa<CXXMethodDecl>(cast<FunctionTemplateDecl>(target) 1756*f4a2713aSLionel Sambuc ->getTemplatedDecl()))); 1757*f4a2713aSLionel Sambuc 1758*f4a2713aSLionel Sambuc // Friendship lookup is a redeclaration lookup, so there's never an 1759*f4a2713aSLionel Sambuc // inheritance path modifying access. 1760*f4a2713aSLionel Sambuc AccessSpecifier access = target->getAccess(); 1761*f4a2713aSLionel Sambuc 1762*f4a2713aSLionel Sambuc if (!getLangOpts().AccessControl || access == AS_public) 1763*f4a2713aSLionel Sambuc return AR_accessible; 1764*f4a2713aSLionel Sambuc 1765*f4a2713aSLionel Sambuc CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(target); 1766*f4a2713aSLionel Sambuc if (!method) 1767*f4a2713aSLionel Sambuc method = cast<CXXMethodDecl>( 1768*f4a2713aSLionel Sambuc cast<FunctionTemplateDecl>(target)->getTemplatedDecl()); 1769*f4a2713aSLionel Sambuc assert(method->getQualifier()); 1770*f4a2713aSLionel Sambuc 1771*f4a2713aSLionel Sambuc AccessTarget entity(Context, AccessTarget::Member, 1772*f4a2713aSLionel Sambuc cast<CXXRecordDecl>(target->getDeclContext()), 1773*f4a2713aSLionel Sambuc DeclAccessPair::make(target, access), 1774*f4a2713aSLionel Sambuc /*no instance context*/ QualType()); 1775*f4a2713aSLionel Sambuc entity.setDiag(diag::err_access_friend_function) 1776*f4a2713aSLionel Sambuc << method->getQualifierLoc().getSourceRange(); 1777*f4a2713aSLionel Sambuc 1778*f4a2713aSLionel Sambuc // We need to bypass delayed-diagnostics because we might be called 1779*f4a2713aSLionel Sambuc // while the ParsingDeclarator is active. 1780*f4a2713aSLionel Sambuc EffectiveContext EC(CurContext); 1781*f4a2713aSLionel Sambuc switch (CheckEffectiveAccess(*this, EC, target->getLocation(), entity)) { 1782*f4a2713aSLionel Sambuc case AR_accessible: return Sema::AR_accessible; 1783*f4a2713aSLionel Sambuc case AR_inaccessible: return Sema::AR_inaccessible; 1784*f4a2713aSLionel Sambuc case AR_dependent: return Sema::AR_dependent; 1785*f4a2713aSLionel Sambuc } 1786*f4a2713aSLionel Sambuc llvm_unreachable("falling off end"); 1787*f4a2713aSLionel Sambuc } 1788*f4a2713aSLionel Sambuc 1789*f4a2713aSLionel Sambuc Sema::AccessResult Sema::CheckAddressOfMemberAccess(Expr *OvlExpr, 1790*f4a2713aSLionel Sambuc DeclAccessPair Found) { 1791*f4a2713aSLionel Sambuc if (!getLangOpts().AccessControl || 1792*f4a2713aSLionel Sambuc Found.getAccess() == AS_none || 1793*f4a2713aSLionel Sambuc Found.getAccess() == AS_public) 1794*f4a2713aSLionel Sambuc return AR_accessible; 1795*f4a2713aSLionel Sambuc 1796*f4a2713aSLionel Sambuc OverloadExpr *Ovl = OverloadExpr::find(OvlExpr).Expression; 1797*f4a2713aSLionel Sambuc CXXRecordDecl *NamingClass = Ovl->getNamingClass(); 1798*f4a2713aSLionel Sambuc 1799*f4a2713aSLionel Sambuc AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found, 1800*f4a2713aSLionel Sambuc /*no instance context*/ QualType()); 1801*f4a2713aSLionel Sambuc Entity.setDiag(diag::err_access) 1802*f4a2713aSLionel Sambuc << Ovl->getSourceRange(); 1803*f4a2713aSLionel Sambuc 1804*f4a2713aSLionel Sambuc return CheckAccess(*this, Ovl->getNameLoc(), Entity); 1805*f4a2713aSLionel Sambuc } 1806*f4a2713aSLionel Sambuc 1807*f4a2713aSLionel Sambuc /// Checks access for a hierarchy conversion. 1808*f4a2713aSLionel Sambuc /// 1809*f4a2713aSLionel Sambuc /// \param ForceCheck true if this check should be performed even if access 1810*f4a2713aSLionel Sambuc /// control is disabled; some things rely on this for semantics 1811*f4a2713aSLionel Sambuc /// \param ForceUnprivileged true if this check should proceed as if the 1812*f4a2713aSLionel Sambuc /// context had no special privileges 1813*f4a2713aSLionel Sambuc Sema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc, 1814*f4a2713aSLionel Sambuc QualType Base, 1815*f4a2713aSLionel Sambuc QualType Derived, 1816*f4a2713aSLionel Sambuc const CXXBasePath &Path, 1817*f4a2713aSLionel Sambuc unsigned DiagID, 1818*f4a2713aSLionel Sambuc bool ForceCheck, 1819*f4a2713aSLionel Sambuc bool ForceUnprivileged) { 1820*f4a2713aSLionel Sambuc if (!ForceCheck && !getLangOpts().AccessControl) 1821*f4a2713aSLionel Sambuc return AR_accessible; 1822*f4a2713aSLionel Sambuc 1823*f4a2713aSLionel Sambuc if (Path.Access == AS_public) 1824*f4a2713aSLionel Sambuc return AR_accessible; 1825*f4a2713aSLionel Sambuc 1826*f4a2713aSLionel Sambuc CXXRecordDecl *BaseD, *DerivedD; 1827*f4a2713aSLionel Sambuc BaseD = cast<CXXRecordDecl>(Base->getAs<RecordType>()->getDecl()); 1828*f4a2713aSLionel Sambuc DerivedD = cast<CXXRecordDecl>(Derived->getAs<RecordType>()->getDecl()); 1829*f4a2713aSLionel Sambuc 1830*f4a2713aSLionel Sambuc AccessTarget Entity(Context, AccessTarget::Base, BaseD, DerivedD, 1831*f4a2713aSLionel Sambuc Path.Access); 1832*f4a2713aSLionel Sambuc if (DiagID) 1833*f4a2713aSLionel Sambuc Entity.setDiag(DiagID) << Derived << Base; 1834*f4a2713aSLionel Sambuc 1835*f4a2713aSLionel Sambuc if (ForceUnprivileged) { 1836*f4a2713aSLionel Sambuc switch (CheckEffectiveAccess(*this, EffectiveContext(), 1837*f4a2713aSLionel Sambuc AccessLoc, Entity)) { 1838*f4a2713aSLionel Sambuc case ::AR_accessible: return Sema::AR_accessible; 1839*f4a2713aSLionel Sambuc case ::AR_inaccessible: return Sema::AR_inaccessible; 1840*f4a2713aSLionel Sambuc case ::AR_dependent: return Sema::AR_dependent; 1841*f4a2713aSLionel Sambuc } 1842*f4a2713aSLionel Sambuc llvm_unreachable("unexpected result from CheckEffectiveAccess"); 1843*f4a2713aSLionel Sambuc } 1844*f4a2713aSLionel Sambuc return CheckAccess(*this, AccessLoc, Entity); 1845*f4a2713aSLionel Sambuc } 1846*f4a2713aSLionel Sambuc 1847*f4a2713aSLionel Sambuc /// Checks access to all the declarations in the given result set. 1848*f4a2713aSLionel Sambuc void Sema::CheckLookupAccess(const LookupResult &R) { 1849*f4a2713aSLionel Sambuc assert(getLangOpts().AccessControl 1850*f4a2713aSLionel Sambuc && "performing access check without access control"); 1851*f4a2713aSLionel Sambuc assert(R.getNamingClass() && "performing access check without naming class"); 1852*f4a2713aSLionel Sambuc 1853*f4a2713aSLionel Sambuc for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { 1854*f4a2713aSLionel Sambuc if (I.getAccess() != AS_public) { 1855*f4a2713aSLionel Sambuc AccessTarget Entity(Context, AccessedEntity::Member, 1856*f4a2713aSLionel Sambuc R.getNamingClass(), I.getPair(), 1857*f4a2713aSLionel Sambuc R.getBaseObjectType()); 1858*f4a2713aSLionel Sambuc Entity.setDiag(diag::err_access); 1859*f4a2713aSLionel Sambuc CheckAccess(*this, R.getNameLoc(), Entity); 1860*f4a2713aSLionel Sambuc } 1861*f4a2713aSLionel Sambuc } 1862*f4a2713aSLionel Sambuc } 1863*f4a2713aSLionel Sambuc 1864*f4a2713aSLionel Sambuc /// Checks access to Decl from the given class. The check will take access 1865*f4a2713aSLionel Sambuc /// specifiers into account, but no member access expressions and such. 1866*f4a2713aSLionel Sambuc /// 1867*f4a2713aSLionel Sambuc /// \param Decl the declaration to check if it can be accessed 1868*f4a2713aSLionel Sambuc /// \param Ctx the class/context from which to start the search 1869*f4a2713aSLionel Sambuc /// \return true if the Decl is accessible from the Class, false otherwise. 1870*f4a2713aSLionel Sambuc bool Sema::IsSimplyAccessible(NamedDecl *Decl, DeclContext *Ctx) { 1871*f4a2713aSLionel Sambuc if (CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(Ctx)) { 1872*f4a2713aSLionel Sambuc if (!Decl->isCXXClassMember()) 1873*f4a2713aSLionel Sambuc return true; 1874*f4a2713aSLionel Sambuc 1875*f4a2713aSLionel Sambuc QualType qType = Class->getTypeForDecl()->getCanonicalTypeInternal(); 1876*f4a2713aSLionel Sambuc AccessTarget Entity(Context, AccessedEntity::Member, Class, 1877*f4a2713aSLionel Sambuc DeclAccessPair::make(Decl, Decl->getAccess()), 1878*f4a2713aSLionel Sambuc qType); 1879*f4a2713aSLionel Sambuc if (Entity.getAccess() == AS_public) 1880*f4a2713aSLionel Sambuc return true; 1881*f4a2713aSLionel Sambuc 1882*f4a2713aSLionel Sambuc EffectiveContext EC(CurContext); 1883*f4a2713aSLionel Sambuc return ::IsAccessible(*this, EC, Entity) != ::AR_inaccessible; 1884*f4a2713aSLionel Sambuc } 1885*f4a2713aSLionel Sambuc 1886*f4a2713aSLionel Sambuc if (ObjCIvarDecl *Ivar = dyn_cast<ObjCIvarDecl>(Decl)) { 1887*f4a2713aSLionel Sambuc // @public and @package ivars are always accessible. 1888*f4a2713aSLionel Sambuc if (Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Public || 1889*f4a2713aSLionel Sambuc Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Package) 1890*f4a2713aSLionel Sambuc return true; 1891*f4a2713aSLionel Sambuc 1892*f4a2713aSLionel Sambuc // If we are inside a class or category implementation, determine the 1893*f4a2713aSLionel Sambuc // interface we're in. 1894*f4a2713aSLionel Sambuc ObjCInterfaceDecl *ClassOfMethodDecl = 0; 1895*f4a2713aSLionel Sambuc if (ObjCMethodDecl *MD = getCurMethodDecl()) 1896*f4a2713aSLionel Sambuc ClassOfMethodDecl = MD->getClassInterface(); 1897*f4a2713aSLionel Sambuc else if (FunctionDecl *FD = getCurFunctionDecl()) { 1898*f4a2713aSLionel Sambuc if (ObjCImplDecl *Impl 1899*f4a2713aSLionel Sambuc = dyn_cast<ObjCImplDecl>(FD->getLexicalDeclContext())) { 1900*f4a2713aSLionel Sambuc if (ObjCImplementationDecl *IMPD 1901*f4a2713aSLionel Sambuc = dyn_cast<ObjCImplementationDecl>(Impl)) 1902*f4a2713aSLionel Sambuc ClassOfMethodDecl = IMPD->getClassInterface(); 1903*f4a2713aSLionel Sambuc else if (ObjCCategoryImplDecl* CatImplClass 1904*f4a2713aSLionel Sambuc = dyn_cast<ObjCCategoryImplDecl>(Impl)) 1905*f4a2713aSLionel Sambuc ClassOfMethodDecl = CatImplClass->getClassInterface(); 1906*f4a2713aSLionel Sambuc } 1907*f4a2713aSLionel Sambuc } 1908*f4a2713aSLionel Sambuc 1909*f4a2713aSLionel Sambuc // If we're not in an interface, this ivar is inaccessible. 1910*f4a2713aSLionel Sambuc if (!ClassOfMethodDecl) 1911*f4a2713aSLionel Sambuc return false; 1912*f4a2713aSLionel Sambuc 1913*f4a2713aSLionel Sambuc // If we're inside the same interface that owns the ivar, we're fine. 1914*f4a2713aSLionel Sambuc if (declaresSameEntity(ClassOfMethodDecl, Ivar->getContainingInterface())) 1915*f4a2713aSLionel Sambuc return true; 1916*f4a2713aSLionel Sambuc 1917*f4a2713aSLionel Sambuc // If the ivar is private, it's inaccessible. 1918*f4a2713aSLionel Sambuc if (Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Private) 1919*f4a2713aSLionel Sambuc return false; 1920*f4a2713aSLionel Sambuc 1921*f4a2713aSLionel Sambuc return Ivar->getContainingInterface()->isSuperClassOf(ClassOfMethodDecl); 1922*f4a2713aSLionel Sambuc } 1923*f4a2713aSLionel Sambuc 1924*f4a2713aSLionel Sambuc return true; 1925*f4a2713aSLionel Sambuc } 1926