SemaAccess.cpp revision fe24e05a87e48fa3318b65d1a92c542107639fd9
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
1379c3087b0b0bea2fd782205c1274ebfc4290265e0John McCall/// 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) {
51932f2fb53d9d7c28c94d8569fd0fcf06cccee0c3dJohn McCall  if (TypeSourceInfo *T = FriendD->getFriendType())
52032f2fb53d9d7c28c94d8569fd0fcf06cccee0c3dJohn McCall    return MatchesFriend(S, EC, T->getType()->getCanonicalTypeUnqualified());
5210c01d18094100db92d38daa923c95661512db203John McCall
5220c01d18094100db92d38daa923c95661512db203John McCall  NamedDecl *Friend
5230c01d18094100db92d38daa923c95661512db203John McCall    = cast<NamedDecl>(FriendD->getFriendDecl()->getCanonicalDecl());
5240c01d18094100db92d38daa923c95661512db203John McCall
5250c01d18094100db92d38daa923c95661512db203John McCall  // FIXME: declarations with dependent or templated scope.
5260c01d18094100db92d38daa923c95661512db203John McCall
5270c01d18094100db92d38daa923c95661512db203John McCall  if (isa<ClassTemplateDecl>(Friend))
5280c01d18094100db92d38daa923c95661512db203John McCall    return MatchesFriend(S, EC, cast<ClassTemplateDecl>(Friend));
5290c01d18094100db92d38daa923c95661512db203John McCall
5300c01d18094100db92d38daa923c95661512db203John McCall  if (isa<FunctionTemplateDecl>(Friend))
5310c01d18094100db92d38daa923c95661512db203John McCall    return MatchesFriend(S, EC, cast<FunctionTemplateDecl>(Friend));
5320c01d18094100db92d38daa923c95661512db203John McCall
5330c01d18094100db92d38daa923c95661512db203John McCall  if (isa<CXXRecordDecl>(Friend))
5340c01d18094100db92d38daa923c95661512db203John McCall    return MatchesFriend(S, EC, cast<CXXRecordDecl>(Friend));
5350c01d18094100db92d38daa923c95661512db203John McCall
5360c01d18094100db92d38daa923c95661512db203John McCall  assert(isa<FunctionDecl>(Friend) && "unknown friend decl kind");
5370c01d18094100db92d38daa923c95661512db203John McCall  return MatchesFriend(S, EC, cast<FunctionDecl>(Friend));
5380c01d18094100db92d38daa923c95661512db203John McCall}
5390c01d18094100db92d38daa923c95661512db203John McCall
540161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic AccessResult GetFriendKind(Sema &S,
541161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                  const EffectiveContext &EC,
542161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                  const CXXRecordDecl *Class) {
543161755a09898c95d21bfff33707da9ca41cd53c5John McCall  AccessResult OnFailure = AR_inaccessible;
54488b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall
545d60e22e601852ae1345f01514318a0951dc09f89John McCall  // Okay, check friends.
546d60e22e601852ae1345f01514318a0951dc09f89John McCall  for (CXXRecordDecl::friend_iterator I = Class->friend_begin(),
547d60e22e601852ae1345f01514318a0951dc09f89John McCall         E = Class->friend_end(); I != E; ++I) {
548d60e22e601852ae1345f01514318a0951dc09f89John McCall    FriendDecl *Friend = *I;
549d60e22e601852ae1345f01514318a0951dc09f89John McCall
550a742db0032d8f458fe229600d2082981a1fb1481John McCall    switch (MatchesFriend(S, EC, Friend)) {
551161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case AR_accessible:
552161755a09898c95d21bfff33707da9ca41cd53c5John McCall      return AR_accessible;
55388b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall
554161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case AR_inaccessible:
555161755a09898c95d21bfff33707da9ca41cd53c5John McCall      continue;
556d60e22e601852ae1345f01514318a0951dc09f89John McCall
557161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case AR_dependent:
558161755a09898c95d21bfff33707da9ca41cd53c5John McCall      OnFailure = AR_dependent;
559a742db0032d8f458fe229600d2082981a1fb1481John McCall      break;
560a742db0032d8f458fe229600d2082981a1fb1481John McCall    }
561d60e22e601852ae1345f01514318a0951dc09f89John McCall  }
562d60e22e601852ae1345f01514318a0951dc09f89John McCall
563d60e22e601852ae1345f01514318a0951dc09f89John McCall  // That's it, give up.
56488b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall  return OnFailure;
5656b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall}
5666b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
5678c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCallnamespace {
5688c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall
5698c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall/// A helper class for checking for a friend which will grant access
5708c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall/// to a protected instance member.
5718c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCallstruct ProtectedFriendContext {
5728c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  Sema &S;
5738c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  const EffectiveContext &EC;
5748c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  const CXXRecordDecl *NamingClass;
5758c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  bool CheckDependent;
5768c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  bool EverDependent;
5778c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall
5788c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  /// The path down to the current base class.
5798c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  llvm::SmallVector<const CXXRecordDecl*, 20> CurPath;
5808c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall
5818c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  ProtectedFriendContext(Sema &S, const EffectiveContext &EC,
5828c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall                         const CXXRecordDecl *InstanceContext,
5838c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall                         const CXXRecordDecl *NamingClass)
5848c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall    : S(S), EC(EC), NamingClass(NamingClass),
5858c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall      CheckDependent(InstanceContext->isDependentContext() ||
5868c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall                     NamingClass->isDependentContext()),
5878c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall      EverDependent(false) {}
5888c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall
589326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall  /// Check classes in the current path for friendship, starting at
590326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall  /// the given index.
591326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall  bool checkFriendshipAlongPath(unsigned I) {
592326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall    assert(I < CurPath.size());
593326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall    for (unsigned E = CurPath.size(); I != E; ++I) {
594326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall      switch (GetFriendKind(S, EC, CurPath[I])) {
5958c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall      case AR_accessible:   return true;
5968c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall      case AR_inaccessible: continue;
5978c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall      case AR_dependent:    EverDependent = true; continue;
5988c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall      }
5998c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall    }
6008c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall    return false;
6018c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  }
6028c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall
6038c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  /// Perform a search starting at the given class.
604326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall  ///
605326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall  /// PrivateDepth is the index of the last (least derived) class
606326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall  /// along the current path such that a notional public member of
607326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall  /// the final class in the path would have access in that class.
608326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall  bool findFriendship(const CXXRecordDecl *Cur, unsigned PrivateDepth) {
6098c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall    // If we ever reach the naming class, check the current path for
6108c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall    // friendship.  We can also stop recursing because we obviously
6118c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall    // won't find the naming class there again.
612326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall    if (Cur == NamingClass)
613326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall      return checkFriendshipAlongPath(PrivateDepth);
6148c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall
6158c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall    if (CheckDependent && MightInstantiateTo(Cur, NamingClass))
6168c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall      EverDependent = true;
6178c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall
6188c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall    // Recurse into the base classes.
6198c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall    for (CXXRecordDecl::base_class_const_iterator
6208c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall           I = Cur->bases_begin(), E = Cur->bases_end(); I != E; ++I) {
6218c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall
622326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall      // If this is private inheritance, then a public member of the
623326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall      // base will not have any access in classes derived from Cur.
624326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall      unsigned BasePrivateDepth = PrivateDepth;
625326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall      if (I->getAccessSpecifier() == AS_private)
626326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall        BasePrivateDepth = CurPath.size() - 1;
6278c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall
6288c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall      const CXXRecordDecl *RD;
6298c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall
6308c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall      QualType T = I->getType();
6318c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall      if (const RecordType *RT = T->getAs<RecordType>()) {
6328c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall        RD = cast<CXXRecordDecl>(RT->getDecl());
6338c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall      } else if (const InjectedClassNameType *IT
6348c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall                   = T->getAs<InjectedClassNameType>()) {
6358c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall        RD = IT->getDecl();
6368c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall      } else {
6378c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall        assert(T->isDependentType() && "non-dependent base wasn't a record?");
6388c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall        EverDependent = true;
6398c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall        continue;
6408c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall      }
6418c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall
6428c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall      // Recurse.  We don't need to clean up if this returns true.
643326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall      CurPath.push_back(RD);
644326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall      if (findFriendship(RD->getCanonicalDecl(), BasePrivateDepth))
645326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall        return true;
646326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall      CurPath.pop_back();
6478c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall    }
6488c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall
6498c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall    return false;
6508c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  }
651326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall
652326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall  bool findFriendship(const CXXRecordDecl *Cur) {
653326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall    assert(CurPath.empty());
654326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall    CurPath.push_back(Cur);
655326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall    return findFriendship(Cur, 0);
656326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall  }
6578c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall};
6588c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall}
6598c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall
6608c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall/// Search for a class P that EC is a friend of, under the constraint
6618c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall///   InstanceContext <= P <= NamingClass
6628c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall/// and with the additional restriction that a protected member of
6638c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall/// NamingClass would have some natural access in P.
6648c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall///
6658c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall/// That second condition isn't actually quite right: the condition in
6668c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall/// the standard is whether the target would have some natural access
6678c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall/// in P.  The difference is that the target might be more accessible
6688c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall/// along some path not passing through NamingClass.  Allowing that
6698c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall/// introduces two problems:
6708c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall///   - It breaks encapsulation because you can suddenly access a
6718c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall///     forbidden base class's members by subclassing it elsewhere.
6728c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall///   - It makes access substantially harder to compute because it
6738c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall///     breaks the hill-climbing algorithm: knowing that the target is
6748c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall///     accessible in some base class would no longer let you change
6758c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall///     the question solely to whether the base class is accessible,
6768c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall///     because the original target might have been more accessible
6778c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall///     because of crazy subclassing.
6788c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall/// So we don't implement that.
6798c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCallstatic AccessResult GetProtectedFriendKind(Sema &S, const EffectiveContext &EC,
6808c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall                                           const CXXRecordDecl *InstanceContext,
6818c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall                                           const CXXRecordDecl *NamingClass) {
6828c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  assert(InstanceContext->getCanonicalDecl() == InstanceContext);
6838c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  assert(NamingClass->getCanonicalDecl() == NamingClass);
6848c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall
6858c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  ProtectedFriendContext PRC(S, EC, InstanceContext, NamingClass);
6868c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  if (PRC.findFriendship(InstanceContext)) return AR_accessible;
6878c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  if (PRC.EverDependent) return AR_dependent;
6888c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  return AR_inaccessible;
6898c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall}
6908c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall
691161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic AccessResult HasAccess(Sema &S,
692161755a09898c95d21bfff33707da9ca41cd53c5John McCall                              const EffectiveContext &EC,
693161755a09898c95d21bfff33707da9ca41cd53c5John McCall                              const CXXRecordDecl *NamingClass,
694161755a09898c95d21bfff33707da9ca41cd53c5John McCall                              AccessSpecifier Access,
695161755a09898c95d21bfff33707da9ca41cd53c5John McCall                              const AccessTarget &Target) {
696db73c684ba61fed4087af488e8610657ec638c17John McCall  assert(NamingClass->getCanonicalDecl() == NamingClass &&
697db73c684ba61fed4087af488e8610657ec638c17John McCall         "declaration should be canonicalized before being passed here");
698db73c684ba61fed4087af488e8610657ec638c17John McCall
699161755a09898c95d21bfff33707da9ca41cd53c5John McCall  if (Access == AS_public) return AR_accessible;
700db73c684ba61fed4087af488e8610657ec638c17John McCall  assert(Access == AS_private || Access == AS_protected);
701db73c684ba61fed4087af488e8610657ec638c17John McCall
702161755a09898c95d21bfff33707da9ca41cd53c5John McCall  AccessResult OnFailure = AR_inaccessible;
703161755a09898c95d21bfff33707da9ca41cd53c5John McCall
704db73c684ba61fed4087af488e8610657ec638c17John McCall  for (EffectiveContext::record_iterator
705db73c684ba61fed4087af488e8610657ec638c17John McCall         I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
706db73c684ba61fed4087af488e8610657ec638c17John McCall    // All the declarations in EC have been canonicalized, so pointer
707db73c684ba61fed4087af488e8610657ec638c17John McCall    // equality from this point on will work fine.
708db73c684ba61fed4087af488e8610657ec638c17John McCall    const CXXRecordDecl *ECRecord = *I;
709db73c684ba61fed4087af488e8610657ec638c17John McCall
710db73c684ba61fed4087af488e8610657ec638c17John McCall    // [B2] and [M2]
711161755a09898c95d21bfff33707da9ca41cd53c5John McCall    if (Access == AS_private) {
712161755a09898c95d21bfff33707da9ca41cd53c5John McCall      if (ECRecord == NamingClass)
713161755a09898c95d21bfff33707da9ca41cd53c5John McCall        return AR_accessible;
714db73c684ba61fed4087af488e8610657ec638c17John McCall
71501ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall      if (EC.isDependent() && MightInstantiateTo(ECRecord, NamingClass))
71601ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall        OnFailure = AR_dependent;
71701ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall
718db73c684ba61fed4087af488e8610657ec638c17John McCall    // [B3] and [M3]
719161755a09898c95d21bfff33707da9ca41cd53c5John McCall    } else {
720161755a09898c95d21bfff33707da9ca41cd53c5John McCall      assert(Access == AS_protected);
721161755a09898c95d21bfff33707da9ca41cd53c5John McCall      switch (IsDerivedFromInclusive(ECRecord, NamingClass)) {
722161755a09898c95d21bfff33707da9ca41cd53c5John McCall      case AR_accessible: break;
723161755a09898c95d21bfff33707da9ca41cd53c5John McCall      case AR_inaccessible: continue;
724161755a09898c95d21bfff33707da9ca41cd53c5John McCall      case AR_dependent: OnFailure = AR_dependent; continue;
725161755a09898c95d21bfff33707da9ca41cd53c5John McCall      }
726161755a09898c95d21bfff33707da9ca41cd53c5John McCall
727161755a09898c95d21bfff33707da9ca41cd53c5John McCall      if (!Target.hasInstanceContext())
728161755a09898c95d21bfff33707da9ca41cd53c5John McCall        return AR_accessible;
729161755a09898c95d21bfff33707da9ca41cd53c5John McCall
730161755a09898c95d21bfff33707da9ca41cd53c5John McCall      const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S);
731161755a09898c95d21bfff33707da9ca41cd53c5John McCall      if (!InstanceContext) {
732161755a09898c95d21bfff33707da9ca41cd53c5John McCall        OnFailure = AR_dependent;
733161755a09898c95d21bfff33707da9ca41cd53c5John McCall        continue;
734161755a09898c95d21bfff33707da9ca41cd53c5John McCall      }
735161755a09898c95d21bfff33707da9ca41cd53c5John McCall
736161755a09898c95d21bfff33707da9ca41cd53c5John McCall      // C++ [class.protected]p1:
737161755a09898c95d21bfff33707da9ca41cd53c5John McCall      //   An additional access check beyond those described earlier in
738161755a09898c95d21bfff33707da9ca41cd53c5John McCall      //   [class.access] is applied when a non-static data member or
739161755a09898c95d21bfff33707da9ca41cd53c5John McCall      //   non-static member function is a protected member of its naming
740161755a09898c95d21bfff33707da9ca41cd53c5John McCall      //   class.  As described earlier, access to a protected member is
741161755a09898c95d21bfff33707da9ca41cd53c5John McCall      //   granted because the reference occurs in a friend or member of
742161755a09898c95d21bfff33707da9ca41cd53c5John McCall      //   some class C.  If the access is to form a pointer to member,
743161755a09898c95d21bfff33707da9ca41cd53c5John McCall      //   the nested-name-specifier shall name C or a class derived from
744161755a09898c95d21bfff33707da9ca41cd53c5John McCall      //   C. All other accesses involve a (possibly implicit) object
745161755a09898c95d21bfff33707da9ca41cd53c5John McCall      //   expression. In this case, the class of the object expression
746161755a09898c95d21bfff33707da9ca41cd53c5John McCall      //   shall be C or a class derived from C.
747161755a09898c95d21bfff33707da9ca41cd53c5John McCall      //
748161755a09898c95d21bfff33707da9ca41cd53c5John McCall      // We interpret this as a restriction on [M3].  Most of the
749161755a09898c95d21bfff33707da9ca41cd53c5John McCall      // conditions are encoded by not having any instance context.
750161755a09898c95d21bfff33707da9ca41cd53c5John McCall      switch (IsDerivedFromInclusive(InstanceContext, ECRecord)) {
751161755a09898c95d21bfff33707da9ca41cd53c5John McCall      case AR_accessible: return AR_accessible;
752161755a09898c95d21bfff33707da9ca41cd53c5John McCall      case AR_inaccessible: continue;
753161755a09898c95d21bfff33707da9ca41cd53c5John McCall      case AR_dependent: OnFailure = AR_dependent; continue;
754161755a09898c95d21bfff33707da9ca41cd53c5John McCall      }
755161755a09898c95d21bfff33707da9ca41cd53c5John McCall    }
756db73c684ba61fed4087af488e8610657ec638c17John McCall  }
757db73c684ba61fed4087af488e8610657ec638c17John McCall
7588c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  // [M3] and [B3] say that, if the target is protected in N, we grant
7598c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  // access if the access occurs in a friend or member of some class P
7608c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  // that's a subclass of N and where the target has some natural
7618c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  // access in P.  The 'member' aspect is easy to handle because P
7628c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  // would necessarily be one of the effective-context records, and we
7638c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  // address that above.  The 'friend' aspect is completely ridiculous
7648c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  // to implement because there are no restrictions at all on P
7658c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  // *unless* the [class.protected] restriction applies.  If it does,
7668c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  // however, we should ignore whether the naming class is a friend,
7678c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  // and instead rely on whether any potential P is a friend.
768161755a09898c95d21bfff33707da9ca41cd53c5John McCall  if (Access == AS_protected && Target.hasInstanceContext()) {
769161755a09898c95d21bfff33707da9ca41cd53c5John McCall    const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S);
770161755a09898c95d21bfff33707da9ca41cd53c5John McCall    if (!InstanceContext) return AR_dependent;
7718c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall    switch (GetProtectedFriendKind(S, EC, InstanceContext, NamingClass)) {
7728c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall    case AR_accessible: return AR_accessible;
773161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case AR_inaccessible: return OnFailure;
774161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case AR_dependent: return AR_dependent;
775161755a09898c95d21bfff33707da9ca41cd53c5John McCall    }
7761797a05f97671d40929224ac030c8c16fe69938cJohn McCall    llvm_unreachable("impossible friendship kind");
777161755a09898c95d21bfff33707da9ca41cd53c5John McCall  }
778161755a09898c95d21bfff33707da9ca41cd53c5John McCall
779161755a09898c95d21bfff33707da9ca41cd53c5John McCall  switch (GetFriendKind(S, EC, NamingClass)) {
780161755a09898c95d21bfff33707da9ca41cd53c5John McCall  case AR_accessible: return AR_accessible;
781161755a09898c95d21bfff33707da9ca41cd53c5John McCall  case AR_inaccessible: return OnFailure;
782161755a09898c95d21bfff33707da9ca41cd53c5John McCall  case AR_dependent: return AR_dependent;
783161755a09898c95d21bfff33707da9ca41cd53c5John McCall  }
784161755a09898c95d21bfff33707da9ca41cd53c5John McCall
785161755a09898c95d21bfff33707da9ca41cd53c5John McCall  // Silence bogus warnings
786161755a09898c95d21bfff33707da9ca41cd53c5John McCall  llvm_unreachable("impossible friendship kind");
787161755a09898c95d21bfff33707da9ca41cd53c5John McCall  return OnFailure;
788db73c684ba61fed4087af488e8610657ec638c17John McCall}
789db73c684ba61fed4087af488e8610657ec638c17John McCall
7906b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// Finds the best path from the naming class to the declaring class,
7916b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// taking friend declarations into account.
7926b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall///
793db73c684ba61fed4087af488e8610657ec638c17John McCall/// C++0x [class.access.base]p5:
794db73c684ba61fed4087af488e8610657ec638c17John McCall///   A member m is accessible at the point R when named in class N if
795db73c684ba61fed4087af488e8610657ec638c17John McCall///   [M1] m as a member of N is public, or
796db73c684ba61fed4087af488e8610657ec638c17John McCall///   [M2] m as a member of N is private, and R occurs in a member or
797db73c684ba61fed4087af488e8610657ec638c17John McCall///        friend of class N, or
798db73c684ba61fed4087af488e8610657ec638c17John McCall///   [M3] m as a member of N is protected, and R occurs in a member or
799db73c684ba61fed4087af488e8610657ec638c17John McCall///        friend of class N, or in a member or friend of a class P
800db73c684ba61fed4087af488e8610657ec638c17John McCall///        derived from N, where m as a member of P is public, private,
801db73c684ba61fed4087af488e8610657ec638c17John McCall///        or protected, or
802db73c684ba61fed4087af488e8610657ec638c17John McCall///   [M4] there exists a base class B of N that is accessible at R, and
803db73c684ba61fed4087af488e8610657ec638c17John McCall///        m is accessible at R when named in class B.
804db73c684ba61fed4087af488e8610657ec638c17John McCall///
805db73c684ba61fed4087af488e8610657ec638c17John McCall/// C++0x [class.access.base]p4:
806db73c684ba61fed4087af488e8610657ec638c17John McCall///   A base class B of N is accessible at R, if
807db73c684ba61fed4087af488e8610657ec638c17John McCall///   [B1] an invented public member of B would be a public member of N, or
808db73c684ba61fed4087af488e8610657ec638c17John McCall///   [B2] R occurs in a member or friend of class N, and an invented public
809db73c684ba61fed4087af488e8610657ec638c17John McCall///        member of B would be a private or protected member of N, or
810db73c684ba61fed4087af488e8610657ec638c17John McCall///   [B3] R occurs in a member or friend of a class P derived from N, and an
811db73c684ba61fed4087af488e8610657ec638c17John McCall///        invented public member of B would be a private or protected member
812db73c684ba61fed4087af488e8610657ec638c17John McCall///        of P, or
813db73c684ba61fed4087af488e8610657ec638c17John McCall///   [B4] there exists a class S such that B is a base class of S accessible
814db73c684ba61fed4087af488e8610657ec638c17John McCall///        at R and S is a base class of N accessible at R.
815db73c684ba61fed4087af488e8610657ec638c17John McCall///
816db73c684ba61fed4087af488e8610657ec638c17John McCall/// Along a single inheritance path we can restate both of these
817db73c684ba61fed4087af488e8610657ec638c17John McCall/// iteratively:
818db73c684ba61fed4087af488e8610657ec638c17John McCall///
819db73c684ba61fed4087af488e8610657ec638c17John McCall/// First, we note that M1-4 are equivalent to B1-4 if the member is
820db73c684ba61fed4087af488e8610657ec638c17John McCall/// treated as a notional base of its declaring class with inheritance
821db73c684ba61fed4087af488e8610657ec638c17John McCall/// access equivalent to the member's access.  Therefore we need only
822db73c684ba61fed4087af488e8610657ec638c17John McCall/// ask whether a class B is accessible from a class N in context R.
823db73c684ba61fed4087af488e8610657ec638c17John McCall///
824db73c684ba61fed4087af488e8610657ec638c17John McCall/// Let B_1 .. B_n be the inheritance path in question (i.e. where
825db73c684ba61fed4087af488e8610657ec638c17John McCall/// B_1 = N, B_n = B, and for all i, B_{i+1} is a direct base class of
826db73c684ba61fed4087af488e8610657ec638c17John McCall/// B_i).  For i in 1..n, we will calculate ACAB(i), the access to the
827db73c684ba61fed4087af488e8610657ec638c17John McCall/// closest accessible base in the path:
828db73c684ba61fed4087af488e8610657ec638c17John McCall///   Access(a, b) = (* access on the base specifier from a to b *)
829db73c684ba61fed4087af488e8610657ec638c17John McCall///   Merge(a, forbidden) = forbidden
830db73c684ba61fed4087af488e8610657ec638c17John McCall///   Merge(a, private) = forbidden
831db73c684ba61fed4087af488e8610657ec638c17John McCall///   Merge(a, b) = min(a,b)
832db73c684ba61fed4087af488e8610657ec638c17John McCall///   Accessible(c, forbidden) = false
833db73c684ba61fed4087af488e8610657ec638c17John McCall///   Accessible(c, private) = (R is c) || IsFriend(c, R)
834db73c684ba61fed4087af488e8610657ec638c17John McCall///   Accessible(c, protected) = (R derived from c) || IsFriend(c, R)
835db73c684ba61fed4087af488e8610657ec638c17John McCall///   Accessible(c, public) = true
836db73c684ba61fed4087af488e8610657ec638c17John McCall///   ACAB(n) = public
837db73c684ba61fed4087af488e8610657ec638c17John McCall///   ACAB(i) =
838db73c684ba61fed4087af488e8610657ec638c17John McCall///     let AccessToBase = Merge(Access(B_i, B_{i+1}), ACAB(i+1)) in
839db73c684ba61fed4087af488e8610657ec638c17John McCall///     if Accessible(B_i, AccessToBase) then public else AccessToBase
840db73c684ba61fed4087af488e8610657ec638c17John McCall///
841db73c684ba61fed4087af488e8610657ec638c17John McCall/// B is an accessible base of N at R iff ACAB(1) = public.
842db73c684ba61fed4087af488e8610657ec638c17John McCall///
843161755a09898c95d21bfff33707da9ca41cd53c5John McCall/// \param FinalAccess the access of the "final step", or AS_public if
8447aceaf8cee77c98478e8934dc283910292711a7eJohn McCall///   there is no final step.
8456b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// \return null if friendship is dependent
8466b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallstatic CXXBasePath *FindBestPath(Sema &S,
8476b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall                                 const EffectiveContext &EC,
848161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                 AccessTarget &Target,
8497aceaf8cee77c98478e8934dc283910292711a7eJohn McCall                                 AccessSpecifier FinalAccess,
8506b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall                                 CXXBasePaths &Paths) {
8516b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  // Derive the paths to the desired base.
852161755a09898c95d21bfff33707da9ca41cd53c5John McCall  const CXXRecordDecl *Derived = Target.getNamingClass();
853161755a09898c95d21bfff33707da9ca41cd53c5John McCall  const CXXRecordDecl *Base = Target.getDeclaringClass();
854161755a09898c95d21bfff33707da9ca41cd53c5John McCall
855161755a09898c95d21bfff33707da9ca41cd53c5John McCall  // FIXME: fail correctly when there are dependent paths.
856161755a09898c95d21bfff33707da9ca41cd53c5John McCall  bool isDerived = Derived->isDerivedFrom(const_cast<CXXRecordDecl*>(Base),
857161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                          Paths);
8586b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  assert(isDerived && "derived class not actually derived from base");
8596b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  (void) isDerived;
8606b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
8616b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  CXXBasePath *BestPath = 0;
8626b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
8637aceaf8cee77c98478e8934dc283910292711a7eJohn McCall  assert(FinalAccess != AS_none && "forbidden access after declaring class");
8647aceaf8cee77c98478e8934dc283910292711a7eJohn McCall
8650c01d18094100db92d38daa923c95661512db203John McCall  bool AnyDependent = false;
8660c01d18094100db92d38daa923c95661512db203John McCall
8676b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  // Derive the friend-modified access along each path.
8686b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  for (CXXBasePaths::paths_iterator PI = Paths.begin(), PE = Paths.end();
8696b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall         PI != PE; ++PI) {
870161755a09898c95d21bfff33707da9ca41cd53c5John McCall    AccessTarget::SavedInstanceContext _ = Target.saveInstanceContext();
8716b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
8726b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    // Walk through the path backwards.
8737aceaf8cee77c98478e8934dc283910292711a7eJohn McCall    AccessSpecifier PathAccess = FinalAccess;
8746b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    CXXBasePath::iterator I = PI->end(), E = PI->begin();
8756b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    while (I != E) {
8766b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall      --I;
8776b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
8787aceaf8cee77c98478e8934dc283910292711a7eJohn McCall      assert(PathAccess != AS_none);
8797aceaf8cee77c98478e8934dc283910292711a7eJohn McCall
8807aceaf8cee77c98478e8934dc283910292711a7eJohn McCall      // If the declaration is a private member of a base class, there
8817aceaf8cee77c98478e8934dc283910292711a7eJohn McCall      // is no level of friendship in derived classes that can make it
8827aceaf8cee77c98478e8934dc283910292711a7eJohn McCall      // accessible.
8837aceaf8cee77c98478e8934dc283910292711a7eJohn McCall      if (PathAccess == AS_private) {
8847aceaf8cee77c98478e8934dc283910292711a7eJohn McCall        PathAccess = AS_none;
8857aceaf8cee77c98478e8934dc283910292711a7eJohn McCall        break;
8867aceaf8cee77c98478e8934dc283910292711a7eJohn McCall      }
8877aceaf8cee77c98478e8934dc283910292711a7eJohn McCall
888161755a09898c95d21bfff33707da9ca41cd53c5John McCall      const CXXRecordDecl *NC = I->Class->getCanonicalDecl();
889161755a09898c95d21bfff33707da9ca41cd53c5John McCall
8906b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall      AccessSpecifier BaseAccess = I->Base->getAccessSpecifier();
891db73c684ba61fed4087af488e8610657ec638c17John McCall      PathAccess = std::max(PathAccess, BaseAccess);
892161755a09898c95d21bfff33707da9ca41cd53c5John McCall
893161755a09898c95d21bfff33707da9ca41cd53c5John McCall      switch (HasAccess(S, EC, NC, PathAccess, Target)) {
894161755a09898c95d21bfff33707da9ca41cd53c5John McCall      case AR_inaccessible: break;
895161755a09898c95d21bfff33707da9ca41cd53c5John McCall      case AR_accessible:
896161755a09898c95d21bfff33707da9ca41cd53c5John McCall        PathAccess = AS_public;
897161755a09898c95d21bfff33707da9ca41cd53c5John McCall
898161755a09898c95d21bfff33707da9ca41cd53c5John McCall        // Future tests are not against members and so do not have
899161755a09898c95d21bfff33707da9ca41cd53c5John McCall        // instance context.
900161755a09898c95d21bfff33707da9ca41cd53c5John McCall        Target.suppressInstanceContext();
901161755a09898c95d21bfff33707da9ca41cd53c5John McCall        break;
902161755a09898c95d21bfff33707da9ca41cd53c5John McCall      case AR_dependent:
903db73c684ba61fed4087af488e8610657ec638c17John McCall        AnyDependent = true;
904db73c684ba61fed4087af488e8610657ec638c17John McCall        goto Next;
905c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson      }
906c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson    }
907726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl
9086b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    // Note that we modify the path's Access field to the
9096b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    // friend-modified access.
9106b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    if (BestPath == 0 || PathAccess < BestPath->Access) {
9116b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall      BestPath = &*PI;
9126b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall      BestPath->Access = PathAccess;
9130c01d18094100db92d38daa923c95661512db203John McCall
9140c01d18094100db92d38daa923c95661512db203John McCall      // Short-circuit if we found a public path.
9150c01d18094100db92d38daa923c95661512db203John McCall      if (BestPath->Access == AS_public)
9160c01d18094100db92d38daa923c95661512db203John McCall        return BestPath;
917c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson    }
9180c01d18094100db92d38daa923c95661512db203John McCall
9190c01d18094100db92d38daa923c95661512db203John McCall  Next: ;
920c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson  }
921c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson
9220c01d18094100db92d38daa923c95661512db203John McCall  assert((!BestPath || BestPath->Access != AS_public) &&
9230c01d18094100db92d38daa923c95661512db203John McCall         "fell out of loop with public path");
9240c01d18094100db92d38daa923c95661512db203John McCall
9250c01d18094100db92d38daa923c95661512db203John McCall  // We didn't find a public path, but at least one path was subject
9260c01d18094100db92d38daa923c95661512db203John McCall  // to dependent friendship, so delay the check.
9270c01d18094100db92d38daa923c95661512db203John McCall  if (AnyDependent)
9280c01d18094100db92d38daa923c95661512db203John McCall    return 0;
9290c01d18094100db92d38daa923c95661512db203John McCall
9306b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  return BestPath;
931726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl}
932726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl
933fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall/// Given that an entity has protected natural access, check whether
934fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall/// access might be denied because of the protected member access
935fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall/// restriction.
936fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall///
937fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall/// \return true if a note was emitted
938fe24e05a87e48fa3318b65d1a92c542107639fd9John McCallstatic bool TryDiagnoseProtectedAccess(Sema &S, const EffectiveContext &EC,
939fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall                                       AccessTarget &Target) {
940fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall  // Only applies to instance accesses.
941fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall  if (!Target.hasInstanceContext())
942fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall    return false;
943fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall  assert(Target.isMemberAccess());
944fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall  NamedDecl *D = Target.getTargetDecl();
945fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall
946fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall  const CXXRecordDecl *DeclaringClass = Target.getDeclaringClass();
947fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall  DeclaringClass = DeclaringClass->getCanonicalDecl();
948fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall
949fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall  for (EffectiveContext::record_iterator
950fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall         I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
951fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall    const CXXRecordDecl *ECRecord = *I;
952fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall    switch (IsDerivedFromInclusive(ECRecord, DeclaringClass)) {
953fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall    case AR_accessible: break;
954fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall    case AR_inaccessible: continue;
955fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall    case AR_dependent: continue;
956fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall    }
957fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall
958fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall    // The effective context is a subclass of the declaring class.
959fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall    // If that class isn't a superclass of the instance context,
960fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall    // then the [class.protected] restriction applies.
961fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall
962fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall    // To get this exactly right, this might need to be checked more
963fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall    // holistically;  it's not necessarily the case that gaining
964fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall    // access here would grant us access overall.
965fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall
966fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall    const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S);
967fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall    assert(InstanceContext && "diagnosing dependent access");
968fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall
969fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall    switch (IsDerivedFromInclusive(InstanceContext, ECRecord)) {
970fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall    case AR_accessible: continue;
971fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall    case AR_dependent: continue;
972fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall    case AR_inaccessible:
973fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall      S.Diag(D->getLocation(), diag::note_access_protected_restricted)
974fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall        << (InstanceContext != Target.getNamingClass()->getCanonicalDecl())
975fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall        << S.Context.getTypeDeclType(InstanceContext)
976fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall        << S.Context.getTypeDeclType(ECRecord);
977fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall      return true;
978fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall    }
979fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall  }
980fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall
981fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall  return false;
982fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall}
983fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall
9846b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// Diagnose the path which caused the given declaration or base class
9856b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// to become inaccessible.
9866b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallstatic void DiagnoseAccessPath(Sema &S,
9876b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall                               const EffectiveContext &EC,
988161755a09898c95d21bfff33707da9ca41cd53c5John McCall                               AccessTarget &Entity) {
989db73c684ba61fed4087af488e8610657ec638c17John McCall  AccessSpecifier Access = Entity.getAccess();
990161755a09898c95d21bfff33707da9ca41cd53c5John McCall  const CXXRecordDecl *NamingClass = Entity.getNamingClass();
991db73c684ba61fed4087af488e8610657ec638c17John McCall  NamingClass = NamingClass->getCanonicalDecl();
992db73c684ba61fed4087af488e8610657ec638c17John McCall
993161755a09898c95d21bfff33707da9ca41cd53c5John McCall  NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : 0);
994161755a09898c95d21bfff33707da9ca41cd53c5John McCall  const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();
995db73c684ba61fed4087af488e8610657ec638c17John McCall
9966b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  // Easy case: the decl's natural access determined its path access.
9976b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  // We have to check against AS_private here in case Access is AS_none,
9986b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  // indicating a non-public member of a private base class.
9996b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  if (D && (Access == D->getAccess() || D->getAccess() == AS_private)) {
1000161755a09898c95d21bfff33707da9ca41cd53c5John McCall    switch (HasAccess(S, EC, DeclaringClass, D->getAccess(), Entity)) {
1001161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case AR_inaccessible: {
1002fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall      if (Access == AS_protected &&
1003fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall          TryDiagnoseProtectedAccess(S, EC, Entity))
1004fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall        return;
1005fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall
10066b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall      S.Diag(D->getLocation(), diag::note_access_natural)
10076b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall        << (unsigned) (Access == AS_protected)
10086b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall        << /*FIXME: not implicitly*/ 0;
10096b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall      return;
10106b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    }
1011726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl
1012161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case AR_accessible: break;
1013726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl
1014161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case AR_dependent:
1015161755a09898c95d21bfff33707da9ca41cd53c5John McCall      llvm_unreachable("can't diagnose dependent access failures");
10166b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall      return;
10176b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    }
10186b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  }
1019c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson
10206b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  CXXBasePaths Paths;
1021161755a09898c95d21bfff33707da9ca41cd53c5John McCall  CXXBasePath &Path = *FindBestPath(S, EC, Entity, AS_public, Paths);
1022726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl
10236b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  CXXBasePath::iterator I = Path.end(), E = Path.begin();
10246b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  while (I != E) {
10256b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    --I;
1026c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson
10276b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    const CXXBaseSpecifier *BS = I->Base;
10286b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    AccessSpecifier BaseAccess = BS->getAccessSpecifier();
10296b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
10306b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    // If this is public inheritance, or the derived class is a friend,
10316b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    // skip this step.
10326b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    if (BaseAccess == AS_public)
10336b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall      continue;
10346b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
10356b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    switch (GetFriendKind(S, EC, I->Class)) {
1036161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case AR_accessible: continue;
1037161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case AR_inaccessible: break;
1038161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case AR_dependent:
1039161755a09898c95d21bfff33707da9ca41cd53c5John McCall      llvm_unreachable("can't diagnose dependent access failures");
10406b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    }
10416b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
10426b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    // Check whether this base specifier is the tighest point
10436b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    // constraining access.  We have to check against AS_private for
10446b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    // the same reasons as above.
10456b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    if (BaseAccess == AS_private || BaseAccess >= Access) {
10466b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
10476b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall      // We're constrained by inheritance, but we want to say
10486b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall      // "declared private here" if we're diagnosing a hierarchy
10496b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall      // conversion and this is the final step.
10506b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall      unsigned diagnostic;
10516b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall      if (D) diagnostic = diag::note_access_constrained_by_path;
10526b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall      else if (I + 1 == Path.end()) diagnostic = diag::note_access_natural;
10536b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall      else diagnostic = diag::note_access_constrained_by_path;
10546b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
10556b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall      S.Diag(BS->getSourceRange().getBegin(), diagnostic)
10566b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall        << BS->getSourceRange()
10576b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall        << (BaseAccess == AS_protected)
10586b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall        << (BS->getAccessSpecifierAsWritten() == AS_none);
105976ef658c703faf72c00f324fb9edc03169718e3eDouglas Gregor
106076ef658c703faf72c00f324fb9edc03169718e3eDouglas Gregor      if (D)
106176ef658c703faf72c00f324fb9edc03169718e3eDouglas Gregor        S.Diag(D->getLocation(), diag::note_field_decl);
106276ef658c703faf72c00f324fb9edc03169718e3eDouglas Gregor
10636b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall      return;
10646b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    }
1065c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson  }
1066726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl
10676b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  llvm_unreachable("access not apparently constrained by path");
106829f006be830fbbcaa0c1cf7c7399bb5080dc7f32Anders Carlsson}
106992f883177b162928a8e632e4e3b93fafd2b26072John McCall
1070db73c684ba61fed4087af488e8610657ec638c17John McCallstatic void DiagnoseBadAccess(Sema &S, SourceLocation Loc,
1071db73c684ba61fed4087af488e8610657ec638c17John McCall                              const EffectiveContext &EC,
1072161755a09898c95d21bfff33707da9ca41cd53c5John McCall                              AccessTarget &Entity) {
1073db73c684ba61fed4087af488e8610657ec638c17John McCall  const CXXRecordDecl *NamingClass = Entity.getNamingClass();
1074161755a09898c95d21bfff33707da9ca41cd53c5John McCall  const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();
1075161755a09898c95d21bfff33707da9ca41cd53c5John McCall  NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : 0);
10766b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
107758e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall  S.Diag(Loc, Entity.getDiag())
1078db73c684ba61fed4087af488e8610657ec638c17John McCall    << (Entity.getAccess() == AS_protected)
1079db73c684ba61fed4087af488e8610657ec638c17John McCall    << (D ? D->getDeclName() : DeclarationName())
108058e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall    << S.Context.getTypeDeclType(NamingClass)
108158e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall    << S.Context.getTypeDeclType(DeclaringClass);
1082db73c684ba61fed4087af488e8610657ec638c17John McCall  DiagnoseAccessPath(S, EC, Entity);
10836b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall}
108492f883177b162928a8e632e4e3b93fafd2b26072John McCall
1085db73c684ba61fed4087af488e8610657ec638c17John McCall/// Determines whether the accessed entity is accessible.  Public members
1086db73c684ba61fed4087af488e8610657ec638c17John McCall/// have been weeded out by this point.
1087161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic AccessResult IsAccessible(Sema &S,
1088161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                 const EffectiveContext &EC,
1089161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                 AccessTarget &Entity) {
1090db73c684ba61fed4087af488e8610657ec638c17John McCall  // Determine the actual naming class.
1091db73c684ba61fed4087af488e8610657ec638c17John McCall  CXXRecordDecl *NamingClass = Entity.getNamingClass();
1092db73c684ba61fed4087af488e8610657ec638c17John McCall  while (NamingClass->isAnonymousStructOrUnion())
1093db73c684ba61fed4087af488e8610657ec638c17John McCall    NamingClass = cast<CXXRecordDecl>(NamingClass->getParent());
1094db73c684ba61fed4087af488e8610657ec638c17John McCall  NamingClass = NamingClass->getCanonicalDecl();
109592f883177b162928a8e632e4e3b93fafd2b26072John McCall
1096db73c684ba61fed4087af488e8610657ec638c17John McCall  AccessSpecifier UnprivilegedAccess = Entity.getAccess();
1097db73c684ba61fed4087af488e8610657ec638c17John McCall  assert(UnprivilegedAccess != AS_public && "public access not weeded out");
109892f883177b162928a8e632e4e3b93fafd2b26072John McCall
1099db73c684ba61fed4087af488e8610657ec638c17John McCall  // Before we try to recalculate access paths, try to white-list
1100db73c684ba61fed4087af488e8610657ec638c17John McCall  // accesses which just trade in on the final step, i.e. accesses
1101db73c684ba61fed4087af488e8610657ec638c17John McCall  // which don't require [M4] or [B4]. These are by far the most
1102161755a09898c95d21bfff33707da9ca41cd53c5John McCall  // common forms of privileged access.
1103db73c684ba61fed4087af488e8610657ec638c17John McCall  if (UnprivilegedAccess != AS_none) {
1104161755a09898c95d21bfff33707da9ca41cd53c5John McCall    switch (HasAccess(S, EC, NamingClass, UnprivilegedAccess, Entity)) {
1105161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case AR_dependent:
1106db73c684ba61fed4087af488e8610657ec638c17John McCall      // This is actually an interesting policy decision.  We don't
1107db73c684ba61fed4087af488e8610657ec638c17John McCall      // *have* to delay immediately here: we can do the full access
1108db73c684ba61fed4087af488e8610657ec638c17John McCall      // calculation in the hope that friendship on some intermediate
1109db73c684ba61fed4087af488e8610657ec638c17John McCall      // class will make the declaration accessible non-dependently.
1110db73c684ba61fed4087af488e8610657ec638c17John McCall      // But that's not cheap, and odds are very good (note: assertion
1111db73c684ba61fed4087af488e8610657ec638c17John McCall      // made without data) that the friend declaration will determine
1112db73c684ba61fed4087af488e8610657ec638c17John McCall      // access.
1113161755a09898c95d21bfff33707da9ca41cd53c5John McCall      return AR_dependent;
1114db73c684ba61fed4087af488e8610657ec638c17John McCall
1115161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case AR_accessible: return AR_accessible;
1116161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case AR_inaccessible: break;
1117db73c684ba61fed4087af488e8610657ec638c17John McCall    }
1118db73c684ba61fed4087af488e8610657ec638c17John McCall  }
111992f883177b162928a8e632e4e3b93fafd2b26072John McCall
1120161755a09898c95d21bfff33707da9ca41cd53c5John McCall  AccessTarget::SavedInstanceContext _ = Entity.saveInstanceContext();
1121db73c684ba61fed4087af488e8610657ec638c17John McCall
1122db73c684ba61fed4087af488e8610657ec638c17John McCall  // We lower member accesses to base accesses by pretending that the
1123db73c684ba61fed4087af488e8610657ec638c17John McCall  // member is a base class of its declaring class.
1124db73c684ba61fed4087af488e8610657ec638c17John McCall  AccessSpecifier FinalAccess;
11256b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
11266b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  if (Entity.isMemberAccess()) {
1127db73c684ba61fed4087af488e8610657ec638c17John McCall    // Determine if the declaration is accessible from EC when named
1128db73c684ba61fed4087af488e8610657ec638c17John McCall    // in its declaring class.
11296b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    NamedDecl *Target = Entity.getTargetDecl();
1130161755a09898c95d21bfff33707da9ca41cd53c5John McCall    const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();
11316b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
1132db73c684ba61fed4087af488e8610657ec638c17John McCall    FinalAccess = Target->getAccess();
1133161755a09898c95d21bfff33707da9ca41cd53c5John McCall    switch (HasAccess(S, EC, DeclaringClass, FinalAccess, Entity)) {
1134161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case AR_accessible:
1135161755a09898c95d21bfff33707da9ca41cd53c5John McCall      FinalAccess = AS_public;
1136161755a09898c95d21bfff33707da9ca41cd53c5John McCall      break;
1137161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case AR_inaccessible: break;
1138161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case AR_dependent: return AR_dependent; // see above
11396b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    }
11402f514480c448708ec382a684cf5e035d3a827ec8John McCall
1141db73c684ba61fed4087af488e8610657ec638c17John McCall    if (DeclaringClass == NamingClass)
1142161755a09898c95d21bfff33707da9ca41cd53c5John McCall      return (FinalAccess == AS_public ? AR_accessible : AR_inaccessible);
1143161755a09898c95d21bfff33707da9ca41cd53c5John McCall
1144161755a09898c95d21bfff33707da9ca41cd53c5John McCall    Entity.suppressInstanceContext();
1145db73c684ba61fed4087af488e8610657ec638c17John McCall  } else {
1146db73c684ba61fed4087af488e8610657ec638c17John McCall    FinalAccess = AS_public;
11476b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  }
11482f514480c448708ec382a684cf5e035d3a827ec8John McCall
1149161755a09898c95d21bfff33707da9ca41cd53c5John McCall  assert(Entity.getDeclaringClass() != NamingClass);
11506b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
11516b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  // Append the declaration's access if applicable.
11526b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  CXXBasePaths Paths;
1153161755a09898c95d21bfff33707da9ca41cd53c5John McCall  CXXBasePath *Path = FindBestPath(S, EC, Entity, FinalAccess, Paths);
11540c01d18094100db92d38daa923c95661512db203John McCall  if (!Path)
1155161755a09898c95d21bfff33707da9ca41cd53c5John McCall    return AR_dependent;
115692f883177b162928a8e632e4e3b93fafd2b26072John McCall
1157db73c684ba61fed4087af488e8610657ec638c17John McCall  assert(Path->Access <= UnprivilegedAccess &&
1158db73c684ba61fed4087af488e8610657ec638c17John McCall         "access along best path worse than direct?");
1159db73c684ba61fed4087af488e8610657ec638c17John McCall  if (Path->Access == AS_public)
1160161755a09898c95d21bfff33707da9ca41cd53c5John McCall    return AR_accessible;
1161161755a09898c95d21bfff33707da9ca41cd53c5John McCall  return AR_inaccessible;
11620c01d18094100db92d38daa923c95661512db203John McCall}
11630c01d18094100db92d38daa923c95661512db203John McCall
1164161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic void DelayDependentAccess(Sema &S,
1165161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                 const EffectiveContext &EC,
1166161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                 SourceLocation Loc,
1167161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                 const AccessTarget &Entity) {
11680c01d18094100db92d38daa923c95661512db203John McCall  assert(EC.isDependent() && "delaying non-dependent access");
11697ad650f88ecbbe659f10f9f6b34a1f29ea9cf8f9John McCall  DeclContext *DC = EC.getInnerContext();
11700c01d18094100db92d38daa923c95661512db203John McCall  assert(DC->isDependentContext() && "delaying non-dependent access");
11710c01d18094100db92d38daa923c95661512db203John McCall  DependentDiagnostic::Create(S.Context, DC, DependentDiagnostic::Access,
11720c01d18094100db92d38daa923c95661512db203John McCall                              Loc,
11730c01d18094100db92d38daa923c95661512db203John McCall                              Entity.isMemberAccess(),
11740c01d18094100db92d38daa923c95661512db203John McCall                              Entity.getAccess(),
11750c01d18094100db92d38daa923c95661512db203John McCall                              Entity.getTargetDecl(),
11760c01d18094100db92d38daa923c95661512db203John McCall                              Entity.getNamingClass(),
1177161755a09898c95d21bfff33707da9ca41cd53c5John McCall                              Entity.getBaseObjectType(),
11780c01d18094100db92d38daa923c95661512db203John McCall                              Entity.getDiag());
11796b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall}
11806b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
11816b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// Checks access to an entity from the given effective context.
1182161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic AccessResult CheckEffectiveAccess(Sema &S,
1183161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                         const EffectiveContext &EC,
1184161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                         SourceLocation Loc,
1185161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                         AccessTarget &Entity) {
1186db73c684ba61fed4087af488e8610657ec638c17John McCall  assert(Entity.getAccess() != AS_public && "called for public access!");
118792f883177b162928a8e632e4e3b93fafd2b26072John McCall
1188db73c684ba61fed4087af488e8610657ec638c17John McCall  switch (IsAccessible(S, EC, Entity)) {
1189161755a09898c95d21bfff33707da9ca41cd53c5John McCall  case AR_dependent:
1190161755a09898c95d21bfff33707da9ca41cd53c5John McCall    DelayDependentAccess(S, EC, Loc, Entity);
1191161755a09898c95d21bfff33707da9ca41cd53c5John McCall    return AR_dependent;
11920c01d18094100db92d38daa923c95661512db203John McCall
1193161755a09898c95d21bfff33707da9ca41cd53c5John McCall  case AR_inaccessible:
1194db73c684ba61fed4087af488e8610657ec638c17John McCall    if (!Entity.isQuiet())
1195db73c684ba61fed4087af488e8610657ec638c17John McCall      DiagnoseBadAccess(S, Loc, EC, Entity);
1196161755a09898c95d21bfff33707da9ca41cd53c5John McCall    return AR_inaccessible;
119792f883177b162928a8e632e4e3b93fafd2b26072John McCall
1198161755a09898c95d21bfff33707da9ca41cd53c5John McCall  case AR_accessible:
1199161755a09898c95d21bfff33707da9ca41cd53c5John McCall    return AR_accessible;
1200db73c684ba61fed4087af488e8610657ec638c17John McCall  }
1201db73c684ba61fed4087af488e8610657ec638c17John McCall
1202161755a09898c95d21bfff33707da9ca41cd53c5John McCall  // silence unnecessary warning
1203161755a09898c95d21bfff33707da9ca41cd53c5John McCall  llvm_unreachable("invalid access result");
1204161755a09898c95d21bfff33707da9ca41cd53c5John McCall  return AR_accessible;
12056b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall}
120692f883177b162928a8e632e4e3b93fafd2b26072John McCall
12076b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallstatic Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc,
1208161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                      AccessTarget &Entity) {
12096b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  // If the access path is public, it's accessible everywhere.
12106b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  if (Entity.getAccess() == AS_public)
12116b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    return Sema::AR_accessible;
121292f883177b162928a8e632e4e3b93fafd2b26072John McCall
1213926c4b486a08f698cd3a367fd6f1a3a07604358dChandler Carruth  if (S.SuppressAccessChecking)
1214926c4b486a08f698cd3a367fd6f1a3a07604358dChandler Carruth    return Sema::AR_accessible;
1215926c4b486a08f698cd3a367fd6f1a3a07604358dChandler Carruth
12166b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  // If we're currently parsing a top-level declaration, delay
12176b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  // diagnostics.  This is the only case where parsing a declaration
12186b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  // can actually change our effective context for the purposes of
12196b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  // access control.
12206b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  if (S.CurContext->isFileContext() && S.ParsingDeclDepth) {
12216b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    S.DelayedDiagnostics.push_back(
12229c3087b0b0bea2fd782205c1274ebfc4290265e0John McCall        DelayedDiagnostic::makeAccess(Loc, Entity));
12236b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    return Sema::AR_delayed;
122492f883177b162928a8e632e4e3b93fafd2b26072John McCall  }
122592f883177b162928a8e632e4e3b93fafd2b26072John McCall
1226161755a09898c95d21bfff33707da9ca41cd53c5John McCall  EffectiveContext EC(S.CurContext);
1227161755a09898c95d21bfff33707da9ca41cd53c5John McCall  switch (CheckEffectiveAccess(S, EC, Loc, Entity)) {
1228161755a09898c95d21bfff33707da9ca41cd53c5John McCall  case AR_accessible: return Sema::AR_accessible;
1229161755a09898c95d21bfff33707da9ca41cd53c5John McCall  case AR_inaccessible: return Sema::AR_inaccessible;
1230161755a09898c95d21bfff33707da9ca41cd53c5John McCall  case AR_dependent: return Sema::AR_dependent;
1231161755a09898c95d21bfff33707da9ca41cd53c5John McCall  }
1232161755a09898c95d21bfff33707da9ca41cd53c5John McCall  llvm_unreachable("falling off end");
1233161755a09898c95d21bfff33707da9ca41cd53c5John McCall  return Sema::AR_accessible;
123492f883177b162928a8e632e4e3b93fafd2b26072John McCall}
123592f883177b162928a8e632e4e3b93fafd2b26072John McCall
12362f514480c448708ec382a684cf5e035d3a827ec8John McCallvoid Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *Ctx) {
12372f514480c448708ec382a684cf5e035d3a827ec8John McCall  // Pretend we did this from the context of the newly-parsed
1238630eb01b2568d0958118eb1a0ded02bebecb2b0fChandler Carruth  // declaration. If that declaration itself forms a declaration context,
1239630eb01b2568d0958118eb1a0ded02bebecb2b0fChandler Carruth  // include it in the effective context so that parameters and return types of
1240630eb01b2568d0958118eb1a0ded02bebecb2b0fChandler Carruth  // befriended functions have that function's access priveledges.
1241630eb01b2568d0958118eb1a0ded02bebecb2b0fChandler Carruth  DeclContext *DC = Ctx->getDeclContext();
1242630eb01b2568d0958118eb1a0ded02bebecb2b0fChandler Carruth  if (isa<FunctionDecl>(Ctx))
1243630eb01b2568d0958118eb1a0ded02bebecb2b0fChandler Carruth    DC = cast<DeclContext>(Ctx);
1244630eb01b2568d0958118eb1a0ded02bebecb2b0fChandler Carruth  else if (FunctionTemplateDecl *FnTpl = dyn_cast<FunctionTemplateDecl>(Ctx))
1245630eb01b2568d0958118eb1a0ded02bebecb2b0fChandler Carruth    DC = cast<DeclContext>(FnTpl->getTemplatedDecl());
1246630eb01b2568d0958118eb1a0ded02bebecb2b0fChandler Carruth  EffectiveContext EC(DC);
12472f514480c448708ec382a684cf5e035d3a827ec8John McCall
1248161755a09898c95d21bfff33707da9ca41cd53c5John McCall  AccessTarget Target(DD.getAccessData());
1249161755a09898c95d21bfff33707da9ca41cd53c5John McCall
1250161755a09898c95d21bfff33707da9ca41cd53c5John McCall  if (CheckEffectiveAccess(*this, EC, DD.Loc, Target) == ::AR_inaccessible)
12512f514480c448708ec382a684cf5e035d3a827ec8John McCall    DD.Triggered = true;
12522f514480c448708ec382a684cf5e035d3a827ec8John McCall}
12532f514480c448708ec382a684cf5e035d3a827ec8John McCall
12540c01d18094100db92d38daa923c95661512db203John McCallvoid Sema::HandleDependentAccessCheck(const DependentDiagnostic &DD,
12550c01d18094100db92d38daa923c95661512db203John McCall                        const MultiLevelTemplateArgumentList &TemplateArgs) {
12560c01d18094100db92d38daa923c95661512db203John McCall  SourceLocation Loc = DD.getAccessLoc();
12570c01d18094100db92d38daa923c95661512db203John McCall  AccessSpecifier Access = DD.getAccess();
12580c01d18094100db92d38daa923c95661512db203John McCall
12590c01d18094100db92d38daa923c95661512db203John McCall  Decl *NamingD = FindInstantiatedDecl(Loc, DD.getAccessNamingClass(),
12600c01d18094100db92d38daa923c95661512db203John McCall                                       TemplateArgs);
12610c01d18094100db92d38daa923c95661512db203John McCall  if (!NamingD) return;
12620c01d18094100db92d38daa923c95661512db203John McCall  Decl *TargetD = FindInstantiatedDecl(Loc, DD.getAccessTarget(),
12630c01d18094100db92d38daa923c95661512db203John McCall                                       TemplateArgs);
12640c01d18094100db92d38daa923c95661512db203John McCall  if (!TargetD) return;
12650c01d18094100db92d38daa923c95661512db203John McCall
12660c01d18094100db92d38daa923c95661512db203John McCall  if (DD.isAccessToMember()) {
1267161755a09898c95d21bfff33707da9ca41cd53c5John McCall    CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(NamingD);
1268161755a09898c95d21bfff33707da9ca41cd53c5John McCall    NamedDecl *TargetDecl = cast<NamedDecl>(TargetD);
1269161755a09898c95d21bfff33707da9ca41cd53c5John McCall    QualType BaseObjectType = DD.getAccessBaseObjectType();
1270161755a09898c95d21bfff33707da9ca41cd53c5John McCall    if (!BaseObjectType.isNull()) {
1271161755a09898c95d21bfff33707da9ca41cd53c5John McCall      BaseObjectType = SubstType(BaseObjectType, TemplateArgs, Loc,
1272161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                 DeclarationName());
1273161755a09898c95d21bfff33707da9ca41cd53c5John McCall      if (BaseObjectType.isNull()) return;
1274161755a09898c95d21bfff33707da9ca41cd53c5John McCall    }
1275161755a09898c95d21bfff33707da9ca41cd53c5John McCall
1276161755a09898c95d21bfff33707da9ca41cd53c5John McCall    AccessTarget Entity(Context,
1277161755a09898c95d21bfff33707da9ca41cd53c5John McCall                        AccessTarget::Member,
1278161755a09898c95d21bfff33707da9ca41cd53c5John McCall                        NamingClass,
1279161755a09898c95d21bfff33707da9ca41cd53c5John McCall                        DeclAccessPair::make(TargetDecl, Access),
1280161755a09898c95d21bfff33707da9ca41cd53c5John McCall                        BaseObjectType);
12810c01d18094100db92d38daa923c95661512db203John McCall    Entity.setDiag(DD.getDiagnostic());
12820c01d18094100db92d38daa923c95661512db203John McCall    CheckAccess(*this, Loc, Entity);
12830c01d18094100db92d38daa923c95661512db203John McCall  } else {
1284161755a09898c95d21bfff33707da9ca41cd53c5John McCall    AccessTarget Entity(Context,
1285161755a09898c95d21bfff33707da9ca41cd53c5John McCall                        AccessTarget::Base,
1286161755a09898c95d21bfff33707da9ca41cd53c5John McCall                        cast<CXXRecordDecl>(TargetD),
1287161755a09898c95d21bfff33707da9ca41cd53c5John McCall                        cast<CXXRecordDecl>(NamingD),
1288161755a09898c95d21bfff33707da9ca41cd53c5John McCall                        Access);
12890c01d18094100db92d38daa923c95661512db203John McCall    Entity.setDiag(DD.getDiagnostic());
12900c01d18094100db92d38daa923c95661512db203John McCall    CheckAccess(*this, Loc, Entity);
12910c01d18094100db92d38daa923c95661512db203John McCall  }
12920c01d18094100db92d38daa923c95661512db203John McCall}
12930c01d18094100db92d38daa923c95661512db203John McCall
12946b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallSema::AccessResult Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E,
12959aa472c45d2bd81b7b52c225e8acc560d716db97John McCall                                                     DeclAccessPair Found) {
129658e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall  if (!getLangOptions().AccessControl ||
129758e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall      !E->getNamingClass() ||
12989aa472c45d2bd81b7b52c225e8acc560d716db97John McCall      Found.getAccess() == AS_public)
12996b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    return AR_accessible;
1300c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall
1301161755a09898c95d21bfff33707da9ca41cd53c5John McCall  AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(),
1302161755a09898c95d21bfff33707da9ca41cd53c5John McCall                      Found, QualType());
130358e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall  Entity.setDiag(diag::err_access) << E->getSourceRange();
130458e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall
130558e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall  return CheckAccess(*this, E->getNameLoc(), Entity);
1306c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall}
1307c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall
1308c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall/// Perform access-control checking on a previously-unresolved member
1309c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall/// access which has now been resolved to a member.
13106b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallSema::AccessResult Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E,
13119aa472c45d2bd81b7b52c225e8acc560d716db97John McCall                                                     DeclAccessPair Found) {
131258e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall  if (!getLangOptions().AccessControl ||
13139aa472c45d2bd81b7b52c225e8acc560d716db97John McCall      Found.getAccess() == AS_public)
13146b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    return AR_accessible;
1315c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall
1316161755a09898c95d21bfff33707da9ca41cd53c5John McCall  QualType BaseType = E->getBaseType();
1317161755a09898c95d21bfff33707da9ca41cd53c5John McCall  if (E->isArrow())
1318161755a09898c95d21bfff33707da9ca41cd53c5John McCall    BaseType = BaseType->getAs<PointerType>()->getPointeeType();
1319161755a09898c95d21bfff33707da9ca41cd53c5John McCall
1320161755a09898c95d21bfff33707da9ca41cd53c5John McCall  AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(),
1321161755a09898c95d21bfff33707da9ca41cd53c5John McCall                      Found, BaseType);
132258e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall  Entity.setDiag(diag::err_access) << E->getSourceRange();
132358e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall
132458e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall  return CheckAccess(*this, E->getMemberLoc(), Entity);
1325c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall}
1326c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall
13276b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallSema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc,
132858e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall                                               CXXDestructorDecl *Dtor,
132958e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall                                               const PartialDiagnostic &PDiag) {
13304f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall  if (!getLangOptions().AccessControl)
13316b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    return AR_accessible;
13324f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall
133358e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall  // There's never a path involved when checking implicit destructor access.
13344f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall  AccessSpecifier Access = Dtor->getAccess();
13354f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall  if (Access == AS_public)
13366b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    return AR_accessible;
13374f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall
133858e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall  CXXRecordDecl *NamingClass = Dtor->getParent();
1339161755a09898c95d21bfff33707da9ca41cd53c5John McCall  AccessTarget Entity(Context, AccessTarget::Member, NamingClass,
1340161755a09898c95d21bfff33707da9ca41cd53c5John McCall                      DeclAccessPair::make(Dtor, Access),
1341161755a09898c95d21bfff33707da9ca41cd53c5John McCall                      QualType());
134258e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall  Entity.setDiag(PDiag); // TODO: avoid copy
134358e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall
134458e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall  return CheckAccess(*this, Loc, Entity);
13454f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall}
13464f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall
1347b13b737a2450167c82e148590e8019b839ce6b98John McCall/// Checks access to a constructor.
13486b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallSema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc,
134957d12fd4a2bc739c4a4d62a364b7f08cd483c59eJeffrey Yasskin                                                CXXConstructorDecl *Constructor,
135057d12fd4a2bc739c4a4d62a364b7f08cd483c59eJeffrey Yasskin                                                const InitializedEntity &Entity,
135157d12fd4a2bc739c4a4d62a364b7f08cd483c59eJeffrey Yasskin                                                AccessSpecifier Access,
135257d12fd4a2bc739c4a4d62a364b7f08cd483c59eJeffrey Yasskin                                                bool IsCopyBindingRefToTemp) {
135358e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall  if (!getLangOptions().AccessControl ||
135458e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall      Access == AS_public)
13556b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    return AR_accessible;
1356b13b737a2450167c82e148590e8019b839ce6b98John McCall
13576b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  CXXRecordDecl *NamingClass = Constructor->getParent();
13589a68a67c6ae4982001815cc04f69b8781058263aAnders Carlsson  AccessTarget AccessEntity(Context, AccessTarget::Member, NamingClass,
13599a68a67c6ae4982001815cc04f69b8781058263aAnders Carlsson                            DeclAccessPair::make(Constructor, Access),
13609a68a67c6ae4982001815cc04f69b8781058263aAnders Carlsson                            QualType());
13619a68a67c6ae4982001815cc04f69b8781058263aAnders Carlsson  switch (Entity.getKind()) {
13629a68a67c6ae4982001815cc04f69b8781058263aAnders Carlsson  default:
136357d12fd4a2bc739c4a4d62a364b7f08cd483c59eJeffrey Yasskin    AccessEntity.setDiag(IsCopyBindingRefToTemp
136457d12fd4a2bc739c4a4d62a364b7f08cd483c59eJeffrey Yasskin                         ? diag::ext_rvalue_to_reference_access_ctor
136557d12fd4a2bc739c4a4d62a364b7f08cd483c59eJeffrey Yasskin                         : diag::err_access_ctor);
13669a68a67c6ae4982001815cc04f69b8781058263aAnders Carlsson    break;
13679a68a67c6ae4982001815cc04f69b8781058263aAnders Carlsson
13683b8c53b619c1c3d77632734d227566071459b9f5Anders Carlsson  case InitializedEntity::EK_Base:
13693b8c53b619c1c3d77632734d227566071459b9f5Anders Carlsson    AccessEntity.setDiag(PDiag(diag::err_access_base)
13703b8c53b619c1c3d77632734d227566071459b9f5Anders Carlsson                          << Entity.isInheritedVirtualBase()
13713b8c53b619c1c3d77632734d227566071459b9f5Anders Carlsson                          << Entity.getBaseSpecifier()->getType()
13723b8c53b619c1c3d77632734d227566071459b9f5Anders Carlsson                          << getSpecialMember(Constructor));
13739a68a67c6ae4982001815cc04f69b8781058263aAnders Carlsson    break;
13743b8c53b619c1c3d77632734d227566071459b9f5Anders Carlsson
1375b99c666a940e93bcfcaeddc01515c94472e28a20Anders Carlsson  case InitializedEntity::EK_Member: {
1376b99c666a940e93bcfcaeddc01515c94472e28a20Anders Carlsson    const FieldDecl *Field = cast<FieldDecl>(Entity.getDecl());
13770e313bd4795c005f23c43f127039fd948c3e0bd9Anders Carlsson    AccessEntity.setDiag(PDiag(diag::err_access_field)
13780e313bd4795c005f23c43f127039fd948c3e0bd9Anders Carlsson                          << Field->getType()
13790e313bd4795c005f23c43f127039fd948c3e0bd9Anders Carlsson                          << getSpecialMember(Constructor));
1380b99c666a940e93bcfcaeddc01515c94472e28a20Anders Carlsson    break;
1381b99c666a940e93bcfcaeddc01515c94472e28a20Anders Carlsson  }
138258e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall
1383711f34adb886cce8ba86c7b1b6513a1eaaf63bb5Anders Carlsson  }
1384711f34adb886cce8ba86c7b1b6513a1eaaf63bb5Anders Carlsson
13859a68a67c6ae4982001815cc04f69b8781058263aAnders Carlsson  return CheckAccess(*this, UseLoc, AccessEntity);
1386b13b737a2450167c82e148590e8019b839ce6b98John McCall}
1387b13b737a2450167c82e148590e8019b839ce6b98John McCall
1388b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall/// Checks direct (i.e. non-inherited) access to an arbitrary class
1389b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall/// member.
1390b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCallSema::AccessResult Sema::CheckDirectMemberAccess(SourceLocation UseLoc,
1391b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall                                                 NamedDecl *Target,
1392b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall                                           const PartialDiagnostic &Diag) {
1393b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall  AccessSpecifier Access = Target->getAccess();
1394b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall  if (!getLangOptions().AccessControl ||
1395b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall      Access == AS_public)
1396b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall    return AR_accessible;
1397b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall
1398b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall  CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(Target->getDeclContext());
1399161755a09898c95d21bfff33707da9ca41cd53c5John McCall  AccessTarget Entity(Context, AccessTarget::Member, NamingClass,
1400161755a09898c95d21bfff33707da9ca41cd53c5John McCall                      DeclAccessPair::make(Target, Access),
1401161755a09898c95d21bfff33707da9ca41cd53c5John McCall                      QualType());
1402b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall  Entity.setDiag(Diag);
1403b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall  return CheckAccess(*this, UseLoc, Entity);
1404b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall}
1405b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall
1406b020748a9954c995f2e616f50bb9ed4fe2df1f72John McCall
140790c8c57bcd84083df85f76aac2aa62acb85eb077John McCall/// Checks access to an overloaded operator new or delete.
140890c8c57bcd84083df85f76aac2aa62acb85eb077John McCallSema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc,
140990c8c57bcd84083df85f76aac2aa62acb85eb077John McCall                                               SourceRange PlacementRange,
141090c8c57bcd84083df85f76aac2aa62acb85eb077John McCall                                               CXXRecordDecl *NamingClass,
14119aa472c45d2bd81b7b52c225e8acc560d716db97John McCall                                               DeclAccessPair Found) {
141290c8c57bcd84083df85f76aac2aa62acb85eb077John McCall  if (!getLangOptions().AccessControl ||
141390c8c57bcd84083df85f76aac2aa62acb85eb077John McCall      !NamingClass ||
14149aa472c45d2bd81b7b52c225e8acc560d716db97John McCall      Found.getAccess() == AS_public)
141590c8c57bcd84083df85f76aac2aa62acb85eb077John McCall    return AR_accessible;
141690c8c57bcd84083df85f76aac2aa62acb85eb077John McCall
1417161755a09898c95d21bfff33707da9ca41cd53c5John McCall  AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
1418161755a09898c95d21bfff33707da9ca41cd53c5John McCall                      QualType());
141990c8c57bcd84083df85f76aac2aa62acb85eb077John McCall  Entity.setDiag(diag::err_access)
142090c8c57bcd84083df85f76aac2aa62acb85eb077John McCall    << PlacementRange;
142190c8c57bcd84083df85f76aac2aa62acb85eb077John McCall
142290c8c57bcd84083df85f76aac2aa62acb85eb077John McCall  return CheckAccess(*this, OpLoc, Entity);
142390c8c57bcd84083df85f76aac2aa62acb85eb077John McCall}
142490c8c57bcd84083df85f76aac2aa62acb85eb077John McCall
1425b13b737a2450167c82e148590e8019b839ce6b98John McCall/// Checks access to an overloaded member operator, including
1426b13b737a2450167c82e148590e8019b839ce6b98John McCall/// conversion operators.
14276b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallSema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc,
14286b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall                                                   Expr *ObjectExpr,
142958e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall                                                   Expr *ArgExpr,
14309aa472c45d2bd81b7b52c225e8acc560d716db97John McCall                                                   DeclAccessPair Found) {
143158e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall  if (!getLangOptions().AccessControl ||
14329aa472c45d2bd81b7b52c225e8acc560d716db97John McCall      Found.getAccess() == AS_public)
14336b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    return AR_accessible;
14345357b615364c17ea024c757354c58ae2a520d216John McCall
14355357b615364c17ea024c757354c58ae2a520d216John McCall  const RecordType *RT = ObjectExpr->getType()->getAs<RecordType>();
14365357b615364c17ea024c757354c58ae2a520d216John McCall  assert(RT && "found member operator but object expr not of record type");
14375357b615364c17ea024c757354c58ae2a520d216John McCall  CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(RT->getDecl());
14385357b615364c17ea024c757354c58ae2a520d216John McCall
1439161755a09898c95d21bfff33707da9ca41cd53c5John McCall  AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
1440161755a09898c95d21bfff33707da9ca41cd53c5John McCall                      ObjectExpr->getType());
144158e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall  Entity.setDiag(diag::err_access)
144258e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall    << ObjectExpr->getSourceRange()
144358e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall    << (ArgExpr ? ArgExpr->getSourceRange() : SourceRange());
144458e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall
144558e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall  return CheckAccess(*this, OpLoc, Entity);
14466b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall}
14475357b615364c17ea024c757354c58ae2a520d216John McCall
14486bb8017bb9e828d118e15e59d71c66bba323c364John McCallSema::AccessResult Sema::CheckAddressOfMemberAccess(Expr *OvlExpr,
14496bb8017bb9e828d118e15e59d71c66bba323c364John McCall                                                    DeclAccessPair Found) {
14506bb8017bb9e828d118e15e59d71c66bba323c364John McCall  if (!getLangOptions().AccessControl ||
1451e2f5ba9d80cfadbb3e1dafb9f375eb526f669b85John McCall      Found.getAccess() == AS_none ||
14526bb8017bb9e828d118e15e59d71c66bba323c364John McCall      Found.getAccess() == AS_public)
14536bb8017bb9e828d118e15e59d71c66bba323c364John McCall    return AR_accessible;
14546bb8017bb9e828d118e15e59d71c66bba323c364John McCall
14559c72c6088d591ace8503b842d39448c2040f3033John McCall  OverloadExpr *Ovl = OverloadExpr::find(OvlExpr).Expression;
1456e9ee23edd17c4bb7f271e67f8790792b4de677fcJohn McCall  CXXRecordDecl *NamingClass = Ovl->getNamingClass();
14576bb8017bb9e828d118e15e59d71c66bba323c364John McCall
1458161755a09898c95d21bfff33707da9ca41cd53c5John McCall  AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
1459161755a09898c95d21bfff33707da9ca41cd53c5John McCall                      Context.getTypeDeclType(NamingClass));
14606bb8017bb9e828d118e15e59d71c66bba323c364John McCall  Entity.setDiag(diag::err_access)
14616bb8017bb9e828d118e15e59d71c66bba323c364John McCall    << Ovl->getSourceRange();
14626bb8017bb9e828d118e15e59d71c66bba323c364John McCall
14636bb8017bb9e828d118e15e59d71c66bba323c364John McCall  return CheckAccess(*this, Ovl->getNameLoc(), Entity);
14646bb8017bb9e828d118e15e59d71c66bba323c364John McCall}
14656bb8017bb9e828d118e15e59d71c66bba323c364John McCall
14666b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// Checks access for a hierarchy conversion.
14676b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall///
14686b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// \param IsBaseToDerived whether this is a base-to-derived conversion (true)
14696b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall///     or a derived-to-base conversion (false)
14706b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// \param ForceCheck true if this check should be performed even if access
14716b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall///     control is disabled;  some things rely on this for semantics
14726b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// \param ForceUnprivileged true if this check should proceed as if the
14736b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall///     context had no special privileges
14746b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// \param ADK controls the kind of diagnostics that are used
14756b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallSema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc,
14766b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall                                              QualType Base,
14776b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall                                              QualType Derived,
14786b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall                                              const CXXBasePath &Path,
147958e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall                                              unsigned DiagID,
14806b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall                                              bool ForceCheck,
148158e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall                                              bool ForceUnprivileged) {
14826b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  if (!ForceCheck && !getLangOptions().AccessControl)
14836b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    return AR_accessible;
14846b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
14856b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  if (Path.Access == AS_public)
14866b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    return AR_accessible;
14876b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
14886b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  CXXRecordDecl *BaseD, *DerivedD;
14896b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  BaseD = cast<CXXRecordDecl>(Base->getAs<RecordType>()->getDecl());
14906b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  DerivedD = cast<CXXRecordDecl>(Derived->getAs<RecordType>()->getDecl());
149158e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall
1492161755a09898c95d21bfff33707da9ca41cd53c5John McCall  AccessTarget Entity(Context, AccessTarget::Base, BaseD, DerivedD,
1493161755a09898c95d21bfff33707da9ca41cd53c5John McCall                      Path.Access);
149458e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall  if (DiagID)
149558e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall    Entity.setDiag(DiagID) << Derived << Base;
14966b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
1497161755a09898c95d21bfff33707da9ca41cd53c5John McCall  if (ForceUnprivileged) {
1498161755a09898c95d21bfff33707da9ca41cd53c5John McCall    switch (CheckEffectiveAccess(*this, EffectiveContext(),
1499161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                 AccessLoc, Entity)) {
1500161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case ::AR_accessible: return Sema::AR_accessible;
1501161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case ::AR_inaccessible: return Sema::AR_inaccessible;
1502161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case ::AR_dependent: return Sema::AR_dependent;
1503161755a09898c95d21bfff33707da9ca41cd53c5John McCall    }
1504161755a09898c95d21bfff33707da9ca41cd53c5John McCall    llvm_unreachable("unexpected result from CheckEffectiveAccess");
1505161755a09898c95d21bfff33707da9ca41cd53c5John McCall  }
150658e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall  return CheckAccess(*this, AccessLoc, Entity);
15075357b615364c17ea024c757354c58ae2a520d216John McCall}
15085357b615364c17ea024c757354c58ae2a520d216John McCall
150992f883177b162928a8e632e4e3b93fafd2b26072John McCall/// Checks access to all the declarations in the given result set.
15106b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallvoid Sema::CheckLookupAccess(const LookupResult &R) {
15116b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  assert(getLangOptions().AccessControl
15126b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall         && "performing access check without access control");
15136b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  assert(R.getNamingClass() && "performing access check without naming class");
15146b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
151558e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall  for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
151658e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall    if (I.getAccess() != AS_public) {
1517161755a09898c95d21bfff33707da9ca41cd53c5John McCall      AccessTarget Entity(Context, AccessedEntity::Member,
1518161755a09898c95d21bfff33707da9ca41cd53c5John McCall                          R.getNamingClass(), I.getPair(),
1519161755a09898c95d21bfff33707da9ca41cd53c5John McCall                          R.getBaseObjectType());
152058e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall      Entity.setDiag(diag::err_access);
152158e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall
152258e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall      CheckAccess(*this, R.getNameLoc(), Entity);
152358e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall    }
152458e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall  }
152592f883177b162928a8e632e4e3b93fafd2b26072John McCall}
1526926c4b486a08f698cd3a367fd6f1a3a07604358dChandler Carruth
1527926c4b486a08f698cd3a367fd6f1a3a07604358dChandler Carruthvoid Sema::ActOnStartSuppressingAccessChecks() {
1528926c4b486a08f698cd3a367fd6f1a3a07604358dChandler Carruth  assert(!SuppressAccessChecking &&
1529926c4b486a08f698cd3a367fd6f1a3a07604358dChandler Carruth         "Tried to start access check suppression when already started.");
1530926c4b486a08f698cd3a367fd6f1a3a07604358dChandler Carruth  SuppressAccessChecking = true;
1531926c4b486a08f698cd3a367fd6f1a3a07604358dChandler Carruth}
1532926c4b486a08f698cd3a367fd6f1a3a07604358dChandler Carruth
1533926c4b486a08f698cd3a367fd6f1a3a07604358dChandler Carruthvoid Sema::ActOnStopSuppressingAccessChecks() {
1534926c4b486a08f698cd3a367fd6f1a3a07604358dChandler Carruth  assert(SuppressAccessChecking &&
1535926c4b486a08f698cd3a367fd6f1a3a07604358dChandler Carruth         "Tried to stop access check suprression when already stopped.");
1536926c4b486a08f698cd3a367fd6f1a3a07604358dChandler Carruth  SuppressAccessChecking = false;
1537926c4b486a08f698cd3a367fd6f1a3a07604358dChandler Carruth}
1538