SemaAccess.cpp revision 57d12fd4a2bc739c4a4d62a364b7f08cd483c59e
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" 159a68a67c6ae4982001815cc04f69b8781058263aAnders Carlsson#include "SemaInit.h" 1692f883177b162928a8e632e4e3b93fafd2b26072John McCall#include "Lookup.h" 17c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson#include "clang/AST/ASTContext.h" 18a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor#include "clang/AST/CXXInheritance.h" 19a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor#include "clang/AST/DeclCXX.h" 20d60e22e601852ae1345f01514318a0951dc09f89John McCall#include "clang/AST/DeclFriend.h" 210c01d18094100db92d38daa923c95661512db203John McCall#include "clang/AST/DependentDiagnostic.h" 22c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall#include "clang/AST/ExprCXX.h" 23c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall 24c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlssonusing namespace clang; 25c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson 26161755a09898c95d21bfff33707da9ca41cd53c5John McCall/// A copy of Sema's enum without AR_delayed. 27161755a09898c95d21bfff33707da9ca41cd53c5John McCallenum AccessResult { 28161755a09898c95d21bfff33707da9ca41cd53c5John McCall AR_accessible, 29161755a09898c95d21bfff33707da9ca41cd53c5John McCall AR_inaccessible, 30161755a09898c95d21bfff33707da9ca41cd53c5John McCall AR_dependent 31161755a09898c95d21bfff33707da9ca41cd53c5John McCall}; 32161755a09898c95d21bfff33707da9ca41cd53c5John McCall 3329f006be830fbbcaa0c1cf7c7399bb5080dc7f32Anders Carlsson/// SetMemberAccessSpecifier - Set the access specifier of a member. 3429f006be830fbbcaa0c1cf7c7399bb5080dc7f32Anders Carlsson/// Returns true on error (when the previous member decl access specifier 3529f006be830fbbcaa0c1cf7c7399bb5080dc7f32Anders Carlsson/// is different from the new member decl access specifier). 361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpbool Sema::SetMemberAccessSpecifier(NamedDecl *MemberDecl, 37c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson NamedDecl *PrevMemberDecl, 38c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson AccessSpecifier LexicalAS) { 39c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson if (!PrevMemberDecl) { 40c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson // Use the lexical access specifier. 41c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson MemberDecl->setAccess(LexicalAS); 42c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson return false; 43c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson } 441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 45c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson // C++ [class.access.spec]p3: When a member is redeclared its access 46c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson // specifier must be same as its initial declaration. 47c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson if (LexicalAS != AS_none && LexicalAS != PrevMemberDecl->getAccess()) { 481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Diag(MemberDecl->getLocation(), 491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump diag::err_class_redeclared_with_different_access) 50c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson << MemberDecl << LexicalAS; 51c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson Diag(PrevMemberDecl->getLocation(), diag::note_previous_access_declaration) 52c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson << PrevMemberDecl << PrevMemberDecl->getAccess(); 5344e067bd8f923ba8e7c24b2189e06717d70015c8John McCall 5444e067bd8f923ba8e7c24b2189e06717d70015c8John McCall MemberDecl->setAccess(LexicalAS); 55c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson return true; 56c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson } 571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 58c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson MemberDecl->setAccess(PrevMemberDecl->getAccess()); 59c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson return false; 60c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson} 6129f006be830fbbcaa0c1cf7c7399bb5080dc7f32Anders Carlsson 62161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic CXXRecordDecl *FindDeclaringClass(NamedDecl *D) { 63161755a09898c95d21bfff33707da9ca41cd53c5John McCall DeclContext *DC = D->getDeclContext(); 64161755a09898c95d21bfff33707da9ca41cd53c5John McCall 65161755a09898c95d21bfff33707da9ca41cd53c5John McCall // This can only happen at top: enum decls only "publish" their 66161755a09898c95d21bfff33707da9ca41cd53c5John McCall // immediate members. 67161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (isa<EnumDecl>(DC)) 68161755a09898c95d21bfff33707da9ca41cd53c5John McCall DC = cast<EnumDecl>(DC)->getDeclContext(); 69161755a09898c95d21bfff33707da9ca41cd53c5John McCall 70161755a09898c95d21bfff33707da9ca41cd53c5John McCall CXXRecordDecl *DeclaringClass = cast<CXXRecordDecl>(DC); 71161755a09898c95d21bfff33707da9ca41cd53c5John McCall while (DeclaringClass->isAnonymousStructOrUnion()) 72161755a09898c95d21bfff33707da9ca41cd53c5John McCall DeclaringClass = cast<CXXRecordDecl>(DeclaringClass->getDeclContext()); 73161755a09898c95d21bfff33707da9ca41cd53c5John McCall return DeclaringClass; 74161755a09898c95d21bfff33707da9ca41cd53c5John McCall} 75161755a09898c95d21bfff33707da9ca41cd53c5John McCall 766b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallnamespace { 776b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallstruct EffectiveContext { 782cc2675d426af23476a9722c08c1b6c5266bd653John McCall EffectiveContext() : Inner(0), Dependent(false) {} 796b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 807ad650f88ecbbe659f10f9f6b34a1f29ea9cf8f9John McCall explicit EffectiveContext(DeclContext *DC) 817ad650f88ecbbe659f10f9f6b34a1f29ea9cf8f9John McCall : Inner(DC), 827ad650f88ecbbe659f10f9f6b34a1f29ea9cf8f9John McCall Dependent(DC->isDependentContext()) { 830c01d18094100db92d38daa923c95661512db203John McCall 8488b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall // C++ [class.access.nest]p1: 8588b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall // A nested class is a member and as such has the same access 8688b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall // rights as any other member. 8788b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall // C++ [class.access]p2: 8888b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall // A member of a class can also access all the names to which 892cc2675d426af23476a9722c08c1b6c5266bd653John McCall // the class has access. A local class of a member function 902cc2675d426af23476a9722c08c1b6c5266bd653John McCall // may access the same names that the member function itself 912cc2675d426af23476a9722c08c1b6c5266bd653John McCall // may access. 922cc2675d426af23476a9722c08c1b6c5266bd653John McCall // This almost implies that the privileges of nesting are transitive. 932cc2675d426af23476a9722c08c1b6c5266bd653John McCall // Technically it says nothing about the local classes of non-member 942cc2675d426af23476a9722c08c1b6c5266bd653John McCall // functions (which can gain privileges through friendship), but we 952cc2675d426af23476a9722c08c1b6c5266bd653John McCall // take that as an oversight. 962cc2675d426af23476a9722c08c1b6c5266bd653John McCall while (true) { 972cc2675d426af23476a9722c08c1b6c5266bd653John McCall if (isa<CXXRecordDecl>(DC)) { 982cc2675d426af23476a9722c08c1b6c5266bd653John McCall CXXRecordDecl *Record = cast<CXXRecordDecl>(DC)->getCanonicalDecl(); 992cc2675d426af23476a9722c08c1b6c5266bd653John McCall Records.push_back(Record); 1002cc2675d426af23476a9722c08c1b6c5266bd653John McCall DC = Record->getDeclContext(); 1012cc2675d426af23476a9722c08c1b6c5266bd653John McCall } else if (isa<FunctionDecl>(DC)) { 1022cc2675d426af23476a9722c08c1b6c5266bd653John McCall FunctionDecl *Function = cast<FunctionDecl>(DC)->getCanonicalDecl(); 1032cc2675d426af23476a9722c08c1b6c5266bd653John McCall Functions.push_back(Function); 1042cc2675d426af23476a9722c08c1b6c5266bd653John McCall DC = Function->getDeclContext(); 1052cc2675d426af23476a9722c08c1b6c5266bd653John McCall } else if (DC->isFileContext()) { 1062cc2675d426af23476a9722c08c1b6c5266bd653John McCall break; 1072cc2675d426af23476a9722c08c1b6c5266bd653John McCall } else { 1082cc2675d426af23476a9722c08c1b6c5266bd653John McCall DC = DC->getParent(); 1092cc2675d426af23476a9722c08c1b6c5266bd653John McCall } 11088b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall } 1116b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall } 1126b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 1130c01d18094100db92d38daa923c95661512db203John McCall bool isDependent() const { return Dependent; } 1140c01d18094100db92d38daa923c95661512db203John McCall 11588b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall bool includesClass(const CXXRecordDecl *R) const { 11688b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall R = R->getCanonicalDecl(); 11788b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall return std::find(Records.begin(), Records.end(), R) 11888b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall != Records.end(); 1196b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall } 1206b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 1217ad650f88ecbbe659f10f9f6b34a1f29ea9cf8f9John McCall /// Retrieves the innermost "useful" context. Can be null if we're 1227ad650f88ecbbe659f10f9f6b34a1f29ea9cf8f9John McCall /// doing access-control without privileges. 1237ad650f88ecbbe659f10f9f6b34a1f29ea9cf8f9John McCall DeclContext *getInnerContext() const { 1247ad650f88ecbbe659f10f9f6b34a1f29ea9cf8f9John McCall return Inner; 1250c01d18094100db92d38daa923c95661512db203John McCall } 1260c01d18094100db92d38daa923c95661512db203John McCall 1270c01d18094100db92d38daa923c95661512db203John McCall typedef llvm::SmallVectorImpl<CXXRecordDecl*>::const_iterator record_iterator; 1280c01d18094100db92d38daa923c95661512db203John McCall 1297ad650f88ecbbe659f10f9f6b34a1f29ea9cf8f9John McCall DeclContext *Inner; 1302cc2675d426af23476a9722c08c1b6c5266bd653John McCall llvm::SmallVector<FunctionDecl*, 4> Functions; 13188b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall llvm::SmallVector<CXXRecordDecl*, 4> Records; 1320c01d18094100db92d38daa923c95661512db203John McCall bool Dependent; 1336b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall}; 134161755a09898c95d21bfff33707da9ca41cd53c5John McCall 135161755a09898c95d21bfff33707da9ca41cd53c5John McCall/// Like Sema's AccessedEntity, but kindly lets us scribble all over 136161755a09898c95d21bfff33707da9ca41cd53c5John McCall/// it. 137161755a09898c95d21bfff33707da9ca41cd53c5John McCallstruct AccessTarget : public Sema::AccessedEntity { 138161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget(const Sema::AccessedEntity &Entity) 139161755a09898c95d21bfff33707da9ca41cd53c5John McCall : AccessedEntity(Entity) { 140161755a09898c95d21bfff33707da9ca41cd53c5John McCall initialize(); 141161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 142161755a09898c95d21bfff33707da9ca41cd53c5John McCall 143161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget(ASTContext &Context, 144161755a09898c95d21bfff33707da9ca41cd53c5John McCall MemberNonce _, 145161755a09898c95d21bfff33707da9ca41cd53c5John McCall CXXRecordDecl *NamingClass, 146161755a09898c95d21bfff33707da9ca41cd53c5John McCall DeclAccessPair FoundDecl, 147161755a09898c95d21bfff33707da9ca41cd53c5John McCall QualType BaseObjectType) 148161755a09898c95d21bfff33707da9ca41cd53c5John McCall : AccessedEntity(Context, Member, NamingClass, FoundDecl, BaseObjectType) { 149161755a09898c95d21bfff33707da9ca41cd53c5John McCall initialize(); 150161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 151161755a09898c95d21bfff33707da9ca41cd53c5John McCall 152161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget(ASTContext &Context, 153161755a09898c95d21bfff33707da9ca41cd53c5John McCall BaseNonce _, 154161755a09898c95d21bfff33707da9ca41cd53c5John McCall CXXRecordDecl *BaseClass, 155161755a09898c95d21bfff33707da9ca41cd53c5John McCall CXXRecordDecl *DerivedClass, 156161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessSpecifier Access) 157161755a09898c95d21bfff33707da9ca41cd53c5John McCall : AccessedEntity(Context, Base, BaseClass, DerivedClass, Access) { 158161755a09898c95d21bfff33707da9ca41cd53c5John McCall initialize(); 159161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 160161755a09898c95d21bfff33707da9ca41cd53c5John McCall 161161755a09898c95d21bfff33707da9ca41cd53c5John McCall bool hasInstanceContext() const { 162161755a09898c95d21bfff33707da9ca41cd53c5John McCall return HasInstanceContext; 163161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 164161755a09898c95d21bfff33707da9ca41cd53c5John McCall 165161755a09898c95d21bfff33707da9ca41cd53c5John McCall class SavedInstanceContext { 166161755a09898c95d21bfff33707da9ca41cd53c5John McCall public: 167161755a09898c95d21bfff33707da9ca41cd53c5John McCall ~SavedInstanceContext() { 168161755a09898c95d21bfff33707da9ca41cd53c5John McCall Target.HasInstanceContext = Has; 169161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 170161755a09898c95d21bfff33707da9ca41cd53c5John McCall 171161755a09898c95d21bfff33707da9ca41cd53c5John McCall private: 172c91cc66e92b084acd1fdbaa1c3c74242741b3d46John McCall friend struct AccessTarget; 173161755a09898c95d21bfff33707da9ca41cd53c5John McCall explicit SavedInstanceContext(AccessTarget &Target) 174161755a09898c95d21bfff33707da9ca41cd53c5John McCall : Target(Target), Has(Target.HasInstanceContext) {} 175161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget &Target; 176161755a09898c95d21bfff33707da9ca41cd53c5John McCall bool Has; 177161755a09898c95d21bfff33707da9ca41cd53c5John McCall }; 178161755a09898c95d21bfff33707da9ca41cd53c5John McCall 179161755a09898c95d21bfff33707da9ca41cd53c5John McCall SavedInstanceContext saveInstanceContext() { 180161755a09898c95d21bfff33707da9ca41cd53c5John McCall return SavedInstanceContext(*this); 181161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 182161755a09898c95d21bfff33707da9ca41cd53c5John McCall 183161755a09898c95d21bfff33707da9ca41cd53c5John McCall void suppressInstanceContext() { 184161755a09898c95d21bfff33707da9ca41cd53c5John McCall HasInstanceContext = false; 185161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 186161755a09898c95d21bfff33707da9ca41cd53c5John McCall 187161755a09898c95d21bfff33707da9ca41cd53c5John McCall const CXXRecordDecl *resolveInstanceContext(Sema &S) const { 188161755a09898c95d21bfff33707da9ca41cd53c5John McCall assert(HasInstanceContext); 189161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (CalculatedInstanceContext) 190161755a09898c95d21bfff33707da9ca41cd53c5John McCall return InstanceContext; 191161755a09898c95d21bfff33707da9ca41cd53c5John McCall 192161755a09898c95d21bfff33707da9ca41cd53c5John McCall CalculatedInstanceContext = true; 193161755a09898c95d21bfff33707da9ca41cd53c5John McCall DeclContext *IC = S.computeDeclContext(getBaseObjectType()); 194161755a09898c95d21bfff33707da9ca41cd53c5John McCall InstanceContext = (IC ? cast<CXXRecordDecl>(IC)->getCanonicalDecl() : 0); 195161755a09898c95d21bfff33707da9ca41cd53c5John McCall return InstanceContext; 196161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 197161755a09898c95d21bfff33707da9ca41cd53c5John McCall 198161755a09898c95d21bfff33707da9ca41cd53c5John McCall const CXXRecordDecl *getDeclaringClass() const { 199161755a09898c95d21bfff33707da9ca41cd53c5John McCall return DeclaringClass; 200161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 201161755a09898c95d21bfff33707da9ca41cd53c5John McCall 202161755a09898c95d21bfff33707da9ca41cd53c5John McCallprivate: 203161755a09898c95d21bfff33707da9ca41cd53c5John McCall void initialize() { 204161755a09898c95d21bfff33707da9ca41cd53c5John McCall HasInstanceContext = (isMemberAccess() && 205161755a09898c95d21bfff33707da9ca41cd53c5John McCall !getBaseObjectType().isNull() && 206161755a09898c95d21bfff33707da9ca41cd53c5John McCall getTargetDecl()->isCXXInstanceMember()); 207161755a09898c95d21bfff33707da9ca41cd53c5John McCall CalculatedInstanceContext = false; 208161755a09898c95d21bfff33707da9ca41cd53c5John McCall InstanceContext = 0; 209161755a09898c95d21bfff33707da9ca41cd53c5John McCall 210161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (isMemberAccess()) 211161755a09898c95d21bfff33707da9ca41cd53c5John McCall DeclaringClass = FindDeclaringClass(getTargetDecl()); 212161755a09898c95d21bfff33707da9ca41cd53c5John McCall else 213161755a09898c95d21bfff33707da9ca41cd53c5John McCall DeclaringClass = getBaseClass(); 214161755a09898c95d21bfff33707da9ca41cd53c5John McCall DeclaringClass = DeclaringClass->getCanonicalDecl(); 215161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 216161755a09898c95d21bfff33707da9ca41cd53c5John McCall 217161755a09898c95d21bfff33707da9ca41cd53c5John McCall bool HasInstanceContext : 1; 218161755a09898c95d21bfff33707da9ca41cd53c5John McCall mutable bool CalculatedInstanceContext : 1; 219161755a09898c95d21bfff33707da9ca41cd53c5John McCall mutable const CXXRecordDecl *InstanceContext; 220161755a09898c95d21bfff33707da9ca41cd53c5John McCall const CXXRecordDecl *DeclaringClass; 221161755a09898c95d21bfff33707da9ca41cd53c5John McCall}; 222161755a09898c95d21bfff33707da9ca41cd53c5John McCall 2236b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall} 224726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl 22501ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall/// Checks whether one class might instantiate to the other. 22601ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCallstatic bool MightInstantiateTo(const CXXRecordDecl *From, 22701ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall const CXXRecordDecl *To) { 22801ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall // Declaration names are always preserved by instantiation. 22901ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall if (From->getDeclName() != To->getDeclName()) 23001ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall return false; 23101ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall 23201ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall const DeclContext *FromDC = From->getDeclContext()->getPrimaryContext(); 23301ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall const DeclContext *ToDC = To->getDeclContext()->getPrimaryContext(); 23401ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall if (FromDC == ToDC) return true; 23501ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall if (FromDC->isFileContext() || ToDC->isFileContext()) return false; 23601ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall 23701ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall // Be conservative. 23801ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall return true; 23901ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall} 24001ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall 241161755a09898c95d21bfff33707da9ca41cd53c5John McCall/// Checks whether one class is derived from another, inclusively. 242161755a09898c95d21bfff33707da9ca41cd53c5John McCall/// Properly indicates when it couldn't be determined due to 243161755a09898c95d21bfff33707da9ca41cd53c5John McCall/// dependence. 244161755a09898c95d21bfff33707da9ca41cd53c5John McCall/// 245161755a09898c95d21bfff33707da9ca41cd53c5John McCall/// This should probably be donated to AST or at least Sema. 246161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic AccessResult IsDerivedFromInclusive(const CXXRecordDecl *Derived, 247161755a09898c95d21bfff33707da9ca41cd53c5John McCall const CXXRecordDecl *Target) { 248161755a09898c95d21bfff33707da9ca41cd53c5John McCall assert(Derived->getCanonicalDecl() == Derived); 249161755a09898c95d21bfff33707da9ca41cd53c5John McCall assert(Target->getCanonicalDecl() == Target); 250c1b621daf98d83075a466c6f4ad9904dc845dd09John McCall 251161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (Derived == Target) return AR_accessible; 252c1b621daf98d83075a466c6f4ad9904dc845dd09John McCall 25301ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall bool CheckDependent = Derived->isDependentContext(); 25401ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall if (CheckDependent && MightInstantiateTo(Derived, Target)) 25501ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall return AR_dependent; 25601ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall 257161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessResult OnFailure = AR_inaccessible; 258161755a09898c95d21bfff33707da9ca41cd53c5John McCall llvm::SmallVector<const CXXRecordDecl*, 8> Queue; // actually a stack 259161755a09898c95d21bfff33707da9ca41cd53c5John McCall 260161755a09898c95d21bfff33707da9ca41cd53c5John McCall while (true) { 261161755a09898c95d21bfff33707da9ca41cd53c5John McCall for (CXXRecordDecl::base_class_const_iterator 262161755a09898c95d21bfff33707da9ca41cd53c5John McCall I = Derived->bases_begin(), E = Derived->bases_end(); I != E; ++I) { 263161755a09898c95d21bfff33707da9ca41cd53c5John McCall 264161755a09898c95d21bfff33707da9ca41cd53c5John McCall const CXXRecordDecl *RD; 265161755a09898c95d21bfff33707da9ca41cd53c5John McCall 266161755a09898c95d21bfff33707da9ca41cd53c5John McCall QualType T = I->getType(); 267161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (const RecordType *RT = T->getAs<RecordType>()) { 268161755a09898c95d21bfff33707da9ca41cd53c5John McCall RD = cast<CXXRecordDecl>(RT->getDecl()); 26901ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall } else if (const InjectedClassNameType *IT 27001ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall = T->getAs<InjectedClassNameType>()) { 27101ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall RD = IT->getDecl(); 272161755a09898c95d21bfff33707da9ca41cd53c5John McCall } else { 273161755a09898c95d21bfff33707da9ca41cd53c5John McCall assert(T->isDependentType() && "non-dependent base wasn't a record?"); 274161755a09898c95d21bfff33707da9ca41cd53c5John McCall OnFailure = AR_dependent; 275161755a09898c95d21bfff33707da9ca41cd53c5John McCall continue; 276161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 277161755a09898c95d21bfff33707da9ca41cd53c5John McCall 278161755a09898c95d21bfff33707da9ca41cd53c5John McCall RD = RD->getCanonicalDecl(); 279161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (RD == Target) return AR_accessible; 28001ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall if (CheckDependent && MightInstantiateTo(RD, Target)) 28101ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall OnFailure = AR_dependent; 28201ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall 283161755a09898c95d21bfff33707da9ca41cd53c5John McCall Queue.push_back(RD); 284161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 285161755a09898c95d21bfff33707da9ca41cd53c5John McCall 286161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (Queue.empty()) break; 287161755a09898c95d21bfff33707da9ca41cd53c5John McCall 288161755a09898c95d21bfff33707da9ca41cd53c5John McCall Derived = Queue.back(); 289161755a09898c95d21bfff33707da9ca41cd53c5John McCall Queue.pop_back(); 290161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 291161755a09898c95d21bfff33707da9ca41cd53c5John McCall 292161755a09898c95d21bfff33707da9ca41cd53c5John McCall return OnFailure; 2936b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall} 2946b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 295161755a09898c95d21bfff33707da9ca41cd53c5John McCall 2960c01d18094100db92d38daa923c95661512db203John McCallstatic bool MightInstantiateTo(Sema &S, DeclContext *Context, 2970c01d18094100db92d38daa923c95661512db203John McCall DeclContext *Friend) { 2980c01d18094100db92d38daa923c95661512db203John McCall if (Friend == Context) 2990c01d18094100db92d38daa923c95661512db203John McCall return true; 3000c01d18094100db92d38daa923c95661512db203John McCall 3010c01d18094100db92d38daa923c95661512db203John McCall assert(!Friend->isDependentContext() && 3020c01d18094100db92d38daa923c95661512db203John McCall "can't handle friends with dependent contexts here"); 3030c01d18094100db92d38daa923c95661512db203John McCall 3040c01d18094100db92d38daa923c95661512db203John McCall if (!Context->isDependentContext()) 3050c01d18094100db92d38daa923c95661512db203John McCall return false; 3060c01d18094100db92d38daa923c95661512db203John McCall 3070c01d18094100db92d38daa923c95661512db203John McCall if (Friend->isFileContext()) 3080c01d18094100db92d38daa923c95661512db203John McCall return false; 3090c01d18094100db92d38daa923c95661512db203John McCall 3100c01d18094100db92d38daa923c95661512db203John McCall // TODO: this is very conservative 3110c01d18094100db92d38daa923c95661512db203John McCall return true; 3120c01d18094100db92d38daa923c95661512db203John McCall} 3130c01d18094100db92d38daa923c95661512db203John McCall 3140c01d18094100db92d38daa923c95661512db203John McCall// Asks whether the type in 'context' can ever instantiate to the type 3150c01d18094100db92d38daa923c95661512db203John McCall// in 'friend'. 3160c01d18094100db92d38daa923c95661512db203John McCallstatic bool MightInstantiateTo(Sema &S, CanQualType Context, CanQualType Friend) { 3170c01d18094100db92d38daa923c95661512db203John McCall if (Friend == Context) 3180c01d18094100db92d38daa923c95661512db203John McCall return true; 3190c01d18094100db92d38daa923c95661512db203John McCall 3200c01d18094100db92d38daa923c95661512db203John McCall if (!Friend->isDependentType() && !Context->isDependentType()) 3210c01d18094100db92d38daa923c95661512db203John McCall return false; 3220c01d18094100db92d38daa923c95661512db203John McCall 3230c01d18094100db92d38daa923c95661512db203John McCall // TODO: this is very conservative. 3240c01d18094100db92d38daa923c95661512db203John McCall return true; 3250c01d18094100db92d38daa923c95661512db203John McCall} 3260c01d18094100db92d38daa923c95661512db203John McCall 3270c01d18094100db92d38daa923c95661512db203John McCallstatic bool MightInstantiateTo(Sema &S, 3280c01d18094100db92d38daa923c95661512db203John McCall FunctionDecl *Context, 3290c01d18094100db92d38daa923c95661512db203John McCall FunctionDecl *Friend) { 3300c01d18094100db92d38daa923c95661512db203John McCall if (Context->getDeclName() != Friend->getDeclName()) 3310c01d18094100db92d38daa923c95661512db203John McCall return false; 3320c01d18094100db92d38daa923c95661512db203John McCall 3330c01d18094100db92d38daa923c95661512db203John McCall if (!MightInstantiateTo(S, 3340c01d18094100db92d38daa923c95661512db203John McCall Context->getDeclContext(), 3350c01d18094100db92d38daa923c95661512db203John McCall Friend->getDeclContext())) 3360c01d18094100db92d38daa923c95661512db203John McCall return false; 3370c01d18094100db92d38daa923c95661512db203John McCall 3380c01d18094100db92d38daa923c95661512db203John McCall CanQual<FunctionProtoType> FriendTy 3390c01d18094100db92d38daa923c95661512db203John McCall = S.Context.getCanonicalType(Friend->getType()) 3400c01d18094100db92d38daa923c95661512db203John McCall ->getAs<FunctionProtoType>(); 3410c01d18094100db92d38daa923c95661512db203John McCall CanQual<FunctionProtoType> ContextTy 3420c01d18094100db92d38daa923c95661512db203John McCall = S.Context.getCanonicalType(Context->getType()) 3430c01d18094100db92d38daa923c95661512db203John McCall ->getAs<FunctionProtoType>(); 3440c01d18094100db92d38daa923c95661512db203John McCall 3450c01d18094100db92d38daa923c95661512db203John McCall // There isn't any way that I know of to add qualifiers 3460c01d18094100db92d38daa923c95661512db203John McCall // during instantiation. 3470c01d18094100db92d38daa923c95661512db203John McCall if (FriendTy.getQualifiers() != ContextTy.getQualifiers()) 3480c01d18094100db92d38daa923c95661512db203John McCall return false; 3490c01d18094100db92d38daa923c95661512db203John McCall 3500c01d18094100db92d38daa923c95661512db203John McCall if (FriendTy->getNumArgs() != ContextTy->getNumArgs()) 3510c01d18094100db92d38daa923c95661512db203John McCall return false; 3520c01d18094100db92d38daa923c95661512db203John McCall 3530c01d18094100db92d38daa923c95661512db203John McCall if (!MightInstantiateTo(S, 3540c01d18094100db92d38daa923c95661512db203John McCall ContextTy->getResultType(), 3550c01d18094100db92d38daa923c95661512db203John McCall FriendTy->getResultType())) 3560c01d18094100db92d38daa923c95661512db203John McCall return false; 3570c01d18094100db92d38daa923c95661512db203John McCall 3580c01d18094100db92d38daa923c95661512db203John McCall for (unsigned I = 0, E = FriendTy->getNumArgs(); I != E; ++I) 3590c01d18094100db92d38daa923c95661512db203John McCall if (!MightInstantiateTo(S, 3600c01d18094100db92d38daa923c95661512db203John McCall ContextTy->getArgType(I), 3610c01d18094100db92d38daa923c95661512db203John McCall FriendTy->getArgType(I))) 3620c01d18094100db92d38daa923c95661512db203John McCall return false; 3630c01d18094100db92d38daa923c95661512db203John McCall 3640c01d18094100db92d38daa923c95661512db203John McCall return true; 3650c01d18094100db92d38daa923c95661512db203John McCall} 3660c01d18094100db92d38daa923c95661512db203John McCall 3670c01d18094100db92d38daa923c95661512db203John McCallstatic bool MightInstantiateTo(Sema &S, 3680c01d18094100db92d38daa923c95661512db203John McCall FunctionTemplateDecl *Context, 3690c01d18094100db92d38daa923c95661512db203John McCall FunctionTemplateDecl *Friend) { 3700c01d18094100db92d38daa923c95661512db203John McCall return MightInstantiateTo(S, 3710c01d18094100db92d38daa923c95661512db203John McCall Context->getTemplatedDecl(), 3720c01d18094100db92d38daa923c95661512db203John McCall Friend->getTemplatedDecl()); 3730c01d18094100db92d38daa923c95661512db203John McCall} 3740c01d18094100db92d38daa923c95661512db203John McCall 375161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic AccessResult MatchesFriend(Sema &S, 376161755a09898c95d21bfff33707da9ca41cd53c5John McCall const EffectiveContext &EC, 377161755a09898c95d21bfff33707da9ca41cd53c5John McCall const CXXRecordDecl *Friend) { 378a742db0032d8f458fe229600d2082981a1fb1481John McCall if (EC.includesClass(Friend)) 379161755a09898c95d21bfff33707da9ca41cd53c5John McCall return AR_accessible; 380a742db0032d8f458fe229600d2082981a1fb1481John McCall 3810c01d18094100db92d38daa923c95661512db203John McCall if (EC.isDependent()) { 3820c01d18094100db92d38daa923c95661512db203John McCall CanQualType FriendTy 3830c01d18094100db92d38daa923c95661512db203John McCall = S.Context.getCanonicalType(S.Context.getTypeDeclType(Friend)); 3840c01d18094100db92d38daa923c95661512db203John McCall 3850c01d18094100db92d38daa923c95661512db203John McCall for (EffectiveContext::record_iterator 3860c01d18094100db92d38daa923c95661512db203John McCall I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { 3870c01d18094100db92d38daa923c95661512db203John McCall CanQualType ContextTy 3880c01d18094100db92d38daa923c95661512db203John McCall = S.Context.getCanonicalType(S.Context.getTypeDeclType(*I)); 3890c01d18094100db92d38daa923c95661512db203John McCall if (MightInstantiateTo(S, ContextTy, FriendTy)) 390161755a09898c95d21bfff33707da9ca41cd53c5John McCall return AR_dependent; 3910c01d18094100db92d38daa923c95661512db203John McCall } 3920c01d18094100db92d38daa923c95661512db203John McCall } 3930c01d18094100db92d38daa923c95661512db203John McCall 394161755a09898c95d21bfff33707da9ca41cd53c5John McCall return AR_inaccessible; 395a742db0032d8f458fe229600d2082981a1fb1481John McCall} 396a742db0032d8f458fe229600d2082981a1fb1481John McCall 397161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic AccessResult MatchesFriend(Sema &S, 398161755a09898c95d21bfff33707da9ca41cd53c5John McCall const EffectiveContext &EC, 399161755a09898c95d21bfff33707da9ca41cd53c5John McCall CanQualType Friend) { 4000c01d18094100db92d38daa923c95661512db203John McCall if (const RecordType *RT = Friend->getAs<RecordType>()) 4010c01d18094100db92d38daa923c95661512db203John McCall return MatchesFriend(S, EC, cast<CXXRecordDecl>(RT->getDecl())); 402a742db0032d8f458fe229600d2082981a1fb1481John McCall 4030c01d18094100db92d38daa923c95661512db203John McCall // TODO: we can do better than this 4040c01d18094100db92d38daa923c95661512db203John McCall if (Friend->isDependentType()) 405161755a09898c95d21bfff33707da9ca41cd53c5John McCall return AR_dependent; 406a742db0032d8f458fe229600d2082981a1fb1481John McCall 407161755a09898c95d21bfff33707da9ca41cd53c5John McCall return AR_inaccessible; 4080c01d18094100db92d38daa923c95661512db203John McCall} 409a742db0032d8f458fe229600d2082981a1fb1481John McCall 4100c01d18094100db92d38daa923c95661512db203John McCall/// Determines whether the given friend class template matches 4110c01d18094100db92d38daa923c95661512db203John McCall/// anything in the effective context. 412161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic AccessResult MatchesFriend(Sema &S, 413161755a09898c95d21bfff33707da9ca41cd53c5John McCall const EffectiveContext &EC, 414161755a09898c95d21bfff33707da9ca41cd53c5John McCall ClassTemplateDecl *Friend) { 415161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessResult OnFailure = AR_inaccessible; 416a742db0032d8f458fe229600d2082981a1fb1481John McCall 41793ba8579c341d5329175f1413cdc3b35a36592d2John McCall // Check whether the friend is the template of a class in the 41893ba8579c341d5329175f1413cdc3b35a36592d2John McCall // context chain. 4190c01d18094100db92d38daa923c95661512db203John McCall for (llvm::SmallVectorImpl<CXXRecordDecl*>::const_iterator 4200c01d18094100db92d38daa923c95661512db203John McCall I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { 4210c01d18094100db92d38daa923c95661512db203John McCall CXXRecordDecl *Record = *I; 422a742db0032d8f458fe229600d2082981a1fb1481John McCall 42393ba8579c341d5329175f1413cdc3b35a36592d2John McCall // Figure out whether the current class has a template: 4240c01d18094100db92d38daa923c95661512db203John McCall ClassTemplateDecl *CTD; 425a742db0032d8f458fe229600d2082981a1fb1481John McCall 4260c01d18094100db92d38daa923c95661512db203John McCall // A specialization of the template... 4270c01d18094100db92d38daa923c95661512db203John McCall if (isa<ClassTemplateSpecializationDecl>(Record)) { 4280c01d18094100db92d38daa923c95661512db203John McCall CTD = cast<ClassTemplateSpecializationDecl>(Record) 4290c01d18094100db92d38daa923c95661512db203John McCall ->getSpecializedTemplate(); 430a742db0032d8f458fe229600d2082981a1fb1481John McCall 4310c01d18094100db92d38daa923c95661512db203John McCall // ... or the template pattern itself. 4320c01d18094100db92d38daa923c95661512db203John McCall } else { 4330c01d18094100db92d38daa923c95661512db203John McCall CTD = Record->getDescribedClassTemplate(); 4340c01d18094100db92d38daa923c95661512db203John McCall if (!CTD) continue; 435a742db0032d8f458fe229600d2082981a1fb1481John McCall } 436a742db0032d8f458fe229600d2082981a1fb1481John McCall 4370c01d18094100db92d38daa923c95661512db203John McCall // It's a match. 4380c01d18094100db92d38daa923c95661512db203John McCall if (Friend == CTD->getCanonicalDecl()) 439161755a09898c95d21bfff33707da9ca41cd53c5John McCall return AR_accessible; 4400c01d18094100db92d38daa923c95661512db203John McCall 44193ba8579c341d5329175f1413cdc3b35a36592d2John McCall // If the context isn't dependent, it can't be a dependent match. 44293ba8579c341d5329175f1413cdc3b35a36592d2John McCall if (!EC.isDependent()) 44393ba8579c341d5329175f1413cdc3b35a36592d2John McCall continue; 44493ba8579c341d5329175f1413cdc3b35a36592d2John McCall 4450c01d18094100db92d38daa923c95661512db203John McCall // If the template names don't match, it can't be a dependent 4460c01d18094100db92d38daa923c95661512db203John McCall // match. This isn't true in C++0x because of template aliases. 4470c01d18094100db92d38daa923c95661512db203John McCall if (!S.LangOpts.CPlusPlus0x && CTD->getDeclName() != Friend->getDeclName()) 4480c01d18094100db92d38daa923c95661512db203John McCall continue; 4490c01d18094100db92d38daa923c95661512db203John McCall 4500c01d18094100db92d38daa923c95661512db203John McCall // If the class's context can't instantiate to the friend's 4510c01d18094100db92d38daa923c95661512db203John McCall // context, it can't be a dependent match. 4520c01d18094100db92d38daa923c95661512db203John McCall if (!MightInstantiateTo(S, CTD->getDeclContext(), 4530c01d18094100db92d38daa923c95661512db203John McCall Friend->getDeclContext())) 4540c01d18094100db92d38daa923c95661512db203John McCall continue; 4550c01d18094100db92d38daa923c95661512db203John McCall 4560c01d18094100db92d38daa923c95661512db203John McCall // Otherwise, it's a dependent match. 457161755a09898c95d21bfff33707da9ca41cd53c5John McCall OnFailure = AR_dependent; 458a742db0032d8f458fe229600d2082981a1fb1481John McCall } 459a742db0032d8f458fe229600d2082981a1fb1481John McCall 4600c01d18094100db92d38daa923c95661512db203John McCall return OnFailure; 4610c01d18094100db92d38daa923c95661512db203John McCall} 462a742db0032d8f458fe229600d2082981a1fb1481John McCall 4630c01d18094100db92d38daa923c95661512db203John McCall/// Determines whether the given friend function matches anything in 4640c01d18094100db92d38daa923c95661512db203John McCall/// the effective context. 465161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic AccessResult MatchesFriend(Sema &S, 466161755a09898c95d21bfff33707da9ca41cd53c5John McCall const EffectiveContext &EC, 467161755a09898c95d21bfff33707da9ca41cd53c5John McCall FunctionDecl *Friend) { 468161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessResult OnFailure = AR_inaccessible; 469a742db0032d8f458fe229600d2082981a1fb1481John McCall 4702cc2675d426af23476a9722c08c1b6c5266bd653John McCall for (llvm::SmallVectorImpl<FunctionDecl*>::const_iterator 4712cc2675d426af23476a9722c08c1b6c5266bd653John McCall I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) { 4722cc2675d426af23476a9722c08c1b6c5266bd653John McCall if (Friend == *I) 473161755a09898c95d21bfff33707da9ca41cd53c5John McCall return AR_accessible; 4740c01d18094100db92d38daa923c95661512db203John McCall 4752cc2675d426af23476a9722c08c1b6c5266bd653John McCall if (EC.isDependent() && MightInstantiateTo(S, *I, Friend)) 476161755a09898c95d21bfff33707da9ca41cd53c5John McCall OnFailure = AR_dependent; 4772cc2675d426af23476a9722c08c1b6c5266bd653John McCall } 4780c01d18094100db92d38daa923c95661512db203John McCall 4792cc2675d426af23476a9722c08c1b6c5266bd653John McCall return OnFailure; 4800c01d18094100db92d38daa923c95661512db203John McCall} 4810c01d18094100db92d38daa923c95661512db203John McCall 4820c01d18094100db92d38daa923c95661512db203John McCall/// Determines whether the given friend function template matches 4830c01d18094100db92d38daa923c95661512db203John McCall/// anything in the effective context. 484161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic AccessResult MatchesFriend(Sema &S, 485161755a09898c95d21bfff33707da9ca41cd53c5John McCall const EffectiveContext &EC, 486161755a09898c95d21bfff33707da9ca41cd53c5John McCall FunctionTemplateDecl *Friend) { 487161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (EC.Functions.empty()) return AR_inaccessible; 4882cc2675d426af23476a9722c08c1b6c5266bd653John McCall 489161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessResult OnFailure = AR_inaccessible; 4900c01d18094100db92d38daa923c95661512db203John McCall 4912cc2675d426af23476a9722c08c1b6c5266bd653John McCall for (llvm::SmallVectorImpl<FunctionDecl*>::const_iterator 4922cc2675d426af23476a9722c08c1b6c5266bd653John McCall I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) { 493a742db0032d8f458fe229600d2082981a1fb1481John McCall 4942cc2675d426af23476a9722c08c1b6c5266bd653John McCall FunctionTemplateDecl *FTD = (*I)->getPrimaryTemplate(); 4952cc2675d426af23476a9722c08c1b6c5266bd653John McCall if (!FTD) 4962cc2675d426af23476a9722c08c1b6c5266bd653John McCall FTD = (*I)->getDescribedFunctionTemplate(); 4972cc2675d426af23476a9722c08c1b6c5266bd653John McCall if (!FTD) 4982cc2675d426af23476a9722c08c1b6c5266bd653John McCall continue; 499a742db0032d8f458fe229600d2082981a1fb1481John McCall 5002cc2675d426af23476a9722c08c1b6c5266bd653John McCall FTD = FTD->getCanonicalDecl(); 501a742db0032d8f458fe229600d2082981a1fb1481John McCall 5022cc2675d426af23476a9722c08c1b6c5266bd653John McCall if (Friend == FTD) 503161755a09898c95d21bfff33707da9ca41cd53c5John McCall return AR_accessible; 5042cc2675d426af23476a9722c08c1b6c5266bd653John McCall 5052cc2675d426af23476a9722c08c1b6c5266bd653John McCall if (EC.isDependent() && MightInstantiateTo(S, FTD, Friend)) 506161755a09898c95d21bfff33707da9ca41cd53c5John McCall OnFailure = AR_dependent; 5072cc2675d426af23476a9722c08c1b6c5266bd653John McCall } 5082cc2675d426af23476a9722c08c1b6c5266bd653John McCall 5092cc2675d426af23476a9722c08c1b6c5266bd653John McCall return OnFailure; 510a742db0032d8f458fe229600d2082981a1fb1481John McCall} 511a742db0032d8f458fe229600d2082981a1fb1481John McCall 5120c01d18094100db92d38daa923c95661512db203John McCall/// Determines whether the given friend declaration matches anything 5130c01d18094100db92d38daa923c95661512db203John McCall/// in the effective context. 514161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic AccessResult MatchesFriend(Sema &S, 515161755a09898c95d21bfff33707da9ca41cd53c5John McCall const EffectiveContext &EC, 516161755a09898c95d21bfff33707da9ca41cd53c5John McCall FriendDecl *FriendD) { 51732f2fb53d9d7c28c94d8569fd0fcf06cccee0c3dJohn McCall if (TypeSourceInfo *T = FriendD->getFriendType()) 51832f2fb53d9d7c28c94d8569fd0fcf06cccee0c3dJohn McCall return MatchesFriend(S, EC, T->getType()->getCanonicalTypeUnqualified()); 5190c01d18094100db92d38daa923c95661512db203John McCall 5200c01d18094100db92d38daa923c95661512db203John McCall NamedDecl *Friend 5210c01d18094100db92d38daa923c95661512db203John McCall = cast<NamedDecl>(FriendD->getFriendDecl()->getCanonicalDecl()); 5220c01d18094100db92d38daa923c95661512db203John McCall 5230c01d18094100db92d38daa923c95661512db203John McCall // FIXME: declarations with dependent or templated scope. 5240c01d18094100db92d38daa923c95661512db203John McCall 5250c01d18094100db92d38daa923c95661512db203John McCall if (isa<ClassTemplateDecl>(Friend)) 5260c01d18094100db92d38daa923c95661512db203John McCall return MatchesFriend(S, EC, cast<ClassTemplateDecl>(Friend)); 5270c01d18094100db92d38daa923c95661512db203John McCall 5280c01d18094100db92d38daa923c95661512db203John McCall if (isa<FunctionTemplateDecl>(Friend)) 5290c01d18094100db92d38daa923c95661512db203John McCall return MatchesFriend(S, EC, cast<FunctionTemplateDecl>(Friend)); 5300c01d18094100db92d38daa923c95661512db203John McCall 5310c01d18094100db92d38daa923c95661512db203John McCall if (isa<CXXRecordDecl>(Friend)) 5320c01d18094100db92d38daa923c95661512db203John McCall return MatchesFriend(S, EC, cast<CXXRecordDecl>(Friend)); 5330c01d18094100db92d38daa923c95661512db203John McCall 5340c01d18094100db92d38daa923c95661512db203John McCall assert(isa<FunctionDecl>(Friend) && "unknown friend decl kind"); 5350c01d18094100db92d38daa923c95661512db203John McCall return MatchesFriend(S, EC, cast<FunctionDecl>(Friend)); 5360c01d18094100db92d38daa923c95661512db203John McCall} 5370c01d18094100db92d38daa923c95661512db203John McCall 538161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic AccessResult GetFriendKind(Sema &S, 539161755a09898c95d21bfff33707da9ca41cd53c5John McCall const EffectiveContext &EC, 540161755a09898c95d21bfff33707da9ca41cd53c5John McCall const CXXRecordDecl *Class) { 541161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessResult OnFailure = AR_inaccessible; 54288b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall 543d60e22e601852ae1345f01514318a0951dc09f89John McCall // Okay, check friends. 544d60e22e601852ae1345f01514318a0951dc09f89John McCall for (CXXRecordDecl::friend_iterator I = Class->friend_begin(), 545d60e22e601852ae1345f01514318a0951dc09f89John McCall E = Class->friend_end(); I != E; ++I) { 546d60e22e601852ae1345f01514318a0951dc09f89John McCall FriendDecl *Friend = *I; 547d60e22e601852ae1345f01514318a0951dc09f89John McCall 548a742db0032d8f458fe229600d2082981a1fb1481John McCall switch (MatchesFriend(S, EC, Friend)) { 549161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_accessible: 550161755a09898c95d21bfff33707da9ca41cd53c5John McCall return AR_accessible; 55188b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall 552161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_inaccessible: 553161755a09898c95d21bfff33707da9ca41cd53c5John McCall continue; 554d60e22e601852ae1345f01514318a0951dc09f89John McCall 555161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_dependent: 556161755a09898c95d21bfff33707da9ca41cd53c5John McCall OnFailure = AR_dependent; 557a742db0032d8f458fe229600d2082981a1fb1481John McCall break; 558a742db0032d8f458fe229600d2082981a1fb1481John McCall } 559d60e22e601852ae1345f01514318a0951dc09f89John McCall } 560d60e22e601852ae1345f01514318a0951dc09f89John McCall 561d60e22e601852ae1345f01514318a0951dc09f89John McCall // That's it, give up. 56288b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall return OnFailure; 5636b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall} 5646b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 565161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic AccessResult HasAccess(Sema &S, 566161755a09898c95d21bfff33707da9ca41cd53c5John McCall const EffectiveContext &EC, 567161755a09898c95d21bfff33707da9ca41cd53c5John McCall const CXXRecordDecl *NamingClass, 568161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessSpecifier Access, 569161755a09898c95d21bfff33707da9ca41cd53c5John McCall const AccessTarget &Target) { 570db73c684ba61fed4087af488e8610657ec638c17John McCall assert(NamingClass->getCanonicalDecl() == NamingClass && 571db73c684ba61fed4087af488e8610657ec638c17John McCall "declaration should be canonicalized before being passed here"); 572db73c684ba61fed4087af488e8610657ec638c17John McCall 573161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (Access == AS_public) return AR_accessible; 574db73c684ba61fed4087af488e8610657ec638c17John McCall assert(Access == AS_private || Access == AS_protected); 575db73c684ba61fed4087af488e8610657ec638c17John McCall 576161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessResult OnFailure = AR_inaccessible; 577161755a09898c95d21bfff33707da9ca41cd53c5John McCall 578db73c684ba61fed4087af488e8610657ec638c17John McCall for (EffectiveContext::record_iterator 579db73c684ba61fed4087af488e8610657ec638c17John McCall I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { 580db73c684ba61fed4087af488e8610657ec638c17John McCall // All the declarations in EC have been canonicalized, so pointer 581db73c684ba61fed4087af488e8610657ec638c17John McCall // equality from this point on will work fine. 582db73c684ba61fed4087af488e8610657ec638c17John McCall const CXXRecordDecl *ECRecord = *I; 583db73c684ba61fed4087af488e8610657ec638c17John McCall 584db73c684ba61fed4087af488e8610657ec638c17John McCall // [B2] and [M2] 585161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (Access == AS_private) { 586161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (ECRecord == NamingClass) 587161755a09898c95d21bfff33707da9ca41cd53c5John McCall return AR_accessible; 588db73c684ba61fed4087af488e8610657ec638c17John McCall 58901ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall if (EC.isDependent() && MightInstantiateTo(ECRecord, NamingClass)) 59001ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall OnFailure = AR_dependent; 59101ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall 592db73c684ba61fed4087af488e8610657ec638c17John McCall // [B3] and [M3] 593161755a09898c95d21bfff33707da9ca41cd53c5John McCall } else { 594161755a09898c95d21bfff33707da9ca41cd53c5John McCall assert(Access == AS_protected); 595161755a09898c95d21bfff33707da9ca41cd53c5John McCall switch (IsDerivedFromInclusive(ECRecord, NamingClass)) { 596161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_accessible: break; 597161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_inaccessible: continue; 598161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_dependent: OnFailure = AR_dependent; continue; 599161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 600161755a09898c95d21bfff33707da9ca41cd53c5John McCall 601161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (!Target.hasInstanceContext()) 602161755a09898c95d21bfff33707da9ca41cd53c5John McCall return AR_accessible; 603161755a09898c95d21bfff33707da9ca41cd53c5John McCall 604161755a09898c95d21bfff33707da9ca41cd53c5John McCall const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S); 605161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (!InstanceContext) { 606161755a09898c95d21bfff33707da9ca41cd53c5John McCall OnFailure = AR_dependent; 607161755a09898c95d21bfff33707da9ca41cd53c5John McCall continue; 608161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 609161755a09898c95d21bfff33707da9ca41cd53c5John McCall 610161755a09898c95d21bfff33707da9ca41cd53c5John McCall // C++ [class.protected]p1: 611161755a09898c95d21bfff33707da9ca41cd53c5John McCall // An additional access check beyond those described earlier in 612161755a09898c95d21bfff33707da9ca41cd53c5John McCall // [class.access] is applied when a non-static data member or 613161755a09898c95d21bfff33707da9ca41cd53c5John McCall // non-static member function is a protected member of its naming 614161755a09898c95d21bfff33707da9ca41cd53c5John McCall // class. As described earlier, access to a protected member is 615161755a09898c95d21bfff33707da9ca41cd53c5John McCall // granted because the reference occurs in a friend or member of 616161755a09898c95d21bfff33707da9ca41cd53c5John McCall // some class C. If the access is to form a pointer to member, 617161755a09898c95d21bfff33707da9ca41cd53c5John McCall // the nested-name-specifier shall name C or a class derived from 618161755a09898c95d21bfff33707da9ca41cd53c5John McCall // C. All other accesses involve a (possibly implicit) object 619161755a09898c95d21bfff33707da9ca41cd53c5John McCall // expression. In this case, the class of the object expression 620161755a09898c95d21bfff33707da9ca41cd53c5John McCall // shall be C or a class derived from C. 621161755a09898c95d21bfff33707da9ca41cd53c5John McCall // 622161755a09898c95d21bfff33707da9ca41cd53c5John McCall // We interpret this as a restriction on [M3]. Most of the 623161755a09898c95d21bfff33707da9ca41cd53c5John McCall // conditions are encoded by not having any instance context. 624161755a09898c95d21bfff33707da9ca41cd53c5John McCall switch (IsDerivedFromInclusive(InstanceContext, ECRecord)) { 625161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_accessible: return AR_accessible; 626161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_inaccessible: continue; 627161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_dependent: OnFailure = AR_dependent; continue; 628161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 629161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 630db73c684ba61fed4087af488e8610657ec638c17John McCall } 631db73c684ba61fed4087af488e8610657ec638c17John McCall 632161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (!NamingClass->hasFriends()) 633161755a09898c95d21bfff33707da9ca41cd53c5John McCall return OnFailure; 634161755a09898c95d21bfff33707da9ca41cd53c5John McCall 635161755a09898c95d21bfff33707da9ca41cd53c5John McCall // Don't consider friends if we're under the [class.protected] 636161755a09898c95d21bfff33707da9ca41cd53c5John McCall // restriction, above. 637161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (Access == AS_protected && Target.hasInstanceContext()) { 638161755a09898c95d21bfff33707da9ca41cd53c5John McCall const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S); 639161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (!InstanceContext) return AR_dependent; 640161755a09898c95d21bfff33707da9ca41cd53c5John McCall 641161755a09898c95d21bfff33707da9ca41cd53c5John McCall switch (IsDerivedFromInclusive(InstanceContext, NamingClass)) { 642161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_accessible: break; 643161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_inaccessible: return OnFailure; 644161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_dependent: return AR_dependent; 645161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 646161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 647161755a09898c95d21bfff33707da9ca41cd53c5John McCall 648161755a09898c95d21bfff33707da9ca41cd53c5John McCall switch (GetFriendKind(S, EC, NamingClass)) { 649161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_accessible: return AR_accessible; 650161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_inaccessible: return OnFailure; 651161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_dependent: return AR_dependent; 652161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 653161755a09898c95d21bfff33707da9ca41cd53c5John McCall 654161755a09898c95d21bfff33707da9ca41cd53c5John McCall // Silence bogus warnings 655161755a09898c95d21bfff33707da9ca41cd53c5John McCall llvm_unreachable("impossible friendship kind"); 656161755a09898c95d21bfff33707da9ca41cd53c5John McCall return OnFailure; 657db73c684ba61fed4087af488e8610657ec638c17John McCall} 658db73c684ba61fed4087af488e8610657ec638c17John McCall 6596b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// Finds the best path from the naming class to the declaring class, 6606b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// taking friend declarations into account. 6616b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// 662db73c684ba61fed4087af488e8610657ec638c17John McCall/// C++0x [class.access.base]p5: 663db73c684ba61fed4087af488e8610657ec638c17John McCall/// A member m is accessible at the point R when named in class N if 664db73c684ba61fed4087af488e8610657ec638c17John McCall/// [M1] m as a member of N is public, or 665db73c684ba61fed4087af488e8610657ec638c17John McCall/// [M2] m as a member of N is private, and R occurs in a member or 666db73c684ba61fed4087af488e8610657ec638c17John McCall/// friend of class N, or 667db73c684ba61fed4087af488e8610657ec638c17John McCall/// [M3] m as a member of N is protected, and R occurs in a member or 668db73c684ba61fed4087af488e8610657ec638c17John McCall/// friend of class N, or in a member or friend of a class P 669db73c684ba61fed4087af488e8610657ec638c17John McCall/// derived from N, where m as a member of P is public, private, 670db73c684ba61fed4087af488e8610657ec638c17John McCall/// or protected, or 671db73c684ba61fed4087af488e8610657ec638c17John McCall/// [M4] there exists a base class B of N that is accessible at R, and 672db73c684ba61fed4087af488e8610657ec638c17John McCall/// m is accessible at R when named in class B. 673db73c684ba61fed4087af488e8610657ec638c17John McCall/// 674db73c684ba61fed4087af488e8610657ec638c17John McCall/// C++0x [class.access.base]p4: 675db73c684ba61fed4087af488e8610657ec638c17John McCall/// A base class B of N is accessible at R, if 676db73c684ba61fed4087af488e8610657ec638c17John McCall/// [B1] an invented public member of B would be a public member of N, or 677db73c684ba61fed4087af488e8610657ec638c17John McCall/// [B2] R occurs in a member or friend of class N, and an invented public 678db73c684ba61fed4087af488e8610657ec638c17John McCall/// member of B would be a private or protected member of N, or 679db73c684ba61fed4087af488e8610657ec638c17John McCall/// [B3] R occurs in a member or friend of a class P derived from N, and an 680db73c684ba61fed4087af488e8610657ec638c17John McCall/// invented public member of B would be a private or protected member 681db73c684ba61fed4087af488e8610657ec638c17John McCall/// of P, or 682db73c684ba61fed4087af488e8610657ec638c17John McCall/// [B4] there exists a class S such that B is a base class of S accessible 683db73c684ba61fed4087af488e8610657ec638c17John McCall/// at R and S is a base class of N accessible at R. 684db73c684ba61fed4087af488e8610657ec638c17John McCall/// 685db73c684ba61fed4087af488e8610657ec638c17John McCall/// Along a single inheritance path we can restate both of these 686db73c684ba61fed4087af488e8610657ec638c17John McCall/// iteratively: 687db73c684ba61fed4087af488e8610657ec638c17John McCall/// 688db73c684ba61fed4087af488e8610657ec638c17John McCall/// First, we note that M1-4 are equivalent to B1-4 if the member is 689db73c684ba61fed4087af488e8610657ec638c17John McCall/// treated as a notional base of its declaring class with inheritance 690db73c684ba61fed4087af488e8610657ec638c17John McCall/// access equivalent to the member's access. Therefore we need only 691db73c684ba61fed4087af488e8610657ec638c17John McCall/// ask whether a class B is accessible from a class N in context R. 692db73c684ba61fed4087af488e8610657ec638c17John McCall/// 693db73c684ba61fed4087af488e8610657ec638c17John McCall/// Let B_1 .. B_n be the inheritance path in question (i.e. where 694db73c684ba61fed4087af488e8610657ec638c17John McCall/// B_1 = N, B_n = B, and for all i, B_{i+1} is a direct base class of 695db73c684ba61fed4087af488e8610657ec638c17John McCall/// B_i). For i in 1..n, we will calculate ACAB(i), the access to the 696db73c684ba61fed4087af488e8610657ec638c17John McCall/// closest accessible base in the path: 697db73c684ba61fed4087af488e8610657ec638c17John McCall/// Access(a, b) = (* access on the base specifier from a to b *) 698db73c684ba61fed4087af488e8610657ec638c17John McCall/// Merge(a, forbidden) = forbidden 699db73c684ba61fed4087af488e8610657ec638c17John McCall/// Merge(a, private) = forbidden 700db73c684ba61fed4087af488e8610657ec638c17John McCall/// Merge(a, b) = min(a,b) 701db73c684ba61fed4087af488e8610657ec638c17John McCall/// Accessible(c, forbidden) = false 702db73c684ba61fed4087af488e8610657ec638c17John McCall/// Accessible(c, private) = (R is c) || IsFriend(c, R) 703db73c684ba61fed4087af488e8610657ec638c17John McCall/// Accessible(c, protected) = (R derived from c) || IsFriend(c, R) 704db73c684ba61fed4087af488e8610657ec638c17John McCall/// Accessible(c, public) = true 705db73c684ba61fed4087af488e8610657ec638c17John McCall/// ACAB(n) = public 706db73c684ba61fed4087af488e8610657ec638c17John McCall/// ACAB(i) = 707db73c684ba61fed4087af488e8610657ec638c17John McCall/// let AccessToBase = Merge(Access(B_i, B_{i+1}), ACAB(i+1)) in 708db73c684ba61fed4087af488e8610657ec638c17John McCall/// if Accessible(B_i, AccessToBase) then public else AccessToBase 709db73c684ba61fed4087af488e8610657ec638c17John McCall/// 710db73c684ba61fed4087af488e8610657ec638c17John McCall/// B is an accessible base of N at R iff ACAB(1) = public. 711db73c684ba61fed4087af488e8610657ec638c17John McCall/// 712161755a09898c95d21bfff33707da9ca41cd53c5John McCall/// \param FinalAccess the access of the "final step", or AS_public if 7137aceaf8cee77c98478e8934dc283910292711a7eJohn McCall/// there is no final step. 7146b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// \return null if friendship is dependent 7156b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallstatic CXXBasePath *FindBestPath(Sema &S, 7166b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall const EffectiveContext &EC, 717161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget &Target, 7187aceaf8cee77c98478e8934dc283910292711a7eJohn McCall AccessSpecifier FinalAccess, 7196b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall CXXBasePaths &Paths) { 7206b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // Derive the paths to the desired base. 721161755a09898c95d21bfff33707da9ca41cd53c5John McCall const CXXRecordDecl *Derived = Target.getNamingClass(); 722161755a09898c95d21bfff33707da9ca41cd53c5John McCall const CXXRecordDecl *Base = Target.getDeclaringClass(); 723161755a09898c95d21bfff33707da9ca41cd53c5John McCall 724161755a09898c95d21bfff33707da9ca41cd53c5John McCall // FIXME: fail correctly when there are dependent paths. 725161755a09898c95d21bfff33707da9ca41cd53c5John McCall bool isDerived = Derived->isDerivedFrom(const_cast<CXXRecordDecl*>(Base), 726161755a09898c95d21bfff33707da9ca41cd53c5John McCall Paths); 7276b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall assert(isDerived && "derived class not actually derived from base"); 7286b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall (void) isDerived; 7296b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 7306b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall CXXBasePath *BestPath = 0; 7316b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 7327aceaf8cee77c98478e8934dc283910292711a7eJohn McCall assert(FinalAccess != AS_none && "forbidden access after declaring class"); 7337aceaf8cee77c98478e8934dc283910292711a7eJohn McCall 7340c01d18094100db92d38daa923c95661512db203John McCall bool AnyDependent = false; 7350c01d18094100db92d38daa923c95661512db203John McCall 7366b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // Derive the friend-modified access along each path. 7376b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall for (CXXBasePaths::paths_iterator PI = Paths.begin(), PE = Paths.end(); 7386b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall PI != PE; ++PI) { 739161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget::SavedInstanceContext _ = Target.saveInstanceContext(); 7406b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 7416b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // Walk through the path backwards. 7427aceaf8cee77c98478e8934dc283910292711a7eJohn McCall AccessSpecifier PathAccess = FinalAccess; 7436b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall CXXBasePath::iterator I = PI->end(), E = PI->begin(); 7446b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall while (I != E) { 7456b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall --I; 7466b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 7477aceaf8cee77c98478e8934dc283910292711a7eJohn McCall assert(PathAccess != AS_none); 7487aceaf8cee77c98478e8934dc283910292711a7eJohn McCall 7497aceaf8cee77c98478e8934dc283910292711a7eJohn McCall // If the declaration is a private member of a base class, there 7507aceaf8cee77c98478e8934dc283910292711a7eJohn McCall // is no level of friendship in derived classes that can make it 7517aceaf8cee77c98478e8934dc283910292711a7eJohn McCall // accessible. 7527aceaf8cee77c98478e8934dc283910292711a7eJohn McCall if (PathAccess == AS_private) { 7537aceaf8cee77c98478e8934dc283910292711a7eJohn McCall PathAccess = AS_none; 7547aceaf8cee77c98478e8934dc283910292711a7eJohn McCall break; 7557aceaf8cee77c98478e8934dc283910292711a7eJohn McCall } 7567aceaf8cee77c98478e8934dc283910292711a7eJohn McCall 757161755a09898c95d21bfff33707da9ca41cd53c5John McCall const CXXRecordDecl *NC = I->Class->getCanonicalDecl(); 758161755a09898c95d21bfff33707da9ca41cd53c5John McCall 7596b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall AccessSpecifier BaseAccess = I->Base->getAccessSpecifier(); 760db73c684ba61fed4087af488e8610657ec638c17John McCall PathAccess = std::max(PathAccess, BaseAccess); 761161755a09898c95d21bfff33707da9ca41cd53c5John McCall 762161755a09898c95d21bfff33707da9ca41cd53c5John McCall switch (HasAccess(S, EC, NC, PathAccess, Target)) { 763161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_inaccessible: break; 764161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_accessible: 765161755a09898c95d21bfff33707da9ca41cd53c5John McCall PathAccess = AS_public; 766161755a09898c95d21bfff33707da9ca41cd53c5John McCall 767161755a09898c95d21bfff33707da9ca41cd53c5John McCall // Future tests are not against members and so do not have 768161755a09898c95d21bfff33707da9ca41cd53c5John McCall // instance context. 769161755a09898c95d21bfff33707da9ca41cd53c5John McCall Target.suppressInstanceContext(); 770161755a09898c95d21bfff33707da9ca41cd53c5John McCall break; 771161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_dependent: 772db73c684ba61fed4087af488e8610657ec638c17John McCall AnyDependent = true; 773db73c684ba61fed4087af488e8610657ec638c17John McCall goto Next; 774c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson } 775c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson } 776726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl 7776b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // Note that we modify the path's Access field to the 7786b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // friend-modified access. 7796b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall if (BestPath == 0 || PathAccess < BestPath->Access) { 7806b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall BestPath = &*PI; 7816b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall BestPath->Access = PathAccess; 7820c01d18094100db92d38daa923c95661512db203John McCall 7830c01d18094100db92d38daa923c95661512db203John McCall // Short-circuit if we found a public path. 7840c01d18094100db92d38daa923c95661512db203John McCall if (BestPath->Access == AS_public) 7850c01d18094100db92d38daa923c95661512db203John McCall return BestPath; 786c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson } 7870c01d18094100db92d38daa923c95661512db203John McCall 7880c01d18094100db92d38daa923c95661512db203John McCall Next: ; 789c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson } 790c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson 7910c01d18094100db92d38daa923c95661512db203John McCall assert((!BestPath || BestPath->Access != AS_public) && 7920c01d18094100db92d38daa923c95661512db203John McCall "fell out of loop with public path"); 7930c01d18094100db92d38daa923c95661512db203John McCall 7940c01d18094100db92d38daa923c95661512db203John McCall // We didn't find a public path, but at least one path was subject 7950c01d18094100db92d38daa923c95661512db203John McCall // to dependent friendship, so delay the check. 7960c01d18094100db92d38daa923c95661512db203John McCall if (AnyDependent) 7970c01d18094100db92d38daa923c95661512db203John McCall return 0; 7980c01d18094100db92d38daa923c95661512db203John McCall 7996b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return BestPath; 800726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl} 801726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl 8026b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// Diagnose the path which caused the given declaration or base class 8036b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// to become inaccessible. 8046b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallstatic void DiagnoseAccessPath(Sema &S, 8056b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall const EffectiveContext &EC, 806161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget &Entity) { 807db73c684ba61fed4087af488e8610657ec638c17John McCall AccessSpecifier Access = Entity.getAccess(); 808161755a09898c95d21bfff33707da9ca41cd53c5John McCall const CXXRecordDecl *NamingClass = Entity.getNamingClass(); 809db73c684ba61fed4087af488e8610657ec638c17John McCall NamingClass = NamingClass->getCanonicalDecl(); 810db73c684ba61fed4087af488e8610657ec638c17John McCall 811161755a09898c95d21bfff33707da9ca41cd53c5John McCall NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : 0); 812161755a09898c95d21bfff33707da9ca41cd53c5John McCall const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass(); 813db73c684ba61fed4087af488e8610657ec638c17John McCall 8146b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // Easy case: the decl's natural access determined its path access. 8156b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // We have to check against AS_private here in case Access is AS_none, 8166b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // indicating a non-public member of a private base class. 8176b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall if (D && (Access == D->getAccess() || D->getAccess() == AS_private)) { 818161755a09898c95d21bfff33707da9ca41cd53c5John McCall switch (HasAccess(S, EC, DeclaringClass, D->getAccess(), Entity)) { 819161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_inaccessible: { 8206b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall S.Diag(D->getLocation(), diag::note_access_natural) 8216b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall << (unsigned) (Access == AS_protected) 8226b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall << /*FIXME: not implicitly*/ 0; 8236b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return; 8246b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall } 825726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl 826161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_accessible: break; 827726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl 828161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_dependent: 829161755a09898c95d21bfff33707da9ca41cd53c5John McCall llvm_unreachable("can't diagnose dependent access failures"); 8306b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return; 8316b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall } 8326b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall } 833c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson 8346b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall CXXBasePaths Paths; 835161755a09898c95d21bfff33707da9ca41cd53c5John McCall CXXBasePath &Path = *FindBestPath(S, EC, Entity, AS_public, Paths); 836726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl 8376b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall CXXBasePath::iterator I = Path.end(), E = Path.begin(); 8386b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall while (I != E) { 8396b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall --I; 840c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson 8416b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall const CXXBaseSpecifier *BS = I->Base; 8426b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall AccessSpecifier BaseAccess = BS->getAccessSpecifier(); 8436b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 8446b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // If this is public inheritance, or the derived class is a friend, 8456b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // skip this step. 8466b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall if (BaseAccess == AS_public) 8476b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall continue; 8486b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 8496b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall switch (GetFriendKind(S, EC, I->Class)) { 850161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_accessible: continue; 851161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_inaccessible: break; 852161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_dependent: 853161755a09898c95d21bfff33707da9ca41cd53c5John McCall llvm_unreachable("can't diagnose dependent access failures"); 8546b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall } 8556b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 8566b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // Check whether this base specifier is the tighest point 8576b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // constraining access. We have to check against AS_private for 8586b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // the same reasons as above. 8596b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall if (BaseAccess == AS_private || BaseAccess >= Access) { 8606b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 8616b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // We're constrained by inheritance, but we want to say 8626b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // "declared private here" if we're diagnosing a hierarchy 8636b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // conversion and this is the final step. 8646b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall unsigned diagnostic; 8656b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall if (D) diagnostic = diag::note_access_constrained_by_path; 8666b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall else if (I + 1 == Path.end()) diagnostic = diag::note_access_natural; 8676b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall else diagnostic = diag::note_access_constrained_by_path; 8686b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 8696b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall S.Diag(BS->getSourceRange().getBegin(), diagnostic) 8706b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall << BS->getSourceRange() 8716b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall << (BaseAccess == AS_protected) 8726b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall << (BS->getAccessSpecifierAsWritten() == AS_none); 87376ef658c703faf72c00f324fb9edc03169718e3eDouglas Gregor 87476ef658c703faf72c00f324fb9edc03169718e3eDouglas Gregor if (D) 87576ef658c703faf72c00f324fb9edc03169718e3eDouglas Gregor S.Diag(D->getLocation(), diag::note_field_decl); 87676ef658c703faf72c00f324fb9edc03169718e3eDouglas Gregor 8776b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return; 8786b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall } 879c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson } 880726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl 8816b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall llvm_unreachable("access not apparently constrained by path"); 88229f006be830fbbcaa0c1cf7c7399bb5080dc7f32Anders Carlsson} 88392f883177b162928a8e632e4e3b93fafd2b26072John McCall 884db73c684ba61fed4087af488e8610657ec638c17John McCallstatic void DiagnoseBadAccess(Sema &S, SourceLocation Loc, 885db73c684ba61fed4087af488e8610657ec638c17John McCall const EffectiveContext &EC, 886161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget &Entity) { 887db73c684ba61fed4087af488e8610657ec638c17John McCall const CXXRecordDecl *NamingClass = Entity.getNamingClass(); 888161755a09898c95d21bfff33707da9ca41cd53c5John McCall const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass(); 889161755a09898c95d21bfff33707da9ca41cd53c5John McCall NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : 0); 8906b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 89158e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall S.Diag(Loc, Entity.getDiag()) 892db73c684ba61fed4087af488e8610657ec638c17John McCall << (Entity.getAccess() == AS_protected) 893db73c684ba61fed4087af488e8610657ec638c17John McCall << (D ? D->getDeclName() : DeclarationName()) 89458e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall << S.Context.getTypeDeclType(NamingClass) 89558e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall << S.Context.getTypeDeclType(DeclaringClass); 896db73c684ba61fed4087af488e8610657ec638c17John McCall DiagnoseAccessPath(S, EC, Entity); 8976b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall} 89892f883177b162928a8e632e4e3b93fafd2b26072John McCall 899db73c684ba61fed4087af488e8610657ec638c17John McCall/// Determines whether the accessed entity is accessible. Public members 900db73c684ba61fed4087af488e8610657ec638c17John McCall/// have been weeded out by this point. 901161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic AccessResult IsAccessible(Sema &S, 902161755a09898c95d21bfff33707da9ca41cd53c5John McCall const EffectiveContext &EC, 903161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget &Entity) { 904db73c684ba61fed4087af488e8610657ec638c17John McCall // Determine the actual naming class. 905db73c684ba61fed4087af488e8610657ec638c17John McCall CXXRecordDecl *NamingClass = Entity.getNamingClass(); 906db73c684ba61fed4087af488e8610657ec638c17John McCall while (NamingClass->isAnonymousStructOrUnion()) 907db73c684ba61fed4087af488e8610657ec638c17John McCall NamingClass = cast<CXXRecordDecl>(NamingClass->getParent()); 908db73c684ba61fed4087af488e8610657ec638c17John McCall NamingClass = NamingClass->getCanonicalDecl(); 90992f883177b162928a8e632e4e3b93fafd2b26072John McCall 910db73c684ba61fed4087af488e8610657ec638c17John McCall AccessSpecifier UnprivilegedAccess = Entity.getAccess(); 911db73c684ba61fed4087af488e8610657ec638c17John McCall assert(UnprivilegedAccess != AS_public && "public access not weeded out"); 91292f883177b162928a8e632e4e3b93fafd2b26072John McCall 913db73c684ba61fed4087af488e8610657ec638c17John McCall // Before we try to recalculate access paths, try to white-list 914db73c684ba61fed4087af488e8610657ec638c17John McCall // accesses which just trade in on the final step, i.e. accesses 915db73c684ba61fed4087af488e8610657ec638c17John McCall // which don't require [M4] or [B4]. These are by far the most 916161755a09898c95d21bfff33707da9ca41cd53c5John McCall // common forms of privileged access. 917db73c684ba61fed4087af488e8610657ec638c17John McCall if (UnprivilegedAccess != AS_none) { 918161755a09898c95d21bfff33707da9ca41cd53c5John McCall switch (HasAccess(S, EC, NamingClass, UnprivilegedAccess, Entity)) { 919161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_dependent: 920db73c684ba61fed4087af488e8610657ec638c17John McCall // This is actually an interesting policy decision. We don't 921db73c684ba61fed4087af488e8610657ec638c17John McCall // *have* to delay immediately here: we can do the full access 922db73c684ba61fed4087af488e8610657ec638c17John McCall // calculation in the hope that friendship on some intermediate 923db73c684ba61fed4087af488e8610657ec638c17John McCall // class will make the declaration accessible non-dependently. 924db73c684ba61fed4087af488e8610657ec638c17John McCall // But that's not cheap, and odds are very good (note: assertion 925db73c684ba61fed4087af488e8610657ec638c17John McCall // made without data) that the friend declaration will determine 926db73c684ba61fed4087af488e8610657ec638c17John McCall // access. 927161755a09898c95d21bfff33707da9ca41cd53c5John McCall return AR_dependent; 928db73c684ba61fed4087af488e8610657ec638c17John McCall 929161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_accessible: return AR_accessible; 930161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_inaccessible: break; 931db73c684ba61fed4087af488e8610657ec638c17John McCall } 932db73c684ba61fed4087af488e8610657ec638c17John McCall } 93392f883177b162928a8e632e4e3b93fafd2b26072John McCall 934161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget::SavedInstanceContext _ = Entity.saveInstanceContext(); 935db73c684ba61fed4087af488e8610657ec638c17John McCall 936db73c684ba61fed4087af488e8610657ec638c17John McCall // We lower member accesses to base accesses by pretending that the 937db73c684ba61fed4087af488e8610657ec638c17John McCall // member is a base class of its declaring class. 938db73c684ba61fed4087af488e8610657ec638c17John McCall AccessSpecifier FinalAccess; 9396b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 9406b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall if (Entity.isMemberAccess()) { 941db73c684ba61fed4087af488e8610657ec638c17John McCall // Determine if the declaration is accessible from EC when named 942db73c684ba61fed4087af488e8610657ec638c17John McCall // in its declaring class. 9436b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall NamedDecl *Target = Entity.getTargetDecl(); 944161755a09898c95d21bfff33707da9ca41cd53c5John McCall const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass(); 9456b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 946db73c684ba61fed4087af488e8610657ec638c17John McCall FinalAccess = Target->getAccess(); 947161755a09898c95d21bfff33707da9ca41cd53c5John McCall switch (HasAccess(S, EC, DeclaringClass, FinalAccess, Entity)) { 948161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_accessible: 949161755a09898c95d21bfff33707da9ca41cd53c5John McCall FinalAccess = AS_public; 950161755a09898c95d21bfff33707da9ca41cd53c5John McCall break; 951161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_inaccessible: break; 952161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_dependent: return AR_dependent; // see above 9536b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall } 9542f514480c448708ec382a684cf5e035d3a827ec8John McCall 955db73c684ba61fed4087af488e8610657ec638c17John McCall if (DeclaringClass == NamingClass) 956161755a09898c95d21bfff33707da9ca41cd53c5John McCall return (FinalAccess == AS_public ? AR_accessible : AR_inaccessible); 957161755a09898c95d21bfff33707da9ca41cd53c5John McCall 958161755a09898c95d21bfff33707da9ca41cd53c5John McCall Entity.suppressInstanceContext(); 959db73c684ba61fed4087af488e8610657ec638c17John McCall } else { 960db73c684ba61fed4087af488e8610657ec638c17John McCall FinalAccess = AS_public; 9616b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall } 9622f514480c448708ec382a684cf5e035d3a827ec8John McCall 963161755a09898c95d21bfff33707da9ca41cd53c5John McCall assert(Entity.getDeclaringClass() != NamingClass); 9646b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 9656b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // Append the declaration's access if applicable. 9666b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall CXXBasePaths Paths; 967161755a09898c95d21bfff33707da9ca41cd53c5John McCall CXXBasePath *Path = FindBestPath(S, EC, Entity, FinalAccess, Paths); 9680c01d18094100db92d38daa923c95661512db203John McCall if (!Path) 969161755a09898c95d21bfff33707da9ca41cd53c5John McCall return AR_dependent; 97092f883177b162928a8e632e4e3b93fafd2b26072John McCall 971db73c684ba61fed4087af488e8610657ec638c17John McCall assert(Path->Access <= UnprivilegedAccess && 972db73c684ba61fed4087af488e8610657ec638c17John McCall "access along best path worse than direct?"); 973db73c684ba61fed4087af488e8610657ec638c17John McCall if (Path->Access == AS_public) 974161755a09898c95d21bfff33707da9ca41cd53c5John McCall return AR_accessible; 975161755a09898c95d21bfff33707da9ca41cd53c5John McCall return AR_inaccessible; 9760c01d18094100db92d38daa923c95661512db203John McCall} 9770c01d18094100db92d38daa923c95661512db203John McCall 978161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic void DelayDependentAccess(Sema &S, 979161755a09898c95d21bfff33707da9ca41cd53c5John McCall const EffectiveContext &EC, 980161755a09898c95d21bfff33707da9ca41cd53c5John McCall SourceLocation Loc, 981161755a09898c95d21bfff33707da9ca41cd53c5John McCall const AccessTarget &Entity) { 9820c01d18094100db92d38daa923c95661512db203John McCall assert(EC.isDependent() && "delaying non-dependent access"); 9837ad650f88ecbbe659f10f9f6b34a1f29ea9cf8f9John McCall DeclContext *DC = EC.getInnerContext(); 9840c01d18094100db92d38daa923c95661512db203John McCall assert(DC->isDependentContext() && "delaying non-dependent access"); 9850c01d18094100db92d38daa923c95661512db203John McCall DependentDiagnostic::Create(S.Context, DC, DependentDiagnostic::Access, 9860c01d18094100db92d38daa923c95661512db203John McCall Loc, 9870c01d18094100db92d38daa923c95661512db203John McCall Entity.isMemberAccess(), 9880c01d18094100db92d38daa923c95661512db203John McCall Entity.getAccess(), 9890c01d18094100db92d38daa923c95661512db203John McCall Entity.getTargetDecl(), 9900c01d18094100db92d38daa923c95661512db203John McCall Entity.getNamingClass(), 991161755a09898c95d21bfff33707da9ca41cd53c5John McCall Entity.getBaseObjectType(), 9920c01d18094100db92d38daa923c95661512db203John McCall Entity.getDiag()); 9936b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall} 9946b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 9956b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// Checks access to an entity from the given effective context. 996161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic AccessResult CheckEffectiveAccess(Sema &S, 997161755a09898c95d21bfff33707da9ca41cd53c5John McCall const EffectiveContext &EC, 998161755a09898c95d21bfff33707da9ca41cd53c5John McCall SourceLocation Loc, 999161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget &Entity) { 1000db73c684ba61fed4087af488e8610657ec638c17John McCall assert(Entity.getAccess() != AS_public && "called for public access!"); 100192f883177b162928a8e632e4e3b93fafd2b26072John McCall 1002db73c684ba61fed4087af488e8610657ec638c17John McCall switch (IsAccessible(S, EC, Entity)) { 1003161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_dependent: 1004161755a09898c95d21bfff33707da9ca41cd53c5John McCall DelayDependentAccess(S, EC, Loc, Entity); 1005161755a09898c95d21bfff33707da9ca41cd53c5John McCall return AR_dependent; 10060c01d18094100db92d38daa923c95661512db203John McCall 1007161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_inaccessible: 1008db73c684ba61fed4087af488e8610657ec638c17John McCall if (!Entity.isQuiet()) 1009db73c684ba61fed4087af488e8610657ec638c17John McCall DiagnoseBadAccess(S, Loc, EC, Entity); 1010161755a09898c95d21bfff33707da9ca41cd53c5John McCall return AR_inaccessible; 101192f883177b162928a8e632e4e3b93fafd2b26072John McCall 1012161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_accessible: 1013161755a09898c95d21bfff33707da9ca41cd53c5John McCall return AR_accessible; 1014db73c684ba61fed4087af488e8610657ec638c17John McCall } 1015db73c684ba61fed4087af488e8610657ec638c17John McCall 1016161755a09898c95d21bfff33707da9ca41cd53c5John McCall // silence unnecessary warning 1017161755a09898c95d21bfff33707da9ca41cd53c5John McCall llvm_unreachable("invalid access result"); 1018161755a09898c95d21bfff33707da9ca41cd53c5John McCall return AR_accessible; 10196b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall} 102092f883177b162928a8e632e4e3b93fafd2b26072John McCall 10216b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallstatic Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc, 1022161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget &Entity) { 10236b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // If the access path is public, it's accessible everywhere. 10246b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall if (Entity.getAccess() == AS_public) 10256b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return Sema::AR_accessible; 102692f883177b162928a8e632e4e3b93fafd2b26072John McCall 10276b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // If we're currently parsing a top-level declaration, delay 10286b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // diagnostics. This is the only case where parsing a declaration 10296b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // can actually change our effective context for the purposes of 10306b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // access control. 10316b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall if (S.CurContext->isFileContext() && S.ParsingDeclDepth) { 10326b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall S.DelayedDiagnostics.push_back( 10336b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall Sema::DelayedDiagnostic::makeAccess(Loc, Entity)); 10346b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return Sema::AR_delayed; 103592f883177b162928a8e632e4e3b93fafd2b26072John McCall } 103692f883177b162928a8e632e4e3b93fafd2b26072John McCall 1037161755a09898c95d21bfff33707da9ca41cd53c5John McCall EffectiveContext EC(S.CurContext); 1038161755a09898c95d21bfff33707da9ca41cd53c5John McCall switch (CheckEffectiveAccess(S, EC, Loc, Entity)) { 1039161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_accessible: return Sema::AR_accessible; 1040161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_inaccessible: return Sema::AR_inaccessible; 1041161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_dependent: return Sema::AR_dependent; 1042161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 1043161755a09898c95d21bfff33707da9ca41cd53c5John McCall llvm_unreachable("falling off end"); 1044161755a09898c95d21bfff33707da9ca41cd53c5John McCall return Sema::AR_accessible; 104592f883177b162928a8e632e4e3b93fafd2b26072John McCall} 104692f883177b162928a8e632e4e3b93fafd2b26072John McCall 10472f514480c448708ec382a684cf5e035d3a827ec8John McCallvoid Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *Ctx) { 10482f514480c448708ec382a684cf5e035d3a827ec8John McCall // Pretend we did this from the context of the newly-parsed 1049630eb01b2568d0958118eb1a0ded02bebecb2b0fChandler Carruth // declaration. If that declaration itself forms a declaration context, 1050630eb01b2568d0958118eb1a0ded02bebecb2b0fChandler Carruth // include it in the effective context so that parameters and return types of 1051630eb01b2568d0958118eb1a0ded02bebecb2b0fChandler Carruth // befriended functions have that function's access priveledges. 1052630eb01b2568d0958118eb1a0ded02bebecb2b0fChandler Carruth DeclContext *DC = Ctx->getDeclContext(); 1053630eb01b2568d0958118eb1a0ded02bebecb2b0fChandler Carruth if (isa<FunctionDecl>(Ctx)) 1054630eb01b2568d0958118eb1a0ded02bebecb2b0fChandler Carruth DC = cast<DeclContext>(Ctx); 1055630eb01b2568d0958118eb1a0ded02bebecb2b0fChandler Carruth else if (FunctionTemplateDecl *FnTpl = dyn_cast<FunctionTemplateDecl>(Ctx)) 1056630eb01b2568d0958118eb1a0ded02bebecb2b0fChandler Carruth DC = cast<DeclContext>(FnTpl->getTemplatedDecl()); 1057630eb01b2568d0958118eb1a0ded02bebecb2b0fChandler Carruth EffectiveContext EC(DC); 10582f514480c448708ec382a684cf5e035d3a827ec8John McCall 1059161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget Target(DD.getAccessData()); 1060161755a09898c95d21bfff33707da9ca41cd53c5John McCall 1061161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (CheckEffectiveAccess(*this, EC, DD.Loc, Target) == ::AR_inaccessible) 10622f514480c448708ec382a684cf5e035d3a827ec8John McCall DD.Triggered = true; 10632f514480c448708ec382a684cf5e035d3a827ec8John McCall} 10642f514480c448708ec382a684cf5e035d3a827ec8John McCall 10650c01d18094100db92d38daa923c95661512db203John McCallvoid Sema::HandleDependentAccessCheck(const DependentDiagnostic &DD, 10660c01d18094100db92d38daa923c95661512db203John McCall const MultiLevelTemplateArgumentList &TemplateArgs) { 10670c01d18094100db92d38daa923c95661512db203John McCall SourceLocation Loc = DD.getAccessLoc(); 10680c01d18094100db92d38daa923c95661512db203John McCall AccessSpecifier Access = DD.getAccess(); 10690c01d18094100db92d38daa923c95661512db203John McCall 10700c01d18094100db92d38daa923c95661512db203John McCall Decl *NamingD = FindInstantiatedDecl(Loc, DD.getAccessNamingClass(), 10710c01d18094100db92d38daa923c95661512db203John McCall TemplateArgs); 10720c01d18094100db92d38daa923c95661512db203John McCall if (!NamingD) return; 10730c01d18094100db92d38daa923c95661512db203John McCall Decl *TargetD = FindInstantiatedDecl(Loc, DD.getAccessTarget(), 10740c01d18094100db92d38daa923c95661512db203John McCall TemplateArgs); 10750c01d18094100db92d38daa923c95661512db203John McCall if (!TargetD) return; 10760c01d18094100db92d38daa923c95661512db203John McCall 10770c01d18094100db92d38daa923c95661512db203John McCall if (DD.isAccessToMember()) { 1078161755a09898c95d21bfff33707da9ca41cd53c5John McCall CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(NamingD); 1079161755a09898c95d21bfff33707da9ca41cd53c5John McCall NamedDecl *TargetDecl = cast<NamedDecl>(TargetD); 1080161755a09898c95d21bfff33707da9ca41cd53c5John McCall QualType BaseObjectType = DD.getAccessBaseObjectType(); 1081161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (!BaseObjectType.isNull()) { 1082161755a09898c95d21bfff33707da9ca41cd53c5John McCall BaseObjectType = SubstType(BaseObjectType, TemplateArgs, Loc, 1083161755a09898c95d21bfff33707da9ca41cd53c5John McCall DeclarationName()); 1084161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (BaseObjectType.isNull()) return; 1085161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 1086161755a09898c95d21bfff33707da9ca41cd53c5John McCall 1087161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget Entity(Context, 1088161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget::Member, 1089161755a09898c95d21bfff33707da9ca41cd53c5John McCall NamingClass, 1090161755a09898c95d21bfff33707da9ca41cd53c5John McCall DeclAccessPair::make(TargetDecl, Access), 1091161755a09898c95d21bfff33707da9ca41cd53c5John McCall BaseObjectType); 10920c01d18094100db92d38daa923c95661512db203John McCall Entity.setDiag(DD.getDiagnostic()); 10930c01d18094100db92d38daa923c95661512db203John McCall CheckAccess(*this, Loc, Entity); 10940c01d18094100db92d38daa923c95661512db203John McCall } else { 1095161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget Entity(Context, 1096161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget::Base, 1097161755a09898c95d21bfff33707da9ca41cd53c5John McCall cast<CXXRecordDecl>(TargetD), 1098161755a09898c95d21bfff33707da9ca41cd53c5John McCall cast<CXXRecordDecl>(NamingD), 1099161755a09898c95d21bfff33707da9ca41cd53c5John McCall Access); 11000c01d18094100db92d38daa923c95661512db203John McCall Entity.setDiag(DD.getDiagnostic()); 11010c01d18094100db92d38daa923c95661512db203John McCall CheckAccess(*this, Loc, Entity); 11020c01d18094100db92d38daa923c95661512db203John McCall } 11030c01d18094100db92d38daa923c95661512db203John McCall} 11040c01d18094100db92d38daa923c95661512db203John McCall 11056b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallSema::AccessResult Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E, 11069aa472c45d2bd81b7b52c225e8acc560d716db97John McCall DeclAccessPair Found) { 110758e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall if (!getLangOptions().AccessControl || 110858e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall !E->getNamingClass() || 11099aa472c45d2bd81b7b52c225e8acc560d716db97John McCall Found.getAccess() == AS_public) 11106b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return AR_accessible; 1111c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall 1112161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(), 1113161755a09898c95d21bfff33707da9ca41cd53c5John McCall Found, QualType()); 111458e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall Entity.setDiag(diag::err_access) << E->getSourceRange(); 111558e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall 111658e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall return CheckAccess(*this, E->getNameLoc(), Entity); 1117c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall} 1118c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall 1119c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall/// Perform access-control checking on a previously-unresolved member 1120c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall/// access which has now been resolved to a member. 11216b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallSema::AccessResult Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E, 11229aa472c45d2bd81b7b52c225e8acc560d716db97John McCall DeclAccessPair Found) { 112358e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall if (!getLangOptions().AccessControl || 11249aa472c45d2bd81b7b52c225e8acc560d716db97John McCall Found.getAccess() == AS_public) 11256b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return AR_accessible; 1126c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall 1127161755a09898c95d21bfff33707da9ca41cd53c5John McCall QualType BaseType = E->getBaseType(); 1128161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (E->isArrow()) 1129161755a09898c95d21bfff33707da9ca41cd53c5John McCall BaseType = BaseType->getAs<PointerType>()->getPointeeType(); 1130161755a09898c95d21bfff33707da9ca41cd53c5John McCall 1131161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(), 1132161755a09898c95d21bfff33707da9ca41cd53c5John McCall Found, BaseType); 113358e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall Entity.setDiag(diag::err_access) << E->getSourceRange(); 113458e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall 113558e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall return CheckAccess(*this, E->getMemberLoc(), Entity); 1136c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall} 1137c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall 11386b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallSema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc, 113958e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall CXXDestructorDecl *Dtor, 114058e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall const PartialDiagnostic &PDiag) { 11414f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall if (!getLangOptions().AccessControl) 11426b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return AR_accessible; 11434f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall 114458e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall // There's never a path involved when checking implicit destructor access. 11454f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall AccessSpecifier Access = Dtor->getAccess(); 11464f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall if (Access == AS_public) 11476b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return AR_accessible; 11484f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall 114958e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall CXXRecordDecl *NamingClass = Dtor->getParent(); 1150161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget Entity(Context, AccessTarget::Member, NamingClass, 1151161755a09898c95d21bfff33707da9ca41cd53c5John McCall DeclAccessPair::make(Dtor, Access), 1152161755a09898c95d21bfff33707da9ca41cd53c5John McCall QualType()); 115358e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall Entity.setDiag(PDiag); // TODO: avoid copy 115458e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall 115558e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall return CheckAccess(*this, Loc, Entity); 11564f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall} 11574f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall 1158b13b737a2450167c82e148590e8019b839ce6b98John McCall/// Checks access to a constructor. 11596b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallSema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc, 116057d12fd4a2bc739c4a4d62a364b7f08cd483c59eJeffrey Yasskin CXXConstructorDecl *Constructor, 116157d12fd4a2bc739c4a4d62a364b7f08cd483c59eJeffrey Yasskin const InitializedEntity &Entity, 116257d12fd4a2bc739c4a4d62a364b7f08cd483c59eJeffrey Yasskin AccessSpecifier Access, 116357d12fd4a2bc739c4a4d62a364b7f08cd483c59eJeffrey Yasskin bool IsCopyBindingRefToTemp) { 116458e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall if (!getLangOptions().AccessControl || 116558e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall Access == AS_public) 11666b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return AR_accessible; 1167b13b737a2450167c82e148590e8019b839ce6b98John McCall 11686b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall CXXRecordDecl *NamingClass = Constructor->getParent(); 11699a68a67c6ae4982001815cc04f69b8781058263aAnders Carlsson AccessTarget AccessEntity(Context, AccessTarget::Member, NamingClass, 11709a68a67c6ae4982001815cc04f69b8781058263aAnders Carlsson DeclAccessPair::make(Constructor, Access), 11719a68a67c6ae4982001815cc04f69b8781058263aAnders Carlsson QualType()); 11729a68a67c6ae4982001815cc04f69b8781058263aAnders Carlsson switch (Entity.getKind()) { 11739a68a67c6ae4982001815cc04f69b8781058263aAnders Carlsson default: 117457d12fd4a2bc739c4a4d62a364b7f08cd483c59eJeffrey Yasskin AccessEntity.setDiag(IsCopyBindingRefToTemp 117557d12fd4a2bc739c4a4d62a364b7f08cd483c59eJeffrey Yasskin ? diag::ext_rvalue_to_reference_access_ctor 117657d12fd4a2bc739c4a4d62a364b7f08cd483c59eJeffrey Yasskin : diag::err_access_ctor); 11779a68a67c6ae4982001815cc04f69b8781058263aAnders Carlsson break; 11789a68a67c6ae4982001815cc04f69b8781058263aAnders Carlsson 11793b8c53b619c1c3d77632734d227566071459b9f5Anders Carlsson case InitializedEntity::EK_Base: 11803b8c53b619c1c3d77632734d227566071459b9f5Anders Carlsson AccessEntity.setDiag(PDiag(diag::err_access_base) 11813b8c53b619c1c3d77632734d227566071459b9f5Anders Carlsson << Entity.isInheritedVirtualBase() 11823b8c53b619c1c3d77632734d227566071459b9f5Anders Carlsson << Entity.getBaseSpecifier()->getType() 11833b8c53b619c1c3d77632734d227566071459b9f5Anders Carlsson << getSpecialMember(Constructor)); 11849a68a67c6ae4982001815cc04f69b8781058263aAnders Carlsson break; 11853b8c53b619c1c3d77632734d227566071459b9f5Anders Carlsson 1186b99c666a940e93bcfcaeddc01515c94472e28a20Anders Carlsson case InitializedEntity::EK_Member: { 1187b99c666a940e93bcfcaeddc01515c94472e28a20Anders Carlsson const FieldDecl *Field = cast<FieldDecl>(Entity.getDecl()); 11880e313bd4795c005f23c43f127039fd948c3e0bd9Anders Carlsson AccessEntity.setDiag(PDiag(diag::err_access_field) 11890e313bd4795c005f23c43f127039fd948c3e0bd9Anders Carlsson << Field->getType() 11900e313bd4795c005f23c43f127039fd948c3e0bd9Anders Carlsson << getSpecialMember(Constructor)); 1191b99c666a940e93bcfcaeddc01515c94472e28a20Anders Carlsson break; 1192b99c666a940e93bcfcaeddc01515c94472e28a20Anders Carlsson } 119358e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall 1194711f34adb886cce8ba86c7b1b6513a1eaaf63bb5Anders Carlsson } 1195711f34adb886cce8ba86c7b1b6513a1eaaf63bb5Anders Carlsson 11969a68a67c6ae4982001815cc04f69b8781058263aAnders Carlsson return CheckAccess(*this, UseLoc, AccessEntity); 1197b13b737a2450167c82e148590e8019b839ce6b98John McCall} 1198b13b737a2450167c82e148590e8019b839ce6b98John McCall 1199b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall/// Checks direct (i.e. non-inherited) access to an arbitrary class 1200b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall/// member. 1201b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCallSema::AccessResult Sema::CheckDirectMemberAccess(SourceLocation UseLoc, 1202b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall NamedDecl *Target, 1203b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall const PartialDiagnostic &Diag) { 1204b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall AccessSpecifier Access = Target->getAccess(); 1205b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall if (!getLangOptions().AccessControl || 1206b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall Access == AS_public) 1207b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall return AR_accessible; 1208b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall 1209b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(Target->getDeclContext()); 1210161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget Entity(Context, AccessTarget::Member, NamingClass, 1211161755a09898c95d21bfff33707da9ca41cd53c5John McCall DeclAccessPair::make(Target, Access), 1212161755a09898c95d21bfff33707da9ca41cd53c5John McCall QualType()); 1213b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall Entity.setDiag(Diag); 1214b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall return CheckAccess(*this, UseLoc, Entity); 1215b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall} 1216b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall 1217b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall 121890c8c57bcd84083df85f76aac2aa62acb85eb077John McCall/// Checks access to an overloaded operator new or delete. 121990c8c57bcd84083df85f76aac2aa62acb85eb077John McCallSema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc, 122090c8c57bcd84083df85f76aac2aa62acb85eb077John McCall SourceRange PlacementRange, 122190c8c57bcd84083df85f76aac2aa62acb85eb077John McCall CXXRecordDecl *NamingClass, 12229aa472c45d2bd81b7b52c225e8acc560d716db97John McCall DeclAccessPair Found) { 122390c8c57bcd84083df85f76aac2aa62acb85eb077John McCall if (!getLangOptions().AccessControl || 122490c8c57bcd84083df85f76aac2aa62acb85eb077John McCall !NamingClass || 12259aa472c45d2bd81b7b52c225e8acc560d716db97John McCall Found.getAccess() == AS_public) 122690c8c57bcd84083df85f76aac2aa62acb85eb077John McCall return AR_accessible; 122790c8c57bcd84083df85f76aac2aa62acb85eb077John McCall 1228161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found, 1229161755a09898c95d21bfff33707da9ca41cd53c5John McCall QualType()); 123090c8c57bcd84083df85f76aac2aa62acb85eb077John McCall Entity.setDiag(diag::err_access) 123190c8c57bcd84083df85f76aac2aa62acb85eb077John McCall << PlacementRange; 123290c8c57bcd84083df85f76aac2aa62acb85eb077John McCall 123390c8c57bcd84083df85f76aac2aa62acb85eb077John McCall return CheckAccess(*this, OpLoc, Entity); 123490c8c57bcd84083df85f76aac2aa62acb85eb077John McCall} 123590c8c57bcd84083df85f76aac2aa62acb85eb077John McCall 1236b13b737a2450167c82e148590e8019b839ce6b98John McCall/// Checks access to an overloaded member operator, including 1237b13b737a2450167c82e148590e8019b839ce6b98John McCall/// conversion operators. 12386b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallSema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc, 12396b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall Expr *ObjectExpr, 124058e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall Expr *ArgExpr, 12419aa472c45d2bd81b7b52c225e8acc560d716db97John McCall DeclAccessPair Found) { 124258e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall if (!getLangOptions().AccessControl || 12439aa472c45d2bd81b7b52c225e8acc560d716db97John McCall Found.getAccess() == AS_public) 12446b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return AR_accessible; 12455357b615364c17ea024c757354c58ae2a520d216John McCall 12465357b615364c17ea024c757354c58ae2a520d216John McCall const RecordType *RT = ObjectExpr->getType()->getAs<RecordType>(); 12475357b615364c17ea024c757354c58ae2a520d216John McCall assert(RT && "found member operator but object expr not of record type"); 12485357b615364c17ea024c757354c58ae2a520d216John McCall CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(RT->getDecl()); 12495357b615364c17ea024c757354c58ae2a520d216John McCall 1250161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found, 1251161755a09898c95d21bfff33707da9ca41cd53c5John McCall ObjectExpr->getType()); 125258e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall Entity.setDiag(diag::err_access) 125358e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall << ObjectExpr->getSourceRange() 125458e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall << (ArgExpr ? ArgExpr->getSourceRange() : SourceRange()); 125558e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall 125658e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall return CheckAccess(*this, OpLoc, Entity); 12576b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall} 12585357b615364c17ea024c757354c58ae2a520d216John McCall 12596bb8017bb9e828d118e15e59d71c66bba323c364John McCallSema::AccessResult Sema::CheckAddressOfMemberAccess(Expr *OvlExpr, 12606bb8017bb9e828d118e15e59d71c66bba323c364John McCall DeclAccessPair Found) { 12616bb8017bb9e828d118e15e59d71c66bba323c364John McCall if (!getLangOptions().AccessControl || 1262e2f5ba9d80cfadbb3e1dafb9f375eb526f669b85John McCall Found.getAccess() == AS_none || 12636bb8017bb9e828d118e15e59d71c66bba323c364John McCall Found.getAccess() == AS_public) 12646bb8017bb9e828d118e15e59d71c66bba323c364John McCall return AR_accessible; 12656bb8017bb9e828d118e15e59d71c66bba323c364John McCall 12666bb8017bb9e828d118e15e59d71c66bba323c364John McCall OverloadExpr *Ovl = OverloadExpr::find(OvlExpr).getPointer(); 1267e9ee23edd17c4bb7f271e67f8790792b4de677fcJohn McCall CXXRecordDecl *NamingClass = Ovl->getNamingClass(); 12686bb8017bb9e828d118e15e59d71c66bba323c364John McCall 1269161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found, 1270161755a09898c95d21bfff33707da9ca41cd53c5John McCall Context.getTypeDeclType(NamingClass)); 12716bb8017bb9e828d118e15e59d71c66bba323c364John McCall Entity.setDiag(diag::err_access) 12726bb8017bb9e828d118e15e59d71c66bba323c364John McCall << Ovl->getSourceRange(); 12736bb8017bb9e828d118e15e59d71c66bba323c364John McCall 12746bb8017bb9e828d118e15e59d71c66bba323c364John McCall return CheckAccess(*this, Ovl->getNameLoc(), Entity); 12756bb8017bb9e828d118e15e59d71c66bba323c364John McCall} 12766bb8017bb9e828d118e15e59d71c66bba323c364John McCall 12776b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// Checks access for a hierarchy conversion. 12786b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// 12796b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// \param IsBaseToDerived whether this is a base-to-derived conversion (true) 12806b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// or a derived-to-base conversion (false) 12816b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// \param ForceCheck true if this check should be performed even if access 12826b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// control is disabled; some things rely on this for semantics 12836b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// \param ForceUnprivileged true if this check should proceed as if the 12846b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// context had no special privileges 12856b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// \param ADK controls the kind of diagnostics that are used 12866b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallSema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc, 12876b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall QualType Base, 12886b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall QualType Derived, 12896b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall const CXXBasePath &Path, 129058e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall unsigned DiagID, 12916b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall bool ForceCheck, 129258e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall bool ForceUnprivileged) { 12936b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall if (!ForceCheck && !getLangOptions().AccessControl) 12946b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return AR_accessible; 12956b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 12966b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall if (Path.Access == AS_public) 12976b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return AR_accessible; 12986b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 12996b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall CXXRecordDecl *BaseD, *DerivedD; 13006b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall BaseD = cast<CXXRecordDecl>(Base->getAs<RecordType>()->getDecl()); 13016b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall DerivedD = cast<CXXRecordDecl>(Derived->getAs<RecordType>()->getDecl()); 130258e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall 1303161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget Entity(Context, AccessTarget::Base, BaseD, DerivedD, 1304161755a09898c95d21bfff33707da9ca41cd53c5John McCall Path.Access); 130558e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall if (DiagID) 130658e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall Entity.setDiag(DiagID) << Derived << Base; 13076b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 1308161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (ForceUnprivileged) { 1309161755a09898c95d21bfff33707da9ca41cd53c5John McCall switch (CheckEffectiveAccess(*this, EffectiveContext(), 1310161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessLoc, Entity)) { 1311161755a09898c95d21bfff33707da9ca41cd53c5John McCall case ::AR_accessible: return Sema::AR_accessible; 1312161755a09898c95d21bfff33707da9ca41cd53c5John McCall case ::AR_inaccessible: return Sema::AR_inaccessible; 1313161755a09898c95d21bfff33707da9ca41cd53c5John McCall case ::AR_dependent: return Sema::AR_dependent; 1314161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 1315161755a09898c95d21bfff33707da9ca41cd53c5John McCall llvm_unreachable("unexpected result from CheckEffectiveAccess"); 1316161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 131758e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall return CheckAccess(*this, AccessLoc, Entity); 13185357b615364c17ea024c757354c58ae2a520d216John McCall} 13195357b615364c17ea024c757354c58ae2a520d216John McCall 132092f883177b162928a8e632e4e3b93fafd2b26072John McCall/// Checks access to all the declarations in the given result set. 13216b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallvoid Sema::CheckLookupAccess(const LookupResult &R) { 13226b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall assert(getLangOptions().AccessControl 13236b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall && "performing access check without access control"); 13246b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall assert(R.getNamingClass() && "performing access check without naming class"); 13256b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 132658e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { 132758e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall if (I.getAccess() != AS_public) { 1328161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget Entity(Context, AccessedEntity::Member, 1329161755a09898c95d21bfff33707da9ca41cd53c5John McCall R.getNamingClass(), I.getPair(), 1330161755a09898c95d21bfff33707da9ca41cd53c5John McCall R.getBaseObjectType()); 133158e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall Entity.setDiag(diag::err_access); 133258e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall 133358e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall CheckAccess(*this, R.getNameLoc(), Entity); 133458e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall } 133558e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall } 133692f883177b162928a8e632e4e3b93fafd2b26072John McCall} 1337