SemaAccess.cpp revision 162e1c1b487352434552147967c3dd296ebee2f7
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 142d88708cbe4e4ec5e04e4acb6bd7f5be68557379John McCall#include "clang/Sema/SemaInternal.h" 159c3087b0b0bea2fd782205c1274ebfc4290265e0John McCall#include "clang/Sema/DelayedDiagnostic.h" 16e737f5041a36d0befb39ffeed8d50ba15916d3daDouglas Gregor#include "clang/Sema/Initialization.h" 17e737f5041a36d0befb39ffeed8d50ba15916d3daDouglas Gregor#include "clang/Sema/Lookup.h" 18c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson#include "clang/AST/ASTContext.h" 19a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor#include "clang/AST/CXXInheritance.h" 20a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor#include "clang/AST/DeclCXX.h" 21d60e22e601852ae1345f01514318a0951dc09f89John McCall#include "clang/AST/DeclFriend.h" 220c01d18094100db92d38daa923c95661512db203John McCall#include "clang/AST/DependentDiagnostic.h" 23c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall#include "clang/AST/ExprCXX.h" 24c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall 25c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlssonusing namespace clang; 269c3087b0b0bea2fd782205c1274ebfc4290265e0John McCallusing namespace sema; 27c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson 28161755a09898c95d21bfff33707da9ca41cd53c5John McCall/// A copy of Sema's enum without AR_delayed. 29161755a09898c95d21bfff33707da9ca41cd53c5John McCallenum AccessResult { 30161755a09898c95d21bfff33707da9ca41cd53c5John McCall AR_accessible, 31161755a09898c95d21bfff33707da9ca41cd53c5John McCall AR_inaccessible, 32161755a09898c95d21bfff33707da9ca41cd53c5John McCall AR_dependent 33161755a09898c95d21bfff33707da9ca41cd53c5John McCall}; 34161755a09898c95d21bfff33707da9ca41cd53c5John McCall 3529f006be830fbbcaa0c1cf7c7399bb5080dc7f32Anders Carlsson/// SetMemberAccessSpecifier - Set the access specifier of a member. 3629f006be830fbbcaa0c1cf7c7399bb5080dc7f32Anders Carlsson/// Returns true on error (when the previous member decl access specifier 3729f006be830fbbcaa0c1cf7c7399bb5080dc7f32Anders Carlsson/// is different from the new member decl access specifier). 381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpbool Sema::SetMemberAccessSpecifier(NamedDecl *MemberDecl, 39c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson NamedDecl *PrevMemberDecl, 40c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson AccessSpecifier LexicalAS) { 41c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson if (!PrevMemberDecl) { 42c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson // Use the lexical access specifier. 43c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson MemberDecl->setAccess(LexicalAS); 44c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson return false; 45c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson } 461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 47c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson // C++ [class.access.spec]p3: When a member is redeclared its access 48c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson // specifier must be same as its initial declaration. 49c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson if (LexicalAS != AS_none && LexicalAS != PrevMemberDecl->getAccess()) { 501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Diag(MemberDecl->getLocation(), 511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump diag::err_class_redeclared_with_different_access) 52c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson << MemberDecl << LexicalAS; 53c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson Diag(PrevMemberDecl->getLocation(), diag::note_previous_access_declaration) 54c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson << PrevMemberDecl << PrevMemberDecl->getAccess(); 5544e067bd8f923ba8e7c24b2189e06717d70015c8John McCall 5644e067bd8f923ba8e7c24b2189e06717d70015c8John McCall MemberDecl->setAccess(LexicalAS); 57c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson return true; 58c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson } 591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 60c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson MemberDecl->setAccess(PrevMemberDecl->getAccess()); 61c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson return false; 62c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson} 6329f006be830fbbcaa0c1cf7c7399bb5080dc7f32Anders Carlsson 64161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic CXXRecordDecl *FindDeclaringClass(NamedDecl *D) { 65161755a09898c95d21bfff33707da9ca41cd53c5John McCall DeclContext *DC = D->getDeclContext(); 66161755a09898c95d21bfff33707da9ca41cd53c5John McCall 67161755a09898c95d21bfff33707da9ca41cd53c5John McCall // This can only happen at top: enum decls only "publish" their 68161755a09898c95d21bfff33707da9ca41cd53c5John McCall // immediate members. 69161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (isa<EnumDecl>(DC)) 70161755a09898c95d21bfff33707da9ca41cd53c5John McCall DC = cast<EnumDecl>(DC)->getDeclContext(); 71161755a09898c95d21bfff33707da9ca41cd53c5John McCall 72161755a09898c95d21bfff33707da9ca41cd53c5John McCall CXXRecordDecl *DeclaringClass = cast<CXXRecordDecl>(DC); 73161755a09898c95d21bfff33707da9ca41cd53c5John McCall while (DeclaringClass->isAnonymousStructOrUnion()) 74161755a09898c95d21bfff33707da9ca41cd53c5John McCall DeclaringClass = cast<CXXRecordDecl>(DeclaringClass->getDeclContext()); 75161755a09898c95d21bfff33707da9ca41cd53c5John McCall return DeclaringClass; 76161755a09898c95d21bfff33707da9ca41cd53c5John McCall} 77161755a09898c95d21bfff33707da9ca41cd53c5John McCall 786b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallnamespace { 796b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallstruct EffectiveContext { 802cc2675d426af23476a9722c08c1b6c5266bd653John McCall EffectiveContext() : Inner(0), Dependent(false) {} 816b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 827ad650f88ecbbe659f10f9f6b34a1f29ea9cf8f9John McCall explicit EffectiveContext(DeclContext *DC) 837ad650f88ecbbe659f10f9f6b34a1f29ea9cf8f9John McCall : Inner(DC), 847ad650f88ecbbe659f10f9f6b34a1f29ea9cf8f9John McCall Dependent(DC->isDependentContext()) { 850c01d18094100db92d38daa923c95661512db203John McCall 8688b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall // C++ [class.access.nest]p1: 8788b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall // A nested class is a member and as such has the same access 8888b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall // rights as any other member. 8988b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall // C++ [class.access]p2: 9088b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall // A member of a class can also access all the names to which 912cc2675d426af23476a9722c08c1b6c5266bd653John McCall // the class has access. A local class of a member function 922cc2675d426af23476a9722c08c1b6c5266bd653John McCall // may access the same names that the member function itself 932cc2675d426af23476a9722c08c1b6c5266bd653John McCall // may access. 942cc2675d426af23476a9722c08c1b6c5266bd653John McCall // This almost implies that the privileges of nesting are transitive. 952cc2675d426af23476a9722c08c1b6c5266bd653John McCall // Technically it says nothing about the local classes of non-member 962cc2675d426af23476a9722c08c1b6c5266bd653John McCall // functions (which can gain privileges through friendship), but we 972cc2675d426af23476a9722c08c1b6c5266bd653John McCall // take that as an oversight. 982cc2675d426af23476a9722c08c1b6c5266bd653John McCall while (true) { 992cc2675d426af23476a9722c08c1b6c5266bd653John McCall if (isa<CXXRecordDecl>(DC)) { 1002cc2675d426af23476a9722c08c1b6c5266bd653John McCall CXXRecordDecl *Record = cast<CXXRecordDecl>(DC)->getCanonicalDecl(); 1012cc2675d426af23476a9722c08c1b6c5266bd653John McCall Records.push_back(Record); 1022cc2675d426af23476a9722c08c1b6c5266bd653John McCall DC = Record->getDeclContext(); 1032cc2675d426af23476a9722c08c1b6c5266bd653John McCall } else if (isa<FunctionDecl>(DC)) { 1042cc2675d426af23476a9722c08c1b6c5266bd653John McCall FunctionDecl *Function = cast<FunctionDecl>(DC)->getCanonicalDecl(); 1052cc2675d426af23476a9722c08c1b6c5266bd653John McCall Functions.push_back(Function); 1062cc2675d426af23476a9722c08c1b6c5266bd653John McCall DC = Function->getDeclContext(); 1072cc2675d426af23476a9722c08c1b6c5266bd653John McCall } else if (DC->isFileContext()) { 1082cc2675d426af23476a9722c08c1b6c5266bd653John McCall break; 1092cc2675d426af23476a9722c08c1b6c5266bd653John McCall } else { 1102cc2675d426af23476a9722c08c1b6c5266bd653John McCall DC = DC->getParent(); 1112cc2675d426af23476a9722c08c1b6c5266bd653John McCall } 11288b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall } 1136b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall } 1146b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 1150c01d18094100db92d38daa923c95661512db203John McCall bool isDependent() const { return Dependent; } 1160c01d18094100db92d38daa923c95661512db203John McCall 11788b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall bool includesClass(const CXXRecordDecl *R) const { 11888b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall R = R->getCanonicalDecl(); 11988b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall return std::find(Records.begin(), Records.end(), R) 12088b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall != Records.end(); 1216b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall } 1226b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 1237ad650f88ecbbe659f10f9f6b34a1f29ea9cf8f9John McCall /// Retrieves the innermost "useful" context. Can be null if we're 1247ad650f88ecbbe659f10f9f6b34a1f29ea9cf8f9John McCall /// doing access-control without privileges. 1257ad650f88ecbbe659f10f9f6b34a1f29ea9cf8f9John McCall DeclContext *getInnerContext() const { 1267ad650f88ecbbe659f10f9f6b34a1f29ea9cf8f9John McCall return Inner; 1270c01d18094100db92d38daa923c95661512db203John McCall } 1280c01d18094100db92d38daa923c95661512db203John McCall 1290c01d18094100db92d38daa923c95661512db203John McCall typedef llvm::SmallVectorImpl<CXXRecordDecl*>::const_iterator record_iterator; 1300c01d18094100db92d38daa923c95661512db203John McCall 1317ad650f88ecbbe659f10f9f6b34a1f29ea9cf8f9John McCall DeclContext *Inner; 1322cc2675d426af23476a9722c08c1b6c5266bd653John McCall llvm::SmallVector<FunctionDecl*, 4> Functions; 13388b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall llvm::SmallVector<CXXRecordDecl*, 4> Records; 1340c01d18094100db92d38daa923c95661512db203John McCall bool Dependent; 1356b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall}; 136161755a09898c95d21bfff33707da9ca41cd53c5John McCall 1376bb4dcb412d53d05a80017df81d41e447e2aa3eaNico Weber/// Like sema::AccessedEntity, but kindly lets us scribble all over 138161755a09898c95d21bfff33707da9ca41cd53c5John McCall/// it. 1399c3087b0b0bea2fd782205c1274ebfc4290265e0John McCallstruct AccessTarget : public AccessedEntity { 1409c3087b0b0bea2fd782205c1274ebfc4290265e0John McCall AccessTarget(const AccessedEntity &Entity) 141161755a09898c95d21bfff33707da9ca41cd53c5John McCall : AccessedEntity(Entity) { 142161755a09898c95d21bfff33707da9ca41cd53c5John McCall initialize(); 143161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 144161755a09898c95d21bfff33707da9ca41cd53c5John McCall 145161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget(ASTContext &Context, 146161755a09898c95d21bfff33707da9ca41cd53c5John McCall MemberNonce _, 147161755a09898c95d21bfff33707da9ca41cd53c5John McCall CXXRecordDecl *NamingClass, 148161755a09898c95d21bfff33707da9ca41cd53c5John McCall DeclAccessPair FoundDecl, 149161755a09898c95d21bfff33707da9ca41cd53c5John McCall QualType BaseObjectType) 150161755a09898c95d21bfff33707da9ca41cd53c5John McCall : AccessedEntity(Context, Member, NamingClass, FoundDecl, BaseObjectType) { 151161755a09898c95d21bfff33707da9ca41cd53c5John McCall initialize(); 152161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 153161755a09898c95d21bfff33707da9ca41cd53c5John McCall 154161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget(ASTContext &Context, 155161755a09898c95d21bfff33707da9ca41cd53c5John McCall BaseNonce _, 156161755a09898c95d21bfff33707da9ca41cd53c5John McCall CXXRecordDecl *BaseClass, 157161755a09898c95d21bfff33707da9ca41cd53c5John McCall CXXRecordDecl *DerivedClass, 158161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessSpecifier Access) 159161755a09898c95d21bfff33707da9ca41cd53c5John McCall : AccessedEntity(Context, Base, BaseClass, DerivedClass, Access) { 160161755a09898c95d21bfff33707da9ca41cd53c5John McCall initialize(); 161161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 162161755a09898c95d21bfff33707da9ca41cd53c5John McCall 163161755a09898c95d21bfff33707da9ca41cd53c5John McCall bool hasInstanceContext() const { 164161755a09898c95d21bfff33707da9ca41cd53c5John McCall return HasInstanceContext; 165161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 166161755a09898c95d21bfff33707da9ca41cd53c5John McCall 167161755a09898c95d21bfff33707da9ca41cd53c5John McCall class SavedInstanceContext { 168161755a09898c95d21bfff33707da9ca41cd53c5John McCall public: 169161755a09898c95d21bfff33707da9ca41cd53c5John McCall ~SavedInstanceContext() { 170161755a09898c95d21bfff33707da9ca41cd53c5John McCall Target.HasInstanceContext = Has; 171161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 172161755a09898c95d21bfff33707da9ca41cd53c5John McCall 173161755a09898c95d21bfff33707da9ca41cd53c5John McCall private: 174c91cc66e92b084acd1fdbaa1c3c74242741b3d46John McCall friend struct AccessTarget; 175161755a09898c95d21bfff33707da9ca41cd53c5John McCall explicit SavedInstanceContext(AccessTarget &Target) 176161755a09898c95d21bfff33707da9ca41cd53c5John McCall : Target(Target), Has(Target.HasInstanceContext) {} 177161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget &Target; 178161755a09898c95d21bfff33707da9ca41cd53c5John McCall bool Has; 179161755a09898c95d21bfff33707da9ca41cd53c5John McCall }; 180161755a09898c95d21bfff33707da9ca41cd53c5John McCall 181161755a09898c95d21bfff33707da9ca41cd53c5John McCall SavedInstanceContext saveInstanceContext() { 182161755a09898c95d21bfff33707da9ca41cd53c5John McCall return SavedInstanceContext(*this); 183161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 184161755a09898c95d21bfff33707da9ca41cd53c5John McCall 185161755a09898c95d21bfff33707da9ca41cd53c5John McCall void suppressInstanceContext() { 186161755a09898c95d21bfff33707da9ca41cd53c5John McCall HasInstanceContext = false; 187161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 188161755a09898c95d21bfff33707da9ca41cd53c5John McCall 189161755a09898c95d21bfff33707da9ca41cd53c5John McCall const CXXRecordDecl *resolveInstanceContext(Sema &S) const { 190161755a09898c95d21bfff33707da9ca41cd53c5John McCall assert(HasInstanceContext); 191161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (CalculatedInstanceContext) 192161755a09898c95d21bfff33707da9ca41cd53c5John McCall return InstanceContext; 193161755a09898c95d21bfff33707da9ca41cd53c5John McCall 194161755a09898c95d21bfff33707da9ca41cd53c5John McCall CalculatedInstanceContext = true; 195161755a09898c95d21bfff33707da9ca41cd53c5John McCall DeclContext *IC = S.computeDeclContext(getBaseObjectType()); 196161755a09898c95d21bfff33707da9ca41cd53c5John McCall InstanceContext = (IC ? cast<CXXRecordDecl>(IC)->getCanonicalDecl() : 0); 197161755a09898c95d21bfff33707da9ca41cd53c5John McCall return InstanceContext; 198161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 199161755a09898c95d21bfff33707da9ca41cd53c5John McCall 200161755a09898c95d21bfff33707da9ca41cd53c5John McCall const CXXRecordDecl *getDeclaringClass() const { 201161755a09898c95d21bfff33707da9ca41cd53c5John McCall return DeclaringClass; 202161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 203161755a09898c95d21bfff33707da9ca41cd53c5John McCall 204161755a09898c95d21bfff33707da9ca41cd53c5John McCallprivate: 205161755a09898c95d21bfff33707da9ca41cd53c5John McCall void initialize() { 206161755a09898c95d21bfff33707da9ca41cd53c5John McCall HasInstanceContext = (isMemberAccess() && 207161755a09898c95d21bfff33707da9ca41cd53c5John McCall !getBaseObjectType().isNull() && 208161755a09898c95d21bfff33707da9ca41cd53c5John McCall getTargetDecl()->isCXXInstanceMember()); 209161755a09898c95d21bfff33707da9ca41cd53c5John McCall CalculatedInstanceContext = false; 210161755a09898c95d21bfff33707da9ca41cd53c5John McCall InstanceContext = 0; 211161755a09898c95d21bfff33707da9ca41cd53c5John McCall 212161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (isMemberAccess()) 213161755a09898c95d21bfff33707da9ca41cd53c5John McCall DeclaringClass = FindDeclaringClass(getTargetDecl()); 214161755a09898c95d21bfff33707da9ca41cd53c5John McCall else 215161755a09898c95d21bfff33707da9ca41cd53c5John McCall DeclaringClass = getBaseClass(); 216161755a09898c95d21bfff33707da9ca41cd53c5John McCall DeclaringClass = DeclaringClass->getCanonicalDecl(); 217161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 218161755a09898c95d21bfff33707da9ca41cd53c5John McCall 219161755a09898c95d21bfff33707da9ca41cd53c5John McCall bool HasInstanceContext : 1; 220161755a09898c95d21bfff33707da9ca41cd53c5John McCall mutable bool CalculatedInstanceContext : 1; 221161755a09898c95d21bfff33707da9ca41cd53c5John McCall mutable const CXXRecordDecl *InstanceContext; 222161755a09898c95d21bfff33707da9ca41cd53c5John McCall const CXXRecordDecl *DeclaringClass; 223161755a09898c95d21bfff33707da9ca41cd53c5John McCall}; 224161755a09898c95d21bfff33707da9ca41cd53c5John McCall 2256b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall} 226726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl 22701ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall/// Checks whether one class might instantiate to the other. 22801ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCallstatic bool MightInstantiateTo(const CXXRecordDecl *From, 22901ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall const CXXRecordDecl *To) { 23001ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall // Declaration names are always preserved by instantiation. 23101ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall if (From->getDeclName() != To->getDeclName()) 23201ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall return false; 23301ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall 23401ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall const DeclContext *FromDC = From->getDeclContext()->getPrimaryContext(); 23501ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall const DeclContext *ToDC = To->getDeclContext()->getPrimaryContext(); 23601ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall if (FromDC == ToDC) return true; 23701ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall if (FromDC->isFileContext() || ToDC->isFileContext()) return false; 23801ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall 23901ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall // Be conservative. 24001ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall return true; 24101ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall} 24201ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall 243161755a09898c95d21bfff33707da9ca41cd53c5John McCall/// Checks whether one class is derived from another, inclusively. 244161755a09898c95d21bfff33707da9ca41cd53c5John McCall/// Properly indicates when it couldn't be determined due to 245161755a09898c95d21bfff33707da9ca41cd53c5John McCall/// dependence. 246161755a09898c95d21bfff33707da9ca41cd53c5John McCall/// 247161755a09898c95d21bfff33707da9ca41cd53c5John McCall/// This should probably be donated to AST or at least Sema. 248161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic AccessResult IsDerivedFromInclusive(const CXXRecordDecl *Derived, 249161755a09898c95d21bfff33707da9ca41cd53c5John McCall const CXXRecordDecl *Target) { 250161755a09898c95d21bfff33707da9ca41cd53c5John McCall assert(Derived->getCanonicalDecl() == Derived); 251161755a09898c95d21bfff33707da9ca41cd53c5John McCall assert(Target->getCanonicalDecl() == Target); 252c1b621daf98d83075a466c6f4ad9904dc845dd09John McCall 253161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (Derived == Target) return AR_accessible; 254c1b621daf98d83075a466c6f4ad9904dc845dd09John McCall 25501ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall bool CheckDependent = Derived->isDependentContext(); 25601ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall if (CheckDependent && MightInstantiateTo(Derived, Target)) 25701ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall return AR_dependent; 25801ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall 259161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessResult OnFailure = AR_inaccessible; 260161755a09898c95d21bfff33707da9ca41cd53c5John McCall llvm::SmallVector<const CXXRecordDecl*, 8> Queue; // actually a stack 261161755a09898c95d21bfff33707da9ca41cd53c5John McCall 262161755a09898c95d21bfff33707da9ca41cd53c5John McCall while (true) { 263161755a09898c95d21bfff33707da9ca41cd53c5John McCall for (CXXRecordDecl::base_class_const_iterator 264161755a09898c95d21bfff33707da9ca41cd53c5John McCall I = Derived->bases_begin(), E = Derived->bases_end(); I != E; ++I) { 265161755a09898c95d21bfff33707da9ca41cd53c5John McCall 266161755a09898c95d21bfff33707da9ca41cd53c5John McCall const CXXRecordDecl *RD; 267161755a09898c95d21bfff33707da9ca41cd53c5John McCall 268161755a09898c95d21bfff33707da9ca41cd53c5John McCall QualType T = I->getType(); 269161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (const RecordType *RT = T->getAs<RecordType>()) { 270161755a09898c95d21bfff33707da9ca41cd53c5John McCall RD = cast<CXXRecordDecl>(RT->getDecl()); 27101ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall } else if (const InjectedClassNameType *IT 27201ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall = T->getAs<InjectedClassNameType>()) { 27301ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall RD = IT->getDecl(); 274161755a09898c95d21bfff33707da9ca41cd53c5John McCall } else { 275161755a09898c95d21bfff33707da9ca41cd53c5John McCall assert(T->isDependentType() && "non-dependent base wasn't a record?"); 276161755a09898c95d21bfff33707da9ca41cd53c5John McCall OnFailure = AR_dependent; 277161755a09898c95d21bfff33707da9ca41cd53c5John McCall continue; 278161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 279161755a09898c95d21bfff33707da9ca41cd53c5John McCall 280161755a09898c95d21bfff33707da9ca41cd53c5John McCall RD = RD->getCanonicalDecl(); 281161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (RD == Target) return AR_accessible; 28201ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall if (CheckDependent && MightInstantiateTo(RD, Target)) 28301ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall OnFailure = AR_dependent; 28401ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall 285161755a09898c95d21bfff33707da9ca41cd53c5John McCall Queue.push_back(RD); 286161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 287161755a09898c95d21bfff33707da9ca41cd53c5John McCall 288161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (Queue.empty()) break; 289161755a09898c95d21bfff33707da9ca41cd53c5John McCall 290161755a09898c95d21bfff33707da9ca41cd53c5John McCall Derived = Queue.back(); 291161755a09898c95d21bfff33707da9ca41cd53c5John McCall Queue.pop_back(); 292161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 293161755a09898c95d21bfff33707da9ca41cd53c5John McCall 294161755a09898c95d21bfff33707da9ca41cd53c5John McCall return OnFailure; 2956b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall} 2966b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 297161755a09898c95d21bfff33707da9ca41cd53c5John McCall 2980c01d18094100db92d38daa923c95661512db203John McCallstatic bool MightInstantiateTo(Sema &S, DeclContext *Context, 2990c01d18094100db92d38daa923c95661512db203John McCall DeclContext *Friend) { 3000c01d18094100db92d38daa923c95661512db203John McCall if (Friend == Context) 3010c01d18094100db92d38daa923c95661512db203John McCall return true; 3020c01d18094100db92d38daa923c95661512db203John McCall 3030c01d18094100db92d38daa923c95661512db203John McCall assert(!Friend->isDependentContext() && 3040c01d18094100db92d38daa923c95661512db203John McCall "can't handle friends with dependent contexts here"); 3050c01d18094100db92d38daa923c95661512db203John McCall 3060c01d18094100db92d38daa923c95661512db203John McCall if (!Context->isDependentContext()) 3070c01d18094100db92d38daa923c95661512db203John McCall return false; 3080c01d18094100db92d38daa923c95661512db203John McCall 3090c01d18094100db92d38daa923c95661512db203John McCall if (Friend->isFileContext()) 3100c01d18094100db92d38daa923c95661512db203John McCall return false; 3110c01d18094100db92d38daa923c95661512db203John McCall 3120c01d18094100db92d38daa923c95661512db203John McCall // TODO: this is very conservative 3130c01d18094100db92d38daa923c95661512db203John McCall return true; 3140c01d18094100db92d38daa923c95661512db203John McCall} 3150c01d18094100db92d38daa923c95661512db203John McCall 3160c01d18094100db92d38daa923c95661512db203John McCall// Asks whether the type in 'context' can ever instantiate to the type 3170c01d18094100db92d38daa923c95661512db203John McCall// in 'friend'. 3180c01d18094100db92d38daa923c95661512db203John McCallstatic bool MightInstantiateTo(Sema &S, CanQualType Context, CanQualType Friend) { 3190c01d18094100db92d38daa923c95661512db203John McCall if (Friend == Context) 3200c01d18094100db92d38daa923c95661512db203John McCall return true; 3210c01d18094100db92d38daa923c95661512db203John McCall 3220c01d18094100db92d38daa923c95661512db203John McCall if (!Friend->isDependentType() && !Context->isDependentType()) 3230c01d18094100db92d38daa923c95661512db203John McCall return false; 3240c01d18094100db92d38daa923c95661512db203John McCall 3250c01d18094100db92d38daa923c95661512db203John McCall // TODO: this is very conservative. 3260c01d18094100db92d38daa923c95661512db203John McCall return true; 3270c01d18094100db92d38daa923c95661512db203John McCall} 3280c01d18094100db92d38daa923c95661512db203John McCall 3290c01d18094100db92d38daa923c95661512db203John McCallstatic bool MightInstantiateTo(Sema &S, 3300c01d18094100db92d38daa923c95661512db203John McCall FunctionDecl *Context, 3310c01d18094100db92d38daa923c95661512db203John McCall FunctionDecl *Friend) { 3320c01d18094100db92d38daa923c95661512db203John McCall if (Context->getDeclName() != Friend->getDeclName()) 3330c01d18094100db92d38daa923c95661512db203John McCall return false; 3340c01d18094100db92d38daa923c95661512db203John McCall 3350c01d18094100db92d38daa923c95661512db203John McCall if (!MightInstantiateTo(S, 3360c01d18094100db92d38daa923c95661512db203John McCall Context->getDeclContext(), 3370c01d18094100db92d38daa923c95661512db203John McCall Friend->getDeclContext())) 3380c01d18094100db92d38daa923c95661512db203John McCall return false; 3390c01d18094100db92d38daa923c95661512db203John McCall 3400c01d18094100db92d38daa923c95661512db203John McCall CanQual<FunctionProtoType> FriendTy 3410c01d18094100db92d38daa923c95661512db203John McCall = S.Context.getCanonicalType(Friend->getType()) 3420c01d18094100db92d38daa923c95661512db203John McCall ->getAs<FunctionProtoType>(); 3430c01d18094100db92d38daa923c95661512db203John McCall CanQual<FunctionProtoType> ContextTy 3440c01d18094100db92d38daa923c95661512db203John McCall = S.Context.getCanonicalType(Context->getType()) 3450c01d18094100db92d38daa923c95661512db203John McCall ->getAs<FunctionProtoType>(); 3460c01d18094100db92d38daa923c95661512db203John McCall 3470c01d18094100db92d38daa923c95661512db203John McCall // There isn't any way that I know of to add qualifiers 3480c01d18094100db92d38daa923c95661512db203John McCall // during instantiation. 3490c01d18094100db92d38daa923c95661512db203John McCall if (FriendTy.getQualifiers() != ContextTy.getQualifiers()) 3500c01d18094100db92d38daa923c95661512db203John McCall return false; 3510c01d18094100db92d38daa923c95661512db203John McCall 3520c01d18094100db92d38daa923c95661512db203John McCall if (FriendTy->getNumArgs() != ContextTy->getNumArgs()) 3530c01d18094100db92d38daa923c95661512db203John McCall return false; 3540c01d18094100db92d38daa923c95661512db203John McCall 3550c01d18094100db92d38daa923c95661512db203John McCall if (!MightInstantiateTo(S, 3560c01d18094100db92d38daa923c95661512db203John McCall ContextTy->getResultType(), 3570c01d18094100db92d38daa923c95661512db203John McCall FriendTy->getResultType())) 3580c01d18094100db92d38daa923c95661512db203John McCall return false; 3590c01d18094100db92d38daa923c95661512db203John McCall 3600c01d18094100db92d38daa923c95661512db203John McCall for (unsigned I = 0, E = FriendTy->getNumArgs(); I != E; ++I) 3610c01d18094100db92d38daa923c95661512db203John McCall if (!MightInstantiateTo(S, 3620c01d18094100db92d38daa923c95661512db203John McCall ContextTy->getArgType(I), 3630c01d18094100db92d38daa923c95661512db203John McCall FriendTy->getArgType(I))) 3640c01d18094100db92d38daa923c95661512db203John McCall return false; 3650c01d18094100db92d38daa923c95661512db203John McCall 3660c01d18094100db92d38daa923c95661512db203John McCall return true; 3670c01d18094100db92d38daa923c95661512db203John McCall} 3680c01d18094100db92d38daa923c95661512db203John McCall 3690c01d18094100db92d38daa923c95661512db203John McCallstatic bool MightInstantiateTo(Sema &S, 3700c01d18094100db92d38daa923c95661512db203John McCall FunctionTemplateDecl *Context, 3710c01d18094100db92d38daa923c95661512db203John McCall FunctionTemplateDecl *Friend) { 3720c01d18094100db92d38daa923c95661512db203John McCall return MightInstantiateTo(S, 3730c01d18094100db92d38daa923c95661512db203John McCall Context->getTemplatedDecl(), 3740c01d18094100db92d38daa923c95661512db203John McCall Friend->getTemplatedDecl()); 3750c01d18094100db92d38daa923c95661512db203John McCall} 3760c01d18094100db92d38daa923c95661512db203John McCall 377161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic AccessResult MatchesFriend(Sema &S, 378161755a09898c95d21bfff33707da9ca41cd53c5John McCall const EffectiveContext &EC, 379161755a09898c95d21bfff33707da9ca41cd53c5John McCall const CXXRecordDecl *Friend) { 380a742db0032d8f458fe229600d2082981a1fb1481John McCall if (EC.includesClass(Friend)) 381161755a09898c95d21bfff33707da9ca41cd53c5John McCall return AR_accessible; 382a742db0032d8f458fe229600d2082981a1fb1481John McCall 3830c01d18094100db92d38daa923c95661512db203John McCall if (EC.isDependent()) { 3840c01d18094100db92d38daa923c95661512db203John McCall CanQualType FriendTy 3850c01d18094100db92d38daa923c95661512db203John McCall = S.Context.getCanonicalType(S.Context.getTypeDeclType(Friend)); 3860c01d18094100db92d38daa923c95661512db203John McCall 3870c01d18094100db92d38daa923c95661512db203John McCall for (EffectiveContext::record_iterator 3880c01d18094100db92d38daa923c95661512db203John McCall I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { 3890c01d18094100db92d38daa923c95661512db203John McCall CanQualType ContextTy 3900c01d18094100db92d38daa923c95661512db203John McCall = S.Context.getCanonicalType(S.Context.getTypeDeclType(*I)); 3910c01d18094100db92d38daa923c95661512db203John McCall if (MightInstantiateTo(S, ContextTy, FriendTy)) 392161755a09898c95d21bfff33707da9ca41cd53c5John McCall return AR_dependent; 3930c01d18094100db92d38daa923c95661512db203John McCall } 3940c01d18094100db92d38daa923c95661512db203John McCall } 3950c01d18094100db92d38daa923c95661512db203John McCall 396161755a09898c95d21bfff33707da9ca41cd53c5John McCall return AR_inaccessible; 397a742db0032d8f458fe229600d2082981a1fb1481John McCall} 398a742db0032d8f458fe229600d2082981a1fb1481John McCall 399161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic AccessResult MatchesFriend(Sema &S, 400161755a09898c95d21bfff33707da9ca41cd53c5John McCall const EffectiveContext &EC, 401161755a09898c95d21bfff33707da9ca41cd53c5John McCall CanQualType Friend) { 4020c01d18094100db92d38daa923c95661512db203John McCall if (const RecordType *RT = Friend->getAs<RecordType>()) 4030c01d18094100db92d38daa923c95661512db203John McCall return MatchesFriend(S, EC, cast<CXXRecordDecl>(RT->getDecl())); 404a742db0032d8f458fe229600d2082981a1fb1481John McCall 4050c01d18094100db92d38daa923c95661512db203John McCall // TODO: we can do better than this 4060c01d18094100db92d38daa923c95661512db203John McCall if (Friend->isDependentType()) 407161755a09898c95d21bfff33707da9ca41cd53c5John McCall return AR_dependent; 408a742db0032d8f458fe229600d2082981a1fb1481John McCall 409161755a09898c95d21bfff33707da9ca41cd53c5John McCall return AR_inaccessible; 4100c01d18094100db92d38daa923c95661512db203John McCall} 411a742db0032d8f458fe229600d2082981a1fb1481John McCall 4120c01d18094100db92d38daa923c95661512db203John McCall/// Determines whether the given friend class template matches 4130c01d18094100db92d38daa923c95661512db203John McCall/// anything in the effective context. 414161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic AccessResult MatchesFriend(Sema &S, 415161755a09898c95d21bfff33707da9ca41cd53c5John McCall const EffectiveContext &EC, 416161755a09898c95d21bfff33707da9ca41cd53c5John McCall ClassTemplateDecl *Friend) { 417161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessResult OnFailure = AR_inaccessible; 418a742db0032d8f458fe229600d2082981a1fb1481John McCall 41993ba8579c341d5329175f1413cdc3b35a36592d2John McCall // Check whether the friend is the template of a class in the 42093ba8579c341d5329175f1413cdc3b35a36592d2John McCall // context chain. 4210c01d18094100db92d38daa923c95661512db203John McCall for (llvm::SmallVectorImpl<CXXRecordDecl*>::const_iterator 4220c01d18094100db92d38daa923c95661512db203John McCall I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { 4230c01d18094100db92d38daa923c95661512db203John McCall CXXRecordDecl *Record = *I; 424a742db0032d8f458fe229600d2082981a1fb1481John McCall 42593ba8579c341d5329175f1413cdc3b35a36592d2John McCall // Figure out whether the current class has a template: 4260c01d18094100db92d38daa923c95661512db203John McCall ClassTemplateDecl *CTD; 427a742db0032d8f458fe229600d2082981a1fb1481John McCall 4280c01d18094100db92d38daa923c95661512db203John McCall // A specialization of the template... 4290c01d18094100db92d38daa923c95661512db203John McCall if (isa<ClassTemplateSpecializationDecl>(Record)) { 4300c01d18094100db92d38daa923c95661512db203John McCall CTD = cast<ClassTemplateSpecializationDecl>(Record) 4310c01d18094100db92d38daa923c95661512db203John McCall ->getSpecializedTemplate(); 432a742db0032d8f458fe229600d2082981a1fb1481John McCall 4330c01d18094100db92d38daa923c95661512db203John McCall // ... or the template pattern itself. 4340c01d18094100db92d38daa923c95661512db203John McCall } else { 4350c01d18094100db92d38daa923c95661512db203John McCall CTD = Record->getDescribedClassTemplate(); 4360c01d18094100db92d38daa923c95661512db203John McCall if (!CTD) continue; 437a742db0032d8f458fe229600d2082981a1fb1481John McCall } 438a742db0032d8f458fe229600d2082981a1fb1481John McCall 4390c01d18094100db92d38daa923c95661512db203John McCall // It's a match. 4400c01d18094100db92d38daa923c95661512db203John McCall if (Friend == CTD->getCanonicalDecl()) 441161755a09898c95d21bfff33707da9ca41cd53c5John McCall return AR_accessible; 4420c01d18094100db92d38daa923c95661512db203John McCall 44393ba8579c341d5329175f1413cdc3b35a36592d2John McCall // If the context isn't dependent, it can't be a dependent match. 44493ba8579c341d5329175f1413cdc3b35a36592d2John McCall if (!EC.isDependent()) 44593ba8579c341d5329175f1413cdc3b35a36592d2John McCall continue; 44693ba8579c341d5329175f1413cdc3b35a36592d2John McCall 4470c01d18094100db92d38daa923c95661512db203John McCall // If the template names don't match, it can't be a dependent 4480c01d18094100db92d38daa923c95661512db203John McCall // match. This isn't true in C++0x because of template aliases. 4490c01d18094100db92d38daa923c95661512db203John McCall if (!S.LangOpts.CPlusPlus0x && CTD->getDeclName() != Friend->getDeclName()) 4500c01d18094100db92d38daa923c95661512db203John McCall continue; 4510c01d18094100db92d38daa923c95661512db203John McCall 4520c01d18094100db92d38daa923c95661512db203John McCall // If the class's context can't instantiate to the friend's 4530c01d18094100db92d38daa923c95661512db203John McCall // context, it can't be a dependent match. 4540c01d18094100db92d38daa923c95661512db203John McCall if (!MightInstantiateTo(S, CTD->getDeclContext(), 4550c01d18094100db92d38daa923c95661512db203John McCall Friend->getDeclContext())) 4560c01d18094100db92d38daa923c95661512db203John McCall continue; 4570c01d18094100db92d38daa923c95661512db203John McCall 4580c01d18094100db92d38daa923c95661512db203John McCall // Otherwise, it's a dependent match. 459161755a09898c95d21bfff33707da9ca41cd53c5John McCall OnFailure = AR_dependent; 460a742db0032d8f458fe229600d2082981a1fb1481John McCall } 461a742db0032d8f458fe229600d2082981a1fb1481John McCall 4620c01d18094100db92d38daa923c95661512db203John McCall return OnFailure; 4630c01d18094100db92d38daa923c95661512db203John McCall} 464a742db0032d8f458fe229600d2082981a1fb1481John McCall 4650c01d18094100db92d38daa923c95661512db203John McCall/// Determines whether the given friend function matches anything in 4660c01d18094100db92d38daa923c95661512db203John McCall/// the effective context. 467161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic AccessResult MatchesFriend(Sema &S, 468161755a09898c95d21bfff33707da9ca41cd53c5John McCall const EffectiveContext &EC, 469161755a09898c95d21bfff33707da9ca41cd53c5John McCall FunctionDecl *Friend) { 470161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessResult OnFailure = AR_inaccessible; 471a742db0032d8f458fe229600d2082981a1fb1481John McCall 4722cc2675d426af23476a9722c08c1b6c5266bd653John McCall for (llvm::SmallVectorImpl<FunctionDecl*>::const_iterator 4732cc2675d426af23476a9722c08c1b6c5266bd653John McCall I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) { 4742cc2675d426af23476a9722c08c1b6c5266bd653John McCall if (Friend == *I) 475161755a09898c95d21bfff33707da9ca41cd53c5John McCall return AR_accessible; 4760c01d18094100db92d38daa923c95661512db203John McCall 4772cc2675d426af23476a9722c08c1b6c5266bd653John McCall if (EC.isDependent() && MightInstantiateTo(S, *I, Friend)) 478161755a09898c95d21bfff33707da9ca41cd53c5John McCall OnFailure = AR_dependent; 4792cc2675d426af23476a9722c08c1b6c5266bd653John McCall } 4800c01d18094100db92d38daa923c95661512db203John McCall 4812cc2675d426af23476a9722c08c1b6c5266bd653John McCall return OnFailure; 4820c01d18094100db92d38daa923c95661512db203John McCall} 4830c01d18094100db92d38daa923c95661512db203John McCall 4840c01d18094100db92d38daa923c95661512db203John McCall/// Determines whether the given friend function template matches 4850c01d18094100db92d38daa923c95661512db203John McCall/// anything in the effective context. 486161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic AccessResult MatchesFriend(Sema &S, 487161755a09898c95d21bfff33707da9ca41cd53c5John McCall const EffectiveContext &EC, 488161755a09898c95d21bfff33707da9ca41cd53c5John McCall FunctionTemplateDecl *Friend) { 489161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (EC.Functions.empty()) return AR_inaccessible; 4902cc2675d426af23476a9722c08c1b6c5266bd653John McCall 491161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessResult OnFailure = AR_inaccessible; 4920c01d18094100db92d38daa923c95661512db203John McCall 4932cc2675d426af23476a9722c08c1b6c5266bd653John McCall for (llvm::SmallVectorImpl<FunctionDecl*>::const_iterator 4942cc2675d426af23476a9722c08c1b6c5266bd653John McCall I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) { 495a742db0032d8f458fe229600d2082981a1fb1481John McCall 4962cc2675d426af23476a9722c08c1b6c5266bd653John McCall FunctionTemplateDecl *FTD = (*I)->getPrimaryTemplate(); 4972cc2675d426af23476a9722c08c1b6c5266bd653John McCall if (!FTD) 4982cc2675d426af23476a9722c08c1b6c5266bd653John McCall FTD = (*I)->getDescribedFunctionTemplate(); 4992cc2675d426af23476a9722c08c1b6c5266bd653John McCall if (!FTD) 5002cc2675d426af23476a9722c08c1b6c5266bd653John McCall continue; 501a742db0032d8f458fe229600d2082981a1fb1481John McCall 5022cc2675d426af23476a9722c08c1b6c5266bd653John McCall FTD = FTD->getCanonicalDecl(); 503a742db0032d8f458fe229600d2082981a1fb1481John McCall 5042cc2675d426af23476a9722c08c1b6c5266bd653John McCall if (Friend == FTD) 505161755a09898c95d21bfff33707da9ca41cd53c5John McCall return AR_accessible; 5062cc2675d426af23476a9722c08c1b6c5266bd653John McCall 5072cc2675d426af23476a9722c08c1b6c5266bd653John McCall if (EC.isDependent() && MightInstantiateTo(S, FTD, Friend)) 508161755a09898c95d21bfff33707da9ca41cd53c5John McCall OnFailure = AR_dependent; 5092cc2675d426af23476a9722c08c1b6c5266bd653John McCall } 5102cc2675d426af23476a9722c08c1b6c5266bd653John McCall 5112cc2675d426af23476a9722c08c1b6c5266bd653John McCall return OnFailure; 512a742db0032d8f458fe229600d2082981a1fb1481John McCall} 513a742db0032d8f458fe229600d2082981a1fb1481John McCall 5140c01d18094100db92d38daa923c95661512db203John McCall/// Determines whether the given friend declaration matches anything 5150c01d18094100db92d38daa923c95661512db203John McCall/// in the effective context. 516161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic AccessResult MatchesFriend(Sema &S, 517161755a09898c95d21bfff33707da9ca41cd53c5John McCall const EffectiveContext &EC, 518161755a09898c95d21bfff33707da9ca41cd53c5John McCall FriendDecl *FriendD) { 5196102ca1d490836096678d7d934f0b2b78f9293ecJohn McCall // Whitelist accesses if there's an invalid or unsupported friend 5206102ca1d490836096678d7d934f0b2b78f9293ecJohn McCall // declaration. 5216102ca1d490836096678d7d934f0b2b78f9293ecJohn McCall if (FriendD->isInvalidDecl() || FriendD->isUnsupportedFriend()) 522337ec3d0e8cb24a591ecbecdc0a995a167f6af01John McCall return AR_accessible; 523337ec3d0e8cb24a591ecbecdc0a995a167f6af01John McCall 52432f2fb53d9d7c28c94d8569fd0fcf06cccee0c3dJohn McCall if (TypeSourceInfo *T = FriendD->getFriendType()) 52532f2fb53d9d7c28c94d8569fd0fcf06cccee0c3dJohn McCall return MatchesFriend(S, EC, T->getType()->getCanonicalTypeUnqualified()); 5260c01d18094100db92d38daa923c95661512db203John McCall 5270c01d18094100db92d38daa923c95661512db203John McCall NamedDecl *Friend 5280c01d18094100db92d38daa923c95661512db203John McCall = cast<NamedDecl>(FriendD->getFriendDecl()->getCanonicalDecl()); 5290c01d18094100db92d38daa923c95661512db203John McCall 5300c01d18094100db92d38daa923c95661512db203John McCall // FIXME: declarations with dependent or templated scope. 5310c01d18094100db92d38daa923c95661512db203John McCall 5320c01d18094100db92d38daa923c95661512db203John McCall if (isa<ClassTemplateDecl>(Friend)) 5330c01d18094100db92d38daa923c95661512db203John McCall return MatchesFriend(S, EC, cast<ClassTemplateDecl>(Friend)); 5340c01d18094100db92d38daa923c95661512db203John McCall 5350c01d18094100db92d38daa923c95661512db203John McCall if (isa<FunctionTemplateDecl>(Friend)) 5360c01d18094100db92d38daa923c95661512db203John McCall return MatchesFriend(S, EC, cast<FunctionTemplateDecl>(Friend)); 5370c01d18094100db92d38daa923c95661512db203John McCall 5380c01d18094100db92d38daa923c95661512db203John McCall if (isa<CXXRecordDecl>(Friend)) 5390c01d18094100db92d38daa923c95661512db203John McCall return MatchesFriend(S, EC, cast<CXXRecordDecl>(Friend)); 5400c01d18094100db92d38daa923c95661512db203John McCall 5410c01d18094100db92d38daa923c95661512db203John McCall assert(isa<FunctionDecl>(Friend) && "unknown friend decl kind"); 5420c01d18094100db92d38daa923c95661512db203John McCall return MatchesFriend(S, EC, cast<FunctionDecl>(Friend)); 5430c01d18094100db92d38daa923c95661512db203John McCall} 5440c01d18094100db92d38daa923c95661512db203John McCall 545161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic AccessResult GetFriendKind(Sema &S, 546161755a09898c95d21bfff33707da9ca41cd53c5John McCall const EffectiveContext &EC, 547161755a09898c95d21bfff33707da9ca41cd53c5John McCall const CXXRecordDecl *Class) { 548161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessResult OnFailure = AR_inaccessible; 54988b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall 550d60e22e601852ae1345f01514318a0951dc09f89John McCall // Okay, check friends. 551d60e22e601852ae1345f01514318a0951dc09f89John McCall for (CXXRecordDecl::friend_iterator I = Class->friend_begin(), 552d60e22e601852ae1345f01514318a0951dc09f89John McCall E = Class->friend_end(); I != E; ++I) { 553d60e22e601852ae1345f01514318a0951dc09f89John McCall FriendDecl *Friend = *I; 554d60e22e601852ae1345f01514318a0951dc09f89John McCall 555a742db0032d8f458fe229600d2082981a1fb1481John McCall switch (MatchesFriend(S, EC, Friend)) { 556161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_accessible: 557161755a09898c95d21bfff33707da9ca41cd53c5John McCall return AR_accessible; 55888b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall 559161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_inaccessible: 560161755a09898c95d21bfff33707da9ca41cd53c5John McCall continue; 561d60e22e601852ae1345f01514318a0951dc09f89John McCall 562161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_dependent: 563161755a09898c95d21bfff33707da9ca41cd53c5John McCall OnFailure = AR_dependent; 564a742db0032d8f458fe229600d2082981a1fb1481John McCall break; 565a742db0032d8f458fe229600d2082981a1fb1481John McCall } 566d60e22e601852ae1345f01514318a0951dc09f89John McCall } 567d60e22e601852ae1345f01514318a0951dc09f89John McCall 568d60e22e601852ae1345f01514318a0951dc09f89John McCall // That's it, give up. 56988b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall return OnFailure; 5706b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall} 5716b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 5728c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCallnamespace { 5738c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall 5748c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall/// A helper class for checking for a friend which will grant access 5758c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall/// to a protected instance member. 5768c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCallstruct ProtectedFriendContext { 5778c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall Sema &S; 5788c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall const EffectiveContext &EC; 5798c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall const CXXRecordDecl *NamingClass; 5808c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall bool CheckDependent; 5818c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall bool EverDependent; 5828c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall 5838c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall /// The path down to the current base class. 5848c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall llvm::SmallVector<const CXXRecordDecl*, 20> CurPath; 5858c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall 5868c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall ProtectedFriendContext(Sema &S, const EffectiveContext &EC, 5878c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall const CXXRecordDecl *InstanceContext, 5888c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall const CXXRecordDecl *NamingClass) 5898c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall : S(S), EC(EC), NamingClass(NamingClass), 5908c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall CheckDependent(InstanceContext->isDependentContext() || 5918c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall NamingClass->isDependentContext()), 5928c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall EverDependent(false) {} 5938c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall 594326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall /// Check classes in the current path for friendship, starting at 595326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall /// the given index. 596326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall bool checkFriendshipAlongPath(unsigned I) { 597326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall assert(I < CurPath.size()); 598326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall for (unsigned E = CurPath.size(); I != E; ++I) { 599326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall switch (GetFriendKind(S, EC, CurPath[I])) { 6008c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall case AR_accessible: return true; 6018c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall case AR_inaccessible: continue; 6028c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall case AR_dependent: EverDependent = true; continue; 6038c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall } 6048c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall } 6058c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall return false; 6068c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall } 6078c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall 6088c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall /// Perform a search starting at the given class. 609326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall /// 610326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall /// PrivateDepth is the index of the last (least derived) class 611326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall /// along the current path such that a notional public member of 612326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall /// the final class in the path would have access in that class. 613326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall bool findFriendship(const CXXRecordDecl *Cur, unsigned PrivateDepth) { 6148c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall // If we ever reach the naming class, check the current path for 6158c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall // friendship. We can also stop recursing because we obviously 6168c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall // won't find the naming class there again. 617326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall if (Cur == NamingClass) 618326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall return checkFriendshipAlongPath(PrivateDepth); 6198c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall 6208c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall if (CheckDependent && MightInstantiateTo(Cur, NamingClass)) 6218c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall EverDependent = true; 6228c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall 6238c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall // Recurse into the base classes. 6248c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall for (CXXRecordDecl::base_class_const_iterator 6258c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall I = Cur->bases_begin(), E = Cur->bases_end(); I != E; ++I) { 6268c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall 627326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall // If this is private inheritance, then a public member of the 628326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall // base will not have any access in classes derived from Cur. 629326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall unsigned BasePrivateDepth = PrivateDepth; 630326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall if (I->getAccessSpecifier() == AS_private) 631326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall BasePrivateDepth = CurPath.size() - 1; 6328c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall 6338c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall const CXXRecordDecl *RD; 6348c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall 6358c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall QualType T = I->getType(); 6368c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall if (const RecordType *RT = T->getAs<RecordType>()) { 6378c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall RD = cast<CXXRecordDecl>(RT->getDecl()); 6388c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall } else if (const InjectedClassNameType *IT 6398c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall = T->getAs<InjectedClassNameType>()) { 6408c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall RD = IT->getDecl(); 6418c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall } else { 6428c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall assert(T->isDependentType() && "non-dependent base wasn't a record?"); 6438c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall EverDependent = true; 6448c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall continue; 6458c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall } 6468c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall 6478c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall // Recurse. We don't need to clean up if this returns true. 648326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall CurPath.push_back(RD); 649326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall if (findFriendship(RD->getCanonicalDecl(), BasePrivateDepth)) 650326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall return true; 651326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall CurPath.pop_back(); 6528c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall } 6538c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall 6548c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall return false; 6558c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall } 656326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall 657326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall bool findFriendship(const CXXRecordDecl *Cur) { 658326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall assert(CurPath.empty()); 659326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall CurPath.push_back(Cur); 660326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall return findFriendship(Cur, 0); 661326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall } 6628c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall}; 6638c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall} 6648c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall 6658c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall/// Search for a class P that EC is a friend of, under the constraint 6668c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall/// InstanceContext <= P <= NamingClass 6678c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall/// and with the additional restriction that a protected member of 6688c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall/// NamingClass would have some natural access in P. 6698c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall/// 6708c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall/// That second condition isn't actually quite right: the condition in 6718c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall/// the standard is whether the target would have some natural access 6728c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall/// in P. The difference is that the target might be more accessible 6738c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall/// along some path not passing through NamingClass. Allowing that 6748c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall/// introduces two problems: 6758c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall/// - It breaks encapsulation because you can suddenly access a 6768c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall/// forbidden base class's members by subclassing it elsewhere. 6778c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall/// - It makes access substantially harder to compute because it 6788c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall/// breaks the hill-climbing algorithm: knowing that the target is 6798c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall/// accessible in some base class would no longer let you change 6808c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall/// the question solely to whether the base class is accessible, 6818c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall/// because the original target might have been more accessible 6828c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall/// because of crazy subclassing. 6838c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall/// So we don't implement that. 6848c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCallstatic AccessResult GetProtectedFriendKind(Sema &S, const EffectiveContext &EC, 6858c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall const CXXRecordDecl *InstanceContext, 6868c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall const CXXRecordDecl *NamingClass) { 6878c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall assert(InstanceContext->getCanonicalDecl() == InstanceContext); 6888c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall assert(NamingClass->getCanonicalDecl() == NamingClass); 6898c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall 6908c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall ProtectedFriendContext PRC(S, EC, InstanceContext, NamingClass); 6918c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall if (PRC.findFriendship(InstanceContext)) return AR_accessible; 6928c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall if (PRC.EverDependent) return AR_dependent; 6938c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall return AR_inaccessible; 6948c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall} 6958c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall 696161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic AccessResult HasAccess(Sema &S, 697161755a09898c95d21bfff33707da9ca41cd53c5John McCall const EffectiveContext &EC, 698161755a09898c95d21bfff33707da9ca41cd53c5John McCall const CXXRecordDecl *NamingClass, 699161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessSpecifier Access, 700161755a09898c95d21bfff33707da9ca41cd53c5John McCall const AccessTarget &Target) { 701db73c684ba61fed4087af488e8610657ec638c17John McCall assert(NamingClass->getCanonicalDecl() == NamingClass && 702db73c684ba61fed4087af488e8610657ec638c17John McCall "declaration should be canonicalized before being passed here"); 703db73c684ba61fed4087af488e8610657ec638c17John McCall 704161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (Access == AS_public) return AR_accessible; 705db73c684ba61fed4087af488e8610657ec638c17John McCall assert(Access == AS_private || Access == AS_protected); 706db73c684ba61fed4087af488e8610657ec638c17John McCall 707161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessResult OnFailure = AR_inaccessible; 708161755a09898c95d21bfff33707da9ca41cd53c5John McCall 709db73c684ba61fed4087af488e8610657ec638c17John McCall for (EffectiveContext::record_iterator 710db73c684ba61fed4087af488e8610657ec638c17John McCall I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { 711db73c684ba61fed4087af488e8610657ec638c17John McCall // All the declarations in EC have been canonicalized, so pointer 712db73c684ba61fed4087af488e8610657ec638c17John McCall // equality from this point on will work fine. 713db73c684ba61fed4087af488e8610657ec638c17John McCall const CXXRecordDecl *ECRecord = *I; 714db73c684ba61fed4087af488e8610657ec638c17John McCall 715db73c684ba61fed4087af488e8610657ec638c17John McCall // [B2] and [M2] 716161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (Access == AS_private) { 717161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (ECRecord == NamingClass) 718161755a09898c95d21bfff33707da9ca41cd53c5John McCall return AR_accessible; 719db73c684ba61fed4087af488e8610657ec638c17John McCall 72001ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall if (EC.isDependent() && MightInstantiateTo(ECRecord, NamingClass)) 72101ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall OnFailure = AR_dependent; 72201ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall 723db73c684ba61fed4087af488e8610657ec638c17John McCall // [B3] and [M3] 724161755a09898c95d21bfff33707da9ca41cd53c5John McCall } else { 725161755a09898c95d21bfff33707da9ca41cd53c5John McCall assert(Access == AS_protected); 726161755a09898c95d21bfff33707da9ca41cd53c5John McCall switch (IsDerivedFromInclusive(ECRecord, NamingClass)) { 727161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_accessible: break; 728161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_inaccessible: continue; 729161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_dependent: OnFailure = AR_dependent; continue; 730161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 731161755a09898c95d21bfff33707da9ca41cd53c5John McCall 732161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (!Target.hasInstanceContext()) 733161755a09898c95d21bfff33707da9ca41cd53c5John McCall return AR_accessible; 734161755a09898c95d21bfff33707da9ca41cd53c5John McCall 735161755a09898c95d21bfff33707da9ca41cd53c5John McCall const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S); 736161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (!InstanceContext) { 737161755a09898c95d21bfff33707da9ca41cd53c5John McCall OnFailure = AR_dependent; 738161755a09898c95d21bfff33707da9ca41cd53c5John McCall continue; 739161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 740161755a09898c95d21bfff33707da9ca41cd53c5John McCall 741161755a09898c95d21bfff33707da9ca41cd53c5John McCall // C++ [class.protected]p1: 742161755a09898c95d21bfff33707da9ca41cd53c5John McCall // An additional access check beyond those described earlier in 743161755a09898c95d21bfff33707da9ca41cd53c5John McCall // [class.access] is applied when a non-static data member or 744161755a09898c95d21bfff33707da9ca41cd53c5John McCall // non-static member function is a protected member of its naming 745161755a09898c95d21bfff33707da9ca41cd53c5John McCall // class. As described earlier, access to a protected member is 746161755a09898c95d21bfff33707da9ca41cd53c5John McCall // granted because the reference occurs in a friend or member of 747161755a09898c95d21bfff33707da9ca41cd53c5John McCall // some class C. If the access is to form a pointer to member, 748161755a09898c95d21bfff33707da9ca41cd53c5John McCall // the nested-name-specifier shall name C or a class derived from 749161755a09898c95d21bfff33707da9ca41cd53c5John McCall // C. All other accesses involve a (possibly implicit) object 750161755a09898c95d21bfff33707da9ca41cd53c5John McCall // expression. In this case, the class of the object expression 751161755a09898c95d21bfff33707da9ca41cd53c5John McCall // shall be C or a class derived from C. 752161755a09898c95d21bfff33707da9ca41cd53c5John McCall // 753161755a09898c95d21bfff33707da9ca41cd53c5John McCall // We interpret this as a restriction on [M3]. Most of the 754161755a09898c95d21bfff33707da9ca41cd53c5John McCall // conditions are encoded by not having any instance context. 755161755a09898c95d21bfff33707da9ca41cd53c5John McCall switch (IsDerivedFromInclusive(InstanceContext, ECRecord)) { 756161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_accessible: return AR_accessible; 757161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_inaccessible: continue; 758161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_dependent: OnFailure = AR_dependent; continue; 759161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 760161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 761db73c684ba61fed4087af488e8610657ec638c17John McCall } 762db73c684ba61fed4087af488e8610657ec638c17John McCall 7638c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall // [M3] and [B3] say that, if the target is protected in N, we grant 7648c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall // access if the access occurs in a friend or member of some class P 7658c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall // that's a subclass of N and where the target has some natural 7668c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall // access in P. The 'member' aspect is easy to handle because P 7678c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall // would necessarily be one of the effective-context records, and we 7688c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall // address that above. The 'friend' aspect is completely ridiculous 7698c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall // to implement because there are no restrictions at all on P 7708c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall // *unless* the [class.protected] restriction applies. If it does, 7718c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall // however, we should ignore whether the naming class is a friend, 7728c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall // and instead rely on whether any potential P is a friend. 773161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (Access == AS_protected && Target.hasInstanceContext()) { 774161755a09898c95d21bfff33707da9ca41cd53c5John McCall const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S); 775161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (!InstanceContext) return AR_dependent; 7768c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall switch (GetProtectedFriendKind(S, EC, InstanceContext, NamingClass)) { 7778c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall case AR_accessible: return AR_accessible; 778161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_inaccessible: return OnFailure; 779161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_dependent: return AR_dependent; 780161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 7811797a05f97671d40929224ac030c8c16fe69938cJohn McCall llvm_unreachable("impossible friendship kind"); 782161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 783161755a09898c95d21bfff33707da9ca41cd53c5John McCall 784161755a09898c95d21bfff33707da9ca41cd53c5John McCall switch (GetFriendKind(S, EC, NamingClass)) { 785161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_accessible: return AR_accessible; 786161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_inaccessible: return OnFailure; 787161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_dependent: return AR_dependent; 788161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 789161755a09898c95d21bfff33707da9ca41cd53c5John McCall 790161755a09898c95d21bfff33707da9ca41cd53c5John McCall // Silence bogus warnings 791161755a09898c95d21bfff33707da9ca41cd53c5John McCall llvm_unreachable("impossible friendship kind"); 792161755a09898c95d21bfff33707da9ca41cd53c5John McCall return OnFailure; 793db73c684ba61fed4087af488e8610657ec638c17John McCall} 794db73c684ba61fed4087af488e8610657ec638c17John McCall 7956b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// Finds the best path from the naming class to the declaring class, 7966b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// taking friend declarations into account. 7976b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// 798db73c684ba61fed4087af488e8610657ec638c17John McCall/// C++0x [class.access.base]p5: 799db73c684ba61fed4087af488e8610657ec638c17John McCall/// A member m is accessible at the point R when named in class N if 800db73c684ba61fed4087af488e8610657ec638c17John McCall/// [M1] m as a member of N is public, or 801db73c684ba61fed4087af488e8610657ec638c17John McCall/// [M2] m as a member of N is private, and R occurs in a member or 802db73c684ba61fed4087af488e8610657ec638c17John McCall/// friend of class N, or 803db73c684ba61fed4087af488e8610657ec638c17John McCall/// [M3] m as a member of N is protected, and R occurs in a member or 804db73c684ba61fed4087af488e8610657ec638c17John McCall/// friend of class N, or in a member or friend of a class P 805db73c684ba61fed4087af488e8610657ec638c17John McCall/// derived from N, where m as a member of P is public, private, 806db73c684ba61fed4087af488e8610657ec638c17John McCall/// or protected, or 807db73c684ba61fed4087af488e8610657ec638c17John McCall/// [M4] there exists a base class B of N that is accessible at R, and 808db73c684ba61fed4087af488e8610657ec638c17John McCall/// m is accessible at R when named in class B. 809db73c684ba61fed4087af488e8610657ec638c17John McCall/// 810db73c684ba61fed4087af488e8610657ec638c17John McCall/// C++0x [class.access.base]p4: 811db73c684ba61fed4087af488e8610657ec638c17John McCall/// A base class B of N is accessible at R, if 812db73c684ba61fed4087af488e8610657ec638c17John McCall/// [B1] an invented public member of B would be a public member of N, or 813db73c684ba61fed4087af488e8610657ec638c17John McCall/// [B2] R occurs in a member or friend of class N, and an invented public 814db73c684ba61fed4087af488e8610657ec638c17John McCall/// member of B would be a private or protected member of N, or 815db73c684ba61fed4087af488e8610657ec638c17John McCall/// [B3] R occurs in a member or friend of a class P derived from N, and an 816db73c684ba61fed4087af488e8610657ec638c17John McCall/// invented public member of B would be a private or protected member 817db73c684ba61fed4087af488e8610657ec638c17John McCall/// of P, or 818db73c684ba61fed4087af488e8610657ec638c17John McCall/// [B4] there exists a class S such that B is a base class of S accessible 819db73c684ba61fed4087af488e8610657ec638c17John McCall/// at R and S is a base class of N accessible at R. 820db73c684ba61fed4087af488e8610657ec638c17John McCall/// 821db73c684ba61fed4087af488e8610657ec638c17John McCall/// Along a single inheritance path we can restate both of these 822db73c684ba61fed4087af488e8610657ec638c17John McCall/// iteratively: 823db73c684ba61fed4087af488e8610657ec638c17John McCall/// 824db73c684ba61fed4087af488e8610657ec638c17John McCall/// First, we note that M1-4 are equivalent to B1-4 if the member is 825db73c684ba61fed4087af488e8610657ec638c17John McCall/// treated as a notional base of its declaring class with inheritance 826db73c684ba61fed4087af488e8610657ec638c17John McCall/// access equivalent to the member's access. Therefore we need only 827db73c684ba61fed4087af488e8610657ec638c17John McCall/// ask whether a class B is accessible from a class N in context R. 828db73c684ba61fed4087af488e8610657ec638c17John McCall/// 829db73c684ba61fed4087af488e8610657ec638c17John McCall/// Let B_1 .. B_n be the inheritance path in question (i.e. where 830db73c684ba61fed4087af488e8610657ec638c17John McCall/// B_1 = N, B_n = B, and for all i, B_{i+1} is a direct base class of 831db73c684ba61fed4087af488e8610657ec638c17John McCall/// B_i). For i in 1..n, we will calculate ACAB(i), the access to the 832db73c684ba61fed4087af488e8610657ec638c17John McCall/// closest accessible base in the path: 833db73c684ba61fed4087af488e8610657ec638c17John McCall/// Access(a, b) = (* access on the base specifier from a to b *) 834db73c684ba61fed4087af488e8610657ec638c17John McCall/// Merge(a, forbidden) = forbidden 835db73c684ba61fed4087af488e8610657ec638c17John McCall/// Merge(a, private) = forbidden 836db73c684ba61fed4087af488e8610657ec638c17John McCall/// Merge(a, b) = min(a,b) 837db73c684ba61fed4087af488e8610657ec638c17John McCall/// Accessible(c, forbidden) = false 838db73c684ba61fed4087af488e8610657ec638c17John McCall/// Accessible(c, private) = (R is c) || IsFriend(c, R) 839db73c684ba61fed4087af488e8610657ec638c17John McCall/// Accessible(c, protected) = (R derived from c) || IsFriend(c, R) 840db73c684ba61fed4087af488e8610657ec638c17John McCall/// Accessible(c, public) = true 841db73c684ba61fed4087af488e8610657ec638c17John McCall/// ACAB(n) = public 842db73c684ba61fed4087af488e8610657ec638c17John McCall/// ACAB(i) = 843db73c684ba61fed4087af488e8610657ec638c17John McCall/// let AccessToBase = Merge(Access(B_i, B_{i+1}), ACAB(i+1)) in 844db73c684ba61fed4087af488e8610657ec638c17John McCall/// if Accessible(B_i, AccessToBase) then public else AccessToBase 845db73c684ba61fed4087af488e8610657ec638c17John McCall/// 846db73c684ba61fed4087af488e8610657ec638c17John McCall/// B is an accessible base of N at R iff ACAB(1) = public. 847db73c684ba61fed4087af488e8610657ec638c17John McCall/// 848161755a09898c95d21bfff33707da9ca41cd53c5John McCall/// \param FinalAccess the access of the "final step", or AS_public if 8497aceaf8cee77c98478e8934dc283910292711a7eJohn McCall/// there is no final step. 8506b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// \return null if friendship is dependent 8516b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallstatic CXXBasePath *FindBestPath(Sema &S, 8526b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall const EffectiveContext &EC, 853161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget &Target, 8547aceaf8cee77c98478e8934dc283910292711a7eJohn McCall AccessSpecifier FinalAccess, 8556b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall CXXBasePaths &Paths) { 8566b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // Derive the paths to the desired base. 857161755a09898c95d21bfff33707da9ca41cd53c5John McCall const CXXRecordDecl *Derived = Target.getNamingClass(); 858161755a09898c95d21bfff33707da9ca41cd53c5John McCall const CXXRecordDecl *Base = Target.getDeclaringClass(); 859161755a09898c95d21bfff33707da9ca41cd53c5John McCall 860161755a09898c95d21bfff33707da9ca41cd53c5John McCall // FIXME: fail correctly when there are dependent paths. 861161755a09898c95d21bfff33707da9ca41cd53c5John McCall bool isDerived = Derived->isDerivedFrom(const_cast<CXXRecordDecl*>(Base), 862161755a09898c95d21bfff33707da9ca41cd53c5John McCall Paths); 8636b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall assert(isDerived && "derived class not actually derived from base"); 8646b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall (void) isDerived; 8656b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 8666b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall CXXBasePath *BestPath = 0; 8676b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 8687aceaf8cee77c98478e8934dc283910292711a7eJohn McCall assert(FinalAccess != AS_none && "forbidden access after declaring class"); 8697aceaf8cee77c98478e8934dc283910292711a7eJohn McCall 8700c01d18094100db92d38daa923c95661512db203John McCall bool AnyDependent = false; 8710c01d18094100db92d38daa923c95661512db203John McCall 8726b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // Derive the friend-modified access along each path. 8736b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall for (CXXBasePaths::paths_iterator PI = Paths.begin(), PE = Paths.end(); 8746b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall PI != PE; ++PI) { 875161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget::SavedInstanceContext _ = Target.saveInstanceContext(); 8766b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 8776b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // Walk through the path backwards. 8787aceaf8cee77c98478e8934dc283910292711a7eJohn McCall AccessSpecifier PathAccess = FinalAccess; 8796b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall CXXBasePath::iterator I = PI->end(), E = PI->begin(); 8806b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall while (I != E) { 8816b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall --I; 8826b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 8837aceaf8cee77c98478e8934dc283910292711a7eJohn McCall assert(PathAccess != AS_none); 8847aceaf8cee77c98478e8934dc283910292711a7eJohn McCall 8857aceaf8cee77c98478e8934dc283910292711a7eJohn McCall // If the declaration is a private member of a base class, there 8867aceaf8cee77c98478e8934dc283910292711a7eJohn McCall // is no level of friendship in derived classes that can make it 8877aceaf8cee77c98478e8934dc283910292711a7eJohn McCall // accessible. 8887aceaf8cee77c98478e8934dc283910292711a7eJohn McCall if (PathAccess == AS_private) { 8897aceaf8cee77c98478e8934dc283910292711a7eJohn McCall PathAccess = AS_none; 8907aceaf8cee77c98478e8934dc283910292711a7eJohn McCall break; 8917aceaf8cee77c98478e8934dc283910292711a7eJohn McCall } 8927aceaf8cee77c98478e8934dc283910292711a7eJohn McCall 893161755a09898c95d21bfff33707da9ca41cd53c5John McCall const CXXRecordDecl *NC = I->Class->getCanonicalDecl(); 894161755a09898c95d21bfff33707da9ca41cd53c5John McCall 8956b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall AccessSpecifier BaseAccess = I->Base->getAccessSpecifier(); 896db73c684ba61fed4087af488e8610657ec638c17John McCall PathAccess = std::max(PathAccess, BaseAccess); 897161755a09898c95d21bfff33707da9ca41cd53c5John McCall 898161755a09898c95d21bfff33707da9ca41cd53c5John McCall switch (HasAccess(S, EC, NC, PathAccess, Target)) { 899161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_inaccessible: break; 900161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_accessible: 901161755a09898c95d21bfff33707da9ca41cd53c5John McCall PathAccess = AS_public; 902161755a09898c95d21bfff33707da9ca41cd53c5John McCall 903161755a09898c95d21bfff33707da9ca41cd53c5John McCall // Future tests are not against members and so do not have 904161755a09898c95d21bfff33707da9ca41cd53c5John McCall // instance context. 905161755a09898c95d21bfff33707da9ca41cd53c5John McCall Target.suppressInstanceContext(); 906161755a09898c95d21bfff33707da9ca41cd53c5John McCall break; 907161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_dependent: 908db73c684ba61fed4087af488e8610657ec638c17John McCall AnyDependent = true; 909db73c684ba61fed4087af488e8610657ec638c17John McCall goto Next; 910c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson } 911c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson } 912726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl 9136b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // Note that we modify the path's Access field to the 9146b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // friend-modified access. 9156b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall if (BestPath == 0 || PathAccess < BestPath->Access) { 9166b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall BestPath = &*PI; 9176b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall BestPath->Access = PathAccess; 9180c01d18094100db92d38daa923c95661512db203John McCall 9190c01d18094100db92d38daa923c95661512db203John McCall // Short-circuit if we found a public path. 9200c01d18094100db92d38daa923c95661512db203John McCall if (BestPath->Access == AS_public) 9210c01d18094100db92d38daa923c95661512db203John McCall return BestPath; 922c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson } 9230c01d18094100db92d38daa923c95661512db203John McCall 9240c01d18094100db92d38daa923c95661512db203John McCall Next: ; 925c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson } 926c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson 9270c01d18094100db92d38daa923c95661512db203John McCall assert((!BestPath || BestPath->Access != AS_public) && 9280c01d18094100db92d38daa923c95661512db203John McCall "fell out of loop with public path"); 9290c01d18094100db92d38daa923c95661512db203John McCall 9300c01d18094100db92d38daa923c95661512db203John McCall // We didn't find a public path, but at least one path was subject 9310c01d18094100db92d38daa923c95661512db203John McCall // to dependent friendship, so delay the check. 9320c01d18094100db92d38daa923c95661512db203John McCall if (AnyDependent) 9330c01d18094100db92d38daa923c95661512db203John McCall return 0; 9340c01d18094100db92d38daa923c95661512db203John McCall 9356b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return BestPath; 936726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl} 937726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl 938fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall/// Given that an entity has protected natural access, check whether 939fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall/// access might be denied because of the protected member access 940fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall/// restriction. 941fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall/// 942fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall/// \return true if a note was emitted 943fe24e05a87e48fa3318b65d1a92c542107639fd9John McCallstatic bool TryDiagnoseProtectedAccess(Sema &S, const EffectiveContext &EC, 944fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall AccessTarget &Target) { 945fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall // Only applies to instance accesses. 946fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall if (!Target.hasInstanceContext()) 947fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall return false; 948fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall assert(Target.isMemberAccess()); 949fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall NamedDecl *D = Target.getTargetDecl(); 950fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall 951fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall const CXXRecordDecl *DeclaringClass = Target.getDeclaringClass(); 952fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall DeclaringClass = DeclaringClass->getCanonicalDecl(); 953fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall 954fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall for (EffectiveContext::record_iterator 955fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { 956fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall const CXXRecordDecl *ECRecord = *I; 957fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall switch (IsDerivedFromInclusive(ECRecord, DeclaringClass)) { 958fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall case AR_accessible: break; 959fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall case AR_inaccessible: continue; 960fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall case AR_dependent: continue; 961fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall } 962fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall 963fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall // The effective context is a subclass of the declaring class. 964fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall // If that class isn't a superclass of the instance context, 965fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall // then the [class.protected] restriction applies. 966fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall 967fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall // To get this exactly right, this might need to be checked more 968fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall // holistically; it's not necessarily the case that gaining 969fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall // access here would grant us access overall. 970fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall 971fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S); 972fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall assert(InstanceContext && "diagnosing dependent access"); 973fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall 974fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall switch (IsDerivedFromInclusive(InstanceContext, ECRecord)) { 975fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall case AR_accessible: continue; 976fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall case AR_dependent: continue; 977fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall case AR_inaccessible: 978fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall S.Diag(D->getLocation(), diag::note_access_protected_restricted) 979fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall << (InstanceContext != Target.getNamingClass()->getCanonicalDecl()) 980fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall << S.Context.getTypeDeclType(InstanceContext) 981fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall << S.Context.getTypeDeclType(ECRecord); 982fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall return true; 983fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall } 984fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall } 985fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall 986fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall return false; 987fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall} 988fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall 9896b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// Diagnose the path which caused the given declaration or base class 9906b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// to become inaccessible. 9916b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallstatic void DiagnoseAccessPath(Sema &S, 9926b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall const EffectiveContext &EC, 993161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget &Entity) { 994db73c684ba61fed4087af488e8610657ec638c17John McCall AccessSpecifier Access = Entity.getAccess(); 995161755a09898c95d21bfff33707da9ca41cd53c5John McCall const CXXRecordDecl *NamingClass = Entity.getNamingClass(); 996db73c684ba61fed4087af488e8610657ec638c17John McCall NamingClass = NamingClass->getCanonicalDecl(); 997db73c684ba61fed4087af488e8610657ec638c17John McCall 998161755a09898c95d21bfff33707da9ca41cd53c5John McCall NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : 0); 999161755a09898c95d21bfff33707da9ca41cd53c5John McCall const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass(); 1000db73c684ba61fed4087af488e8610657ec638c17John McCall 10016b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // Easy case: the decl's natural access determined its path access. 10026b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // We have to check against AS_private here in case Access is AS_none, 10036b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // indicating a non-public member of a private base class. 10046b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall if (D && (Access == D->getAccess() || D->getAccess() == AS_private)) { 1005161755a09898c95d21bfff33707da9ca41cd53c5John McCall switch (HasAccess(S, EC, DeclaringClass, D->getAccess(), Entity)) { 1006161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_inaccessible: { 1007fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall if (Access == AS_protected && 1008fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall TryDiagnoseProtectedAccess(S, EC, Entity)) 1009fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall return; 1010fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall 1011aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall // Find an original declaration. 1012aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall while (D->isOutOfLine()) { 1013aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall NamedDecl *PrevDecl = 0; 1014162e1c1b487352434552147967c3dd296ebee2f7Richard Smith if (VarDecl *VD = dyn_cast<VarDecl>(D)) 1015162e1c1b487352434552147967c3dd296ebee2f7Richard Smith PrevDecl = VD->getPreviousDeclaration(); 1016162e1c1b487352434552147967c3dd296ebee2f7Richard Smith else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) 1017162e1c1b487352434552147967c3dd296ebee2f7Richard Smith PrevDecl = FD->getPreviousDeclaration(); 1018162e1c1b487352434552147967c3dd296ebee2f7Richard Smith else if (TypedefNameDecl *TND = dyn_cast<TypedefNameDecl>(D)) 1019162e1c1b487352434552147967c3dd296ebee2f7Richard Smith PrevDecl = TND->getPreviousDeclaration(); 1020162e1c1b487352434552147967c3dd296ebee2f7Richard Smith else if (TagDecl *TD = dyn_cast<TagDecl>(D)) { 1021aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall if (isa<RecordDecl>(D) && cast<RecordDecl>(D)->isInjectedClassName()) 1022aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall break; 1023162e1c1b487352434552147967c3dd296ebee2f7Richard Smith PrevDecl = TD->getPreviousDeclaration(); 1024aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall } 1025aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall if (!PrevDecl) break; 1026aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall D = PrevDecl; 1027aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall } 1028aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall 1029aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall CXXRecordDecl *DeclaringClass = FindDeclaringClass(D); 1030aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall Decl *ImmediateChild; 1031aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall if (D->getDeclContext() == DeclaringClass) 1032aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall ImmediateChild = D; 1033aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall else { 1034aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall DeclContext *DC = D->getDeclContext(); 1035aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall while (DC->getParent() != DeclaringClass) 1036aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall DC = DC->getParent(); 1037aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall ImmediateChild = cast<Decl>(DC); 1038aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall } 1039aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall 1040aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall // Check whether there's an AccessSpecDecl preceding this in the 1041aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall // chain of the DeclContext. 1042aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall bool Implicit = true; 1043aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall for (CXXRecordDecl::decl_iterator 1044aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall I = DeclaringClass->decls_begin(), E = DeclaringClass->decls_end(); 1045aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall I != E; ++I) { 1046aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall if (*I == ImmediateChild) break; 1047aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall if (isa<AccessSpecDecl>(*I)) { 1048aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall Implicit = false; 1049aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall break; 1050aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall } 1051aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall } 1052aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall 10536b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall S.Diag(D->getLocation(), diag::note_access_natural) 10546b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall << (unsigned) (Access == AS_protected) 1055aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall << Implicit; 10566b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return; 10576b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall } 1058726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl 1059161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_accessible: break; 1060726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl 1061161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_dependent: 1062161755a09898c95d21bfff33707da9ca41cd53c5John McCall llvm_unreachable("can't diagnose dependent access failures"); 10636b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return; 10646b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall } 10656b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall } 1066c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson 10676b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall CXXBasePaths Paths; 1068161755a09898c95d21bfff33707da9ca41cd53c5John McCall CXXBasePath &Path = *FindBestPath(S, EC, Entity, AS_public, Paths); 1069726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl 10706b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall CXXBasePath::iterator I = Path.end(), E = Path.begin(); 10716b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall while (I != E) { 10726b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall --I; 1073c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson 10746b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall const CXXBaseSpecifier *BS = I->Base; 10756b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall AccessSpecifier BaseAccess = BS->getAccessSpecifier(); 10766b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 10776b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // If this is public inheritance, or the derived class is a friend, 10786b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // skip this step. 10796b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall if (BaseAccess == AS_public) 10806b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall continue; 10816b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 10826b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall switch (GetFriendKind(S, EC, I->Class)) { 1083161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_accessible: continue; 1084161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_inaccessible: break; 1085161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_dependent: 1086161755a09898c95d21bfff33707da9ca41cd53c5John McCall llvm_unreachable("can't diagnose dependent access failures"); 10876b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall } 10886b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 10896b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // Check whether this base specifier is the tighest point 10906b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // constraining access. We have to check against AS_private for 10916b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // the same reasons as above. 10926b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall if (BaseAccess == AS_private || BaseAccess >= Access) { 10936b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 10946b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // We're constrained by inheritance, but we want to say 10956b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // "declared private here" if we're diagnosing a hierarchy 10966b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // conversion and this is the final step. 10976b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall unsigned diagnostic; 10986b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall if (D) diagnostic = diag::note_access_constrained_by_path; 10996b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall else if (I + 1 == Path.end()) diagnostic = diag::note_access_natural; 11006b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall else diagnostic = diag::note_access_constrained_by_path; 11016b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 11026b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall S.Diag(BS->getSourceRange().getBegin(), diagnostic) 11036b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall << BS->getSourceRange() 11046b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall << (BaseAccess == AS_protected) 11056b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall << (BS->getAccessSpecifierAsWritten() == AS_none); 110676ef658c703faf72c00f324fb9edc03169718e3eDouglas Gregor 110776ef658c703faf72c00f324fb9edc03169718e3eDouglas Gregor if (D) 110876ef658c703faf72c00f324fb9edc03169718e3eDouglas Gregor S.Diag(D->getLocation(), diag::note_field_decl); 110976ef658c703faf72c00f324fb9edc03169718e3eDouglas Gregor 11106b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return; 11116b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall } 1112c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson } 1113726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl 11146b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall llvm_unreachable("access not apparently constrained by path"); 111529f006be830fbbcaa0c1cf7c7399bb5080dc7f32Anders Carlsson} 111692f883177b162928a8e632e4e3b93fafd2b26072John McCall 1117db73c684ba61fed4087af488e8610657ec638c17John McCallstatic void DiagnoseBadAccess(Sema &S, SourceLocation Loc, 1118db73c684ba61fed4087af488e8610657ec638c17John McCall const EffectiveContext &EC, 1119161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget &Entity) { 1120db73c684ba61fed4087af488e8610657ec638c17John McCall const CXXRecordDecl *NamingClass = Entity.getNamingClass(); 1121161755a09898c95d21bfff33707da9ca41cd53c5John McCall const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass(); 1122161755a09898c95d21bfff33707da9ca41cd53c5John McCall NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : 0); 11236b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 112458e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall S.Diag(Loc, Entity.getDiag()) 1125db73c684ba61fed4087af488e8610657ec638c17John McCall << (Entity.getAccess() == AS_protected) 1126db73c684ba61fed4087af488e8610657ec638c17John McCall << (D ? D->getDeclName() : DeclarationName()) 112758e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall << S.Context.getTypeDeclType(NamingClass) 112858e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall << S.Context.getTypeDeclType(DeclaringClass); 1129db73c684ba61fed4087af488e8610657ec638c17John McCall DiagnoseAccessPath(S, EC, Entity); 11306b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall} 113192f883177b162928a8e632e4e3b93fafd2b26072John McCall 1132db73c684ba61fed4087af488e8610657ec638c17John McCall/// Determines whether the accessed entity is accessible. Public members 1133db73c684ba61fed4087af488e8610657ec638c17John McCall/// have been weeded out by this point. 1134161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic AccessResult IsAccessible(Sema &S, 1135161755a09898c95d21bfff33707da9ca41cd53c5John McCall const EffectiveContext &EC, 1136161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget &Entity) { 1137db73c684ba61fed4087af488e8610657ec638c17John McCall // Determine the actual naming class. 1138db73c684ba61fed4087af488e8610657ec638c17John McCall CXXRecordDecl *NamingClass = Entity.getNamingClass(); 1139db73c684ba61fed4087af488e8610657ec638c17John McCall while (NamingClass->isAnonymousStructOrUnion()) 1140db73c684ba61fed4087af488e8610657ec638c17John McCall NamingClass = cast<CXXRecordDecl>(NamingClass->getParent()); 1141db73c684ba61fed4087af488e8610657ec638c17John McCall NamingClass = NamingClass->getCanonicalDecl(); 114292f883177b162928a8e632e4e3b93fafd2b26072John McCall 1143db73c684ba61fed4087af488e8610657ec638c17John McCall AccessSpecifier UnprivilegedAccess = Entity.getAccess(); 1144db73c684ba61fed4087af488e8610657ec638c17John McCall assert(UnprivilegedAccess != AS_public && "public access not weeded out"); 114592f883177b162928a8e632e4e3b93fafd2b26072John McCall 1146db73c684ba61fed4087af488e8610657ec638c17John McCall // Before we try to recalculate access paths, try to white-list 1147db73c684ba61fed4087af488e8610657ec638c17John McCall // accesses which just trade in on the final step, i.e. accesses 1148db73c684ba61fed4087af488e8610657ec638c17John McCall // which don't require [M4] or [B4]. These are by far the most 1149161755a09898c95d21bfff33707da9ca41cd53c5John McCall // common forms of privileged access. 1150db73c684ba61fed4087af488e8610657ec638c17John McCall if (UnprivilegedAccess != AS_none) { 1151161755a09898c95d21bfff33707da9ca41cd53c5John McCall switch (HasAccess(S, EC, NamingClass, UnprivilegedAccess, Entity)) { 1152161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_dependent: 1153db73c684ba61fed4087af488e8610657ec638c17John McCall // This is actually an interesting policy decision. We don't 1154db73c684ba61fed4087af488e8610657ec638c17John McCall // *have* to delay immediately here: we can do the full access 1155db73c684ba61fed4087af488e8610657ec638c17John McCall // calculation in the hope that friendship on some intermediate 1156db73c684ba61fed4087af488e8610657ec638c17John McCall // class will make the declaration accessible non-dependently. 1157db73c684ba61fed4087af488e8610657ec638c17John McCall // But that's not cheap, and odds are very good (note: assertion 1158db73c684ba61fed4087af488e8610657ec638c17John McCall // made without data) that the friend declaration will determine 1159db73c684ba61fed4087af488e8610657ec638c17John McCall // access. 1160161755a09898c95d21bfff33707da9ca41cd53c5John McCall return AR_dependent; 1161db73c684ba61fed4087af488e8610657ec638c17John McCall 1162161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_accessible: return AR_accessible; 1163161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_inaccessible: break; 1164db73c684ba61fed4087af488e8610657ec638c17John McCall } 1165db73c684ba61fed4087af488e8610657ec638c17John McCall } 116692f883177b162928a8e632e4e3b93fafd2b26072John McCall 1167161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget::SavedInstanceContext _ = Entity.saveInstanceContext(); 1168db73c684ba61fed4087af488e8610657ec638c17John McCall 1169db73c684ba61fed4087af488e8610657ec638c17John McCall // We lower member accesses to base accesses by pretending that the 1170db73c684ba61fed4087af488e8610657ec638c17John McCall // member is a base class of its declaring class. 1171db73c684ba61fed4087af488e8610657ec638c17John McCall AccessSpecifier FinalAccess; 11726b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 11736b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall if (Entity.isMemberAccess()) { 1174db73c684ba61fed4087af488e8610657ec638c17John McCall // Determine if the declaration is accessible from EC when named 1175db73c684ba61fed4087af488e8610657ec638c17John McCall // in its declaring class. 11766b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall NamedDecl *Target = Entity.getTargetDecl(); 1177161755a09898c95d21bfff33707da9ca41cd53c5John McCall const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass(); 11786b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 1179db73c684ba61fed4087af488e8610657ec638c17John McCall FinalAccess = Target->getAccess(); 1180161755a09898c95d21bfff33707da9ca41cd53c5John McCall switch (HasAccess(S, EC, DeclaringClass, FinalAccess, Entity)) { 1181161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_accessible: 1182161755a09898c95d21bfff33707da9ca41cd53c5John McCall FinalAccess = AS_public; 1183161755a09898c95d21bfff33707da9ca41cd53c5John McCall break; 1184161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_inaccessible: break; 1185161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_dependent: return AR_dependent; // see above 11866b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall } 11872f514480c448708ec382a684cf5e035d3a827ec8John McCall 1188db73c684ba61fed4087af488e8610657ec638c17John McCall if (DeclaringClass == NamingClass) 1189161755a09898c95d21bfff33707da9ca41cd53c5John McCall return (FinalAccess == AS_public ? AR_accessible : AR_inaccessible); 1190161755a09898c95d21bfff33707da9ca41cd53c5John McCall 1191161755a09898c95d21bfff33707da9ca41cd53c5John McCall Entity.suppressInstanceContext(); 1192db73c684ba61fed4087af488e8610657ec638c17John McCall } else { 1193db73c684ba61fed4087af488e8610657ec638c17John McCall FinalAccess = AS_public; 11946b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall } 11952f514480c448708ec382a684cf5e035d3a827ec8John McCall 1196161755a09898c95d21bfff33707da9ca41cd53c5John McCall assert(Entity.getDeclaringClass() != NamingClass); 11976b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 11986b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // Append the declaration's access if applicable. 11996b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall CXXBasePaths Paths; 1200161755a09898c95d21bfff33707da9ca41cd53c5John McCall CXXBasePath *Path = FindBestPath(S, EC, Entity, FinalAccess, Paths); 12010c01d18094100db92d38daa923c95661512db203John McCall if (!Path) 1202161755a09898c95d21bfff33707da9ca41cd53c5John McCall return AR_dependent; 120392f883177b162928a8e632e4e3b93fafd2b26072John McCall 1204db73c684ba61fed4087af488e8610657ec638c17John McCall assert(Path->Access <= UnprivilegedAccess && 1205db73c684ba61fed4087af488e8610657ec638c17John McCall "access along best path worse than direct?"); 1206db73c684ba61fed4087af488e8610657ec638c17John McCall if (Path->Access == AS_public) 1207161755a09898c95d21bfff33707da9ca41cd53c5John McCall return AR_accessible; 1208161755a09898c95d21bfff33707da9ca41cd53c5John McCall return AR_inaccessible; 12090c01d18094100db92d38daa923c95661512db203John McCall} 12100c01d18094100db92d38daa923c95661512db203John McCall 1211161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic void DelayDependentAccess(Sema &S, 1212161755a09898c95d21bfff33707da9ca41cd53c5John McCall const EffectiveContext &EC, 1213161755a09898c95d21bfff33707da9ca41cd53c5John McCall SourceLocation Loc, 1214161755a09898c95d21bfff33707da9ca41cd53c5John McCall const AccessTarget &Entity) { 12150c01d18094100db92d38daa923c95661512db203John McCall assert(EC.isDependent() && "delaying non-dependent access"); 12167ad650f88ecbbe659f10f9f6b34a1f29ea9cf8f9John McCall DeclContext *DC = EC.getInnerContext(); 12170c01d18094100db92d38daa923c95661512db203John McCall assert(DC->isDependentContext() && "delaying non-dependent access"); 12180c01d18094100db92d38daa923c95661512db203John McCall DependentDiagnostic::Create(S.Context, DC, DependentDiagnostic::Access, 12190c01d18094100db92d38daa923c95661512db203John McCall Loc, 12200c01d18094100db92d38daa923c95661512db203John McCall Entity.isMemberAccess(), 12210c01d18094100db92d38daa923c95661512db203John McCall Entity.getAccess(), 12220c01d18094100db92d38daa923c95661512db203John McCall Entity.getTargetDecl(), 12230c01d18094100db92d38daa923c95661512db203John McCall Entity.getNamingClass(), 1224161755a09898c95d21bfff33707da9ca41cd53c5John McCall Entity.getBaseObjectType(), 12250c01d18094100db92d38daa923c95661512db203John McCall Entity.getDiag()); 12266b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall} 12276b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 12286b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// Checks access to an entity from the given effective context. 1229161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic AccessResult CheckEffectiveAccess(Sema &S, 1230161755a09898c95d21bfff33707da9ca41cd53c5John McCall const EffectiveContext &EC, 1231161755a09898c95d21bfff33707da9ca41cd53c5John McCall SourceLocation Loc, 1232161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget &Entity) { 1233db73c684ba61fed4087af488e8610657ec638c17John McCall assert(Entity.getAccess() != AS_public && "called for public access!"); 123492f883177b162928a8e632e4e3b93fafd2b26072John McCall 1235db73c684ba61fed4087af488e8610657ec638c17John McCall switch (IsAccessible(S, EC, Entity)) { 1236161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_dependent: 1237161755a09898c95d21bfff33707da9ca41cd53c5John McCall DelayDependentAccess(S, EC, Loc, Entity); 1238161755a09898c95d21bfff33707da9ca41cd53c5John McCall return AR_dependent; 12390c01d18094100db92d38daa923c95661512db203John McCall 1240161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_inaccessible: 1241db73c684ba61fed4087af488e8610657ec638c17John McCall if (!Entity.isQuiet()) 1242db73c684ba61fed4087af488e8610657ec638c17John McCall DiagnoseBadAccess(S, Loc, EC, Entity); 1243161755a09898c95d21bfff33707da9ca41cd53c5John McCall return AR_inaccessible; 124492f883177b162928a8e632e4e3b93fafd2b26072John McCall 1245161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_accessible: 1246161755a09898c95d21bfff33707da9ca41cd53c5John McCall return AR_accessible; 1247db73c684ba61fed4087af488e8610657ec638c17John McCall } 1248db73c684ba61fed4087af488e8610657ec638c17John McCall 1249161755a09898c95d21bfff33707da9ca41cd53c5John McCall // silence unnecessary warning 1250161755a09898c95d21bfff33707da9ca41cd53c5John McCall llvm_unreachable("invalid access result"); 1251161755a09898c95d21bfff33707da9ca41cd53c5John McCall return AR_accessible; 12526b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall} 125392f883177b162928a8e632e4e3b93fafd2b26072John McCall 12546b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallstatic Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc, 1255161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget &Entity) { 12566b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall // If the access path is public, it's accessible everywhere. 12576b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall if (Entity.getAccess() == AS_public) 12586b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return Sema::AR_accessible; 125992f883177b162928a8e632e4e3b93fafd2b26072John McCall 1260926c4b486a08f698cd3a367fd6f1a3a07604358dChandler Carruth if (S.SuppressAccessChecking) 1261926c4b486a08f698cd3a367fd6f1a3a07604358dChandler Carruth return Sema::AR_accessible; 1262926c4b486a08f698cd3a367fd6f1a3a07604358dChandler Carruth 1263eee1d5434ebfa955ffc3c493aecd68bb7b3f4838John McCall // If we're currently parsing a declaration, we may need to delay 1264eee1d5434ebfa955ffc3c493aecd68bb7b3f4838John McCall // access control checking, because our effective context might be 1265eee1d5434ebfa955ffc3c493aecd68bb7b3f4838John McCall // different based on what the declaration comes out as. 1266eee1d5434ebfa955ffc3c493aecd68bb7b3f4838John McCall // 1267eee1d5434ebfa955ffc3c493aecd68bb7b3f4838John McCall // For example, we might be parsing a declaration with a scope 1268eee1d5434ebfa955ffc3c493aecd68bb7b3f4838John McCall // specifier, like this: 1269eee1d5434ebfa955ffc3c493aecd68bb7b3f4838John McCall // A::private_type A::foo() { ... } 1270eee1d5434ebfa955ffc3c493aecd68bb7b3f4838John McCall // 1271eee1d5434ebfa955ffc3c493aecd68bb7b3f4838John McCall // Or we might be parsing something that will turn out to be a friend: 1272eee1d5434ebfa955ffc3c493aecd68bb7b3f4838John McCall // void foo(A::private_type); 1273eee1d5434ebfa955ffc3c493aecd68bb7b3f4838John McCall // void B::foo(A::private_type); 1274eee1d5434ebfa955ffc3c493aecd68bb7b3f4838John McCall if (S.DelayedDiagnostics.shouldDelayDiagnostics()) { 1275eee1d5434ebfa955ffc3c493aecd68bb7b3f4838John McCall S.DelayedDiagnostics.add(DelayedDiagnostic::makeAccess(Loc, Entity)); 12766b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return Sema::AR_delayed; 127792f883177b162928a8e632e4e3b93fafd2b26072John McCall } 127892f883177b162928a8e632e4e3b93fafd2b26072John McCall 1279161755a09898c95d21bfff33707da9ca41cd53c5John McCall EffectiveContext EC(S.CurContext); 1280161755a09898c95d21bfff33707da9ca41cd53c5John McCall switch (CheckEffectiveAccess(S, EC, Loc, Entity)) { 1281161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_accessible: return Sema::AR_accessible; 1282161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_inaccessible: return Sema::AR_inaccessible; 1283161755a09898c95d21bfff33707da9ca41cd53c5John McCall case AR_dependent: return Sema::AR_dependent; 1284161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 1285161755a09898c95d21bfff33707da9ca41cd53c5John McCall llvm_unreachable("falling off end"); 1286161755a09898c95d21bfff33707da9ca41cd53c5John McCall return Sema::AR_accessible; 128792f883177b162928a8e632e4e3b93fafd2b26072John McCall} 128892f883177b162928a8e632e4e3b93fafd2b26072John McCall 12894bfd680597862e437fcba739dce58531d0b15d6eJohn McCallvoid Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *decl) { 12904bfd680597862e437fcba739dce58531d0b15d6eJohn McCall // Access control for names used in the declarations of functions 12914bfd680597862e437fcba739dce58531d0b15d6eJohn McCall // and function templates should normally be evaluated in the context 12924bfd680597862e437fcba739dce58531d0b15d6eJohn McCall // of the declaration, just in case it's a friend of something. 12934bfd680597862e437fcba739dce58531d0b15d6eJohn McCall // However, this does not apply to local extern declarations. 12944bfd680597862e437fcba739dce58531d0b15d6eJohn McCall 12954bfd680597862e437fcba739dce58531d0b15d6eJohn McCall DeclContext *DC = decl->getDeclContext(); 12964bfd680597862e437fcba739dce58531d0b15d6eJohn McCall if (FunctionDecl *fn = dyn_cast<FunctionDecl>(decl)) { 12974bfd680597862e437fcba739dce58531d0b15d6eJohn McCall if (!DC->isFunctionOrMethod()) DC = fn; 12984bfd680597862e437fcba739dce58531d0b15d6eJohn McCall } else if (FunctionTemplateDecl *fnt = dyn_cast<FunctionTemplateDecl>(decl)) { 12994bfd680597862e437fcba739dce58531d0b15d6eJohn McCall // Never a local declaration. 13004bfd680597862e437fcba739dce58531d0b15d6eJohn McCall DC = fnt->getTemplatedDecl(); 13014bfd680597862e437fcba739dce58531d0b15d6eJohn McCall } 13024bfd680597862e437fcba739dce58531d0b15d6eJohn McCall 1303630eb01b2568d0958118eb1a0ded02bebecb2b0fChandler Carruth EffectiveContext EC(DC); 13042f514480c448708ec382a684cf5e035d3a827ec8John McCall 1305161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget Target(DD.getAccessData()); 1306161755a09898c95d21bfff33707da9ca41cd53c5John McCall 1307161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (CheckEffectiveAccess(*this, EC, DD.Loc, Target) == ::AR_inaccessible) 13082f514480c448708ec382a684cf5e035d3a827ec8John McCall DD.Triggered = true; 13092f514480c448708ec382a684cf5e035d3a827ec8John McCall} 13102f514480c448708ec382a684cf5e035d3a827ec8John McCall 13110c01d18094100db92d38daa923c95661512db203John McCallvoid Sema::HandleDependentAccessCheck(const DependentDiagnostic &DD, 13120c01d18094100db92d38daa923c95661512db203John McCall const MultiLevelTemplateArgumentList &TemplateArgs) { 13130c01d18094100db92d38daa923c95661512db203John McCall SourceLocation Loc = DD.getAccessLoc(); 13140c01d18094100db92d38daa923c95661512db203John McCall AccessSpecifier Access = DD.getAccess(); 13150c01d18094100db92d38daa923c95661512db203John McCall 13160c01d18094100db92d38daa923c95661512db203John McCall Decl *NamingD = FindInstantiatedDecl(Loc, DD.getAccessNamingClass(), 13170c01d18094100db92d38daa923c95661512db203John McCall TemplateArgs); 13180c01d18094100db92d38daa923c95661512db203John McCall if (!NamingD) return; 13190c01d18094100db92d38daa923c95661512db203John McCall Decl *TargetD = FindInstantiatedDecl(Loc, DD.getAccessTarget(), 13200c01d18094100db92d38daa923c95661512db203John McCall TemplateArgs); 13210c01d18094100db92d38daa923c95661512db203John McCall if (!TargetD) return; 13220c01d18094100db92d38daa923c95661512db203John McCall 13230c01d18094100db92d38daa923c95661512db203John McCall if (DD.isAccessToMember()) { 1324161755a09898c95d21bfff33707da9ca41cd53c5John McCall CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(NamingD); 1325161755a09898c95d21bfff33707da9ca41cd53c5John McCall NamedDecl *TargetDecl = cast<NamedDecl>(TargetD); 1326161755a09898c95d21bfff33707da9ca41cd53c5John McCall QualType BaseObjectType = DD.getAccessBaseObjectType(); 1327161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (!BaseObjectType.isNull()) { 1328161755a09898c95d21bfff33707da9ca41cd53c5John McCall BaseObjectType = SubstType(BaseObjectType, TemplateArgs, Loc, 1329161755a09898c95d21bfff33707da9ca41cd53c5John McCall DeclarationName()); 1330161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (BaseObjectType.isNull()) return; 1331161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 1332161755a09898c95d21bfff33707da9ca41cd53c5John McCall 1333161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget Entity(Context, 1334161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget::Member, 1335161755a09898c95d21bfff33707da9ca41cd53c5John McCall NamingClass, 1336161755a09898c95d21bfff33707da9ca41cd53c5John McCall DeclAccessPair::make(TargetDecl, Access), 1337161755a09898c95d21bfff33707da9ca41cd53c5John McCall BaseObjectType); 13380c01d18094100db92d38daa923c95661512db203John McCall Entity.setDiag(DD.getDiagnostic()); 13390c01d18094100db92d38daa923c95661512db203John McCall CheckAccess(*this, Loc, Entity); 13400c01d18094100db92d38daa923c95661512db203John McCall } else { 1341161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget Entity(Context, 1342161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget::Base, 1343161755a09898c95d21bfff33707da9ca41cd53c5John McCall cast<CXXRecordDecl>(TargetD), 1344161755a09898c95d21bfff33707da9ca41cd53c5John McCall cast<CXXRecordDecl>(NamingD), 1345161755a09898c95d21bfff33707da9ca41cd53c5John McCall Access); 13460c01d18094100db92d38daa923c95661512db203John McCall Entity.setDiag(DD.getDiagnostic()); 13470c01d18094100db92d38daa923c95661512db203John McCall CheckAccess(*this, Loc, Entity); 13480c01d18094100db92d38daa923c95661512db203John McCall } 13490c01d18094100db92d38daa923c95661512db203John McCall} 13500c01d18094100db92d38daa923c95661512db203John McCall 13516b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallSema::AccessResult Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E, 13529aa472c45d2bd81b7b52c225e8acc560d716db97John McCall DeclAccessPair Found) { 135358e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall if (!getLangOptions().AccessControl || 135458e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall !E->getNamingClass() || 13559aa472c45d2bd81b7b52c225e8acc560d716db97John McCall Found.getAccess() == AS_public) 13566b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return AR_accessible; 1357c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall 1358161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(), 1359161755a09898c95d21bfff33707da9ca41cd53c5John McCall Found, QualType()); 136058e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall Entity.setDiag(diag::err_access) << E->getSourceRange(); 136158e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall 136258e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall return CheckAccess(*this, E->getNameLoc(), Entity); 1363c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall} 1364c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall 1365c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall/// Perform access-control checking on a previously-unresolved member 1366c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall/// access which has now been resolved to a member. 13676b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallSema::AccessResult Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E, 13689aa472c45d2bd81b7b52c225e8acc560d716db97John McCall DeclAccessPair Found) { 136958e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall if (!getLangOptions().AccessControl || 13709aa472c45d2bd81b7b52c225e8acc560d716db97John McCall Found.getAccess() == AS_public) 13716b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return AR_accessible; 1372c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall 1373161755a09898c95d21bfff33707da9ca41cd53c5John McCall QualType BaseType = E->getBaseType(); 1374161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (E->isArrow()) 1375161755a09898c95d21bfff33707da9ca41cd53c5John McCall BaseType = BaseType->getAs<PointerType>()->getPointeeType(); 1376161755a09898c95d21bfff33707da9ca41cd53c5John McCall 1377161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(), 1378161755a09898c95d21bfff33707da9ca41cd53c5John McCall Found, BaseType); 137958e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall Entity.setDiag(diag::err_access) << E->getSourceRange(); 138058e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall 138158e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall return CheckAccess(*this, E->getMemberLoc(), Entity); 1382c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall} 1383c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall 13846b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallSema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc, 138558e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall CXXDestructorDecl *Dtor, 138658e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall const PartialDiagnostic &PDiag) { 13874f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall if (!getLangOptions().AccessControl) 13886b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return AR_accessible; 13894f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall 139058e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall // There's never a path involved when checking implicit destructor access. 13914f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall AccessSpecifier Access = Dtor->getAccess(); 13924f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall if (Access == AS_public) 13936b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return AR_accessible; 13944f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall 139558e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall CXXRecordDecl *NamingClass = Dtor->getParent(); 1396161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget Entity(Context, AccessTarget::Member, NamingClass, 1397161755a09898c95d21bfff33707da9ca41cd53c5John McCall DeclAccessPair::make(Dtor, Access), 1398161755a09898c95d21bfff33707da9ca41cd53c5John McCall QualType()); 139958e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall Entity.setDiag(PDiag); // TODO: avoid copy 140058e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall 140158e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall return CheckAccess(*this, Loc, Entity); 14024f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall} 14034f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall 1404b13b737a2450167c82e148590e8019b839ce6b98John McCall/// Checks access to a constructor. 14056b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallSema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc, 140657d12fd4a2bc739c4a4d62a364b7f08cd483c59eJeffrey Yasskin CXXConstructorDecl *Constructor, 140757d12fd4a2bc739c4a4d62a364b7f08cd483c59eJeffrey Yasskin const InitializedEntity &Entity, 140857d12fd4a2bc739c4a4d62a364b7f08cd483c59eJeffrey Yasskin AccessSpecifier Access, 140957d12fd4a2bc739c4a4d62a364b7f08cd483c59eJeffrey Yasskin bool IsCopyBindingRefToTemp) { 141058e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall if (!getLangOptions().AccessControl || 141158e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall Access == AS_public) 14126b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return AR_accessible; 1413b13b737a2450167c82e148590e8019b839ce6b98John McCall 14146b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall CXXRecordDecl *NamingClass = Constructor->getParent(); 14159a68a67c6ae4982001815cc04f69b8781058263aAnders Carlsson AccessTarget AccessEntity(Context, AccessTarget::Member, NamingClass, 14169a68a67c6ae4982001815cc04f69b8781058263aAnders Carlsson DeclAccessPair::make(Constructor, Access), 14179a68a67c6ae4982001815cc04f69b8781058263aAnders Carlsson QualType()); 14189a68a67c6ae4982001815cc04f69b8781058263aAnders Carlsson switch (Entity.getKind()) { 14199a68a67c6ae4982001815cc04f69b8781058263aAnders Carlsson default: 142057d12fd4a2bc739c4a4d62a364b7f08cd483c59eJeffrey Yasskin AccessEntity.setDiag(IsCopyBindingRefToTemp 142157d12fd4a2bc739c4a4d62a364b7f08cd483c59eJeffrey Yasskin ? diag::ext_rvalue_to_reference_access_ctor 142257d12fd4a2bc739c4a4d62a364b7f08cd483c59eJeffrey Yasskin : diag::err_access_ctor); 14239a68a67c6ae4982001815cc04f69b8781058263aAnders Carlsson break; 14249a68a67c6ae4982001815cc04f69b8781058263aAnders Carlsson 14253b8c53b619c1c3d77632734d227566071459b9f5Anders Carlsson case InitializedEntity::EK_Base: 14263b8c53b619c1c3d77632734d227566071459b9f5Anders Carlsson AccessEntity.setDiag(PDiag(diag::err_access_base) 14273b8c53b619c1c3d77632734d227566071459b9f5Anders Carlsson << Entity.isInheritedVirtualBase() 14283b8c53b619c1c3d77632734d227566071459b9f5Anders Carlsson << Entity.getBaseSpecifier()->getType() 14293b8c53b619c1c3d77632734d227566071459b9f5Anders Carlsson << getSpecialMember(Constructor)); 14309a68a67c6ae4982001815cc04f69b8781058263aAnders Carlsson break; 14313b8c53b619c1c3d77632734d227566071459b9f5Anders Carlsson 1432b99c666a940e93bcfcaeddc01515c94472e28a20Anders Carlsson case InitializedEntity::EK_Member: { 1433b99c666a940e93bcfcaeddc01515c94472e28a20Anders Carlsson const FieldDecl *Field = cast<FieldDecl>(Entity.getDecl()); 14340e313bd4795c005f23c43f127039fd948c3e0bd9Anders Carlsson AccessEntity.setDiag(PDiag(diag::err_access_field) 14350e313bd4795c005f23c43f127039fd948c3e0bd9Anders Carlsson << Field->getType() 14360e313bd4795c005f23c43f127039fd948c3e0bd9Anders Carlsson << getSpecialMember(Constructor)); 1437b99c666a940e93bcfcaeddc01515c94472e28a20Anders Carlsson break; 1438b99c666a940e93bcfcaeddc01515c94472e28a20Anders Carlsson } 143958e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall 1440711f34adb886cce8ba86c7b1b6513a1eaaf63bb5Anders Carlsson } 1441711f34adb886cce8ba86c7b1b6513a1eaaf63bb5Anders Carlsson 14429a68a67c6ae4982001815cc04f69b8781058263aAnders Carlsson return CheckAccess(*this, UseLoc, AccessEntity); 1443b13b737a2450167c82e148590e8019b839ce6b98John McCall} 1444b13b737a2450167c82e148590e8019b839ce6b98John McCall 1445b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall/// Checks direct (i.e. non-inherited) access to an arbitrary class 1446b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall/// member. 1447b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCallSema::AccessResult Sema::CheckDirectMemberAccess(SourceLocation UseLoc, 1448b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall NamedDecl *Target, 1449b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall const PartialDiagnostic &Diag) { 1450b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall AccessSpecifier Access = Target->getAccess(); 1451b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall if (!getLangOptions().AccessControl || 1452b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall Access == AS_public) 1453b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall return AR_accessible; 1454b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall 1455b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(Target->getDeclContext()); 1456161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget Entity(Context, AccessTarget::Member, NamingClass, 1457161755a09898c95d21bfff33707da9ca41cd53c5John McCall DeclAccessPair::make(Target, Access), 1458161755a09898c95d21bfff33707da9ca41cd53c5John McCall QualType()); 1459b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall Entity.setDiag(Diag); 1460b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall return CheckAccess(*this, UseLoc, Entity); 1461b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall} 1462b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall 1463b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall 146490c8c57bcd84083df85f76aac2aa62acb85eb077John McCall/// Checks access to an overloaded operator new or delete. 146590c8c57bcd84083df85f76aac2aa62acb85eb077John McCallSema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc, 146690c8c57bcd84083df85f76aac2aa62acb85eb077John McCall SourceRange PlacementRange, 146790c8c57bcd84083df85f76aac2aa62acb85eb077John McCall CXXRecordDecl *NamingClass, 14689aa472c45d2bd81b7b52c225e8acc560d716db97John McCall DeclAccessPair Found) { 146990c8c57bcd84083df85f76aac2aa62acb85eb077John McCall if (!getLangOptions().AccessControl || 147090c8c57bcd84083df85f76aac2aa62acb85eb077John McCall !NamingClass || 14719aa472c45d2bd81b7b52c225e8acc560d716db97John McCall Found.getAccess() == AS_public) 147290c8c57bcd84083df85f76aac2aa62acb85eb077John McCall return AR_accessible; 147390c8c57bcd84083df85f76aac2aa62acb85eb077John McCall 1474161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found, 1475161755a09898c95d21bfff33707da9ca41cd53c5John McCall QualType()); 147690c8c57bcd84083df85f76aac2aa62acb85eb077John McCall Entity.setDiag(diag::err_access) 147790c8c57bcd84083df85f76aac2aa62acb85eb077John McCall << PlacementRange; 147890c8c57bcd84083df85f76aac2aa62acb85eb077John McCall 147990c8c57bcd84083df85f76aac2aa62acb85eb077John McCall return CheckAccess(*this, OpLoc, Entity); 148090c8c57bcd84083df85f76aac2aa62acb85eb077John McCall} 148190c8c57bcd84083df85f76aac2aa62acb85eb077John McCall 1482b13b737a2450167c82e148590e8019b839ce6b98John McCall/// Checks access to an overloaded member operator, including 1483b13b737a2450167c82e148590e8019b839ce6b98John McCall/// conversion operators. 14846b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallSema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc, 14856b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall Expr *ObjectExpr, 148658e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall Expr *ArgExpr, 14879aa472c45d2bd81b7b52c225e8acc560d716db97John McCall DeclAccessPair Found) { 148858e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall if (!getLangOptions().AccessControl || 14899aa472c45d2bd81b7b52c225e8acc560d716db97John McCall Found.getAccess() == AS_public) 14906b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return AR_accessible; 14915357b615364c17ea024c757354c58ae2a520d216John McCall 14925357b615364c17ea024c757354c58ae2a520d216John McCall const RecordType *RT = ObjectExpr->getType()->getAs<RecordType>(); 14935357b615364c17ea024c757354c58ae2a520d216John McCall assert(RT && "found member operator but object expr not of record type"); 14945357b615364c17ea024c757354c58ae2a520d216John McCall CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(RT->getDecl()); 14955357b615364c17ea024c757354c58ae2a520d216John McCall 1496161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found, 1497161755a09898c95d21bfff33707da9ca41cd53c5John McCall ObjectExpr->getType()); 149858e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall Entity.setDiag(diag::err_access) 149958e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall << ObjectExpr->getSourceRange() 150058e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall << (ArgExpr ? ArgExpr->getSourceRange() : SourceRange()); 150158e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall 150258e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall return CheckAccess(*this, OpLoc, Entity); 15036b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall} 15045357b615364c17ea024c757354c58ae2a520d216John McCall 15056bb8017bb9e828d118e15e59d71c66bba323c364John McCallSema::AccessResult Sema::CheckAddressOfMemberAccess(Expr *OvlExpr, 15066bb8017bb9e828d118e15e59d71c66bba323c364John McCall DeclAccessPair Found) { 15076bb8017bb9e828d118e15e59d71c66bba323c364John McCall if (!getLangOptions().AccessControl || 1508e2f5ba9d80cfadbb3e1dafb9f375eb526f669b85John McCall Found.getAccess() == AS_none || 15096bb8017bb9e828d118e15e59d71c66bba323c364John McCall Found.getAccess() == AS_public) 15106bb8017bb9e828d118e15e59d71c66bba323c364John McCall return AR_accessible; 15116bb8017bb9e828d118e15e59d71c66bba323c364John McCall 15129c72c6088d591ace8503b842d39448c2040f3033John McCall OverloadExpr *Ovl = OverloadExpr::find(OvlExpr).Expression; 1513e9ee23edd17c4bb7f271e67f8790792b4de677fcJohn McCall CXXRecordDecl *NamingClass = Ovl->getNamingClass(); 15146bb8017bb9e828d118e15e59d71c66bba323c364John McCall 1515161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found, 1516161755a09898c95d21bfff33707da9ca41cd53c5John McCall Context.getTypeDeclType(NamingClass)); 15176bb8017bb9e828d118e15e59d71c66bba323c364John McCall Entity.setDiag(diag::err_access) 15186bb8017bb9e828d118e15e59d71c66bba323c364John McCall << Ovl->getSourceRange(); 15196bb8017bb9e828d118e15e59d71c66bba323c364John McCall 15206bb8017bb9e828d118e15e59d71c66bba323c364John McCall return CheckAccess(*this, Ovl->getNameLoc(), Entity); 15216bb8017bb9e828d118e15e59d71c66bba323c364John McCall} 15226bb8017bb9e828d118e15e59d71c66bba323c364John McCall 15236b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// Checks access for a hierarchy conversion. 15246b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// 15256b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// \param IsBaseToDerived whether this is a base-to-derived conversion (true) 15266b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// or a derived-to-base conversion (false) 15276b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// \param ForceCheck true if this check should be performed even if access 15286b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// control is disabled; some things rely on this for semantics 15296b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// \param ForceUnprivileged true if this check should proceed as if the 15306b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// context had no special privileges 15316b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// \param ADK controls the kind of diagnostics that are used 15326b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallSema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc, 15336b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall QualType Base, 15346b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall QualType Derived, 15356b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall const CXXBasePath &Path, 153658e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall unsigned DiagID, 15376b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall bool ForceCheck, 153858e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall bool ForceUnprivileged) { 15396b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall if (!ForceCheck && !getLangOptions().AccessControl) 15406b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return AR_accessible; 15416b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 15426b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall if (Path.Access == AS_public) 15436b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall return AR_accessible; 15446b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 15456b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall CXXRecordDecl *BaseD, *DerivedD; 15466b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall BaseD = cast<CXXRecordDecl>(Base->getAs<RecordType>()->getDecl()); 15476b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall DerivedD = cast<CXXRecordDecl>(Derived->getAs<RecordType>()->getDecl()); 154858e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall 1549161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget Entity(Context, AccessTarget::Base, BaseD, DerivedD, 1550161755a09898c95d21bfff33707da9ca41cd53c5John McCall Path.Access); 155158e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall if (DiagID) 155258e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall Entity.setDiag(DiagID) << Derived << Base; 15536b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 1554161755a09898c95d21bfff33707da9ca41cd53c5John McCall if (ForceUnprivileged) { 1555161755a09898c95d21bfff33707da9ca41cd53c5John McCall switch (CheckEffectiveAccess(*this, EffectiveContext(), 1556161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessLoc, Entity)) { 1557161755a09898c95d21bfff33707da9ca41cd53c5John McCall case ::AR_accessible: return Sema::AR_accessible; 1558161755a09898c95d21bfff33707da9ca41cd53c5John McCall case ::AR_inaccessible: return Sema::AR_inaccessible; 1559161755a09898c95d21bfff33707da9ca41cd53c5John McCall case ::AR_dependent: return Sema::AR_dependent; 1560161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 1561161755a09898c95d21bfff33707da9ca41cd53c5John McCall llvm_unreachable("unexpected result from CheckEffectiveAccess"); 1562161755a09898c95d21bfff33707da9ca41cd53c5John McCall } 156358e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall return CheckAccess(*this, AccessLoc, Entity); 15645357b615364c17ea024c757354c58ae2a520d216John McCall} 15655357b615364c17ea024c757354c58ae2a520d216John McCall 156692f883177b162928a8e632e4e3b93fafd2b26072John McCall/// Checks access to all the declarations in the given result set. 15676b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallvoid Sema::CheckLookupAccess(const LookupResult &R) { 15686b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall assert(getLangOptions().AccessControl 15696b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall && "performing access check without access control"); 15706b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall assert(R.getNamingClass() && "performing access check without naming class"); 15716b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall 157258e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { 157358e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall if (I.getAccess() != AS_public) { 1574161755a09898c95d21bfff33707da9ca41cd53c5John McCall AccessTarget Entity(Context, AccessedEntity::Member, 1575161755a09898c95d21bfff33707da9ca41cd53c5John McCall R.getNamingClass(), I.getPair(), 1576161755a09898c95d21bfff33707da9ca41cd53c5John McCall R.getBaseObjectType()); 157758e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall Entity.setDiag(diag::err_access); 157858e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall 157958e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall CheckAccess(*this, R.getNameLoc(), Entity); 158058e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall } 158158e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall } 158292f883177b162928a8e632e4e3b93fafd2b26072John McCall} 1583926c4b486a08f698cd3a367fd6f1a3a07604358dChandler Carruth 1584926c4b486a08f698cd3a367fd6f1a3a07604358dChandler Carruthvoid Sema::ActOnStartSuppressingAccessChecks() { 1585926c4b486a08f698cd3a367fd6f1a3a07604358dChandler Carruth assert(!SuppressAccessChecking && 1586926c4b486a08f698cd3a367fd6f1a3a07604358dChandler Carruth "Tried to start access check suppression when already started."); 1587926c4b486a08f698cd3a367fd6f1a3a07604358dChandler Carruth SuppressAccessChecking = true; 1588926c4b486a08f698cd3a367fd6f1a3a07604358dChandler Carruth} 1589926c4b486a08f698cd3a367fd6f1a3a07604358dChandler Carruth 1590926c4b486a08f698cd3a367fd6f1a3a07604358dChandler Carruthvoid Sema::ActOnStopSuppressingAccessChecks() { 1591926c4b486a08f698cd3a367fd6f1a3a07604358dChandler Carruth assert(SuppressAccessChecking && 1592926c4b486a08f698cd3a367fd6f1a3a07604358dChandler Carruth "Tried to stop access check suprression when already stopped."); 1593926c4b486a08f698cd3a367fd6f1a3a07604358dChandler Carruth SuppressAccessChecking = false; 1594926c4b486a08f698cd3a367fd6f1a3a07604358dChandler Carruth} 1595