SemaAccess.cpp revision 9aa472c45d2bd81b7b52c225e8acc560d716db97
129f006be830fbbcaa0c1cf7c7399bb5080dc7f32Anders Carlsson//===---- SemaAccess.cpp - C++ Access Control -------------------*- C++ -*-===// 260d6b0d35e3c7c09554f8a4618b97a5d8d0c67a6Anders Carlsson// 360d6b0d35e3c7c09554f8a4618b97a5d8d0c67a6Anders Carlsson// The LLVM Compiler Infrastructure 460d6b0d35e3c7c09554f8a4618b97a5d8d0c67a6Anders Carlsson// 560d6b0d35e3c7c09554f8a4618b97a5d8d0c67a6Anders Carlsson// This file is distributed under the University of Illinois Open Source 660d6b0d35e3c7c09554f8a4618b97a5d8d0c67a6Anders Carlsson// License. See LICENSE.TXT for details. 760d6b0d35e3c7c09554f8a4618b97a5d8d0c67a6Anders Carlsson// 860d6b0d35e3c7c09554f8a4618b97a5d8d0c67a6Anders Carlsson//===----------------------------------------------------------------------===// 960d6b0d35e3c7c09554f8a4618b97a5d8d0c67a6Anders Carlsson// 1060d6b0d35e3c7c09554f8a4618b97a5d8d0c67a6Anders Carlsson// This file provides Sema routines for C++ access control semantics. 1160d6b0d35e3c7c09554f8a4618b97a5d8d0c67a6Anders Carlsson// 1260d6b0d35e3c7c09554f8a4618b97a5d8d0c67a6Anders Carlsson//===----------------------------------------------------------------------===// 13c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson 14c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson#include "Sema.h" 1592f883177b162928a8e632e4e3b93fafd2b26072John McCall#include "Lookup.h" 16c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson#include "clang/AST/ASTContext.h" 17a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor#include "clang/AST/CXXInheritance.h" 18a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor#include "clang/AST/DeclCXX.h" 19d60e22e601852ae1345f01514318a0951dc09f89John McCall#include "clang/AST/DeclFriend.h" 20c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall#include "clang/AST/ExprCXX.h" 21c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall 22c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlssonusing namespace clang; 23c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson 2429f006be830fbbcaa0c1cf7c7399bb5080dc7f32Anders Carlsson/// SetMemberAccessSpecifier - Set the access specifier of a member. 2529f006be830fbbcaa0c1cf7c7399bb5080dc7f32Anders Carlsson/// Returns true on error (when the previous member decl access specifier 2629f006be830fbbcaa0c1cf7c7399bb5080dc7f32Anders Carlsson/// is different from the new member decl access specifier). 271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpbool Sema::SetMemberAccessSpecifier(NamedDecl *MemberDecl, 28c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson NamedDecl *PrevMemberDecl, 29c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson AccessSpecifier LexicalAS) { 30c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson if (!PrevMemberDecl) { 31c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson // Use the lexical access specifier. 32c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson MemberDecl->setAccess(LexicalAS); 33c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson return false; 34c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson } 351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 36c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson // C++ [class.access.spec]p3: When a member is redeclared its access 37c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson // specifier must be same as its initial declaration. 38c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson if (LexicalAS != AS_none && LexicalAS != PrevMemberDecl->getAccess()) { 391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Diag(MemberDecl->getLocation(), 401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump diag::err_class_redeclared_with_different_access) 41c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson << MemberDecl << LexicalAS; 42c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson Diag(PrevMemberDecl->getLocation(), diag::note_previous_access_declaration) 43c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson << PrevMemberDecl << PrevMemberDecl->getAccess(); 4444e067bd8f923ba8e7c24b2189e06717d70015c8John McCall 4544e067bd8f923ba8e7c24b2189e06717d70015c8John McCall MemberDecl->setAccess(LexicalAS); 46c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson return true; 47c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson } 481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 49c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson MemberDecl->setAccess(PrevMemberDecl->getAccess()); 50c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson return false; 51c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson} 5229f006be830fbbcaa0c1cf7c7399bb5080dc7f32Anders Carlsson 536b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallnamespace { 546b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallstruct EffectiveContext { 5588b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall EffectiveContext() : Function(0) {} 566b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 576b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall explicit EffectiveContext(DeclContext *DC) { 586b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall if (isa<FunctionDecl>(DC)) { 59d60e22e601852ae1345f01514318a0951dc09f89John McCall Function = cast<FunctionDecl>(DC)->getCanonicalDecl(); 606b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall DC = Function->getDeclContext(); 616b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall } else 626b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall Function = 0; 6388b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall 6488b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall // C++ [class.access.nest]p1: 6588b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall // A nested class is a member and as such has the same access 6688b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall // rights as any other member. 6788b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall // C++ [class.access]p2: 6888b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall // A member of a class can also access all the names to which 6988b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall // the class has access. 7088b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall // This implies that the privileges of nesting are transitive. 7188b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall while (isa<CXXRecordDecl>(DC)) { 7288b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall CXXRecordDecl *Record = cast<CXXRecordDecl>(DC)->getCanonicalDecl(); 7388b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall Records.push_back(Record); 7488b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall DC = Record->getDeclContext(); 7588b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall } 766b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall } 776b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 7888b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall bool includesClass(const CXXRecordDecl *R) const { 7988b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall R = R->getCanonicalDecl(); 8088b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall return std::find(Records.begin(), Records.end(), R) 8188b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall != Records.end(); 826b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall } 836b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 8488b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall llvm::SmallVector<CXXRecordDecl*, 4> Records; 856b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall FunctionDecl *Function; 866b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall}; 876b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall} 88726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl 896b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallstatic CXXRecordDecl *FindDeclaringClass(NamedDecl *D) { 906b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall CXXRecordDecl *DeclaringClass = cast<CXXRecordDecl>(D->getDeclContext()); 916b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall while (DeclaringClass->isAnonymousStructOrUnion()) 926b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall DeclaringClass = cast<CXXRecordDecl>(DeclaringClass->getDeclContext()); 936b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return DeclaringClass; 946b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall} 956b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 96a742db0032d8f458fe229600d2082981a1fb1481John McCallstatic Sema::AccessResult MatchesFriend(Sema &S, 97a742db0032d8f458fe229600d2082981a1fb1481John McCall const EffectiveContext &EC, 98a742db0032d8f458fe229600d2082981a1fb1481John McCall const CXXRecordDecl *Friend) { 99a742db0032d8f458fe229600d2082981a1fb1481John McCall // FIXME: close matches becuse of dependency 100a742db0032d8f458fe229600d2082981a1fb1481John McCall if (EC.includesClass(Friend)) 101a742db0032d8f458fe229600d2082981a1fb1481John McCall return Sema::AR_accessible; 102a742db0032d8f458fe229600d2082981a1fb1481John McCall 103a742db0032d8f458fe229600d2082981a1fb1481John McCall return Sema::AR_inaccessible; 104a742db0032d8f458fe229600d2082981a1fb1481John McCall} 105a742db0032d8f458fe229600d2082981a1fb1481John McCall 106a742db0032d8f458fe229600d2082981a1fb1481John McCallstatic Sema::AccessResult MatchesFriend(Sema &S, 107a742db0032d8f458fe229600d2082981a1fb1481John McCall const EffectiveContext &EC, 108a742db0032d8f458fe229600d2082981a1fb1481John McCall FriendDecl *Friend) { 109a742db0032d8f458fe229600d2082981a1fb1481John McCall if (Type *T = Friend->getFriendType()) { 110a742db0032d8f458fe229600d2082981a1fb1481John McCall CanQualType CT = T->getCanonicalTypeUnqualified(); 111a742db0032d8f458fe229600d2082981a1fb1481John McCall if (const RecordType *RT = CT->getAs<RecordType>()) 112a742db0032d8f458fe229600d2082981a1fb1481John McCall return MatchesFriend(S, EC, cast<CXXRecordDecl>(RT->getDecl())); 113a742db0032d8f458fe229600d2082981a1fb1481John McCall 114a742db0032d8f458fe229600d2082981a1fb1481John McCall // TODO: we can fail early for a lot of type classes. 115a742db0032d8f458fe229600d2082981a1fb1481John McCall if (T->isDependentType()) 116a742db0032d8f458fe229600d2082981a1fb1481John McCall return Sema::AR_dependent; 117a742db0032d8f458fe229600d2082981a1fb1481John McCall 118a742db0032d8f458fe229600d2082981a1fb1481John McCall return Sema::AR_inaccessible; 119a742db0032d8f458fe229600d2082981a1fb1481John McCall } 120a742db0032d8f458fe229600d2082981a1fb1481John McCall 121a742db0032d8f458fe229600d2082981a1fb1481John McCall NamedDecl *D 122a742db0032d8f458fe229600d2082981a1fb1481John McCall = cast<NamedDecl>(Friend->getFriendDecl()->getCanonicalDecl()); 123a742db0032d8f458fe229600d2082981a1fb1481John McCall 124a742db0032d8f458fe229600d2082981a1fb1481John McCall // FIXME: declarations with dependent or templated scope. 125a742db0032d8f458fe229600d2082981a1fb1481John McCall 126a742db0032d8f458fe229600d2082981a1fb1481John McCall // For class templates, we want to check whether any of the records 127a742db0032d8f458fe229600d2082981a1fb1481John McCall // are possible specializations of the template. 128a742db0032d8f458fe229600d2082981a1fb1481John McCall if (isa<ClassTemplateDecl>(D)) { 129a742db0032d8f458fe229600d2082981a1fb1481John McCall for (llvm::SmallVectorImpl<CXXRecordDecl*>::const_iterator 130a742db0032d8f458fe229600d2082981a1fb1481John McCall I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { 131a742db0032d8f458fe229600d2082981a1fb1481John McCall CXXRecordDecl *Record = *I; 132a742db0032d8f458fe229600d2082981a1fb1481John McCall ClassTemplateDecl *CTD; 133a742db0032d8f458fe229600d2082981a1fb1481John McCall 134a742db0032d8f458fe229600d2082981a1fb1481John McCall // A specialization of the template... 135a742db0032d8f458fe229600d2082981a1fb1481John McCall if (isa<ClassTemplateSpecializationDecl>(Record)) { 136a742db0032d8f458fe229600d2082981a1fb1481John McCall CTD = cast<ClassTemplateSpecializationDecl>(Record) 137a742db0032d8f458fe229600d2082981a1fb1481John McCall ->getSpecializedTemplate(); 138a742db0032d8f458fe229600d2082981a1fb1481John McCall 139a742db0032d8f458fe229600d2082981a1fb1481John McCall // ... or the template pattern itself. 140a742db0032d8f458fe229600d2082981a1fb1481John McCall } else { 141a742db0032d8f458fe229600d2082981a1fb1481John McCall CTD = Record->getDescribedClassTemplate(); 142a742db0032d8f458fe229600d2082981a1fb1481John McCall } 143a742db0032d8f458fe229600d2082981a1fb1481John McCall 144a742db0032d8f458fe229600d2082981a1fb1481John McCall if (CTD && D == CTD->getCanonicalDecl()) 145a742db0032d8f458fe229600d2082981a1fb1481John McCall return Sema::AR_accessible; 146a742db0032d8f458fe229600d2082981a1fb1481John McCall } 147a742db0032d8f458fe229600d2082981a1fb1481John McCall 148a742db0032d8f458fe229600d2082981a1fb1481John McCall return Sema::AR_inaccessible; 149a742db0032d8f458fe229600d2082981a1fb1481John McCall } 150a742db0032d8f458fe229600d2082981a1fb1481John McCall 151a742db0032d8f458fe229600d2082981a1fb1481John McCall // Same thing for function templates. 152a742db0032d8f458fe229600d2082981a1fb1481John McCall if (isa<FunctionTemplateDecl>(D)) { 153a742db0032d8f458fe229600d2082981a1fb1481John McCall if (!EC.Function) return Sema::AR_inaccessible; 154a742db0032d8f458fe229600d2082981a1fb1481John McCall 155a742db0032d8f458fe229600d2082981a1fb1481John McCall FunctionTemplateDecl *FTD = EC.Function->getPrimaryTemplate(); 156a742db0032d8f458fe229600d2082981a1fb1481John McCall if (!FTD) 157a742db0032d8f458fe229600d2082981a1fb1481John McCall FTD = EC.Function->getDescribedFunctionTemplate(); 158a742db0032d8f458fe229600d2082981a1fb1481John McCall 159a742db0032d8f458fe229600d2082981a1fb1481John McCall if (FTD && D == FTD->getCanonicalDecl()) 160a742db0032d8f458fe229600d2082981a1fb1481John McCall return Sema::AR_accessible; 161a742db0032d8f458fe229600d2082981a1fb1481John McCall 162a742db0032d8f458fe229600d2082981a1fb1481John McCall return Sema::AR_inaccessible; 163a742db0032d8f458fe229600d2082981a1fb1481John McCall } 164a742db0032d8f458fe229600d2082981a1fb1481John McCall 165a742db0032d8f458fe229600d2082981a1fb1481John McCall // Friend functions. FIXME: close matches due to dependency. 166a742db0032d8f458fe229600d2082981a1fb1481John McCall // 167a742db0032d8f458fe229600d2082981a1fb1481John McCall // The decl pointers in EC have been canonicalized, so pointer 168a742db0032d8f458fe229600d2082981a1fb1481John McCall // equality is sufficient. 169a742db0032d8f458fe229600d2082981a1fb1481John McCall if (D == EC.Function) 170a742db0032d8f458fe229600d2082981a1fb1481John McCall return Sema::AR_accessible; 171a742db0032d8f458fe229600d2082981a1fb1481John McCall 172a742db0032d8f458fe229600d2082981a1fb1481John McCall if (isa<CXXRecordDecl>(D)) 173a742db0032d8f458fe229600d2082981a1fb1481John McCall return MatchesFriend(S, EC, cast<CXXRecordDecl>(D)); 174a742db0032d8f458fe229600d2082981a1fb1481John McCall 175a742db0032d8f458fe229600d2082981a1fb1481John McCall return Sema::AR_inaccessible; 176a742db0032d8f458fe229600d2082981a1fb1481John McCall} 177a742db0032d8f458fe229600d2082981a1fb1481John McCall 1786b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallstatic Sema::AccessResult GetFriendKind(Sema &S, 1796b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall const EffectiveContext &EC, 1806b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall const CXXRecordDecl *Class) { 181d60e22e601852ae1345f01514318a0951dc09f89John McCall // A class always has access to its own members. 18288b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall if (EC.includesClass(Class)) 1836b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return Sema::AR_accessible; 1846b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 18588b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall Sema::AccessResult OnFailure = Sema::AR_inaccessible; 18688b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall 187d60e22e601852ae1345f01514318a0951dc09f89John McCall // Okay, check friends. 188d60e22e601852ae1345f01514318a0951dc09f89John McCall for (CXXRecordDecl::friend_iterator I = Class->friend_begin(), 189d60e22e601852ae1345f01514318a0951dc09f89John McCall E = Class->friend_end(); I != E; ++I) { 190d60e22e601852ae1345f01514318a0951dc09f89John McCall FriendDecl *Friend = *I; 191d60e22e601852ae1345f01514318a0951dc09f89John McCall 192a742db0032d8f458fe229600d2082981a1fb1481John McCall switch (MatchesFriend(S, EC, Friend)) { 193a742db0032d8f458fe229600d2082981a1fb1481John McCall case Sema::AR_accessible: 194a742db0032d8f458fe229600d2082981a1fb1481John McCall return Sema::AR_accessible; 19588b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall 196a742db0032d8f458fe229600d2082981a1fb1481John McCall case Sema::AR_inaccessible: 197a742db0032d8f458fe229600d2082981a1fb1481John McCall break; 198d60e22e601852ae1345f01514318a0951dc09f89John McCall 199a742db0032d8f458fe229600d2082981a1fb1481John McCall case Sema::AR_dependent: 200a742db0032d8f458fe229600d2082981a1fb1481John McCall OnFailure = Sema::AR_dependent; 201a742db0032d8f458fe229600d2082981a1fb1481John McCall break; 202a742db0032d8f458fe229600d2082981a1fb1481John McCall 203a742db0032d8f458fe229600d2082981a1fb1481John McCall case Sema::AR_delayed: 204a742db0032d8f458fe229600d2082981a1fb1481John McCall llvm_unreachable("cannot get delayed answer from MatchesFriend"); 205a742db0032d8f458fe229600d2082981a1fb1481John McCall } 206d60e22e601852ae1345f01514318a0951dc09f89John McCall } 207d60e22e601852ae1345f01514318a0951dc09f89John McCall 208d60e22e601852ae1345f01514318a0951dc09f89John McCall // That's it, give up. 20988b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall return OnFailure; 2106b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall} 2116b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 2126b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// Finds the best path from the naming class to the declaring class, 2136b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// taking friend declarations into account. 2146b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// 2157aceaf8cee77c98478e8934dc283910292711a7eJohn McCall/// \param FinalAccess the access of the "final step", or AS_none if 2167aceaf8cee77c98478e8934dc283910292711a7eJohn McCall/// there is no final step. 2176b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// \return null if friendship is dependent 2186b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallstatic CXXBasePath *FindBestPath(Sema &S, 2196b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall const EffectiveContext &EC, 2206b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall CXXRecordDecl *Derived, 2216b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall CXXRecordDecl *Base, 2227aceaf8cee77c98478e8934dc283910292711a7eJohn McCall AccessSpecifier FinalAccess, 2236b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall CXXBasePaths &Paths) { 2246b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // Derive the paths to the desired base. 2256b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall bool isDerived = Derived->isDerivedFrom(Base, Paths); 2266b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall assert(isDerived && "derived class not actually derived from base"); 2276b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall (void) isDerived; 2286b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 2296b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall CXXBasePath *BestPath = 0; 2306b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 2317aceaf8cee77c98478e8934dc283910292711a7eJohn McCall assert(FinalAccess != AS_none && "forbidden access after declaring class"); 2327aceaf8cee77c98478e8934dc283910292711a7eJohn McCall 2336b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // Derive the friend-modified access along each path. 2346b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall for (CXXBasePaths::paths_iterator PI = Paths.begin(), PE = Paths.end(); 2356b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall PI != PE; ++PI) { 2366b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 2376b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // Walk through the path backwards. 2387aceaf8cee77c98478e8934dc283910292711a7eJohn McCall AccessSpecifier PathAccess = FinalAccess; 2396b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall CXXBasePath::iterator I = PI->end(), E = PI->begin(); 2406b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall while (I != E) { 2416b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall --I; 2426b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 2437aceaf8cee77c98478e8934dc283910292711a7eJohn McCall assert(PathAccess != AS_none); 2447aceaf8cee77c98478e8934dc283910292711a7eJohn McCall 2457aceaf8cee77c98478e8934dc283910292711a7eJohn McCall // If the declaration is a private member of a base class, there 2467aceaf8cee77c98478e8934dc283910292711a7eJohn McCall // is no level of friendship in derived classes that can make it 2477aceaf8cee77c98478e8934dc283910292711a7eJohn McCall // accessible. 2487aceaf8cee77c98478e8934dc283910292711a7eJohn McCall if (PathAccess == AS_private) { 2497aceaf8cee77c98478e8934dc283910292711a7eJohn McCall PathAccess = AS_none; 2507aceaf8cee77c98478e8934dc283910292711a7eJohn McCall break; 2517aceaf8cee77c98478e8934dc283910292711a7eJohn McCall } 2527aceaf8cee77c98478e8934dc283910292711a7eJohn McCall 2536b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall AccessSpecifier BaseAccess = I->Base->getAccessSpecifier(); 2546b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall if (BaseAccess != AS_public) { 2556b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall switch (GetFriendKind(S, EC, I->Class)) { 2567aceaf8cee77c98478e8934dc283910292711a7eJohn McCall case Sema::AR_inaccessible: 2577aceaf8cee77c98478e8934dc283910292711a7eJohn McCall PathAccess = CXXRecordDecl::MergeAccess(BaseAccess, PathAccess); 2587aceaf8cee77c98478e8934dc283910292711a7eJohn McCall break; 2597aceaf8cee77c98478e8934dc283910292711a7eJohn McCall case Sema::AR_accessible: 2607aceaf8cee77c98478e8934dc283910292711a7eJohn McCall PathAccess = AS_public; 2617aceaf8cee77c98478e8934dc283910292711a7eJohn McCall break; 2627aceaf8cee77c98478e8934dc283910292711a7eJohn McCall case Sema::AR_dependent: 2637aceaf8cee77c98478e8934dc283910292711a7eJohn McCall return 0; 2646b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall case Sema::AR_delayed: 2656b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall llvm_unreachable("friend resolution is never delayed"); break; 2666b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall } 267c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson } 268c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson } 269726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl 2706b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // Note that we modify the path's Access field to the 2716b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // friend-modified access. 2726b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall if (BestPath == 0 || PathAccess < BestPath->Access) { 2736b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall BestPath = &*PI; 2746b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall BestPath->Access = PathAccess; 275c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson } 276c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson } 277c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson 2786b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return BestPath; 279726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl} 280726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl 2816b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// Diagnose the path which caused the given declaration or base class 2826b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// to become inaccessible. 2836b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallstatic void DiagnoseAccessPath(Sema &S, 2846b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall const EffectiveContext &EC, 2856b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall CXXRecordDecl *NamingClass, 2866b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall CXXRecordDecl *DeclaringClass, 2876b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall NamedDecl *D, AccessSpecifier Access) { 2886b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // Easy case: the decl's natural access determined its path access. 2896b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // We have to check against AS_private here in case Access is AS_none, 2906b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // indicating a non-public member of a private base class. 2916b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // 2926b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // DependentFriend should be impossible here. 2936b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall if (D && (Access == D->getAccess() || D->getAccess() == AS_private)) { 2946b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall switch (GetFriendKind(S, EC, DeclaringClass)) { 2956b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall case Sema::AR_inaccessible: { 2966b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall S.Diag(D->getLocation(), diag::note_access_natural) 2976b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall << (unsigned) (Access == AS_protected) 2986b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall << /*FIXME: not implicitly*/ 0; 2996b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return; 3006b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall } 301726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl 3026b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall case Sema::AR_accessible: break; 303726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl 3046b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall case Sema::AR_dependent: 3056b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall case Sema::AR_delayed: 3066b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall llvm_unreachable("dependent/delayed not allowed"); 3076b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return; 3086b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall } 3096b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall } 310c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson 3116b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall CXXBasePaths Paths; 3127aceaf8cee77c98478e8934dc283910292711a7eJohn McCall CXXBasePath &Path = *FindBestPath(S, EC, NamingClass, DeclaringClass, 3137aceaf8cee77c98478e8934dc283910292711a7eJohn McCall AS_public, Paths); 314726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl 3156b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall CXXBasePath::iterator I = Path.end(), E = Path.begin(); 3166b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall while (I != E) { 3176b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall --I; 318c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson 3196b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall const CXXBaseSpecifier *BS = I->Base; 3206b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall AccessSpecifier BaseAccess = BS->getAccessSpecifier(); 3216b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 3226b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // If this is public inheritance, or the derived class is a friend, 3236b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // skip this step. 3246b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall if (BaseAccess == AS_public) 3256b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall continue; 3266b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 3276b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall switch (GetFriendKind(S, EC, I->Class)) { 3286b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall case Sema::AR_accessible: continue; 3296b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall case Sema::AR_inaccessible: break; 3306b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 3316b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall case Sema::AR_dependent: 3326b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall case Sema::AR_delayed: 3336b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall llvm_unreachable("dependent friendship, should not be diagnosing"); 3346b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall } 3356b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 3366b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // Check whether this base specifier is the tighest point 3376b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // constraining access. We have to check against AS_private for 3386b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // the same reasons as above. 3396b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall if (BaseAccess == AS_private || BaseAccess >= Access) { 3406b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 3416b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // We're constrained by inheritance, but we want to say 3426b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // "declared private here" if we're diagnosing a hierarchy 3436b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // conversion and this is the final step. 3446b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall unsigned diagnostic; 3456b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall if (D) diagnostic = diag::note_access_constrained_by_path; 3466b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall else if (I + 1 == Path.end()) diagnostic = diag::note_access_natural; 3476b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall else diagnostic = diag::note_access_constrained_by_path; 3486b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 3496b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall S.Diag(BS->getSourceRange().getBegin(), diagnostic) 3506b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall << BS->getSourceRange() 3516b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall << (BaseAccess == AS_protected) 3526b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall << (BS->getAccessSpecifierAsWritten() == AS_none); 3536b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return; 3546b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall } 355c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson } 356726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl 3576b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall llvm_unreachable("access not apparently constrained by path"); 35829f006be830fbbcaa0c1cf7c7399bb5080dc7f32Anders Carlsson} 35992f883177b162928a8e632e4e3b93fafd2b26072John McCall 3606b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// Diagnose an inaccessible class member. 3616b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallstatic void DiagnoseInaccessibleMember(Sema &S, SourceLocation Loc, 3626b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall const EffectiveContext &EC, 3636b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall CXXRecordDecl *NamingClass, 3646b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall AccessSpecifier Access, 3656b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall const Sema::AccessedEntity &Entity) { 3666b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall NamedDecl *D = Entity.getTargetDecl(); 3676b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall CXXRecordDecl *DeclaringClass = FindDeclaringClass(D); 3686b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 36958e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall S.Diag(Loc, Entity.getDiag()) 37058e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall << (Access == AS_protected) 37158e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall << D->getDeclName() 37258e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall << S.Context.getTypeDeclType(NamingClass) 37358e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall << S.Context.getTypeDeclType(DeclaringClass); 3746b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall DiagnoseAccessPath(S, EC, NamingClass, DeclaringClass, D, Access); 3756b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall} 37692f883177b162928a8e632e4e3b93fafd2b26072John McCall 3776b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// Diagnose an inaccessible hierarchy conversion. 3786b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallstatic void DiagnoseInaccessibleBase(Sema &S, SourceLocation Loc, 3796b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall const EffectiveContext &EC, 3806b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall AccessSpecifier Access, 38158e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall const Sema::AccessedEntity &Entity) { 38258e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall S.Diag(Loc, Entity.getDiag()) 38358e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall << (Access == AS_protected) 38458e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall << DeclarationName() 38558e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall << S.Context.getTypeDeclType(Entity.getDerivedClass()) 38658e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall << S.Context.getTypeDeclType(Entity.getBaseClass()); 3876b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall DiagnoseAccessPath(S, EC, Entity.getDerivedClass(), 3886b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall Entity.getBaseClass(), 0, Access); 38992f883177b162928a8e632e4e3b93fafd2b26072John McCall} 39092f883177b162928a8e632e4e3b93fafd2b26072John McCall 39158e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCallstatic void DiagnoseBadAccess(Sema &S, SourceLocation Loc, 3926b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall const EffectiveContext &EC, 3936b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall CXXRecordDecl *NamingClass, 3946b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall AccessSpecifier Access, 39558e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall const Sema::AccessedEntity &Entity) { 3966b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall if (Entity.isMemberAccess()) 3976b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall DiagnoseInaccessibleMember(S, Loc, EC, NamingClass, Access, Entity); 3986b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall else 39958e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall DiagnoseInaccessibleBase(S, Loc, EC, Access, Entity); 4006b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall} 40192f883177b162928a8e632e4e3b93fafd2b26072John McCall 40292f883177b162928a8e632e4e3b93fafd2b26072John McCall 4036b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// Try to elevate access using friend declarations. This is 4046b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// potentially quite expensive. 4056b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallstatic void TryElevateAccess(Sema &S, 4066b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall const EffectiveContext &EC, 4076b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall const Sema::AccessedEntity &Entity, 4086b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall AccessSpecifier &Access) { 4096b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall CXXRecordDecl *DeclaringClass; 4106b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall if (Entity.isMemberAccess()) { 4116b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall DeclaringClass = FindDeclaringClass(Entity.getTargetDecl()); 4126b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall } else { 4136b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall DeclaringClass = Entity.getBaseClass(); 4142f514480c448708ec382a684cf5e035d3a827ec8John McCall } 4156b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall CXXRecordDecl *NamingClass = Entity.getNamingClass(); 4166b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 4176b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // Adjust the declaration of the referred entity. 4187aceaf8cee77c98478e8934dc283910292711a7eJohn McCall AccessSpecifier DeclAccess = AS_public; 4196b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall if (Entity.isMemberAccess()) { 4206b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall NamedDecl *Target = Entity.getTargetDecl(); 4216b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 4226b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall DeclAccess = Target->getAccess(); 4236b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall if (DeclAccess != AS_public) { 4246b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall switch (GetFriendKind(S, EC, DeclaringClass)) { 4256b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall case Sema::AR_accessible: DeclAccess = AS_public; break; 4266b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall case Sema::AR_inaccessible: break; 4276b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall case Sema::AR_dependent: /* FIXME: delay dependent friendship */ return; 4286b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall case Sema::AR_delayed: llvm_unreachable("friend status is never delayed"); 4296b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall } 4306b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall } 4312f514480c448708ec382a684cf5e035d3a827ec8John McCall 4326b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall if (DeclaringClass == NamingClass) { 4336b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall Access = DeclAccess; 4346b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return; 4356b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall } 4366b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall } 4372f514480c448708ec382a684cf5e035d3a827ec8John McCall 4386b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall assert(DeclaringClass != NamingClass); 4396b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 4406b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // Append the declaration's access if applicable. 4416b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall CXXBasePaths Paths; 4426b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall CXXBasePath *Path = FindBestPath(S, EC, Entity.getNamingClass(), 4437aceaf8cee77c98478e8934dc283910292711a7eJohn McCall DeclaringClass, DeclAccess, Paths); 4446b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall if (!Path) { 4456b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // FIXME: delay dependent friendship 4466b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return; 44792f883177b162928a8e632e4e3b93fafd2b26072John McCall } 44892f883177b162928a8e632e4e3b93fafd2b26072John McCall 4497aceaf8cee77c98478e8934dc283910292711a7eJohn McCall // Grab the access along the best path (note that this includes the 4507aceaf8cee77c98478e8934dc283910292711a7eJohn McCall // final-step access). 4516b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall AccessSpecifier NewAccess = Path->Access; 4526b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall assert(NewAccess <= Access && "access along best path worse than direct?"); 4536b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall Access = NewAccess; 4546b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall} 4556b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 4566b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// Checks access to an entity from the given effective context. 4576b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallstatic Sema::AccessResult CheckEffectiveAccess(Sema &S, 4586b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall const EffectiveContext &EC, 4596b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall SourceLocation Loc, 46058e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall Sema::AccessedEntity const &Entity) { 4616b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall AccessSpecifier Access = Entity.getAccess(); 46288b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall assert(Access != AS_public && "called for public access!"); 4636b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 46488b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall // Find a non-anonymous naming class. For records with access, 46588b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall // there should always be one of these. 4666b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall CXXRecordDecl *NamingClass = Entity.getNamingClass(); 46792f883177b162928a8e632e4e3b93fafd2b26072John McCall while (NamingClass->isAnonymousStructOrUnion()) 46858e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall NamingClass = cast<CXXRecordDecl>(NamingClass->getParent()); 46992f883177b162928a8e632e4e3b93fafd2b26072John McCall 47088b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall // White-list accesses from classes with privileges equivalent to the 47188b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall // naming class --- but only if the access path isn't forbidden 47288b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall // (i.e. an access of a private member from a subclass). 47388b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall if (Access != AS_none && EC.includesClass(NamingClass)) 4746b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return Sema::AR_accessible; 47588b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall 47688b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall // Try to elevate access. 47788b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall // FIXME: delay if elevation was dependent? 47888b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall // TODO: on some code, it might be better to do the protected check 47988b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall // without trying to elevate first. 48088b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall TryElevateAccess(S, EC, Entity, Access); 48188b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall if (Access == AS_public) return Sema::AR_accessible; 48292f883177b162928a8e632e4e3b93fafd2b26072John McCall 48392f883177b162928a8e632e4e3b93fafd2b26072John McCall // Protected access. 48492f883177b162928a8e632e4e3b93fafd2b26072John McCall if (Access == AS_protected) { 48592f883177b162928a8e632e4e3b93fafd2b26072John McCall // FIXME: implement [class.protected]p1 48688b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall for (llvm::SmallVectorImpl<CXXRecordDecl*>::const_iterator 48788b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) 48888b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall if ((*I)->isDerivedFrom(NamingClass)) 48988b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall return Sema::AR_accessible; 49092f883177b162928a8e632e4e3b93fafd2b26072John McCall 49188b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall // FIXME: delay if we can't decide class derivation yet. 49292f883177b162928a8e632e4e3b93fafd2b26072John McCall } 49392f883177b162928a8e632e4e3b93fafd2b26072John McCall 4946b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // Okay, that's it, reject it. 49558e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall if (!Entity.isQuiet()) 49658e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall DiagnoseBadAccess(S, Loc, EC, NamingClass, Access, Entity); 4976b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return Sema::AR_inaccessible; 4986b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall} 49992f883177b162928a8e632e4e3b93fafd2b26072John McCall 5006b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallstatic Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc, 50158e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall const Sema::AccessedEntity &Entity) { 5026b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // If the access path is public, it's accessible everywhere. 5036b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall if (Entity.getAccess() == AS_public) 5046b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return Sema::AR_accessible; 50592f883177b162928a8e632e4e3b93fafd2b26072John McCall 5066b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // If we're currently parsing a top-level declaration, delay 5076b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // diagnostics. This is the only case where parsing a declaration 5086b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // can actually change our effective context for the purposes of 5096b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // access control. 5106b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall if (S.CurContext->isFileContext() && S.ParsingDeclDepth) { 5116b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall S.DelayedDiagnostics.push_back( 5126b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall Sema::DelayedDiagnostic::makeAccess(Loc, Entity)); 5136b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return Sema::AR_delayed; 51492f883177b162928a8e632e4e3b93fafd2b26072John McCall } 51592f883177b162928a8e632e4e3b93fafd2b26072John McCall 5166b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return CheckEffectiveAccess(S, EffectiveContext(S.CurContext), 51758e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall Loc, Entity); 51892f883177b162928a8e632e4e3b93fafd2b26072John McCall} 51992f883177b162928a8e632e4e3b93fafd2b26072John McCall 5202f514480c448708ec382a684cf5e035d3a827ec8John McCallvoid Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *Ctx) { 5212f514480c448708ec382a684cf5e035d3a827ec8John McCall // Pretend we did this from the context of the newly-parsed 5222f514480c448708ec382a684cf5e035d3a827ec8John McCall // declaration. 5236b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall EffectiveContext EC(Ctx->getDeclContext()); 5242f514480c448708ec382a684cf5e035d3a827ec8John McCall 52558e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall if (CheckEffectiveAccess(*this, EC, DD.Loc, DD.getAccessData())) 5262f514480c448708ec382a684cf5e035d3a827ec8John McCall DD.Triggered = true; 5272f514480c448708ec382a684cf5e035d3a827ec8John McCall} 5282f514480c448708ec382a684cf5e035d3a827ec8John McCall 5296b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallSema::AccessResult Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E, 5309aa472c45d2bd81b7b52c225e8acc560d716db97John McCall DeclAccessPair Found) { 53158e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall if (!getLangOptions().AccessControl || 53258e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall !E->getNamingClass() || 5339aa472c45d2bd81b7b52c225e8acc560d716db97John McCall Found.getAccess() == AS_public) 5346b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return AR_accessible; 535c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall 5369aa472c45d2bd81b7b52c225e8acc560d716db97John McCall AccessedEntity Entity(AccessedEntity::Member, E->getNamingClass(), Found); 53758e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall Entity.setDiag(diag::err_access) << E->getSourceRange(); 53858e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall 53958e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall return CheckAccess(*this, E->getNameLoc(), Entity); 540c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall} 541c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall 542c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall/// Perform access-control checking on a previously-unresolved member 543c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall/// access which has now been resolved to a member. 5446b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallSema::AccessResult Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E, 5459aa472c45d2bd81b7b52c225e8acc560d716db97John McCall DeclAccessPair Found) { 54658e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall if (!getLangOptions().AccessControl || 5479aa472c45d2bd81b7b52c225e8acc560d716db97John McCall Found.getAccess() == AS_public) 5486b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return AR_accessible; 549c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall 5509aa472c45d2bd81b7b52c225e8acc560d716db97John McCall AccessedEntity Entity(AccessedEntity::Member, E->getNamingClass(), Found); 55158e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall Entity.setDiag(diag::err_access) << E->getSourceRange(); 55258e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall 55358e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall return CheckAccess(*this, E->getMemberLoc(), Entity); 554c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall} 555c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall 5566b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallSema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc, 55758e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall CXXDestructorDecl *Dtor, 55858e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall const PartialDiagnostic &PDiag) { 5594f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall if (!getLangOptions().AccessControl) 5606b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return AR_accessible; 5614f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall 56258e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall // There's never a path involved when checking implicit destructor access. 5634f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall AccessSpecifier Access = Dtor->getAccess(); 5644f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall if (Access == AS_public) 5656b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return AR_accessible; 5664f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall 56758e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall CXXRecordDecl *NamingClass = Dtor->getParent(); 5689aa472c45d2bd81b7b52c225e8acc560d716db97John McCall AccessedEntity Entity(AccessedEntity::Member, NamingClass, 5699aa472c45d2bd81b7b52c225e8acc560d716db97John McCall DeclAccessPair::make(Dtor, Access)); 57058e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall Entity.setDiag(PDiag); // TODO: avoid copy 57158e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall 57258e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall return CheckAccess(*this, Loc, Entity); 5734f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall} 5744f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall 575b13b737a2450167c82e148590e8019b839ce6b98John McCall/// Checks access to a constructor. 5766b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallSema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc, 577b13b737a2450167c82e148590e8019b839ce6b98John McCall CXXConstructorDecl *Constructor, 578b13b737a2450167c82e148590e8019b839ce6b98John McCall AccessSpecifier Access) { 57958e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall if (!getLangOptions().AccessControl || 58058e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall Access == AS_public) 5816b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return AR_accessible; 582b13b737a2450167c82e148590e8019b839ce6b98John McCall 5836b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall CXXRecordDecl *NamingClass = Constructor->getParent(); 5849aa472c45d2bd81b7b52c225e8acc560d716db97John McCall AccessedEntity Entity(AccessedEntity::Member, NamingClass, 5859aa472c45d2bd81b7b52c225e8acc560d716db97John McCall DeclAccessPair::make(Constructor, Access)); 58658e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall Entity.setDiag(diag::err_access_ctor); 58758e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall 58858e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall return CheckAccess(*this, UseLoc, Entity); 589b13b737a2450167c82e148590e8019b839ce6b98John McCall} 590b13b737a2450167c82e148590e8019b839ce6b98John McCall 591b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall/// Checks direct (i.e. non-inherited) access to an arbitrary class 592b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall/// member. 593b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCallSema::AccessResult Sema::CheckDirectMemberAccess(SourceLocation UseLoc, 594b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall NamedDecl *Target, 595b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall const PartialDiagnostic &Diag) { 596b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall AccessSpecifier Access = Target->getAccess(); 597b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall if (!getLangOptions().AccessControl || 598b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall Access == AS_public) 599b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall return AR_accessible; 600b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall 601b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(Target->getDeclContext()); 6029aa472c45d2bd81b7b52c225e8acc560d716db97John McCall AccessedEntity Entity(AccessedEntity::Member, NamingClass, 6039aa472c45d2bd81b7b52c225e8acc560d716db97John McCall DeclAccessPair::make(Target, Access)); 604b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall Entity.setDiag(Diag); 605b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall return CheckAccess(*this, UseLoc, Entity); 606b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall} 607b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall 608b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall 60990c8c57bcd84083df85f76aac2aa62acb85eb077John McCall/// Checks access to an overloaded operator new or delete. 61090c8c57bcd84083df85f76aac2aa62acb85eb077John McCallSema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc, 61190c8c57bcd84083df85f76aac2aa62acb85eb077John McCall SourceRange PlacementRange, 61290c8c57bcd84083df85f76aac2aa62acb85eb077John McCall CXXRecordDecl *NamingClass, 6139aa472c45d2bd81b7b52c225e8acc560d716db97John McCall DeclAccessPair Found) { 61490c8c57bcd84083df85f76aac2aa62acb85eb077John McCall if (!getLangOptions().AccessControl || 61590c8c57bcd84083df85f76aac2aa62acb85eb077John McCall !NamingClass || 6169aa472c45d2bd81b7b52c225e8acc560d716db97John McCall Found.getAccess() == AS_public) 61790c8c57bcd84083df85f76aac2aa62acb85eb077John McCall return AR_accessible; 61890c8c57bcd84083df85f76aac2aa62acb85eb077John McCall 6199aa472c45d2bd81b7b52c225e8acc560d716db97John McCall AccessedEntity Entity(AccessedEntity::Member, NamingClass, Found); 62090c8c57bcd84083df85f76aac2aa62acb85eb077John McCall Entity.setDiag(diag::err_access) 62190c8c57bcd84083df85f76aac2aa62acb85eb077John McCall << PlacementRange; 62290c8c57bcd84083df85f76aac2aa62acb85eb077John McCall 62390c8c57bcd84083df85f76aac2aa62acb85eb077John McCall return CheckAccess(*this, OpLoc, Entity); 62490c8c57bcd84083df85f76aac2aa62acb85eb077John McCall} 62590c8c57bcd84083df85f76aac2aa62acb85eb077John McCall 626b13b737a2450167c82e148590e8019b839ce6b98John McCall/// Checks access to an overloaded member operator, including 627b13b737a2450167c82e148590e8019b839ce6b98John McCall/// conversion operators. 6286b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallSema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc, 6296b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall Expr *ObjectExpr, 63058e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall Expr *ArgExpr, 6319aa472c45d2bd81b7b52c225e8acc560d716db97John McCall DeclAccessPair Found) { 63258e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall if (!getLangOptions().AccessControl || 6339aa472c45d2bd81b7b52c225e8acc560d716db97John McCall Found.getAccess() == AS_public) 6346b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return AR_accessible; 6355357b615364c17ea024c757354c58ae2a520d216John McCall 6365357b615364c17ea024c757354c58ae2a520d216John McCall const RecordType *RT = ObjectExpr->getType()->getAs<RecordType>(); 6375357b615364c17ea024c757354c58ae2a520d216John McCall assert(RT && "found member operator but object expr not of record type"); 6385357b615364c17ea024c757354c58ae2a520d216John McCall CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(RT->getDecl()); 6395357b615364c17ea024c757354c58ae2a520d216John McCall 6409aa472c45d2bd81b7b52c225e8acc560d716db97John McCall AccessedEntity Entity(AccessedEntity::Member, NamingClass, Found); 64158e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall Entity.setDiag(diag::err_access) 64258e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall << ObjectExpr->getSourceRange() 64358e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall << (ArgExpr ? ArgExpr->getSourceRange() : SourceRange()); 64458e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall 64558e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall return CheckAccess(*this, OpLoc, Entity); 6466b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall} 6475357b615364c17ea024c757354c58ae2a520d216John McCall 6486b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// Checks access for a hierarchy conversion. 6496b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// 6506b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// \param IsBaseToDerived whether this is a base-to-derived conversion (true) 6516b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// or a derived-to-base conversion (false) 6526b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// \param ForceCheck true if this check should be performed even if access 6536b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// control is disabled; some things rely on this for semantics 6546b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// \param ForceUnprivileged true if this check should proceed as if the 6556b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// context had no special privileges 6566b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// \param ADK controls the kind of diagnostics that are used 6576b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallSema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc, 6586b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall QualType Base, 6596b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall QualType Derived, 6606b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall const CXXBasePath &Path, 66158e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall unsigned DiagID, 6626b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall bool ForceCheck, 66358e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall bool ForceUnprivileged) { 6646b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall if (!ForceCheck && !getLangOptions().AccessControl) 6656b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return AR_accessible; 6666b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 6676b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall if (Path.Access == AS_public) 6686b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return AR_accessible; 6696b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 6706b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall CXXRecordDecl *BaseD, *DerivedD; 6716b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall BaseD = cast<CXXRecordDecl>(Base->getAs<RecordType>()->getDecl()); 6726b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall DerivedD = cast<CXXRecordDecl>(Derived->getAs<RecordType>()->getDecl()); 67358e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall 67458e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall AccessedEntity Entity(AccessedEntity::Base, BaseD, DerivedD, Path.Access); 67558e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall if (DiagID) 67658e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall Entity.setDiag(DiagID) << Derived << Base; 6776b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 6786b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall if (ForceUnprivileged) 67958e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall return CheckEffectiveAccess(*this, EffectiveContext(), AccessLoc, Entity); 68058e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall return CheckAccess(*this, AccessLoc, Entity); 6815357b615364c17ea024c757354c58ae2a520d216John McCall} 6825357b615364c17ea024c757354c58ae2a520d216John McCall 68392f883177b162928a8e632e4e3b93fafd2b26072John McCall/// Checks access to all the declarations in the given result set. 6846b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallvoid Sema::CheckLookupAccess(const LookupResult &R) { 6856b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall assert(getLangOptions().AccessControl 6866b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall && "performing access check without access control"); 6876b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall assert(R.getNamingClass() && "performing access check without naming class"); 6886b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 68958e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { 69058e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall if (I.getAccess() != AS_public) { 69158e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall AccessedEntity Entity(AccessedEntity::Member, 6929aa472c45d2bd81b7b52c225e8acc560d716db97John McCall R.getNamingClass(), 6939aa472c45d2bd81b7b52c225e8acc560d716db97John McCall I.getPair()); 69458e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall Entity.setDiag(diag::err_access); 69558e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall 69658e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall CheckAccess(*this, R.getNameLoc(), Entity); 69758e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall } 69858e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall } 69992f883177b162928a8e632e4e3b93fafd2b26072John McCall} 700