SemaAccess.cpp revision 263508
1168404Spjd//===---- SemaAccess.cpp - C++ Access Control -------------------*- C++ -*-===// 2168404Spjd// 3168404Spjd// The LLVM Compiler Infrastructure 4168404Spjd// 5168404Spjd// This file is distributed under the University of Illinois Open Source 6168404Spjd// License. See LICENSE.TXT for details. 7168404Spjd// 8168404Spjd//===----------------------------------------------------------------------===// 9168404Spjd// 10168404Spjd// This file provides Sema routines for C++ access control semantics. 11168404Spjd// 12168404Spjd//===----------------------------------------------------------------------===// 13168404Spjd 14168404Spjd#include "clang/Sema/SemaInternal.h" 15168404Spjd#include "clang/AST/ASTContext.h" 16168404Spjd#include "clang/AST/CXXInheritance.h" 17168404Spjd#include "clang/AST/DeclCXX.h" 18168404Spjd#include "clang/AST/DeclFriend.h" 19168404Spjd#include "clang/AST/DeclObjC.h" 20168404Spjd#include "clang/AST/DependentDiagnostic.h" 21168404Spjd#include "clang/AST/ExprCXX.h" 22185029Spjd#include "clang/Sema/DelayedDiagnostic.h" 23168404Spjd#include "clang/Sema/Initialization.h" 24168404Spjd#include "clang/Sema/Lookup.h" 25168404Spjd 26168404Spjdusing namespace clang; 27168404Spjdusing namespace sema; 28168404Spjd 29168404Spjd/// A copy of Sema's enum without AR_delayed. 30168404Spjdenum AccessResult { 31168404Spjd AR_accessible, 32168404Spjd AR_inaccessible, 33168404Spjd AR_dependent 34168404Spjd}; 35168404Spjd 36168404Spjd/// SetMemberAccessSpecifier - Set the access specifier of a member. 37168404Spjd/// Returns true on error (when the previous member decl access specifier 38168404Spjd/// is different from the new member decl access specifier). 39168404Spjdbool Sema::SetMemberAccessSpecifier(NamedDecl *MemberDecl, 40168404Spjd NamedDecl *PrevMemberDecl, 41168404Spjd AccessSpecifier LexicalAS) { 42168404Spjd if (!PrevMemberDecl) { 43168404Spjd // Use the lexical access specifier. 44168404Spjd MemberDecl->setAccess(LexicalAS); 45168404Spjd return false; 46168404Spjd } 47168404Spjd 48168404Spjd // C++ [class.access.spec]p3: When a member is redeclared its access 49168404Spjd // specifier must be same as its initial declaration. 50168404Spjd if (LexicalAS != AS_none && LexicalAS != PrevMemberDecl->getAccess()) { 51168404Spjd Diag(MemberDecl->getLocation(), 52168404Spjd diag::err_class_redeclared_with_different_access) 53168404Spjd << MemberDecl << LexicalAS; 54168404Spjd Diag(PrevMemberDecl->getLocation(), diag::note_previous_access_declaration) 55168404Spjd << PrevMemberDecl << PrevMemberDecl->getAccess(); 56168404Spjd 57168404Spjd MemberDecl->setAccess(LexicalAS); 58168404Spjd return true; 59168404Spjd } 60168404Spjd 61168404Spjd MemberDecl->setAccess(PrevMemberDecl->getAccess()); 62168404Spjd return false; 63168404Spjd} 64168404Spjd 65168404Spjdstatic CXXRecordDecl *FindDeclaringClass(NamedDecl *D) { 66168404Spjd DeclContext *DC = D->getDeclContext(); 67168404Spjd 68168404Spjd // This can only happen at top: enum decls only "publish" their 69168404Spjd // immediate members. 70168404Spjd if (isa<EnumDecl>(DC)) 71169028Spjd DC = cast<EnumDecl>(DC)->getDeclContext(); 72168404Spjd 73168404Spjd CXXRecordDecl *DeclaringClass = cast<CXXRecordDecl>(DC); 74168404Spjd while (DeclaringClass->isAnonymousStructOrUnion()) 75168404Spjd DeclaringClass = cast<CXXRecordDecl>(DeclaringClass->getDeclContext()); 76168404Spjd return DeclaringClass; 77168404Spjd} 78168404Spjd 79168404Spjdnamespace { 80168404Spjdstruct EffectiveContext { 81168404Spjd EffectiveContext() : Inner(0), Dependent(false) {} 82168404Spjd 83168404Spjd explicit EffectiveContext(DeclContext *DC) 84168404Spjd : Inner(DC), 85168404Spjd Dependent(DC->isDependentContext()) { 86168404Spjd 87168404Spjd // C++11 [class.access.nest]p1: 88168404Spjd // A nested class is a member and as such has the same access 89168404Spjd // rights as any other member. 90168404Spjd // C++11 [class.access]p2: 91168404Spjd // A member of a class can also access all the names to which 92168404Spjd // the class has access. A local class of a member function 93168404Spjd // may access the same names that the member function itself 94168404Spjd // may access. 95168404Spjd // This almost implies that the privileges of nesting are transitive. 96168404Spjd // Technically it says nothing about the local classes of non-member 97168404Spjd // functions (which can gain privileges through friendship), but we 98168404Spjd // take that as an oversight. 99168404Spjd while (true) { 100168404Spjd // We want to add canonical declarations to the EC lists for 101168404Spjd // simplicity of checking, but we need to walk up through the 102168404Spjd // actual current DC chain. Otherwise, something like a local 103168404Spjd // extern or friend which happens to be the canonical 104168404Spjd // declaration will really mess us up. 105168404Spjd 106168404Spjd if (isa<CXXRecordDecl>(DC)) { 107168404Spjd CXXRecordDecl *Record = cast<CXXRecordDecl>(DC); 108168404Spjd Records.push_back(Record->getCanonicalDecl()); 109168404Spjd DC = Record->getDeclContext(); 110168404Spjd } else if (isa<FunctionDecl>(DC)) { 111168404Spjd FunctionDecl *Function = cast<FunctionDecl>(DC); 112168404Spjd Functions.push_back(Function->getCanonicalDecl()); 113168404Spjd if (Function->getFriendObjectKind()) 114168404Spjd DC = Function->getLexicalDeclContext(); 115168404Spjd else 116168404Spjd DC = Function->getDeclContext(); 117168404Spjd } else if (DC->isFileContext()) { 118168404Spjd break; 119168404Spjd } else { 120168404Spjd DC = DC->getParent(); 121168404Spjd } 122168404Spjd } 123168404Spjd } 124168404Spjd 125168404Spjd bool isDependent() const { return Dependent; } 126168404Spjd 127168404Spjd bool includesClass(const CXXRecordDecl *R) const { 128168404Spjd R = R->getCanonicalDecl(); 129168404Spjd return std::find(Records.begin(), Records.end(), R) 130168404Spjd != Records.end(); 131168404Spjd } 132168404Spjd 133168404Spjd /// Retrieves the innermost "useful" context. Can be null if we're 134168404Spjd /// doing access-control without privileges. 135168404Spjd DeclContext *getInnerContext() const { 136168404Spjd return Inner; 137168404Spjd } 138168404Spjd 139168404Spjd typedef SmallVectorImpl<CXXRecordDecl*>::const_iterator record_iterator; 140168404Spjd 141168404Spjd DeclContext *Inner; 142168404Spjd SmallVector<FunctionDecl*, 4> Functions; 143168404Spjd SmallVector<CXXRecordDecl*, 4> Records; 144168404Spjd bool Dependent; 145168404Spjd}; 146168404Spjd 147168404Spjd/// Like sema::AccessedEntity, but kindly lets us scribble all over 148168404Spjd/// it. 149168404Spjdstruct AccessTarget : public AccessedEntity { 150168404Spjd AccessTarget(const AccessedEntity &Entity) 151168404Spjd : AccessedEntity(Entity) { 152168404Spjd initialize(); 153168404Spjd } 154168404Spjd 155168404Spjd AccessTarget(ASTContext &Context, 156168404Spjd MemberNonce _, 157168404Spjd CXXRecordDecl *NamingClass, 158168404Spjd DeclAccessPair FoundDecl, 159168404Spjd QualType BaseObjectType) 160168404Spjd : AccessedEntity(Context.getDiagAllocator(), Member, NamingClass, 161168404Spjd FoundDecl, BaseObjectType) { 162168404Spjd initialize(); 163168404Spjd } 164168404Spjd 165168404Spjd AccessTarget(ASTContext &Context, 166168404Spjd BaseNonce _, 167168404Spjd CXXRecordDecl *BaseClass, 168168404Spjd CXXRecordDecl *DerivedClass, 169168404Spjd AccessSpecifier Access) 170168404Spjd : AccessedEntity(Context.getDiagAllocator(), Base, BaseClass, DerivedClass, 171168404Spjd Access) { 172168404Spjd initialize(); 173168404Spjd } 174168404Spjd 175185029Spjd bool isInstanceMember() const { 176185029Spjd return (isMemberAccess() && getTargetDecl()->isCXXInstanceMember()); 177185029Spjd } 178185029Spjd 179185029Spjd bool hasInstanceContext() const { 180168404Spjd return HasInstanceContext; 181168404Spjd } 182168404Spjd 183168404Spjd class SavedInstanceContext { 184168404Spjd public: 185168404Spjd ~SavedInstanceContext() { 186168404Spjd Target.HasInstanceContext = Has; 187168404Spjd } 188168404Spjd 189168404Spjd private: 190185029Spjd friend struct AccessTarget; 191185029Spjd explicit SavedInstanceContext(AccessTarget &Target) 192168404Spjd : Target(Target), Has(Target.HasInstanceContext) {} 193168404Spjd AccessTarget &Target; 194185029Spjd bool Has; 195185029Spjd }; 196168404Spjd 197168404Spjd SavedInstanceContext saveInstanceContext() { 198168404Spjd return SavedInstanceContext(*this); 199185029Spjd } 200185029Spjd 201185029Spjd void suppressInstanceContext() { 202185029Spjd HasInstanceContext = false; 203185029Spjd } 204168404Spjd 205168404Spjd const CXXRecordDecl *resolveInstanceContext(Sema &S) const { 206168404Spjd assert(HasInstanceContext); 207168404Spjd if (CalculatedInstanceContext) 208168404Spjd return InstanceContext; 209168404Spjd 210168404Spjd CalculatedInstanceContext = true; 211168404Spjd DeclContext *IC = S.computeDeclContext(getBaseObjectType()); 212168404Spjd InstanceContext = (IC ? cast<CXXRecordDecl>(IC)->getCanonicalDecl() : 0); 213168404Spjd return InstanceContext; 214168404Spjd } 215168404Spjd 216168404Spjd const CXXRecordDecl *getDeclaringClass() const { 217168404Spjd return DeclaringClass; 218168404Spjd } 219168404Spjd 220168404Spjd /// The "effective" naming class is the canonical non-anonymous 221168404Spjd /// class containing the actual naming class. 222168404Spjd const CXXRecordDecl *getEffectiveNamingClass() const { 223168404Spjd const CXXRecordDecl *namingClass = getNamingClass(); 224168404Spjd while (namingClass->isAnonymousStructOrUnion()) 225168404Spjd namingClass = cast<CXXRecordDecl>(namingClass->getParent()); 226168404Spjd return namingClass->getCanonicalDecl(); 227168404Spjd } 228168404Spjd 229168404Spjdprivate: 230168404Spjd void initialize() { 231168404Spjd HasInstanceContext = (isMemberAccess() && 232168404Spjd !getBaseObjectType().isNull() && 233168404Spjd getTargetDecl()->isCXXInstanceMember()); 234168404Spjd CalculatedInstanceContext = false; 235168404Spjd InstanceContext = 0; 236168404Spjd 237168404Spjd if (isMemberAccess()) 238168404Spjd DeclaringClass = FindDeclaringClass(getTargetDecl()); 239168404Spjd else 240168404Spjd DeclaringClass = getBaseClass(); 241168404Spjd DeclaringClass = DeclaringClass->getCanonicalDecl(); 242168404Spjd } 243168404Spjd 244168404Spjd bool HasInstanceContext : 1; 245168404Spjd mutable bool CalculatedInstanceContext : 1; 246168404Spjd mutable const CXXRecordDecl *InstanceContext; 247168404Spjd const CXXRecordDecl *DeclaringClass; 248168404Spjd}; 249168404Spjd 250168404Spjd} 251168404Spjd 252168404Spjd/// Checks whether one class might instantiate to the other. 253168404Spjdstatic bool MightInstantiateTo(const CXXRecordDecl *From, 254168404Spjd const CXXRecordDecl *To) { 255168404Spjd // Declaration names are always preserved by instantiation. 256168404Spjd if (From->getDeclName() != To->getDeclName()) 257168404Spjd return false; 258168404Spjd 259168404Spjd const DeclContext *FromDC = From->getDeclContext()->getPrimaryContext(); 260168404Spjd const DeclContext *ToDC = To->getDeclContext()->getPrimaryContext(); 261168404Spjd if (FromDC == ToDC) return true; 262168404Spjd if (FromDC->isFileContext() || ToDC->isFileContext()) return false; 263168404Spjd 264168404Spjd // Be conservative. 265168404Spjd return true; 266168404Spjd} 267168404Spjd 268168404Spjd/// Checks whether one class is derived from another, inclusively. 269168404Spjd/// Properly indicates when it couldn't be determined due to 270168404Spjd/// dependence. 271168404Spjd/// 272168404Spjd/// This should probably be donated to AST or at least Sema. 273168404Spjdstatic AccessResult IsDerivedFromInclusive(const CXXRecordDecl *Derived, 274168404Spjd const CXXRecordDecl *Target) { 275168404Spjd assert(Derived->getCanonicalDecl() == Derived); 276168404Spjd assert(Target->getCanonicalDecl() == Target); 277168404Spjd 278168404Spjd if (Derived == Target) return AR_accessible; 279168404Spjd 280168404Spjd bool CheckDependent = Derived->isDependentContext(); 281168404Spjd if (CheckDependent && MightInstantiateTo(Derived, Target)) 282168404Spjd return AR_dependent; 283168404Spjd 284168404Spjd AccessResult OnFailure = AR_inaccessible; 285168404Spjd SmallVector<const CXXRecordDecl*, 8> Queue; // actually a stack 286168404Spjd 287168404Spjd while (true) { 288168404Spjd if (Derived->isDependentContext() && !Derived->hasDefinition()) 289168404Spjd return AR_dependent; 290168404Spjd 291168404Spjd for (CXXRecordDecl::base_class_const_iterator 292168404Spjd I = Derived->bases_begin(), E = Derived->bases_end(); I != E; ++I) { 293168404Spjd 294168404Spjd const CXXRecordDecl *RD; 295168404Spjd 296168404Spjd QualType T = I->getType(); 297168404Spjd if (const RecordType *RT = T->getAs<RecordType>()) { 298185029Spjd RD = cast<CXXRecordDecl>(RT->getDecl()); 299185029Spjd } else if (const InjectedClassNameType *IT 300168404Spjd = T->getAs<InjectedClassNameType>()) { 301168404Spjd RD = IT->getDecl(); 302168404Spjd } else { 303168404Spjd assert(T->isDependentType() && "non-dependent base wasn't a record?"); 304168404Spjd OnFailure = AR_dependent; 305168404Spjd continue; 306168404Spjd } 307168404Spjd 308168404Spjd RD = RD->getCanonicalDecl(); 309168404Spjd if (RD == Target) return AR_accessible; 310168404Spjd if (CheckDependent && MightInstantiateTo(RD, Target)) 311168404Spjd OnFailure = AR_dependent; 312168404Spjd 313168404Spjd Queue.push_back(RD); 314168404Spjd } 315168404Spjd 316168404Spjd if (Queue.empty()) break; 317168404Spjd 318168404Spjd Derived = Queue.pop_back_val(); 319168404Spjd } 320168404Spjd 321168404Spjd return OnFailure; 322168404Spjd} 323168404Spjd 324168404Spjd 325168404Spjdstatic bool MightInstantiateTo(Sema &S, DeclContext *Context, 326168404Spjd DeclContext *Friend) { 327168404Spjd if (Friend == Context) 328168404Spjd return true; 329168404Spjd 330168404Spjd assert(!Friend->isDependentContext() && 331168404Spjd "can't handle friends with dependent contexts here"); 332168404Spjd 333168404Spjd if (!Context->isDependentContext()) 334168404Spjd return false; 335168404Spjd 336168404Spjd if (Friend->isFileContext()) 337168404Spjd return false; 338168404Spjd 339168404Spjd // TODO: this is very conservative 340168404Spjd return true; 341168404Spjd} 342168404Spjd 343168404Spjd// Asks whether the type in 'context' can ever instantiate to the type 344168404Spjd// in 'friend'. 345168404Spjdstatic bool MightInstantiateTo(Sema &S, CanQualType Context, CanQualType Friend) { 346168404Spjd if (Friend == Context) 347168404Spjd return true; 348168404Spjd 349168404Spjd if (!Friend->isDependentType() && !Context->isDependentType()) 350168404Spjd return false; 351168404Spjd 352168404Spjd // TODO: this is very conservative. 353168404Spjd return true; 354168404Spjd} 355168404Spjd 356168404Spjdstatic bool MightInstantiateTo(Sema &S, 357168404Spjd FunctionDecl *Context, 358168404Spjd FunctionDecl *Friend) { 359168404Spjd if (Context->getDeclName() != Friend->getDeclName()) 360168404Spjd return false; 361168404Spjd 362168404Spjd if (!MightInstantiateTo(S, 363168404Spjd Context->getDeclContext(), 364168404Spjd Friend->getDeclContext())) 365168404Spjd return false; 366168404Spjd 367168404Spjd CanQual<FunctionProtoType> FriendTy 368168404Spjd = S.Context.getCanonicalType(Friend->getType()) 369168404Spjd ->getAs<FunctionProtoType>(); 370168404Spjd CanQual<FunctionProtoType> ContextTy 371168404Spjd = S.Context.getCanonicalType(Context->getType()) 372168404Spjd ->getAs<FunctionProtoType>(); 373168404Spjd 374168404Spjd // There isn't any way that I know of to add qualifiers 375168404Spjd // during instantiation. 376168404Spjd if (FriendTy.getQualifiers() != ContextTy.getQualifiers()) 377168404Spjd return false; 378168404Spjd 379168404Spjd if (FriendTy->getNumArgs() != ContextTy->getNumArgs()) 380168404Spjd return false; 381168404Spjd 382168404Spjd if (!MightInstantiateTo(S, 383168404Spjd ContextTy->getResultType(), 384168404Spjd FriendTy->getResultType())) 385168404Spjd return false; 386168404Spjd 387168404Spjd for (unsigned I = 0, E = FriendTy->getNumArgs(); I != E; ++I) 388168404Spjd if (!MightInstantiateTo(S, 389168404Spjd ContextTy->getArgType(I), 390168404Spjd FriendTy->getArgType(I))) 391168404Spjd return false; 392168404Spjd 393168404Spjd return true; 394168404Spjd} 395168404Spjd 396168404Spjdstatic bool MightInstantiateTo(Sema &S, 397168404Spjd FunctionTemplateDecl *Context, 398168404Spjd FunctionTemplateDecl *Friend) { 399168404Spjd return MightInstantiateTo(S, 400168404Spjd Context->getTemplatedDecl(), 401168404Spjd Friend->getTemplatedDecl()); 402168404Spjd} 403168404Spjd 404168404Spjdstatic AccessResult MatchesFriend(Sema &S, 405168404Spjd const EffectiveContext &EC, 406168404Spjd const CXXRecordDecl *Friend) { 407168404Spjd if (EC.includesClass(Friend)) 408168404Spjd return AR_accessible; 409168404Spjd 410168404Spjd if (EC.isDependent()) { 411168404Spjd CanQualType FriendTy 412168404Spjd = S.Context.getCanonicalType(S.Context.getTypeDeclType(Friend)); 413168404Spjd 414168404Spjd for (EffectiveContext::record_iterator 415168404Spjd I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { 416168404Spjd CanQualType ContextTy 417168404Spjd = S.Context.getCanonicalType(S.Context.getTypeDeclType(*I)); 418168404Spjd if (MightInstantiateTo(S, ContextTy, FriendTy)) 419168404Spjd return AR_dependent; 420168404Spjd } 421168404Spjd } 422168404Spjd 423168404Spjd return AR_inaccessible; 424168404Spjd} 425168404Spjd 426168404Spjdstatic AccessResult MatchesFriend(Sema &S, 427168404Spjd const EffectiveContext &EC, 428168404Spjd CanQualType Friend) { 429168404Spjd if (const RecordType *RT = Friend->getAs<RecordType>()) 430168404Spjd return MatchesFriend(S, EC, cast<CXXRecordDecl>(RT->getDecl())); 431168404Spjd 432168404Spjd // TODO: we can do better than this 433168404Spjd if (Friend->isDependentType()) 434168404Spjd return AR_dependent; 435168404Spjd 436168404Spjd return AR_inaccessible; 437168404Spjd} 438168404Spjd 439185029Spjd/// Determines whether the given friend class template matches 440185029Spjd/// anything in the effective context. 441185029Spjdstatic AccessResult MatchesFriend(Sema &S, 442185029Spjd const EffectiveContext &EC, 443185029Spjd ClassTemplateDecl *Friend) { 444185029Spjd AccessResult OnFailure = AR_inaccessible; 445185029Spjd 446185029Spjd // Check whether the friend is the template of a class in the 447185029Spjd // context chain. 448185029Spjd for (SmallVectorImpl<CXXRecordDecl*>::const_iterator 449168404Spjd I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { 450168404Spjd CXXRecordDecl *Record = *I; 451168404Spjd 452168404Spjd // Figure out whether the current class has a template: 453168404Spjd ClassTemplateDecl *CTD; 454168404Spjd 455168404Spjd // A specialization of the template... 456168404Spjd if (isa<ClassTemplateSpecializationDecl>(Record)) { 457168404Spjd CTD = cast<ClassTemplateSpecializationDecl>(Record) 458168404Spjd ->getSpecializedTemplate(); 459168404Spjd 460168404Spjd // ... or the template pattern itself. 461168404Spjd } else { 462168404Spjd CTD = Record->getDescribedClassTemplate(); 463168404Spjd if (!CTD) continue; 464168404Spjd } 465168404Spjd 466168404Spjd // It's a match. 467168404Spjd if (Friend == CTD->getCanonicalDecl()) 468168404Spjd return AR_accessible; 469168404Spjd 470168404Spjd // If the context isn't dependent, it can't be a dependent match. 471168404Spjd if (!EC.isDependent()) 472185029Spjd continue; 473168404Spjd 474185029Spjd // If the template names don't match, it can't be a dependent 475185029Spjd // match. 476185029Spjd if (CTD->getDeclName() != Friend->getDeclName()) 477185029Spjd continue; 478185029Spjd 479185029Spjd // If the class's context can't instantiate to the friend's 480185029Spjd // context, it can't be a dependent match. 481185029Spjd if (!MightInstantiateTo(S, CTD->getDeclContext(), 482185029Spjd Friend->getDeclContext())) 483185029Spjd continue; 484185029Spjd 485185029Spjd // Otherwise, it's a dependent match. 486185029Spjd OnFailure = AR_dependent; 487185029Spjd } 488168404Spjd 489168404Spjd return OnFailure; 490185029Spjd} 491185029Spjd 492185029Spjd/// Determines whether the given friend function matches anything in 493185029Spjd/// the effective context. 494185029Spjdstatic AccessResult MatchesFriend(Sema &S, 495185029Spjd const EffectiveContext &EC, 496185029Spjd FunctionDecl *Friend) { 497185029Spjd AccessResult OnFailure = AR_inaccessible; 498185029Spjd 499185029Spjd for (SmallVectorImpl<FunctionDecl*>::const_iterator 500185029Spjd I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) { 501185029Spjd if (Friend == *I) 502185029Spjd return AR_accessible; 503168404Spjd 504168404Spjd if (EC.isDependent() && MightInstantiateTo(S, *I, Friend)) 505200724Sdelphij OnFailure = AR_dependent; 506200724Sdelphij } 507200724Sdelphij 508200724Sdelphij return OnFailure; 509200724Sdelphij} 510200724Sdelphij 511200724Sdelphij/// Determines whether the given friend function template matches 512200724Sdelphij/// anything in the effective context. 513200724Sdelphijstatic AccessResult MatchesFriend(Sema &S, 514200724Sdelphij const EffectiveContext &EC, 515200724Sdelphij FunctionTemplateDecl *Friend) { 516200724Sdelphij if (EC.Functions.empty()) return AR_inaccessible; 517200724Sdelphij 518200724Sdelphij AccessResult OnFailure = AR_inaccessible; 519200724Sdelphij 520200724Sdelphij for (SmallVectorImpl<FunctionDecl*>::const_iterator 521200724Sdelphij I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) { 522200724Sdelphij 523200724Sdelphij FunctionTemplateDecl *FTD = (*I)->getPrimaryTemplate(); 524168404Spjd if (!FTD) 525168404Spjd FTD = (*I)->getDescribedFunctionTemplate(); 526168404Spjd if (!FTD) 527168404Spjd continue; 528168404Spjd 529168404Spjd FTD = FTD->getCanonicalDecl(); 530168404Spjd 531168404Spjd if (Friend == FTD) 532168404Spjd return AR_accessible; 533168404Spjd 534185029Spjd if (EC.isDependent() && MightInstantiateTo(S, FTD, Friend)) 535168404Spjd OnFailure = AR_dependent; 536185029Spjd } 537168404Spjd 538168404Spjd return OnFailure; 539168404Spjd} 540168404Spjd 541168404Spjd/// Determines whether the given friend declaration matches anything 542168404Spjd/// in the effective context. 543168404Spjdstatic AccessResult MatchesFriend(Sema &S, 544200724Sdelphij const EffectiveContext &EC, 545200724Sdelphij FriendDecl *FriendD) { 546200724Sdelphij // Whitelist accesses if there's an invalid or unsupported friend 547200724Sdelphij // declaration. 548200724Sdelphij if (FriendD->isInvalidDecl() || FriendD->isUnsupportedFriend()) 549200724Sdelphij return AR_accessible; 550200724Sdelphij 551200724Sdelphij if (TypeSourceInfo *T = FriendD->getFriendType()) 552200724Sdelphij return MatchesFriend(S, EC, T->getType()->getCanonicalTypeUnqualified()); 553200724Sdelphij 554200724Sdelphij NamedDecl *Friend 555200724Sdelphij = cast<NamedDecl>(FriendD->getFriendDecl()->getCanonicalDecl()); 556200724Sdelphij 557200724Sdelphij // FIXME: declarations with dependent or templated scope. 558200724Sdelphij 559168404Spjd if (isa<ClassTemplateDecl>(Friend)) 560168404Spjd return MatchesFriend(S, EC, cast<ClassTemplateDecl>(Friend)); 561168404Spjd 562168404Spjd if (isa<FunctionTemplateDecl>(Friend)) 563168404Spjd return MatchesFriend(S, EC, cast<FunctionTemplateDecl>(Friend)); 564168404Spjd 565168404Spjd if (isa<CXXRecordDecl>(Friend)) 566168404Spjd return MatchesFriend(S, EC, cast<CXXRecordDecl>(Friend)); 567168404Spjd 568168404Spjd assert(isa<FunctionDecl>(Friend) && "unknown friend decl kind"); 569168404Spjd return MatchesFriend(S, EC, cast<FunctionDecl>(Friend)); 570168404Spjd} 571168404Spjd 572168404Spjdstatic AccessResult GetFriendKind(Sema &S, 573168404Spjd const EffectiveContext &EC, 574168404Spjd const CXXRecordDecl *Class) { 575168404Spjd AccessResult OnFailure = AR_inaccessible; 576168404Spjd 577168404Spjd // Okay, check friends. 578185029Spjd for (CXXRecordDecl::friend_iterator I = Class->friend_begin(), 579185029Spjd E = Class->friend_end(); I != E; ++I) { 580185029Spjd FriendDecl *Friend = *I; 581185029Spjd 582185029Spjd switch (MatchesFriend(S, EC, Friend)) { 583185029Spjd case AR_accessible: 584185029Spjd return AR_accessible; 585185029Spjd 586168404Spjd case AR_inaccessible: 587185029Spjd continue; 588185029Spjd 589185029Spjd case AR_dependent: 590185029Spjd OnFailure = AR_dependent; 591185029Spjd break; 592185029Spjd } 593185029Spjd } 594185029Spjd 595168404Spjd // That's it, give up. 596185029Spjd return OnFailure; 597185029Spjd} 598185029Spjd 599185029Spjdnamespace { 600185029Spjd 601168404Spjd/// A helper class for checking for a friend which will grant access 602185029Spjd/// to a protected instance member. 603185029Spjdstruct ProtectedFriendContext { 604185029Spjd Sema &S; 605185029Spjd const EffectiveContext &EC; 606185029Spjd const CXXRecordDecl *NamingClass; 607185029Spjd bool CheckDependent; 608168404Spjd bool EverDependent; 609185029Spjd 610185029Spjd /// The path down to the current base class. 611185029Spjd SmallVector<const CXXRecordDecl*, 20> CurPath; 612185029Spjd 613185029Spjd ProtectedFriendContext(Sema &S, const EffectiveContext &EC, 614185029Spjd const CXXRecordDecl *InstanceContext, 615185029Spjd const CXXRecordDecl *NamingClass) 616185029Spjd : S(S), EC(EC), NamingClass(NamingClass), 617185029Spjd CheckDependent(InstanceContext->isDependentContext() || 618185029Spjd NamingClass->isDependentContext()), 619185029Spjd EverDependent(false) {} 620185029Spjd 621185029Spjd /// Check classes in the current path for friendship, starting at 622185029Spjd /// the given index. 623168404Spjd bool checkFriendshipAlongPath(unsigned I) { 624168404Spjd assert(I < CurPath.size()); 625185029Spjd for (unsigned E = CurPath.size(); I != E; ++I) { 626185029Spjd switch (GetFriendKind(S, EC, CurPath[I])) { 627185029Spjd case AR_accessible: return true; 628185029Spjd case AR_inaccessible: continue; 629185029Spjd case AR_dependent: EverDependent = true; continue; 630185029Spjd } 631185029Spjd } 632185029Spjd return false; 633185029Spjd } 634185029Spjd 635185029Spjd /// Perform a search starting at the given class. 636185029Spjd /// 637185029Spjd /// PrivateDepth is the index of the last (least derived) class 638185029Spjd /// along the current path such that a notional public member of 639185029Spjd /// the final class in the path would have access in that class. 640185029Spjd bool findFriendship(const CXXRecordDecl *Cur, unsigned PrivateDepth) { 641185029Spjd // If we ever reach the naming class, check the current path for 642185029Spjd // friendship. We can also stop recursing because we obviously 643185029Spjd // won't find the naming class there again. 644185029Spjd if (Cur == NamingClass) 645185029Spjd return checkFriendshipAlongPath(PrivateDepth); 646185029Spjd 647185029Spjd if (CheckDependent && MightInstantiateTo(Cur, NamingClass)) 648185029Spjd EverDependent = true; 649185029Spjd 650185029Spjd // Recurse into the base classes. 651185029Spjd for (CXXRecordDecl::base_class_const_iterator 652185029Spjd I = Cur->bases_begin(), E = Cur->bases_end(); I != E; ++I) { 653185029Spjd 654185029Spjd // If this is private inheritance, then a public member of the 655185029Spjd // base will not have any access in classes derived from Cur. 656185029Spjd unsigned BasePrivateDepth = PrivateDepth; 657185029Spjd if (I->getAccessSpecifier() == AS_private) 658185029Spjd BasePrivateDepth = CurPath.size() - 1; 659185029Spjd 660185029Spjd const CXXRecordDecl *RD; 661185029Spjd 662185029Spjd QualType T = I->getType(); 663185029Spjd if (const RecordType *RT = T->getAs<RecordType>()) { 664185029Spjd RD = cast<CXXRecordDecl>(RT->getDecl()); 665185029Spjd } else if (const InjectedClassNameType *IT 666185029Spjd = T->getAs<InjectedClassNameType>()) { 667185029Spjd RD = IT->getDecl(); 668185029Spjd } else { 669168404Spjd assert(T->isDependentType() && "non-dependent base wasn't a record?"); 670185029Spjd EverDependent = true; 671168404Spjd continue; 672185029Spjd } 673185029Spjd 674185029Spjd // Recurse. We don't need to clean up if this returns true. 675185029Spjd CurPath.push_back(RD); 676185029Spjd if (findFriendship(RD->getCanonicalDecl(), BasePrivateDepth)) 677168404Spjd return true; 678185029Spjd CurPath.pop_back(); 679185029Spjd } 680168404Spjd 681185029Spjd return false; 682168404Spjd } 683185029Spjd 684185029Spjd bool findFriendship(const CXXRecordDecl *Cur) { 685185029Spjd assert(CurPath.empty()); 686185029Spjd CurPath.push_back(Cur); 687185029Spjd return findFriendship(Cur, 0); 688185029Spjd } 689185029Spjd}; 690185029Spjd} 691185029Spjd 692185029Spjd/// Search for a class P that EC is a friend of, under the constraint 693185029Spjd/// InstanceContext <= P 694185029Spjd/// if InstanceContext exists, or else 695185029Spjd/// NamingClass <= P 696185029Spjd/// and with the additional restriction that a protected member of 697185029Spjd/// NamingClass would have some natural access in P, which implicitly 698168404Spjd/// imposes the constraint that P <= NamingClass. 699168404Spjd/// 700168404Spjd/// This isn't quite the condition laid out in the standard. 701168404Spjd/// Instead of saying that a notional protected member of NamingClass 702168404Spjd/// would have to have some natural access in P, it says the actual 703168404Spjd/// target has to have some natural access in P, which opens up the 704185029Spjd/// possibility that the target (which is not necessarily a member 705185029Spjd/// of NamingClass) might be more accessible along some path not 706185029Spjd/// passing through it. That's really a bad idea, though, because it 707185029Spjd/// introduces two problems: 708168404Spjd/// - Most importantly, it breaks encapsulation because you can 709168404Spjd/// access a forbidden base class's members by directly subclassing 710168404Spjd/// it elsewhere. 711185029Spjd/// - It also makes access substantially harder to compute because it 712185029Spjd/// breaks the hill-climbing algorithm: knowing that the target is 713185029Spjd/// accessible in some base class would no longer let you change 714185029Spjd/// the question solely to whether the base class is accessible, 715185029Spjd/// because the original target might have been more accessible 716185029Spjd/// because of crazy subclassing. 717185029Spjd/// So we don't implement that. 718185029Spjdstatic AccessResult GetProtectedFriendKind(Sema &S, const EffectiveContext &EC, 719185029Spjd const CXXRecordDecl *InstanceContext, 720185029Spjd const CXXRecordDecl *NamingClass) { 721185029Spjd assert(InstanceContext == 0 || 722185029Spjd InstanceContext->getCanonicalDecl() == InstanceContext); 723185029Spjd assert(NamingClass->getCanonicalDecl() == NamingClass); 724185029Spjd 725185029Spjd // If we don't have an instance context, our constraints give us 726185029Spjd // that NamingClass <= P <= NamingClass, i.e. P == NamingClass. 727168404Spjd // This is just the usual friendship check. 728168404Spjd if (!InstanceContext) return GetFriendKind(S, EC, NamingClass); 729168404Spjd 730168404Spjd ProtectedFriendContext PRC(S, EC, InstanceContext, NamingClass); 731168404Spjd if (PRC.findFriendship(InstanceContext)) return AR_accessible; 732168404Spjd if (PRC.EverDependent) return AR_dependent; 733185029Spjd return AR_inaccessible; 734185029Spjd} 735185029Spjd 736168404Spjdstatic AccessResult HasAccess(Sema &S, 737168404Spjd const EffectiveContext &EC, 738168404Spjd const CXXRecordDecl *NamingClass, 739168404Spjd AccessSpecifier Access, 740168404Spjd const AccessTarget &Target) { 741168404Spjd assert(NamingClass->getCanonicalDecl() == NamingClass && 742168404Spjd "declaration should be canonicalized before being passed here"); 743168404Spjd 744168404Spjd if (Access == AS_public) return AR_accessible; 745168404Spjd assert(Access == AS_private || Access == AS_protected); 746168404Spjd 747185029Spjd AccessResult OnFailure = AR_inaccessible; 748185029Spjd 749185029Spjd for (EffectiveContext::record_iterator 750185029Spjd I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { 751185029Spjd // All the declarations in EC have been canonicalized, so pointer 752185029Spjd // equality from this point on will work fine. 753185029Spjd const CXXRecordDecl *ECRecord = *I; 754185029Spjd 755185029Spjd // [B2] and [M2] 756168404Spjd if (Access == AS_private) { 757168404Spjd if (ECRecord == NamingClass) 758168404Spjd return AR_accessible; 759168404Spjd 760168404Spjd if (EC.isDependent() && MightInstantiateTo(ECRecord, NamingClass)) 761168404Spjd OnFailure = AR_dependent; 762168404Spjd 763168404Spjd // [B3] and [M3] 764168404Spjd } else { 765168404Spjd assert(Access == AS_protected); 766185029Spjd switch (IsDerivedFromInclusive(ECRecord, NamingClass)) { 767168404Spjd case AR_accessible: break; 768168404Spjd case AR_inaccessible: continue; 769168404Spjd case AR_dependent: OnFailure = AR_dependent; continue; 770168404Spjd } 771168404Spjd 772168404Spjd // C++ [class.protected]p1: 773168404Spjd // An additional access check beyond those described earlier in 774168404Spjd // [class.access] is applied when a non-static data member or 775168404Spjd // non-static member function is a protected member of its naming 776168404Spjd // class. As described earlier, access to a protected member is 777168404Spjd // granted because the reference occurs in a friend or member of 778168404Spjd // some class C. If the access is to form a pointer to member, 779168404Spjd // the nested-name-specifier shall name C or a class derived from 780168404Spjd // C. All other accesses involve a (possibly implicit) object 781168404Spjd // expression. In this case, the class of the object expression 782168404Spjd // shall be C or a class derived from C. 783168404Spjd // 784168404Spjd // We interpret this as a restriction on [M3]. 785168404Spjd 786168404Spjd // In this part of the code, 'C' is just our context class ECRecord. 787168404Spjd 788168404Spjd // These rules are different if we don't have an instance context. 789168404Spjd if (!Target.hasInstanceContext()) { 790185029Spjd // If it's not an instance member, these restrictions don't apply. 791168404Spjd if (!Target.isInstanceMember()) return AR_accessible; 792185029Spjd 793168404Spjd // If it's an instance member, use the pointer-to-member rule 794168404Spjd // that the naming class has to be derived from the effective 795168404Spjd // context. 796168404Spjd 797168404Spjd // Emulate a MSVC bug where the creation of pointer-to-member 798168404Spjd // to protected member of base class is allowed but only from 799168404Spjd // static member functions. 800168404Spjd if (S.getLangOpts().MicrosoftMode && !EC.Functions.empty()) 801168404Spjd if (CXXMethodDecl* MD = dyn_cast<CXXMethodDecl>(EC.Functions.front())) 802168404Spjd if (MD->isStatic()) return AR_accessible; 803168404Spjd 804168404Spjd // Despite the standard's confident wording, there is a case 805168404Spjd // where you can have an instance member that's neither in a 806168404Spjd // pointer-to-member expression nor in a member access: when 807168404Spjd // it names a field in an unevaluated context that can't be an 808168404Spjd // implicit member. Pending clarification, we just apply the 809168404Spjd // same naming-class restriction here. 810168404Spjd // FIXME: we're probably not correctly adding the 811168404Spjd // protected-member restriction when we retroactively convert 812168404Spjd // an expression to being evaluated. 813168404Spjd 814168404Spjd // We know that ECRecord derives from NamingClass. The 815168404Spjd // restriction says to check whether NamingClass derives from 816168404Spjd // ECRecord, but that's not really necessary: two distinct 817168404Spjd // classes can't be recursively derived from each other. So 818168404Spjd // along this path, we just need to check whether the classes 819168404Spjd // are equal. 820168404Spjd if (NamingClass == ECRecord) return AR_accessible; 821168404Spjd 822168404Spjd // Otherwise, this context class tells us nothing; on to the next. 823168404Spjd continue; 824168404Spjd } 825168404Spjd 826168404Spjd assert(Target.isInstanceMember()); 827168404Spjd 828168404Spjd const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S); 829168404Spjd if (!InstanceContext) { 830168404Spjd OnFailure = AR_dependent; 831168404Spjd continue; 832168404Spjd } 833168404Spjd 834168404Spjd switch (IsDerivedFromInclusive(InstanceContext, ECRecord)) { 835168404Spjd case AR_accessible: return AR_accessible; 836168404Spjd case AR_inaccessible: continue; 837168404Spjd case AR_dependent: OnFailure = AR_dependent; continue; 838168404Spjd } 839168404Spjd } 840168404Spjd } 841168404Spjd 842168404Spjd // [M3] and [B3] say that, if the target is protected in N, we grant 843168404Spjd // access if the access occurs in a friend or member of some class P 844168404Spjd // that's a subclass of N and where the target has some natural 845168404Spjd // access in P. The 'member' aspect is easy to handle because P 846168404Spjd // would necessarily be one of the effective-context records, and we 847168404Spjd // address that above. The 'friend' aspect is completely ridiculous 848168404Spjd // to implement because there are no restrictions at all on P 849168404Spjd // *unless* the [class.protected] restriction applies. If it does, 850168404Spjd // however, we should ignore whether the naming class is a friend, 851168404Spjd // and instead rely on whether any potential P is a friend. 852168404Spjd if (Access == AS_protected && Target.isInstanceMember()) { 853168404Spjd // Compute the instance context if possible. 854168404Spjd const CXXRecordDecl *InstanceContext = 0; 855168404Spjd if (Target.hasInstanceContext()) { 856168404Spjd InstanceContext = Target.resolveInstanceContext(S); 857168404Spjd if (!InstanceContext) return AR_dependent; 858168404Spjd } 859168404Spjd 860168404Spjd switch (GetProtectedFriendKind(S, EC, InstanceContext, NamingClass)) { 861168404Spjd case AR_accessible: return AR_accessible; 862168404Spjd case AR_inaccessible: return OnFailure; 863168404Spjd case AR_dependent: return AR_dependent; 864168404Spjd } 865168404Spjd llvm_unreachable("impossible friendship kind"); 866168404Spjd } 867168404Spjd 868168404Spjd switch (GetFriendKind(S, EC, NamingClass)) { 869168404Spjd case AR_accessible: return AR_accessible; 870168404Spjd case AR_inaccessible: return OnFailure; 871168404Spjd case AR_dependent: return AR_dependent; 872168404Spjd } 873168404Spjd 874168404Spjd // Silence bogus warnings 875168404Spjd llvm_unreachable("impossible friendship kind"); 876168404Spjd} 877168404Spjd 878168404Spjd/// Finds the best path from the naming class to the declaring class, 879168404Spjd/// taking friend declarations into account. 880168404Spjd/// 881168404Spjd/// C++0x [class.access.base]p5: 882168404Spjd/// A member m is accessible at the point R when named in class N if 883168404Spjd/// [M1] m as a member of N is public, or 884168404Spjd/// [M2] m as a member of N is private, and R occurs in a member or 885168404Spjd/// friend of class N, or 886168404Spjd/// [M3] m as a member of N is protected, and R occurs in a member or 887168404Spjd/// friend of class N, or in a member or friend of a class P 888168404Spjd/// derived from N, where m as a member of P is public, private, 889168404Spjd/// or protected, or 890168404Spjd/// [M4] there exists a base class B of N that is accessible at R, and 891168404Spjd/// m is accessible at R when named in class B. 892185029Spjd/// 893185029Spjd/// C++0x [class.access.base]p4: 894168404Spjd/// A base class B of N is accessible at R, if 895168404Spjd/// [B1] an invented public member of B would be a public member of N, or 896168404Spjd/// [B2] R occurs in a member or friend of class N, and an invented public 897168404Spjd/// member of B would be a private or protected member of N, or 898168404Spjd/// [B3] R occurs in a member or friend of a class P derived from N, and an 899168404Spjd/// invented public member of B would be a private or protected member 900168404Spjd/// of P, or 901168404Spjd/// [B4] there exists a class S such that B is a base class of S accessible 902168404Spjd/// at R and S is a base class of N accessible at R. 903168404Spjd/// 904168404Spjd/// Along a single inheritance path we can restate both of these 905168404Spjd/// iteratively: 906168404Spjd/// 907168404Spjd/// First, we note that M1-4 are equivalent to B1-4 if the member is 908168404Spjd/// treated as a notional base of its declaring class with inheritance 909168404Spjd/// access equivalent to the member's access. Therefore we need only 910168404Spjd/// ask whether a class B is accessible from a class N in context R. 911168404Spjd/// 912168404Spjd/// Let B_1 .. B_n be the inheritance path in question (i.e. where 913168404Spjd/// B_1 = N, B_n = B, and for all i, B_{i+1} is a direct base class of 914168404Spjd/// B_i). For i in 1..n, we will calculate ACAB(i), the access to the 915168404Spjd/// closest accessible base in the path: 916168404Spjd/// Access(a, b) = (* access on the base specifier from a to b *) 917168404Spjd/// Merge(a, forbidden) = forbidden 918168404Spjd/// Merge(a, private) = forbidden 919168404Spjd/// Merge(a, b) = min(a,b) 920168404Spjd/// Accessible(c, forbidden) = false 921168404Spjd/// Accessible(c, private) = (R is c) || IsFriend(c, R) 922168404Spjd/// Accessible(c, protected) = (R derived from c) || IsFriend(c, R) 923168404Spjd/// Accessible(c, public) = true 924168404Spjd/// ACAB(n) = public 925168404Spjd/// ACAB(i) = 926168404Spjd/// let AccessToBase = Merge(Access(B_i, B_{i+1}), ACAB(i+1)) in 927168404Spjd/// if Accessible(B_i, AccessToBase) then public else AccessToBase 928168404Spjd/// 929168404Spjd/// B is an accessible base of N at R iff ACAB(1) = public. 930168404Spjd/// 931168404Spjd/// \param FinalAccess the access of the "final step", or AS_public if 932168404Spjd/// there is no final step. 933168404Spjd/// \return null if friendship is dependent 934168404Spjdstatic CXXBasePath *FindBestPath(Sema &S, 935168404Spjd const EffectiveContext &EC, 936168404Spjd AccessTarget &Target, 937168404Spjd AccessSpecifier FinalAccess, 938168404Spjd CXXBasePaths &Paths) { 939168404Spjd // Derive the paths to the desired base. 940168404Spjd const CXXRecordDecl *Derived = Target.getNamingClass(); 941168404Spjd const CXXRecordDecl *Base = Target.getDeclaringClass(); 942168404Spjd 943168404Spjd // FIXME: fail correctly when there are dependent paths. 944168404Spjd bool isDerived = Derived->isDerivedFrom(const_cast<CXXRecordDecl*>(Base), 945168404Spjd Paths); 946168404Spjd assert(isDerived && "derived class not actually derived from base"); 947168404Spjd (void) isDerived; 948168404Spjd 949168404Spjd CXXBasePath *BestPath = 0; 950168404Spjd 951168404Spjd assert(FinalAccess != AS_none && "forbidden access after declaring class"); 952168404Spjd 953168404Spjd bool AnyDependent = false; 954168404Spjd 955168404Spjd // Derive the friend-modified access along each path. 956168404Spjd for (CXXBasePaths::paths_iterator PI = Paths.begin(), PE = Paths.end(); 957168404Spjd PI != PE; ++PI) { 958168404Spjd AccessTarget::SavedInstanceContext _ = Target.saveInstanceContext(); 959168404Spjd 960168404Spjd // Walk through the path backwards. 961168404Spjd AccessSpecifier PathAccess = FinalAccess; 962168404Spjd CXXBasePath::iterator I = PI->end(), E = PI->begin(); 963168404Spjd while (I != E) { 964168404Spjd --I; 965168404Spjd 966168404Spjd assert(PathAccess != AS_none); 967168404Spjd 968168404Spjd // If the declaration is a private member of a base class, there 969168404Spjd // is no level of friendship in derived classes that can make it 970168404Spjd // accessible. 971168404Spjd if (PathAccess == AS_private) { 972168404Spjd PathAccess = AS_none; 973168404Spjd break; 974168404Spjd } 975168404Spjd 976168404Spjd const CXXRecordDecl *NC = I->Class->getCanonicalDecl(); 977168404Spjd 978168404Spjd AccessSpecifier BaseAccess = I->Base->getAccessSpecifier(); 979168404Spjd PathAccess = std::max(PathAccess, BaseAccess); 980168404Spjd 981168404Spjd switch (HasAccess(S, EC, NC, PathAccess, Target)) { 982168404Spjd case AR_inaccessible: break; 983168404Spjd case AR_accessible: 984168404Spjd PathAccess = AS_public; 985168404Spjd 986168404Spjd // Future tests are not against members and so do not have 987168404Spjd // instance context. 988168404Spjd Target.suppressInstanceContext(); 989185029Spjd break; 990168404Spjd case AR_dependent: 991168404Spjd AnyDependent = true; 992168404Spjd goto Next; 993168404Spjd } 994168404Spjd } 995168404Spjd 996168404Spjd // Note that we modify the path's Access field to the 997168404Spjd // friend-modified access. 998185029Spjd if (BestPath == 0 || PathAccess < BestPath->Access) { 999168404Spjd BestPath = &*PI; 1000168404Spjd BestPath->Access = PathAccess; 1001168404Spjd 1002168404Spjd // Short-circuit if we found a public path. 1003168404Spjd if (BestPath->Access == AS_public) 1004168404Spjd return BestPath; 1005168404Spjd } 1006168404Spjd 1007168404Spjd Next: ; 1008168404Spjd } 1009168404Spjd 1010168404Spjd assert((!BestPath || BestPath->Access != AS_public) && 1011168404Spjd "fell out of loop with public path"); 1012168404Spjd 1013185029Spjd // We didn't find a public path, but at least one path was subject 1014168404Spjd // to dependent friendship, so delay the check. 1015168404Spjd if (AnyDependent) 1016168404Spjd return 0; 1017168404Spjd 1018168404Spjd return BestPath; 1019168404Spjd} 1020168404Spjd 1021168404Spjd/// Given that an entity has protected natural access, check whether 1022168404Spjd/// access might be denied because of the protected member access 1023168404Spjd/// restriction. 1024168404Spjd/// 1025168404Spjd/// \return true if a note was emitted 1026168404Spjdstatic bool TryDiagnoseProtectedAccess(Sema &S, const EffectiveContext &EC, 1027168404Spjd AccessTarget &Target) { 1028168404Spjd // Only applies to instance accesses. 1029168404Spjd if (!Target.isInstanceMember()) 1030168404Spjd return false; 1031168404Spjd 1032168404Spjd assert(Target.isMemberAccess()); 1033168404Spjd 1034168404Spjd const CXXRecordDecl *NamingClass = Target.getEffectiveNamingClass(); 1035168404Spjd 1036168404Spjd for (EffectiveContext::record_iterator 1037168404Spjd I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { 1038168404Spjd const CXXRecordDecl *ECRecord = *I; 1039168404Spjd switch (IsDerivedFromInclusive(ECRecord, NamingClass)) { 1040168404Spjd case AR_accessible: break; 1041168404Spjd case AR_inaccessible: continue; 1042168404Spjd case AR_dependent: continue; 1043168404Spjd } 1044168404Spjd 1045168404Spjd // The effective context is a subclass of the declaring class. 1046168404Spjd // Check whether the [class.protected] restriction is limiting 1047168404Spjd // access. 1048168404Spjd 1049185029Spjd // To get this exactly right, this might need to be checked more 1050168404Spjd // holistically; it's not necessarily the case that gaining 1051168404Spjd // access here would grant us access overall. 1052168404Spjd 1053168404Spjd NamedDecl *D = Target.getTargetDecl(); 1054168404Spjd 1055168404Spjd // If we don't have an instance context, [class.protected] says the 1056168404Spjd // naming class has to equal the context class. 1057168404Spjd if (!Target.hasInstanceContext()) { 1058168404Spjd // If it does, the restriction doesn't apply. 1059168404Spjd if (NamingClass == ECRecord) continue; 1060168404Spjd 1061168404Spjd // TODO: it would be great to have a fixit here, since this is 1062168404Spjd // such an obvious error. 1063168404Spjd S.Diag(D->getLocation(), diag::note_access_protected_restricted_noobject) 1064168404Spjd << S.Context.getTypeDeclType(ECRecord); 1065168404Spjd return true; 1066168404Spjd } 1067168404Spjd 1068168404Spjd const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S); 1069168404Spjd assert(InstanceContext && "diagnosing dependent access"); 1070168404Spjd 1071168404Spjd switch (IsDerivedFromInclusive(InstanceContext, ECRecord)) { 1072168404Spjd case AR_accessible: continue; 1073168404Spjd case AR_dependent: continue; 1074168404Spjd case AR_inaccessible: 1075168404Spjd break; 1076168404Spjd } 1077168404Spjd 1078191900Skmacy // Okay, the restriction seems to be what's limiting us. 1079168404Spjd 1080168404Spjd // Use a special diagnostic for constructors and destructors. 1081168404Spjd if (isa<CXXConstructorDecl>(D) || isa<CXXDestructorDecl>(D) || 1082168404Spjd (isa<FunctionTemplateDecl>(D) && 1083185029Spjd isa<CXXConstructorDecl>( 1084168404Spjd cast<FunctionTemplateDecl>(D)->getTemplatedDecl()))) { 1085168404Spjd S.Diag(D->getLocation(), diag::note_access_protected_restricted_ctordtor) 1086168404Spjd << isa<CXXDestructorDecl>(D); 1087168404Spjd return true; 1088168404Spjd } 1089168404Spjd 1090168404Spjd // Otherwise, use the generic diagnostic. 1091168404Spjd S.Diag(D->getLocation(), diag::note_access_protected_restricted_object) 1092168404Spjd << S.Context.getTypeDeclType(ECRecord); 1093185029Spjd return true; 1094168404Spjd } 1095168404Spjd 1096168404Spjd return false; 1097168404Spjd} 1098168404Spjd 1099168404Spjd/// We are unable to access a given declaration due to its direct 1100168404Spjd/// access control; diagnose that. 1101168404Spjdstatic void diagnoseBadDirectAccess(Sema &S, 1102168404Spjd const EffectiveContext &EC, 1103168404Spjd AccessTarget &entity) { 1104168404Spjd assert(entity.isMemberAccess()); 1105168404Spjd NamedDecl *D = entity.getTargetDecl(); 1106168404Spjd 1107168404Spjd if (D->getAccess() == AS_protected && 1108168404Spjd TryDiagnoseProtectedAccess(S, EC, entity)) 1109168404Spjd return; 1110168404Spjd 1111168404Spjd // Find an original declaration. 1112168404Spjd while (D->isOutOfLine()) { 1113168404Spjd NamedDecl *PrevDecl = 0; 1114168404Spjd if (VarDecl *VD = dyn_cast<VarDecl>(D)) 1115168404Spjd PrevDecl = VD->getPreviousDecl(); 1116168404Spjd else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) 1117168404Spjd PrevDecl = FD->getPreviousDecl(); 1118168404Spjd else if (TypedefNameDecl *TND = dyn_cast<TypedefNameDecl>(D)) 1119168404Spjd PrevDecl = TND->getPreviousDecl(); 1120168404Spjd else if (TagDecl *TD = dyn_cast<TagDecl>(D)) { 1121168404Spjd if (isa<RecordDecl>(D) && cast<RecordDecl>(D)->isInjectedClassName()) 1122168404Spjd break; 1123168404Spjd PrevDecl = TD->getPreviousDecl(); 1124168404Spjd } 1125168404Spjd if (!PrevDecl) break; 1126168404Spjd D = PrevDecl; 1127168404Spjd } 1128168404Spjd 1129168404Spjd CXXRecordDecl *DeclaringClass = FindDeclaringClass(D); 1130168404Spjd Decl *ImmediateChild; 1131168404Spjd if (D->getDeclContext() == DeclaringClass) 1132168404Spjd ImmediateChild = D; 1133168404Spjd else { 1134168404Spjd DeclContext *DC = D->getDeclContext(); 1135168404Spjd while (DC->getParent() != DeclaringClass) 1136168404Spjd DC = DC->getParent(); 1137168404Spjd ImmediateChild = cast<Decl>(DC); 1138168404Spjd } 1139168404Spjd 1140168404Spjd // Check whether there's an AccessSpecDecl preceding this in the 1141168404Spjd // chain of the DeclContext. 1142168404Spjd bool isImplicit = true; 1143168404Spjd for (CXXRecordDecl::decl_iterator 1144168404Spjd I = DeclaringClass->decls_begin(), E = DeclaringClass->decls_end(); 1145168404Spjd I != E; ++I) { 1146168404Spjd if (*I == ImmediateChild) break; 1147168404Spjd if (isa<AccessSpecDecl>(*I)) { 1148168404Spjd isImplicit = false; 1149168404Spjd break; 1150168404Spjd } 1151168404Spjd } 1152185029Spjd 1153168404Spjd S.Diag(D->getLocation(), diag::note_access_natural) 1154168404Spjd << (unsigned) (D->getAccess() == AS_protected) 1155168404Spjd << isImplicit; 1156168404Spjd} 1157168404Spjd 1158168404Spjd/// Diagnose the path which caused the given declaration or base class 1159168404Spjd/// to become inaccessible. 1160168404Spjdstatic void DiagnoseAccessPath(Sema &S, 1161168404Spjd const EffectiveContext &EC, 1162168404Spjd AccessTarget &entity) { 1163168404Spjd // Save the instance context to preserve invariants. 1164185029Spjd AccessTarget::SavedInstanceContext _ = entity.saveInstanceContext(); 1165168404Spjd 1166168404Spjd // This basically repeats the main algorithm but keeps some more 1167168404Spjd // information. 1168168404Spjd 1169168404Spjd // The natural access so far. 1170168404Spjd AccessSpecifier accessSoFar = AS_public; 1171168404Spjd 1172168404Spjd // Check whether we have special rights to the declaring class. 1173168404Spjd if (entity.isMemberAccess()) { 1174168404Spjd NamedDecl *D = entity.getTargetDecl(); 1175168404Spjd accessSoFar = D->getAccess(); 1176168404Spjd const CXXRecordDecl *declaringClass = entity.getDeclaringClass(); 1177168404Spjd 1178168404Spjd switch (HasAccess(S, EC, declaringClass, accessSoFar, entity)) { 1179168404Spjd // If the declaration is accessible when named in its declaring 1180168404Spjd // class, then we must be constrained by the path. 1181168404Spjd case AR_accessible: 1182168404Spjd accessSoFar = AS_public; 1183168404Spjd entity.suppressInstanceContext(); 1184168404Spjd break; 1185168404Spjd 1186168404Spjd case AR_inaccessible: 1187168404Spjd if (accessSoFar == AS_private || 1188168404Spjd declaringClass == entity.getEffectiveNamingClass()) 1189168404Spjd return diagnoseBadDirectAccess(S, EC, entity); 1190168404Spjd break; 1191168404Spjd 1192168404Spjd case AR_dependent: 1193168404Spjd llvm_unreachable("cannot diagnose dependent access"); 1194168404Spjd } 1195168404Spjd } 1196168404Spjd 1197168404Spjd CXXBasePaths paths; 1198185029Spjd CXXBasePath &path = *FindBestPath(S, EC, entity, accessSoFar, paths); 1199168404Spjd assert(path.Access != AS_public); 1200185029Spjd 1201168404Spjd CXXBasePath::iterator i = path.end(), e = path.begin(); 1202168404Spjd CXXBasePath::iterator constrainingBase = i; 1203168404Spjd while (i != e) { 1204168404Spjd --i; 1205168404Spjd 1206168404Spjd assert(accessSoFar != AS_none && accessSoFar != AS_private); 1207168404Spjd 1208168404Spjd // Is the entity accessible when named in the deriving class, as 1209168404Spjd // modified by the base specifier? 1210168404Spjd const CXXRecordDecl *derivingClass = i->Class->getCanonicalDecl(); 1211168404Spjd const CXXBaseSpecifier *base = i->Base; 1212168404Spjd 1213168404Spjd // If the access to this base is worse than the access we have to 1214168404Spjd // the declaration, remember it. 1215168404Spjd AccessSpecifier baseAccess = base->getAccessSpecifier(); 1216168404Spjd if (baseAccess > accessSoFar) { 1217168404Spjd constrainingBase = i; 1218168404Spjd accessSoFar = baseAccess; 1219168404Spjd } 1220168404Spjd 1221168404Spjd switch (HasAccess(S, EC, derivingClass, accessSoFar, entity)) { 1222168404Spjd case AR_inaccessible: break; 1223168404Spjd case AR_accessible: 1224168404Spjd accessSoFar = AS_public; 1225168404Spjd entity.suppressInstanceContext(); 1226168404Spjd constrainingBase = 0; 1227168404Spjd break; 1228168404Spjd case AR_dependent: 1229168404Spjd llvm_unreachable("cannot diagnose dependent access"); 1230168404Spjd } 1231168404Spjd 1232168404Spjd // If this was private inheritance, but we don't have access to 1233168404Spjd // the deriving class, we're done. 1234168404Spjd if (accessSoFar == AS_private) { 1235168404Spjd assert(baseAccess == AS_private); 1236168404Spjd assert(constrainingBase == i); 1237168404Spjd break; 1238168404Spjd } 1239168404Spjd } 1240168404Spjd 1241168404Spjd // If we don't have a constraining base, the access failure must be 1242168404Spjd // due to the original declaration. 1243168404Spjd if (constrainingBase == path.end()) 1244168404Spjd return diagnoseBadDirectAccess(S, EC, entity); 1245168404Spjd 1246168404Spjd // We're constrained by inheritance, but we want to say 1247168404Spjd // "declared private here" if we're diagnosing a hierarchy 1248168404Spjd // conversion and this is the final step. 1249168404Spjd unsigned diagnostic; 1250168404Spjd if (entity.isMemberAccess() || 1251168404Spjd constrainingBase + 1 != path.end()) { 1252168404Spjd diagnostic = diag::note_access_constrained_by_path; 1253168404Spjd } else { 1254168404Spjd diagnostic = diag::note_access_natural; 1255168404Spjd } 1256168404Spjd 1257168404Spjd const CXXBaseSpecifier *base = constrainingBase->Base; 1258168404Spjd 1259168404Spjd S.Diag(base->getSourceRange().getBegin(), diagnostic) 1260168404Spjd << base->getSourceRange() 1261168404Spjd << (base->getAccessSpecifier() == AS_protected) 1262168404Spjd << (base->getAccessSpecifierAsWritten() == AS_none); 1263168404Spjd 1264168404Spjd if (entity.isMemberAccess()) 1265168404Spjd S.Diag(entity.getTargetDecl()->getLocation(), diag::note_field_decl); 1266168404Spjd} 1267168404Spjd 1268168404Spjdstatic void DiagnoseBadAccess(Sema &S, SourceLocation Loc, 1269168404Spjd const EffectiveContext &EC, 1270168404Spjd AccessTarget &Entity) { 1271168404Spjd const CXXRecordDecl *NamingClass = Entity.getNamingClass(); 1272168404Spjd const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass(); 1273168404Spjd NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : 0); 1274168404Spjd 1275168404Spjd S.Diag(Loc, Entity.getDiag()) 1276168404Spjd << (Entity.getAccess() == AS_protected) 1277168404Spjd << (D ? D->getDeclName() : DeclarationName()) 1278168404Spjd << S.Context.getTypeDeclType(NamingClass) 1279168404Spjd << S.Context.getTypeDeclType(DeclaringClass); 1280168404Spjd DiagnoseAccessPath(S, EC, Entity); 1281168404Spjd} 1282168404Spjd 1283168404Spjd/// MSVC has a bug where if during an using declaration name lookup, 1284168404Spjd/// the declaration found is unaccessible (private) and that declaration 1285168404Spjd/// was bring into scope via another using declaration whose target 1286168404Spjd/// declaration is accessible (public) then no error is generated. 1287168404Spjd/// Example: 1288168404Spjd/// class A { 1289168404Spjd/// public: 1290168404Spjd/// int f(); 1291168404Spjd/// }; 1292168404Spjd/// class B : public A { 1293168404Spjd/// private: 1294168404Spjd/// using A::f; 1295168404Spjd/// }; 1296168404Spjd/// class C : public B { 1297168404Spjd/// private: 1298168404Spjd/// using B::f; 1299168404Spjd/// }; 1300168404Spjd/// 1301168404Spjd/// Here, B::f is private so this should fail in Standard C++, but 1302168404Spjd/// because B::f refers to A::f which is public MSVC accepts it. 1303168404Spjdstatic bool IsMicrosoftUsingDeclarationAccessBug(Sema& S, 1304168404Spjd SourceLocation AccessLoc, 1305168404Spjd AccessTarget &Entity) { 1306168404Spjd if (UsingShadowDecl *Shadow = 1307168404Spjd dyn_cast<UsingShadowDecl>(Entity.getTargetDecl())) { 1308168404Spjd const NamedDecl *OrigDecl = Entity.getTargetDecl()->getUnderlyingDecl(); 1309168404Spjd if (Entity.getTargetDecl()->getAccess() == AS_private && 1310168404Spjd (OrigDecl->getAccess() == AS_public || 1311168404Spjd OrigDecl->getAccess() == AS_protected)) { 1312168404Spjd S.Diag(AccessLoc, diag::ext_ms_using_declaration_inaccessible) 1313168404Spjd << Shadow->getUsingDecl()->getQualifiedNameAsString() 1314168404Spjd << OrigDecl->getQualifiedNameAsString(); 1315168404Spjd return true; 1316168404Spjd } 1317168404Spjd } 1318168404Spjd return false; 1319168404Spjd} 1320168404Spjd 1321168404Spjd/// Determines whether the accessed entity is accessible. Public members 1322168404Spjd/// have been weeded out by this point. 1323168404Spjdstatic AccessResult IsAccessible(Sema &S, 1324168404Spjd const EffectiveContext &EC, 1325168404Spjd AccessTarget &Entity) { 1326168404Spjd // Determine the actual naming class. 1327168404Spjd const CXXRecordDecl *NamingClass = Entity.getEffectiveNamingClass(); 1328168404Spjd 1329168404Spjd AccessSpecifier UnprivilegedAccess = Entity.getAccess(); 1330168404Spjd assert(UnprivilegedAccess != AS_public && "public access not weeded out"); 1331168404Spjd 1332168404Spjd // Before we try to recalculate access paths, try to white-list 1333168404Spjd // accesses which just trade in on the final step, i.e. accesses 1334168404Spjd // which don't require [M4] or [B4]. These are by far the most 1335168404Spjd // common forms of privileged access. 1336168404Spjd if (UnprivilegedAccess != AS_none) { 1337168404Spjd switch (HasAccess(S, EC, NamingClass, UnprivilegedAccess, Entity)) { 1338168404Spjd case AR_dependent: 1339168404Spjd // This is actually an interesting policy decision. We don't 1340168404Spjd // *have* to delay immediately here: we can do the full access 1341168404Spjd // calculation in the hope that friendship on some intermediate 1342185029Spjd // class will make the declaration accessible non-dependently. 1343168404Spjd // But that's not cheap, and odds are very good (note: assertion 1344185029Spjd // made without data) that the friend declaration will determine 1345185029Spjd // access. 1346185029Spjd return AR_dependent; 1347185029Spjd 1348185029Spjd case AR_accessible: return AR_accessible; 1349185029Spjd case AR_inaccessible: break; 1350168404Spjd } 1351168404Spjd } 1352168404Spjd 1353168404Spjd AccessTarget::SavedInstanceContext _ = Entity.saveInstanceContext(); 1354168404Spjd 1355168404Spjd // We lower member accesses to base accesses by pretending that the 1356168404Spjd // member is a base class of its declaring class. 1357168404Spjd AccessSpecifier FinalAccess; 1358168404Spjd 1359168404Spjd if (Entity.isMemberAccess()) { 1360168404Spjd // Determine if the declaration is accessible from EC when named 1361168404Spjd // in its declaring class. 1362168404Spjd NamedDecl *Target = Entity.getTargetDecl(); 1363168404Spjd const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass(); 1364168404Spjd 1365168404Spjd FinalAccess = Target->getAccess(); 1366168404Spjd switch (HasAccess(S, EC, DeclaringClass, FinalAccess, Entity)) { 1367168404Spjd case AR_accessible: 1368185029Spjd // Target is accessible at EC when named in its declaring class. 1369185029Spjd // We can now hill-climb and simply check whether the declaring 1370168404Spjd // class is accessible as a base of the naming class. This is 1371168404Spjd // equivalent to checking the access of a notional public 1372168404Spjd // member with no instance context. 1373168404Spjd FinalAccess = AS_public; 1374168404Spjd Entity.suppressInstanceContext(); 1375185029Spjd break; 1376185029Spjd case AR_inaccessible: break; 1377185029Spjd case AR_dependent: return AR_dependent; // see above 1378168404Spjd } 1379168404Spjd 1380168404Spjd if (DeclaringClass == NamingClass) 1381168404Spjd return (FinalAccess == AS_public ? AR_accessible : AR_inaccessible); 1382168404Spjd } else { 1383168404Spjd FinalAccess = AS_public; 1384168404Spjd } 1385168404Spjd 1386168404Spjd assert(Entity.getDeclaringClass() != NamingClass); 1387168404Spjd 1388168404Spjd // Append the declaration's access if applicable. 1389168404Spjd CXXBasePaths Paths; 1390168404Spjd CXXBasePath *Path = FindBestPath(S, EC, Entity, FinalAccess, Paths); 1391168404Spjd if (!Path) 1392168404Spjd return AR_dependent; 1393168404Spjd 1394168404Spjd assert(Path->Access <= UnprivilegedAccess && 1395168404Spjd "access along best path worse than direct?"); 1396168404Spjd if (Path->Access == AS_public) 1397168404Spjd return AR_accessible; 1398168404Spjd return AR_inaccessible; 1399168404Spjd} 1400168404Spjd 1401168404Spjdstatic void DelayDependentAccess(Sema &S, 1402168404Spjd const EffectiveContext &EC, 1403168404Spjd SourceLocation Loc, 1404168404Spjd const AccessTarget &Entity) { 1405168404Spjd assert(EC.isDependent() && "delaying non-dependent access"); 1406168404Spjd DeclContext *DC = EC.getInnerContext(); 1407168404Spjd assert(DC->isDependentContext() && "delaying non-dependent access"); 1408168404Spjd DependentDiagnostic::Create(S.Context, DC, DependentDiagnostic::Access, 1409168404Spjd Loc, 1410168404Spjd Entity.isMemberAccess(), 1411168404Spjd Entity.getAccess(), 1412168404Spjd Entity.getTargetDecl(), 1413168404Spjd Entity.getNamingClass(), 1414168404Spjd Entity.getBaseObjectType(), 1415168404Spjd Entity.getDiag()); 1416168404Spjd} 1417168404Spjd 1418168404Spjd/// Checks access to an entity from the given effective context. 1419168404Spjdstatic AccessResult CheckEffectiveAccess(Sema &S, 1420168404Spjd const EffectiveContext &EC, 1421168404Spjd SourceLocation Loc, 1422168404Spjd AccessTarget &Entity) { 1423168404Spjd assert(Entity.getAccess() != AS_public && "called for public access!"); 1424168404Spjd 1425168404Spjd if (S.getLangOpts().MicrosoftMode && 1426168404Spjd IsMicrosoftUsingDeclarationAccessBug(S, Loc, Entity)) 1427168404Spjd return AR_accessible; 1428168404Spjd 1429168404Spjd switch (IsAccessible(S, EC, Entity)) { 1430168404Spjd case AR_dependent: 1431168404Spjd DelayDependentAccess(S, EC, Loc, Entity); 1432168404Spjd return AR_dependent; 1433168404Spjd 1434168404Spjd case AR_inaccessible: 1435168404Spjd if (!Entity.isQuiet()) 1436200724Sdelphij DiagnoseBadAccess(S, Loc, EC, Entity); 1437168404Spjd return AR_inaccessible; 1438168404Spjd 1439168404Spjd case AR_accessible: 1440168404Spjd return AR_accessible; 1441168404Spjd } 1442168404Spjd 1443168404Spjd // silence unnecessary warning 1444168404Spjd llvm_unreachable("invalid access result"); 1445168404Spjd} 1446168404Spjd 1447168404Spjdstatic Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc, 1448168404Spjd AccessTarget &Entity) { 1449168404Spjd // If the access path is public, it's accessible everywhere. 1450168404Spjd if (Entity.getAccess() == AS_public) 1451168404Spjd return Sema::AR_accessible; 1452168404Spjd 1453168404Spjd // If we're currently parsing a declaration, we may need to delay 1454168404Spjd // access control checking, because our effective context might be 1455168404Spjd // different based on what the declaration comes out as. 1456168404Spjd // 1457168404Spjd // For example, we might be parsing a declaration with a scope 1458168404Spjd // specifier, like this: 1459168404Spjd // A::private_type A::foo() { ... } 1460168404Spjd // 1461168404Spjd // Or we might be parsing something that will turn out to be a friend: 1462168404Spjd // void foo(A::private_type); 1463168404Spjd // void B::foo(A::private_type); 1464168404Spjd if (S.DelayedDiagnostics.shouldDelayDiagnostics()) { 1465168404Spjd S.DelayedDiagnostics.add(DelayedDiagnostic::makeAccess(Loc, Entity)); 1466168404Spjd return Sema::AR_delayed; 1467168404Spjd } 1468168404Spjd 1469168404Spjd EffectiveContext EC(S.CurContext); 1470168404Spjd switch (CheckEffectiveAccess(S, EC, Loc, Entity)) { 1471168404Spjd case AR_accessible: return Sema::AR_accessible; 1472168404Spjd case AR_inaccessible: return Sema::AR_inaccessible; 1473168404Spjd case AR_dependent: return Sema::AR_dependent; 1474168404Spjd } 1475168404Spjd llvm_unreachable("falling off end"); 1476168404Spjd} 1477168404Spjd 1478168404Spjdvoid Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *D) { 1479168404Spjd // Access control for names used in the declarations of functions 1480168404Spjd // and function templates should normally be evaluated in the context 1481168404Spjd // of the declaration, just in case it's a friend of something. 1482168404Spjd // However, this does not apply to local extern declarations. 1483168404Spjd 1484168404Spjd DeclContext *DC = D->getDeclContext(); 1485185029Spjd if (FunctionDecl *FN = dyn_cast<FunctionDecl>(D)) { 1486168404Spjd if (D->getLexicalDeclContext()->isFunctionOrMethod()) 1487168404Spjd DC = D->getLexicalDeclContext(); 1488168404Spjd else 1489168404Spjd DC = FN; 1490168404Spjd } else if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D)) { 1491168404Spjd DC = cast<DeclContext>(TD->getTemplatedDecl()); 1492168404Spjd } 1493168404Spjd 1494168404Spjd EffectiveContext EC(DC); 1495168404Spjd 1496168404Spjd AccessTarget Target(DD.getAccessData()); 1497168404Spjd 1498168404Spjd if (CheckEffectiveAccess(*this, EC, DD.Loc, Target) == ::AR_inaccessible) 1499168404Spjd DD.Triggered = true; 1500168404Spjd} 1501168404Spjd 1502168404Spjdvoid Sema::HandleDependentAccessCheck(const DependentDiagnostic &DD, 1503168404Spjd const MultiLevelTemplateArgumentList &TemplateArgs) { 1504168404Spjd SourceLocation Loc = DD.getAccessLoc(); 1505168404Spjd AccessSpecifier Access = DD.getAccess(); 1506168404Spjd 1507168404Spjd Decl *NamingD = FindInstantiatedDecl(Loc, DD.getAccessNamingClass(), 1508168404Spjd TemplateArgs); 1509168404Spjd if (!NamingD) return; 1510168404Spjd Decl *TargetD = FindInstantiatedDecl(Loc, DD.getAccessTarget(), 1511185029Spjd TemplateArgs); 1512185029Spjd if (!TargetD) return; 1513185029Spjd 1514168404Spjd if (DD.isAccessToMember()) { 1515168404Spjd CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(NamingD); 1516168404Spjd NamedDecl *TargetDecl = cast<NamedDecl>(TargetD); 1517168404Spjd QualType BaseObjectType = DD.getAccessBaseObjectType(); 1518168404Spjd if (!BaseObjectType.isNull()) { 1519168404Spjd BaseObjectType = SubstType(BaseObjectType, TemplateArgs, Loc, 1520168404Spjd DeclarationName()); 1521168404Spjd if (BaseObjectType.isNull()) return; 1522168404Spjd } 1523168404Spjd 1524168404Spjd AccessTarget Entity(Context, 1525168404Spjd AccessTarget::Member, 1526168404Spjd NamingClass, 1527168404Spjd DeclAccessPair::make(TargetDecl, Access), 1528168404Spjd BaseObjectType); 1529168404Spjd Entity.setDiag(DD.getDiagnostic()); 1530168404Spjd CheckAccess(*this, Loc, Entity); 1531168404Spjd } else { 1532168404Spjd AccessTarget Entity(Context, 1533168404Spjd AccessTarget::Base, 1534168404Spjd cast<CXXRecordDecl>(TargetD), 1535168404Spjd cast<CXXRecordDecl>(NamingD), 1536168404Spjd Access); 1537168404Spjd Entity.setDiag(DD.getDiagnostic()); 1538168404Spjd CheckAccess(*this, Loc, Entity); 1539168404Spjd } 1540168404Spjd} 1541168404Spjd 1542168404SpjdSema::AccessResult Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E, 1543168404Spjd DeclAccessPair Found) { 1544168404Spjd if (!getLangOpts().AccessControl || 1545168404Spjd !E->getNamingClass() || 1546168404Spjd Found.getAccess() == AS_public) 1547168404Spjd return AR_accessible; 1548168404Spjd 1549168404Spjd AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(), 1550168404Spjd Found, QualType()); 1551168404Spjd Entity.setDiag(diag::err_access) << E->getSourceRange(); 1552168404Spjd 1553168404Spjd return CheckAccess(*this, E->getNameLoc(), Entity); 1554168404Spjd} 1555168404Spjd 1556168404Spjd/// Perform access-control checking on a previously-unresolved member 1557168404Spjd/// access which has now been resolved to a member. 1558168404SpjdSema::AccessResult Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E, 1559168404Spjd DeclAccessPair Found) { 1560168404Spjd if (!getLangOpts().AccessControl || 1561168404Spjd Found.getAccess() == AS_public) 1562168404Spjd return AR_accessible; 1563168404Spjd 1564168404Spjd QualType BaseType = E->getBaseType(); 1565168404Spjd if (E->isArrow()) 1566168404Spjd BaseType = BaseType->getAs<PointerType>()->getPointeeType(); 1567168404Spjd 1568168404Spjd AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(), 1569168404Spjd Found, BaseType); 1570168404Spjd Entity.setDiag(diag::err_access) << E->getSourceRange(); 1571168404Spjd 1572168404Spjd return CheckAccess(*this, E->getMemberLoc(), Entity); 1573168404Spjd} 1574168404Spjd 1575168404Spjd/// Is the given special member function accessible for the purposes of 1576168404Spjd/// deciding whether to define a special member function as deleted? 1577168404Spjdbool Sema::isSpecialMemberAccessibleForDeletion(CXXMethodDecl *decl, 1578168404Spjd AccessSpecifier access, 1579168404Spjd QualType objectType) { 1580168404Spjd // Fast path. 1581168404Spjd if (access == AS_public || !getLangOpts().AccessControl) return true; 1582168404Spjd 1583168404Spjd AccessTarget entity(Context, AccessTarget::Member, decl->getParent(), 1584168404Spjd DeclAccessPair::make(decl, access), objectType); 1585168404Spjd 1586168404Spjd // Suppress diagnostics. 1587168404Spjd entity.setDiag(PDiag()); 1588185029Spjd 1589185029Spjd switch (CheckAccess(*this, SourceLocation(), entity)) { 1590168404Spjd case AR_accessible: return true; 1591168404Spjd case AR_inaccessible: return false; 1592168404Spjd case AR_dependent: llvm_unreachable("dependent for =delete computation"); 1593185029Spjd case AR_delayed: llvm_unreachable("cannot delay =delete computation"); 1594168404Spjd } 1595168404Spjd llvm_unreachable("bad access result"); 1596168404Spjd} 1597168404Spjd 1598168404SpjdSema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc, 1599168404Spjd CXXDestructorDecl *Dtor, 1600168404Spjd const PartialDiagnostic &PDiag, 1601168404Spjd QualType ObjectTy) { 1602168404Spjd if (!getLangOpts().AccessControl) 1603168404Spjd return AR_accessible; 1604168404Spjd 1605168404Spjd // There's never a path involved when checking implicit destructor access. 1606168404Spjd AccessSpecifier Access = Dtor->getAccess(); 1607168404Spjd if (Access == AS_public) 1608168404Spjd return AR_accessible; 1609168404Spjd 1610168404Spjd CXXRecordDecl *NamingClass = Dtor->getParent(); 1611168404Spjd if (ObjectTy.isNull()) ObjectTy = Context.getTypeDeclType(NamingClass); 1612168404Spjd 1613168404Spjd AccessTarget Entity(Context, AccessTarget::Member, NamingClass, 1614168404Spjd DeclAccessPair::make(Dtor, Access), 1615168404Spjd ObjectTy); 1616185029Spjd Entity.setDiag(PDiag); // TODO: avoid copy 1617185029Spjd 1618168404Spjd return CheckAccess(*this, Loc, Entity); 1619168404Spjd} 1620168404Spjd 1621168404Spjd/// Checks access to a constructor. 1622168404SpjdSema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc, 1623168404Spjd CXXConstructorDecl *Constructor, 1624168404Spjd const InitializedEntity &Entity, 1625168404Spjd AccessSpecifier Access, 1626168404Spjd bool IsCopyBindingRefToTemp) { 1627168404Spjd if (!getLangOpts().AccessControl || Access == AS_public) 1628168404Spjd return AR_accessible; 1629168404Spjd 1630168404Spjd PartialDiagnostic PD(PDiag()); 1631168404Spjd switch (Entity.getKind()) { 1632168404Spjd default: 1633168404Spjd PD = PDiag(IsCopyBindingRefToTemp 1634168404Spjd ? diag::ext_rvalue_to_reference_access_ctor 1635168404Spjd : diag::err_access_ctor); 1636168404Spjd 1637185029Spjd break; 1638185029Spjd 1639185029Spjd case InitializedEntity::EK_Base: 1640168404Spjd PD = PDiag(diag::err_access_base_ctor); 1641168404Spjd PD << Entity.isInheritedVirtualBase() 1642168404Spjd << Entity.getBaseSpecifier()->getType() << getSpecialMember(Constructor); 1643168404Spjd break; 1644168404Spjd 1645168404Spjd case InitializedEntity::EK_Member: { 1646168404Spjd const FieldDecl *Field = cast<FieldDecl>(Entity.getDecl()); 1647168404Spjd PD = PDiag(diag::err_access_field_ctor); 1648168404Spjd PD << Field->getType() << getSpecialMember(Constructor); 1649168404Spjd break; 1650168404Spjd } 1651168404Spjd 1652168404Spjd case InitializedEntity::EK_LambdaCapture: { 1653168404Spjd StringRef VarName = Entity.getCapturedVarName(); 1654168404Spjd PD = PDiag(diag::err_access_lambda_capture); 1655168404Spjd PD << VarName << Entity.getType() << getSpecialMember(Constructor); 1656185029Spjd break; 1657185029Spjd } 1658168404Spjd 1659168404Spjd } 1660168404Spjd 1661168404Spjd return CheckConstructorAccess(UseLoc, Constructor, Entity, Access, PD); 1662168404Spjd} 1663200724Sdelphij 1664168404Spjd/// Checks access to a constructor. 1665168404SpjdSema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc, 1666168404Spjd CXXConstructorDecl *Constructor, 1667168404Spjd const InitializedEntity &Entity, 1668168404Spjd AccessSpecifier Access, 1669168404Spjd const PartialDiagnostic &PD) { 1670168404Spjd if (!getLangOpts().AccessControl || 1671185029Spjd Access == AS_public) 1672168404Spjd return AR_accessible; 1673168404Spjd 1674168404Spjd CXXRecordDecl *NamingClass = Constructor->getParent(); 1675168404Spjd 1676168404Spjd // Initializing a base sub-object is an instance method call on an 1677168404Spjd // object of the derived class. Otherwise, we have an instance method 1678168404Spjd // call on an object of the constructed type. 1679168404Spjd CXXRecordDecl *ObjectClass; 1680168404Spjd if (Entity.getKind() == InitializedEntity::EK_Base) { 1681168404Spjd ObjectClass = cast<CXXConstructorDecl>(CurContext)->getParent(); 1682168404Spjd } else { 1683174049Sjb ObjectClass = NamingClass; 1684168404Spjd } 1685168404Spjd 1686168404Spjd AccessTarget AccessEntity(Context, AccessTarget::Member, NamingClass, 1687168404Spjd DeclAccessPair::make(Constructor, Access), 1688168404Spjd Context.getTypeDeclType(ObjectClass)); 1689168404Spjd AccessEntity.setDiag(PD); 1690185029Spjd 1691168404Spjd return CheckAccess(*this, UseLoc, AccessEntity); 1692168404Spjd} 1693168404Spjd 1694168404Spjd/// Checks access to an overloaded operator new or delete. 1695168404SpjdSema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc, 1696168404Spjd SourceRange PlacementRange, 1697168404Spjd CXXRecordDecl *NamingClass, 1698168404Spjd DeclAccessPair Found, 1699168404Spjd bool Diagnose) { 1700168404Spjd if (!getLangOpts().AccessControl || 1701168404Spjd !NamingClass || 1702168404Spjd Found.getAccess() == AS_public) 1703168404Spjd return AR_accessible; 1704168404Spjd 1705168404Spjd AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found, 1706168404Spjd QualType()); 1707168404Spjd if (Diagnose) 1708168404Spjd Entity.setDiag(diag::err_access) 1709168404Spjd << PlacementRange; 1710168404Spjd 1711168404Spjd return CheckAccess(*this, OpLoc, Entity); 1712168404Spjd} 1713168404Spjd 1714168404Spjd/// \brief Checks access to a member. 1715168404SpjdSema::AccessResult Sema::CheckMemberAccess(SourceLocation UseLoc, 1716168404Spjd CXXRecordDecl *NamingClass, 1717168404Spjd DeclAccessPair Found) { 1718168404Spjd if (!getLangOpts().AccessControl || 1719168404Spjd !NamingClass || 1720168404Spjd Found.getAccess() == AS_public) 1721168404Spjd return AR_accessible; 1722168404Spjd 1723168404Spjd AccessTarget Entity(Context, AccessTarget::Member, NamingClass, 1724168404Spjd Found, QualType()); 1725168404Spjd 1726168404Spjd return CheckAccess(*this, UseLoc, Entity); 1727168404Spjd} 1728168404Spjd 1729168404Spjd/// Checks access to an overloaded member operator, including 1730168404Spjd/// conversion operators. 1731168404SpjdSema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc, 1732168404Spjd Expr *ObjectExpr, 1733168404Spjd Expr *ArgExpr, 1734168404Spjd DeclAccessPair Found) { 1735168404Spjd if (!getLangOpts().AccessControl || 1736 Found.getAccess() == AS_public) 1737 return AR_accessible; 1738 1739 const RecordType *RT = ObjectExpr->getType()->castAs<RecordType>(); 1740 CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(RT->getDecl()); 1741 1742 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found, 1743 ObjectExpr->getType()); 1744 Entity.setDiag(diag::err_access) 1745 << ObjectExpr->getSourceRange() 1746 << (ArgExpr ? ArgExpr->getSourceRange() : SourceRange()); 1747 1748 return CheckAccess(*this, OpLoc, Entity); 1749} 1750 1751/// Checks access to the target of a friend declaration. 1752Sema::AccessResult Sema::CheckFriendAccess(NamedDecl *target) { 1753 assert(isa<CXXMethodDecl>(target) || 1754 (isa<FunctionTemplateDecl>(target) && 1755 isa<CXXMethodDecl>(cast<FunctionTemplateDecl>(target) 1756 ->getTemplatedDecl()))); 1757 1758 // Friendship lookup is a redeclaration lookup, so there's never an 1759 // inheritance path modifying access. 1760 AccessSpecifier access = target->getAccess(); 1761 1762 if (!getLangOpts().AccessControl || access == AS_public) 1763 return AR_accessible; 1764 1765 CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(target); 1766 if (!method) 1767 method = cast<CXXMethodDecl>( 1768 cast<FunctionTemplateDecl>(target)->getTemplatedDecl()); 1769 assert(method->getQualifier()); 1770 1771 AccessTarget entity(Context, AccessTarget::Member, 1772 cast<CXXRecordDecl>(target->getDeclContext()), 1773 DeclAccessPair::make(target, access), 1774 /*no instance context*/ QualType()); 1775 entity.setDiag(diag::err_access_friend_function) 1776 << method->getQualifierLoc().getSourceRange(); 1777 1778 // We need to bypass delayed-diagnostics because we might be called 1779 // while the ParsingDeclarator is active. 1780 EffectiveContext EC(CurContext); 1781 switch (CheckEffectiveAccess(*this, EC, target->getLocation(), entity)) { 1782 case AR_accessible: return Sema::AR_accessible; 1783 case AR_inaccessible: return Sema::AR_inaccessible; 1784 case AR_dependent: return Sema::AR_dependent; 1785 } 1786 llvm_unreachable("falling off end"); 1787} 1788 1789Sema::AccessResult Sema::CheckAddressOfMemberAccess(Expr *OvlExpr, 1790 DeclAccessPair Found) { 1791 if (!getLangOpts().AccessControl || 1792 Found.getAccess() == AS_none || 1793 Found.getAccess() == AS_public) 1794 return AR_accessible; 1795 1796 OverloadExpr *Ovl = OverloadExpr::find(OvlExpr).Expression; 1797 CXXRecordDecl *NamingClass = Ovl->getNamingClass(); 1798 1799 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found, 1800 /*no instance context*/ QualType()); 1801 Entity.setDiag(diag::err_access) 1802 << Ovl->getSourceRange(); 1803 1804 return CheckAccess(*this, Ovl->getNameLoc(), Entity); 1805} 1806 1807/// Checks access for a hierarchy conversion. 1808/// 1809/// \param ForceCheck true if this check should be performed even if access 1810/// control is disabled; some things rely on this for semantics 1811/// \param ForceUnprivileged true if this check should proceed as if the 1812/// context had no special privileges 1813Sema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc, 1814 QualType Base, 1815 QualType Derived, 1816 const CXXBasePath &Path, 1817 unsigned DiagID, 1818 bool ForceCheck, 1819 bool ForceUnprivileged) { 1820 if (!ForceCheck && !getLangOpts().AccessControl) 1821 return AR_accessible; 1822 1823 if (Path.Access == AS_public) 1824 return AR_accessible; 1825 1826 CXXRecordDecl *BaseD, *DerivedD; 1827 BaseD = cast<CXXRecordDecl>(Base->getAs<RecordType>()->getDecl()); 1828 DerivedD = cast<CXXRecordDecl>(Derived->getAs<RecordType>()->getDecl()); 1829 1830 AccessTarget Entity(Context, AccessTarget::Base, BaseD, DerivedD, 1831 Path.Access); 1832 if (DiagID) 1833 Entity.setDiag(DiagID) << Derived << Base; 1834 1835 if (ForceUnprivileged) { 1836 switch (CheckEffectiveAccess(*this, EffectiveContext(), 1837 AccessLoc, Entity)) { 1838 case ::AR_accessible: return Sema::AR_accessible; 1839 case ::AR_inaccessible: return Sema::AR_inaccessible; 1840 case ::AR_dependent: return Sema::AR_dependent; 1841 } 1842 llvm_unreachable("unexpected result from CheckEffectiveAccess"); 1843 } 1844 return CheckAccess(*this, AccessLoc, Entity); 1845} 1846 1847/// Checks access to all the declarations in the given result set. 1848void Sema::CheckLookupAccess(const LookupResult &R) { 1849 assert(getLangOpts().AccessControl 1850 && "performing access check without access control"); 1851 assert(R.getNamingClass() && "performing access check without naming class"); 1852 1853 for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { 1854 if (I.getAccess() != AS_public) { 1855 AccessTarget Entity(Context, AccessedEntity::Member, 1856 R.getNamingClass(), I.getPair(), 1857 R.getBaseObjectType()); 1858 Entity.setDiag(diag::err_access); 1859 CheckAccess(*this, R.getNameLoc(), Entity); 1860 } 1861 } 1862} 1863 1864/// Checks access to Decl from the given class. The check will take access 1865/// specifiers into account, but no member access expressions and such. 1866/// 1867/// \param Decl the declaration to check if it can be accessed 1868/// \param Ctx the class/context from which to start the search 1869/// \return true if the Decl is accessible from the Class, false otherwise. 1870bool Sema::IsSimplyAccessible(NamedDecl *Decl, DeclContext *Ctx) { 1871 if (CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(Ctx)) { 1872 if (!Decl->isCXXClassMember()) 1873 return true; 1874 1875 QualType qType = Class->getTypeForDecl()->getCanonicalTypeInternal(); 1876 AccessTarget Entity(Context, AccessedEntity::Member, Class, 1877 DeclAccessPair::make(Decl, Decl->getAccess()), 1878 qType); 1879 if (Entity.getAccess() == AS_public) 1880 return true; 1881 1882 EffectiveContext EC(CurContext); 1883 return ::IsAccessible(*this, EC, Entity) != ::AR_inaccessible; 1884 } 1885 1886 if (ObjCIvarDecl *Ivar = dyn_cast<ObjCIvarDecl>(Decl)) { 1887 // @public and @package ivars are always accessible. 1888 if (Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Public || 1889 Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Package) 1890 return true; 1891 1892 // If we are inside a class or category implementation, determine the 1893 // interface we're in. 1894 ObjCInterfaceDecl *ClassOfMethodDecl = 0; 1895 if (ObjCMethodDecl *MD = getCurMethodDecl()) 1896 ClassOfMethodDecl = MD->getClassInterface(); 1897 else if (FunctionDecl *FD = getCurFunctionDecl()) { 1898 if (ObjCImplDecl *Impl 1899 = dyn_cast<ObjCImplDecl>(FD->getLexicalDeclContext())) { 1900 if (ObjCImplementationDecl *IMPD 1901 = dyn_cast<ObjCImplementationDecl>(Impl)) 1902 ClassOfMethodDecl = IMPD->getClassInterface(); 1903 else if (ObjCCategoryImplDecl* CatImplClass 1904 = dyn_cast<ObjCCategoryImplDecl>(Impl)) 1905 ClassOfMethodDecl = CatImplClass->getClassInterface(); 1906 } 1907 } 1908 1909 // If we're not in an interface, this ivar is inaccessible. 1910 if (!ClassOfMethodDecl) 1911 return false; 1912 1913 // If we're inside the same interface that owns the ivar, we're fine. 1914 if (declaresSameEntity(ClassOfMethodDecl, Ivar->getContainingInterface())) 1915 return true; 1916 1917 // If the ivar is private, it's inaccessible. 1918 if (Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Private) 1919 return false; 1920 1921 return Ivar->getContainingInterface()->isSuperClassOf(ClassOfMethodDecl); 1922 } 1923 1924 return true; 1925} 1926