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"
22f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor#include "clang/AST/DeclObjC.h"
230c01d18094100db92d38daa923c95661512db203John McCall#include "clang/AST/DependentDiagnostic.h"
24c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall#include "clang/AST/ExprCXX.h"
25c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall
26c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlssonusing namespace clang;
279c3087b0b0bea2fd782205c1274ebfc4290265e0John McCallusing namespace sema;
28c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson
29161755a09898c95d21bfff33707da9ca41cd53c5John McCall/// A copy of Sema's enum without AR_delayed.
30161755a09898c95d21bfff33707da9ca41cd53c5John McCallenum AccessResult {
31161755a09898c95d21bfff33707da9ca41cd53c5John McCall  AR_accessible,
32161755a09898c95d21bfff33707da9ca41cd53c5John McCall  AR_inaccessible,
33161755a09898c95d21bfff33707da9ca41cd53c5John McCall  AR_dependent
34161755a09898c95d21bfff33707da9ca41cd53c5John McCall};
35161755a09898c95d21bfff33707da9ca41cd53c5John McCall
3629f006be830fbbcaa0c1cf7c7399bb5080dc7f32Anders Carlsson/// SetMemberAccessSpecifier - Set the access specifier of a member.
3729f006be830fbbcaa0c1cf7c7399bb5080dc7f32Anders Carlsson/// Returns true on error (when the previous member decl access specifier
3829f006be830fbbcaa0c1cf7c7399bb5080dc7f32Anders Carlsson/// is different from the new member decl access specifier).
391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpbool Sema::SetMemberAccessSpecifier(NamedDecl *MemberDecl,
40c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson                                    NamedDecl *PrevMemberDecl,
41c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson                                    AccessSpecifier LexicalAS) {
42c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson  if (!PrevMemberDecl) {
43c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson    // Use the lexical access specifier.
44c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson    MemberDecl->setAccess(LexicalAS);
45c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson    return false;
46c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson  }
471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
48c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson  // C++ [class.access.spec]p3: When a member is redeclared its access
49c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson  // specifier must be same as its initial declaration.
50c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson  if (LexicalAS != AS_none && LexicalAS != PrevMemberDecl->getAccess()) {
511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    Diag(MemberDecl->getLocation(),
521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump         diag::err_class_redeclared_with_different_access)
53c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson      << MemberDecl << LexicalAS;
54c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson    Diag(PrevMemberDecl->getLocation(), diag::note_previous_access_declaration)
55c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson      << PrevMemberDecl << PrevMemberDecl->getAccess();
5644e067bd8f923ba8e7c24b2189e06717d70015c8John McCall
5744e067bd8f923ba8e7c24b2189e06717d70015c8John McCall    MemberDecl->setAccess(LexicalAS);
58c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson    return true;
59c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson  }
601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
61c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson  MemberDecl->setAccess(PrevMemberDecl->getAccess());
62c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson  return false;
63c60e88819a273d54faa71a2cd6c3d79dd48c12e0Anders Carlsson}
6429f006be830fbbcaa0c1cf7c7399bb5080dc7f32Anders Carlsson
65161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic CXXRecordDecl *FindDeclaringClass(NamedDecl *D) {
66161755a09898c95d21bfff33707da9ca41cd53c5John McCall  DeclContext *DC = D->getDeclContext();
67161755a09898c95d21bfff33707da9ca41cd53c5John McCall
68161755a09898c95d21bfff33707da9ca41cd53c5John McCall  // This can only happen at top: enum decls only "publish" their
69161755a09898c95d21bfff33707da9ca41cd53c5John McCall  // immediate members.
70161755a09898c95d21bfff33707da9ca41cd53c5John McCall  if (isa<EnumDecl>(DC))
71161755a09898c95d21bfff33707da9ca41cd53c5John McCall    DC = cast<EnumDecl>(DC)->getDeclContext();
72161755a09898c95d21bfff33707da9ca41cd53c5John McCall
73161755a09898c95d21bfff33707da9ca41cd53c5John McCall  CXXRecordDecl *DeclaringClass = cast<CXXRecordDecl>(DC);
74161755a09898c95d21bfff33707da9ca41cd53c5John McCall  while (DeclaringClass->isAnonymousStructOrUnion())
75161755a09898c95d21bfff33707da9ca41cd53c5John McCall    DeclaringClass = cast<CXXRecordDecl>(DeclaringClass->getDeclContext());
76161755a09898c95d21bfff33707da9ca41cd53c5John McCall  return DeclaringClass;
77161755a09898c95d21bfff33707da9ca41cd53c5John McCall}
78161755a09898c95d21bfff33707da9ca41cd53c5John McCall
796b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallnamespace {
806b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallstruct EffectiveContext {
812cc2675d426af23476a9722c08c1b6c5266bd653John McCall  EffectiveContext() : Inner(0), Dependent(false) {}
826b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
837ad650f88ecbbe659f10f9f6b34a1f29ea9cf8f9John McCall  explicit EffectiveContext(DeclContext *DC)
847ad650f88ecbbe659f10f9f6b34a1f29ea9cf8f9John McCall    : Inner(DC),
857ad650f88ecbbe659f10f9f6b34a1f29ea9cf8f9John McCall      Dependent(DC->isDependentContext()) {
860c01d18094100db92d38daa923c95661512db203John McCall
8788b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall    // C++ [class.access.nest]p1:
8888b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall    //   A nested class is a member and as such has the same access
8988b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall    //   rights as any other member.
9088b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall    // C++ [class.access]p2:
9188b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall    //   A member of a class can also access all the names to which
922cc2675d426af23476a9722c08c1b6c5266bd653John McCall    //   the class has access.  A local class of a member function
932cc2675d426af23476a9722c08c1b6c5266bd653John McCall    //   may access the same names that the member function itself
942cc2675d426af23476a9722c08c1b6c5266bd653John McCall    //   may access.
952cc2675d426af23476a9722c08c1b6c5266bd653John McCall    // This almost implies that the privileges of nesting are transitive.
962cc2675d426af23476a9722c08c1b6c5266bd653John McCall    // Technically it says nothing about the local classes of non-member
972cc2675d426af23476a9722c08c1b6c5266bd653John McCall    // functions (which can gain privileges through friendship), but we
982cc2675d426af23476a9722c08c1b6c5266bd653John McCall    // take that as an oversight.
992cc2675d426af23476a9722c08c1b6c5266bd653John McCall    while (true) {
1008bddeb57d134c0e5f14e319271aa9015886a8ac7John McCall      // We want to add canonical declarations to the EC lists for
1018bddeb57d134c0e5f14e319271aa9015886a8ac7John McCall      // simplicity of checking, but we need to walk up through the
1028bddeb57d134c0e5f14e319271aa9015886a8ac7John McCall      // actual current DC chain.  Otherwise, something like a local
1038bddeb57d134c0e5f14e319271aa9015886a8ac7John McCall      // extern or friend which happens to be the canonical
1048bddeb57d134c0e5f14e319271aa9015886a8ac7John McCall      // declaration will really mess us up.
1058bddeb57d134c0e5f14e319271aa9015886a8ac7John McCall
1062cc2675d426af23476a9722c08c1b6c5266bd653John McCall      if (isa<CXXRecordDecl>(DC)) {
1078bddeb57d134c0e5f14e319271aa9015886a8ac7John McCall        CXXRecordDecl *Record = cast<CXXRecordDecl>(DC);
1088bddeb57d134c0e5f14e319271aa9015886a8ac7John McCall        Records.push_back(Record->getCanonicalDecl());
1092cc2675d426af23476a9722c08c1b6c5266bd653John McCall        DC = Record->getDeclContext();
1102cc2675d426af23476a9722c08c1b6c5266bd653John McCall      } else if (isa<FunctionDecl>(DC)) {
1118bddeb57d134c0e5f14e319271aa9015886a8ac7John McCall        FunctionDecl *Function = cast<FunctionDecl>(DC);
1128bddeb57d134c0e5f14e319271aa9015886a8ac7John McCall        Functions.push_back(Function->getCanonicalDecl());
113ac57f0b9097e04f70a631549383a2944f74ad844Douglas Gregor        if (Function->getFriendObjectKind())
114ac57f0b9097e04f70a631549383a2944f74ad844Douglas Gregor          DC = Function->getLexicalDeclContext();
115ac57f0b9097e04f70a631549383a2944f74ad844Douglas Gregor        else
116ac57f0b9097e04f70a631549383a2944f74ad844Douglas Gregor          DC = Function->getDeclContext();
1172cc2675d426af23476a9722c08c1b6c5266bd653John McCall      } else if (DC->isFileContext()) {
1182cc2675d426af23476a9722c08c1b6c5266bd653John McCall        break;
1192cc2675d426af23476a9722c08c1b6c5266bd653John McCall      } else {
1202cc2675d426af23476a9722c08c1b6c5266bd653John McCall        DC = DC->getParent();
1212cc2675d426af23476a9722c08c1b6c5266bd653John McCall      }
12288b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall    }
1236b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  }
1246b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
1250c01d18094100db92d38daa923c95661512db203John McCall  bool isDependent() const { return Dependent; }
1260c01d18094100db92d38daa923c95661512db203John McCall
12788b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall  bool includesClass(const CXXRecordDecl *R) const {
12888b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall    R = R->getCanonicalDecl();
12988b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall    return std::find(Records.begin(), Records.end(), R)
13088b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall             != Records.end();
1316b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  }
1326b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
1337ad650f88ecbbe659f10f9f6b34a1f29ea9cf8f9John McCall  /// Retrieves the innermost "useful" context.  Can be null if we're
1347ad650f88ecbbe659f10f9f6b34a1f29ea9cf8f9John McCall  /// doing access-control without privileges.
1357ad650f88ecbbe659f10f9f6b34a1f29ea9cf8f9John McCall  DeclContext *getInnerContext() const {
1367ad650f88ecbbe659f10f9f6b34a1f29ea9cf8f9John McCall    return Inner;
1370c01d18094100db92d38daa923c95661512db203John McCall  }
1380c01d18094100db92d38daa923c95661512db203John McCall
1395f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  typedef SmallVectorImpl<CXXRecordDecl*>::const_iterator record_iterator;
1400c01d18094100db92d38daa923c95661512db203John McCall
1417ad650f88ecbbe659f10f9f6b34a1f29ea9cf8f9John McCall  DeclContext *Inner;
1425f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  SmallVector<FunctionDecl*, 4> Functions;
1435f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  SmallVector<CXXRecordDecl*, 4> Records;
1440c01d18094100db92d38daa923c95661512db203John McCall  bool Dependent;
1456b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall};
146161755a09898c95d21bfff33707da9ca41cd53c5John McCall
1476bb4dcb412d53d05a80017df81d41e447e2aa3eaNico Weber/// Like sema::AccessedEntity, but kindly lets us scribble all over
148161755a09898c95d21bfff33707da9ca41cd53c5John McCall/// it.
1499c3087b0b0bea2fd782205c1274ebfc4290265e0John McCallstruct AccessTarget : public AccessedEntity {
1509c3087b0b0bea2fd782205c1274ebfc4290265e0John McCall  AccessTarget(const AccessedEntity &Entity)
151161755a09898c95d21bfff33707da9ca41cd53c5John McCall    : AccessedEntity(Entity) {
152161755a09898c95d21bfff33707da9ca41cd53c5John McCall    initialize();
153161755a09898c95d21bfff33707da9ca41cd53c5John McCall  }
154161755a09898c95d21bfff33707da9ca41cd53c5John McCall
155161755a09898c95d21bfff33707da9ca41cd53c5John McCall  AccessTarget(ASTContext &Context,
156161755a09898c95d21bfff33707da9ca41cd53c5John McCall               MemberNonce _,
157161755a09898c95d21bfff33707da9ca41cd53c5John McCall               CXXRecordDecl *NamingClass,
158161755a09898c95d21bfff33707da9ca41cd53c5John McCall               DeclAccessPair FoundDecl,
15924dd9ad9001d1aa16223de135d7e4ed34e94b207Erik Verbruggen               QualType BaseObjectType)
160478851c3ed6bd784e7377dffd8e57b200c1b9ba9Benjamin Kramer    : AccessedEntity(Context.getDiagAllocator(), Member, NamingClass,
161478851c3ed6bd784e7377dffd8e57b200c1b9ba9Benjamin Kramer                     FoundDecl, BaseObjectType) {
162161755a09898c95d21bfff33707da9ca41cd53c5John McCall    initialize();
163161755a09898c95d21bfff33707da9ca41cd53c5John McCall  }
164161755a09898c95d21bfff33707da9ca41cd53c5John McCall
165161755a09898c95d21bfff33707da9ca41cd53c5John McCall  AccessTarget(ASTContext &Context,
166161755a09898c95d21bfff33707da9ca41cd53c5John McCall               BaseNonce _,
167161755a09898c95d21bfff33707da9ca41cd53c5John McCall               CXXRecordDecl *BaseClass,
168161755a09898c95d21bfff33707da9ca41cd53c5John McCall               CXXRecordDecl *DerivedClass,
169161755a09898c95d21bfff33707da9ca41cd53c5John McCall               AccessSpecifier Access)
170478851c3ed6bd784e7377dffd8e57b200c1b9ba9Benjamin Kramer    : AccessedEntity(Context.getDiagAllocator(), Base, BaseClass, DerivedClass,
171478851c3ed6bd784e7377dffd8e57b200c1b9ba9Benjamin Kramer                     Access) {
172161755a09898c95d21bfff33707da9ca41cd53c5John McCall    initialize();
173161755a09898c95d21bfff33707da9ca41cd53c5John McCall  }
174161755a09898c95d21bfff33707da9ca41cd53c5John McCall
175b9abd87283ac6e929b7e12a577663bc99e61d020John McCall  bool isInstanceMember() const {
176b9abd87283ac6e929b7e12a577663bc99e61d020John McCall    return (isMemberAccess() && getTargetDecl()->isCXXInstanceMember());
177b9abd87283ac6e929b7e12a577663bc99e61d020John McCall  }
178b9abd87283ac6e929b7e12a577663bc99e61d020John McCall
179161755a09898c95d21bfff33707da9ca41cd53c5John McCall  bool hasInstanceContext() const {
180161755a09898c95d21bfff33707da9ca41cd53c5John McCall    return HasInstanceContext;
181161755a09898c95d21bfff33707da9ca41cd53c5John McCall  }
182161755a09898c95d21bfff33707da9ca41cd53c5John McCall
183161755a09898c95d21bfff33707da9ca41cd53c5John McCall  class SavedInstanceContext {
184161755a09898c95d21bfff33707da9ca41cd53c5John McCall  public:
185161755a09898c95d21bfff33707da9ca41cd53c5John McCall    ~SavedInstanceContext() {
186161755a09898c95d21bfff33707da9ca41cd53c5John McCall      Target.HasInstanceContext = Has;
187161755a09898c95d21bfff33707da9ca41cd53c5John McCall    }
188161755a09898c95d21bfff33707da9ca41cd53c5John McCall
189161755a09898c95d21bfff33707da9ca41cd53c5John McCall  private:
190c91cc66e92b084acd1fdbaa1c3c74242741b3d46John McCall    friend struct AccessTarget;
191161755a09898c95d21bfff33707da9ca41cd53c5John McCall    explicit SavedInstanceContext(AccessTarget &Target)
192161755a09898c95d21bfff33707da9ca41cd53c5John McCall      : Target(Target), Has(Target.HasInstanceContext) {}
193161755a09898c95d21bfff33707da9ca41cd53c5John McCall    AccessTarget &Target;
194161755a09898c95d21bfff33707da9ca41cd53c5John McCall    bool Has;
195161755a09898c95d21bfff33707da9ca41cd53c5John McCall  };
196161755a09898c95d21bfff33707da9ca41cd53c5John McCall
197161755a09898c95d21bfff33707da9ca41cd53c5John McCall  SavedInstanceContext saveInstanceContext() {
198161755a09898c95d21bfff33707da9ca41cd53c5John McCall    return SavedInstanceContext(*this);
199161755a09898c95d21bfff33707da9ca41cd53c5John McCall  }
200161755a09898c95d21bfff33707da9ca41cd53c5John McCall
201161755a09898c95d21bfff33707da9ca41cd53c5John McCall  void suppressInstanceContext() {
202161755a09898c95d21bfff33707da9ca41cd53c5John McCall    HasInstanceContext = false;
203161755a09898c95d21bfff33707da9ca41cd53c5John McCall  }
204161755a09898c95d21bfff33707da9ca41cd53c5John McCall
205161755a09898c95d21bfff33707da9ca41cd53c5John McCall  const CXXRecordDecl *resolveInstanceContext(Sema &S) const {
206161755a09898c95d21bfff33707da9ca41cd53c5John McCall    assert(HasInstanceContext);
207161755a09898c95d21bfff33707da9ca41cd53c5John McCall    if (CalculatedInstanceContext)
208161755a09898c95d21bfff33707da9ca41cd53c5John McCall      return InstanceContext;
209161755a09898c95d21bfff33707da9ca41cd53c5John McCall
210161755a09898c95d21bfff33707da9ca41cd53c5John McCall    CalculatedInstanceContext = true;
211161755a09898c95d21bfff33707da9ca41cd53c5John McCall    DeclContext *IC = S.computeDeclContext(getBaseObjectType());
212161755a09898c95d21bfff33707da9ca41cd53c5John McCall    InstanceContext = (IC ? cast<CXXRecordDecl>(IC)->getCanonicalDecl() : 0);
213161755a09898c95d21bfff33707da9ca41cd53c5John McCall    return InstanceContext;
214161755a09898c95d21bfff33707da9ca41cd53c5John McCall  }
215161755a09898c95d21bfff33707da9ca41cd53c5John McCall
216161755a09898c95d21bfff33707da9ca41cd53c5John McCall  const CXXRecordDecl *getDeclaringClass() const {
217161755a09898c95d21bfff33707da9ca41cd53c5John McCall    return DeclaringClass;
218161755a09898c95d21bfff33707da9ca41cd53c5John McCall  }
219161755a09898c95d21bfff33707da9ca41cd53c5John McCall
220161755a09898c95d21bfff33707da9ca41cd53c5John McCallprivate:
221161755a09898c95d21bfff33707da9ca41cd53c5John McCall  void initialize() {
222161755a09898c95d21bfff33707da9ca41cd53c5John McCall    HasInstanceContext = (isMemberAccess() &&
223161755a09898c95d21bfff33707da9ca41cd53c5John McCall                          !getBaseObjectType().isNull() &&
224161755a09898c95d21bfff33707da9ca41cd53c5John McCall                          getTargetDecl()->isCXXInstanceMember());
225161755a09898c95d21bfff33707da9ca41cd53c5John McCall    CalculatedInstanceContext = false;
226161755a09898c95d21bfff33707da9ca41cd53c5John McCall    InstanceContext = 0;
227161755a09898c95d21bfff33707da9ca41cd53c5John McCall
228161755a09898c95d21bfff33707da9ca41cd53c5John McCall    if (isMemberAccess())
229161755a09898c95d21bfff33707da9ca41cd53c5John McCall      DeclaringClass = FindDeclaringClass(getTargetDecl());
230161755a09898c95d21bfff33707da9ca41cd53c5John McCall    else
231161755a09898c95d21bfff33707da9ca41cd53c5John McCall      DeclaringClass = getBaseClass();
232161755a09898c95d21bfff33707da9ca41cd53c5John McCall    DeclaringClass = DeclaringClass->getCanonicalDecl();
233161755a09898c95d21bfff33707da9ca41cd53c5John McCall  }
234161755a09898c95d21bfff33707da9ca41cd53c5John McCall
235161755a09898c95d21bfff33707da9ca41cd53c5John McCall  bool HasInstanceContext : 1;
236161755a09898c95d21bfff33707da9ca41cd53c5John McCall  mutable bool CalculatedInstanceContext : 1;
237161755a09898c95d21bfff33707da9ca41cd53c5John McCall  mutable const CXXRecordDecl *InstanceContext;
238161755a09898c95d21bfff33707da9ca41cd53c5John McCall  const CXXRecordDecl *DeclaringClass;
239161755a09898c95d21bfff33707da9ca41cd53c5John McCall};
240161755a09898c95d21bfff33707da9ca41cd53c5John McCall
2416b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall}
242726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl
24301ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall/// Checks whether one class might instantiate to the other.
24401ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCallstatic bool MightInstantiateTo(const CXXRecordDecl *From,
24501ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall                               const CXXRecordDecl *To) {
24601ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall  // Declaration names are always preserved by instantiation.
24701ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall  if (From->getDeclName() != To->getDeclName())
24801ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall    return false;
24901ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall
25001ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall  const DeclContext *FromDC = From->getDeclContext()->getPrimaryContext();
25101ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall  const DeclContext *ToDC = To->getDeclContext()->getPrimaryContext();
25201ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall  if (FromDC == ToDC) return true;
25301ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall  if (FromDC->isFileContext() || ToDC->isFileContext()) return false;
25401ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall
25501ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall  // Be conservative.
25601ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall  return true;
25701ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall}
25801ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall
259161755a09898c95d21bfff33707da9ca41cd53c5John McCall/// Checks whether one class is derived from another, inclusively.
260161755a09898c95d21bfff33707da9ca41cd53c5John McCall/// Properly indicates when it couldn't be determined due to
261161755a09898c95d21bfff33707da9ca41cd53c5John McCall/// dependence.
262161755a09898c95d21bfff33707da9ca41cd53c5John McCall///
263161755a09898c95d21bfff33707da9ca41cd53c5John McCall/// This should probably be donated to AST or at least Sema.
264161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic AccessResult IsDerivedFromInclusive(const CXXRecordDecl *Derived,
265161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                           const CXXRecordDecl *Target) {
266161755a09898c95d21bfff33707da9ca41cd53c5John McCall  assert(Derived->getCanonicalDecl() == Derived);
267161755a09898c95d21bfff33707da9ca41cd53c5John McCall  assert(Target->getCanonicalDecl() == Target);
268c1b621daf98d83075a466c6f4ad9904dc845dd09John McCall
269161755a09898c95d21bfff33707da9ca41cd53c5John McCall  if (Derived == Target) return AR_accessible;
270c1b621daf98d83075a466c6f4ad9904dc845dd09John McCall
27101ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall  bool CheckDependent = Derived->isDependentContext();
27201ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall  if (CheckDependent && MightInstantiateTo(Derived, Target))
27301ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall    return AR_dependent;
27401ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall
275161755a09898c95d21bfff33707da9ca41cd53c5John McCall  AccessResult OnFailure = AR_inaccessible;
2765f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  SmallVector<const CXXRecordDecl*, 8> Queue; // actually a stack
277161755a09898c95d21bfff33707da9ca41cd53c5John McCall
278161755a09898c95d21bfff33707da9ca41cd53c5John McCall  while (true) {
2797432b90e88ac9e219f6e8a3151c097b0b7da933cDouglas Gregor    if (Derived->isDependentContext() && !Derived->hasDefinition())
2807432b90e88ac9e219f6e8a3151c097b0b7da933cDouglas Gregor      return AR_dependent;
2817432b90e88ac9e219f6e8a3151c097b0b7da933cDouglas Gregor
282161755a09898c95d21bfff33707da9ca41cd53c5John McCall    for (CXXRecordDecl::base_class_const_iterator
283161755a09898c95d21bfff33707da9ca41cd53c5John McCall           I = Derived->bases_begin(), E = Derived->bases_end(); I != E; ++I) {
284161755a09898c95d21bfff33707da9ca41cd53c5John McCall
285161755a09898c95d21bfff33707da9ca41cd53c5John McCall      const CXXRecordDecl *RD;
286161755a09898c95d21bfff33707da9ca41cd53c5John McCall
287161755a09898c95d21bfff33707da9ca41cd53c5John McCall      QualType T = I->getType();
288161755a09898c95d21bfff33707da9ca41cd53c5John McCall      if (const RecordType *RT = T->getAs<RecordType>()) {
289161755a09898c95d21bfff33707da9ca41cd53c5John McCall        RD = cast<CXXRecordDecl>(RT->getDecl());
29001ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall      } else if (const InjectedClassNameType *IT
29101ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall                   = T->getAs<InjectedClassNameType>()) {
29201ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall        RD = IT->getDecl();
293161755a09898c95d21bfff33707da9ca41cd53c5John McCall      } else {
294161755a09898c95d21bfff33707da9ca41cd53c5John McCall        assert(T->isDependentType() && "non-dependent base wasn't a record?");
295161755a09898c95d21bfff33707da9ca41cd53c5John McCall        OnFailure = AR_dependent;
296161755a09898c95d21bfff33707da9ca41cd53c5John McCall        continue;
297161755a09898c95d21bfff33707da9ca41cd53c5John McCall      }
298161755a09898c95d21bfff33707da9ca41cd53c5John McCall
299161755a09898c95d21bfff33707da9ca41cd53c5John McCall      RD = RD->getCanonicalDecl();
300161755a09898c95d21bfff33707da9ca41cd53c5John McCall      if (RD == Target) return AR_accessible;
30101ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall      if (CheckDependent && MightInstantiateTo(RD, Target))
30201ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall        OnFailure = AR_dependent;
30301ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall
304161755a09898c95d21bfff33707da9ca41cd53c5John McCall      Queue.push_back(RD);
305161755a09898c95d21bfff33707da9ca41cd53c5John McCall    }
306161755a09898c95d21bfff33707da9ca41cd53c5John McCall
307161755a09898c95d21bfff33707da9ca41cd53c5John McCall    if (Queue.empty()) break;
308161755a09898c95d21bfff33707da9ca41cd53c5John McCall
309161755a09898c95d21bfff33707da9ca41cd53c5John McCall    Derived = Queue.back();
310161755a09898c95d21bfff33707da9ca41cd53c5John McCall    Queue.pop_back();
311161755a09898c95d21bfff33707da9ca41cd53c5John McCall  }
312161755a09898c95d21bfff33707da9ca41cd53c5John McCall
313161755a09898c95d21bfff33707da9ca41cd53c5John McCall  return OnFailure;
3146b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall}
3156b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
316161755a09898c95d21bfff33707da9ca41cd53c5John McCall
3170c01d18094100db92d38daa923c95661512db203John McCallstatic bool MightInstantiateTo(Sema &S, DeclContext *Context,
3180c01d18094100db92d38daa923c95661512db203John McCall                               DeclContext *Friend) {
3190c01d18094100db92d38daa923c95661512db203John McCall  if (Friend == Context)
3200c01d18094100db92d38daa923c95661512db203John McCall    return true;
3210c01d18094100db92d38daa923c95661512db203John McCall
3220c01d18094100db92d38daa923c95661512db203John McCall  assert(!Friend->isDependentContext() &&
3230c01d18094100db92d38daa923c95661512db203John McCall         "can't handle friends with dependent contexts here");
3240c01d18094100db92d38daa923c95661512db203John McCall
3250c01d18094100db92d38daa923c95661512db203John McCall  if (!Context->isDependentContext())
3260c01d18094100db92d38daa923c95661512db203John McCall    return false;
3270c01d18094100db92d38daa923c95661512db203John McCall
3280c01d18094100db92d38daa923c95661512db203John McCall  if (Friend->isFileContext())
3290c01d18094100db92d38daa923c95661512db203John McCall    return false;
3300c01d18094100db92d38daa923c95661512db203John McCall
3310c01d18094100db92d38daa923c95661512db203John McCall  // TODO: this is very conservative
3320c01d18094100db92d38daa923c95661512db203John McCall  return true;
3330c01d18094100db92d38daa923c95661512db203John McCall}
3340c01d18094100db92d38daa923c95661512db203John McCall
3350c01d18094100db92d38daa923c95661512db203John McCall// Asks whether the type in 'context' can ever instantiate to the type
3360c01d18094100db92d38daa923c95661512db203John McCall// in 'friend'.
3370c01d18094100db92d38daa923c95661512db203John McCallstatic bool MightInstantiateTo(Sema &S, CanQualType Context, CanQualType Friend) {
3380c01d18094100db92d38daa923c95661512db203John McCall  if (Friend == Context)
3390c01d18094100db92d38daa923c95661512db203John McCall    return true;
3400c01d18094100db92d38daa923c95661512db203John McCall
3410c01d18094100db92d38daa923c95661512db203John McCall  if (!Friend->isDependentType() && !Context->isDependentType())
3420c01d18094100db92d38daa923c95661512db203John McCall    return false;
3430c01d18094100db92d38daa923c95661512db203John McCall
3440c01d18094100db92d38daa923c95661512db203John McCall  // TODO: this is very conservative.
3450c01d18094100db92d38daa923c95661512db203John McCall  return true;
3460c01d18094100db92d38daa923c95661512db203John McCall}
3470c01d18094100db92d38daa923c95661512db203John McCall
3480c01d18094100db92d38daa923c95661512db203John McCallstatic bool MightInstantiateTo(Sema &S,
3490c01d18094100db92d38daa923c95661512db203John McCall                               FunctionDecl *Context,
3500c01d18094100db92d38daa923c95661512db203John McCall                               FunctionDecl *Friend) {
3510c01d18094100db92d38daa923c95661512db203John McCall  if (Context->getDeclName() != Friend->getDeclName())
3520c01d18094100db92d38daa923c95661512db203John McCall    return false;
3530c01d18094100db92d38daa923c95661512db203John McCall
3540c01d18094100db92d38daa923c95661512db203John McCall  if (!MightInstantiateTo(S,
3550c01d18094100db92d38daa923c95661512db203John McCall                          Context->getDeclContext(),
3560c01d18094100db92d38daa923c95661512db203John McCall                          Friend->getDeclContext()))
3570c01d18094100db92d38daa923c95661512db203John McCall    return false;
3580c01d18094100db92d38daa923c95661512db203John McCall
3590c01d18094100db92d38daa923c95661512db203John McCall  CanQual<FunctionProtoType> FriendTy
3600c01d18094100db92d38daa923c95661512db203John McCall    = S.Context.getCanonicalType(Friend->getType())
3610c01d18094100db92d38daa923c95661512db203John McCall         ->getAs<FunctionProtoType>();
3620c01d18094100db92d38daa923c95661512db203John McCall  CanQual<FunctionProtoType> ContextTy
3630c01d18094100db92d38daa923c95661512db203John McCall    = S.Context.getCanonicalType(Context->getType())
3640c01d18094100db92d38daa923c95661512db203John McCall         ->getAs<FunctionProtoType>();
3650c01d18094100db92d38daa923c95661512db203John McCall
3660c01d18094100db92d38daa923c95661512db203John McCall  // There isn't any way that I know of to add qualifiers
3670c01d18094100db92d38daa923c95661512db203John McCall  // during instantiation.
3680c01d18094100db92d38daa923c95661512db203John McCall  if (FriendTy.getQualifiers() != ContextTy.getQualifiers())
3690c01d18094100db92d38daa923c95661512db203John McCall    return false;
3700c01d18094100db92d38daa923c95661512db203John McCall
3710c01d18094100db92d38daa923c95661512db203John McCall  if (FriendTy->getNumArgs() != ContextTy->getNumArgs())
3720c01d18094100db92d38daa923c95661512db203John McCall    return false;
3730c01d18094100db92d38daa923c95661512db203John McCall
3740c01d18094100db92d38daa923c95661512db203John McCall  if (!MightInstantiateTo(S,
3750c01d18094100db92d38daa923c95661512db203John McCall                          ContextTy->getResultType(),
3760c01d18094100db92d38daa923c95661512db203John McCall                          FriendTy->getResultType()))
3770c01d18094100db92d38daa923c95661512db203John McCall    return false;
3780c01d18094100db92d38daa923c95661512db203John McCall
3790c01d18094100db92d38daa923c95661512db203John McCall  for (unsigned I = 0, E = FriendTy->getNumArgs(); I != E; ++I)
3800c01d18094100db92d38daa923c95661512db203John McCall    if (!MightInstantiateTo(S,
3810c01d18094100db92d38daa923c95661512db203John McCall                            ContextTy->getArgType(I),
3820c01d18094100db92d38daa923c95661512db203John McCall                            FriendTy->getArgType(I)))
3830c01d18094100db92d38daa923c95661512db203John McCall      return false;
3840c01d18094100db92d38daa923c95661512db203John McCall
3850c01d18094100db92d38daa923c95661512db203John McCall  return true;
3860c01d18094100db92d38daa923c95661512db203John McCall}
3870c01d18094100db92d38daa923c95661512db203John McCall
3880c01d18094100db92d38daa923c95661512db203John McCallstatic bool MightInstantiateTo(Sema &S,
3890c01d18094100db92d38daa923c95661512db203John McCall                               FunctionTemplateDecl *Context,
3900c01d18094100db92d38daa923c95661512db203John McCall                               FunctionTemplateDecl *Friend) {
3910c01d18094100db92d38daa923c95661512db203John McCall  return MightInstantiateTo(S,
3920c01d18094100db92d38daa923c95661512db203John McCall                            Context->getTemplatedDecl(),
3930c01d18094100db92d38daa923c95661512db203John McCall                            Friend->getTemplatedDecl());
3940c01d18094100db92d38daa923c95661512db203John McCall}
3950c01d18094100db92d38daa923c95661512db203John McCall
396161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic AccessResult MatchesFriend(Sema &S,
397161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                  const EffectiveContext &EC,
398161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                  const CXXRecordDecl *Friend) {
399a742db0032d8f458fe229600d2082981a1fb1481John McCall  if (EC.includesClass(Friend))
400161755a09898c95d21bfff33707da9ca41cd53c5John McCall    return AR_accessible;
401a742db0032d8f458fe229600d2082981a1fb1481John McCall
4020c01d18094100db92d38daa923c95661512db203John McCall  if (EC.isDependent()) {
4030c01d18094100db92d38daa923c95661512db203John McCall    CanQualType FriendTy
4040c01d18094100db92d38daa923c95661512db203John McCall      = S.Context.getCanonicalType(S.Context.getTypeDeclType(Friend));
4050c01d18094100db92d38daa923c95661512db203John McCall
4060c01d18094100db92d38daa923c95661512db203John McCall    for (EffectiveContext::record_iterator
4070c01d18094100db92d38daa923c95661512db203John McCall           I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
4080c01d18094100db92d38daa923c95661512db203John McCall      CanQualType ContextTy
4090c01d18094100db92d38daa923c95661512db203John McCall        = S.Context.getCanonicalType(S.Context.getTypeDeclType(*I));
4100c01d18094100db92d38daa923c95661512db203John McCall      if (MightInstantiateTo(S, ContextTy, FriendTy))
411161755a09898c95d21bfff33707da9ca41cd53c5John McCall        return AR_dependent;
4120c01d18094100db92d38daa923c95661512db203John McCall    }
4130c01d18094100db92d38daa923c95661512db203John McCall  }
4140c01d18094100db92d38daa923c95661512db203John McCall
415161755a09898c95d21bfff33707da9ca41cd53c5John McCall  return AR_inaccessible;
416a742db0032d8f458fe229600d2082981a1fb1481John McCall}
417a742db0032d8f458fe229600d2082981a1fb1481John McCall
418161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic AccessResult MatchesFriend(Sema &S,
419161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                  const EffectiveContext &EC,
420161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                  CanQualType Friend) {
4210c01d18094100db92d38daa923c95661512db203John McCall  if (const RecordType *RT = Friend->getAs<RecordType>())
4220c01d18094100db92d38daa923c95661512db203John McCall    return MatchesFriend(S, EC, cast<CXXRecordDecl>(RT->getDecl()));
423a742db0032d8f458fe229600d2082981a1fb1481John McCall
4240c01d18094100db92d38daa923c95661512db203John McCall  // TODO: we can do better than this
4250c01d18094100db92d38daa923c95661512db203John McCall  if (Friend->isDependentType())
426161755a09898c95d21bfff33707da9ca41cd53c5John McCall    return AR_dependent;
427a742db0032d8f458fe229600d2082981a1fb1481John McCall
428161755a09898c95d21bfff33707da9ca41cd53c5John McCall  return AR_inaccessible;
4290c01d18094100db92d38daa923c95661512db203John McCall}
430a742db0032d8f458fe229600d2082981a1fb1481John McCall
4310c01d18094100db92d38daa923c95661512db203John McCall/// Determines whether the given friend class template matches
4320c01d18094100db92d38daa923c95661512db203John McCall/// anything in the effective context.
433161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic AccessResult MatchesFriend(Sema &S,
434161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                  const EffectiveContext &EC,
435161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                  ClassTemplateDecl *Friend) {
436161755a09898c95d21bfff33707da9ca41cd53c5John McCall  AccessResult OnFailure = AR_inaccessible;
437a742db0032d8f458fe229600d2082981a1fb1481John McCall
43893ba8579c341d5329175f1413cdc3b35a36592d2John McCall  // Check whether the friend is the template of a class in the
43993ba8579c341d5329175f1413cdc3b35a36592d2John McCall  // context chain.
4405f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  for (SmallVectorImpl<CXXRecordDecl*>::const_iterator
4410c01d18094100db92d38daa923c95661512db203John McCall         I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
4420c01d18094100db92d38daa923c95661512db203John McCall    CXXRecordDecl *Record = *I;
443a742db0032d8f458fe229600d2082981a1fb1481John McCall
44493ba8579c341d5329175f1413cdc3b35a36592d2John McCall    // Figure out whether the current class has a template:
4450c01d18094100db92d38daa923c95661512db203John McCall    ClassTemplateDecl *CTD;
446a742db0032d8f458fe229600d2082981a1fb1481John McCall
4470c01d18094100db92d38daa923c95661512db203John McCall    // A specialization of the template...
4480c01d18094100db92d38daa923c95661512db203John McCall    if (isa<ClassTemplateSpecializationDecl>(Record)) {
4490c01d18094100db92d38daa923c95661512db203John McCall      CTD = cast<ClassTemplateSpecializationDecl>(Record)
4500c01d18094100db92d38daa923c95661512db203John McCall        ->getSpecializedTemplate();
451a742db0032d8f458fe229600d2082981a1fb1481John McCall
4520c01d18094100db92d38daa923c95661512db203John McCall    // ... or the template pattern itself.
4530c01d18094100db92d38daa923c95661512db203John McCall    } else {
4540c01d18094100db92d38daa923c95661512db203John McCall      CTD = Record->getDescribedClassTemplate();
4550c01d18094100db92d38daa923c95661512db203John McCall      if (!CTD) continue;
456a742db0032d8f458fe229600d2082981a1fb1481John McCall    }
457a742db0032d8f458fe229600d2082981a1fb1481John McCall
4580c01d18094100db92d38daa923c95661512db203John McCall    // It's a match.
4590c01d18094100db92d38daa923c95661512db203John McCall    if (Friend == CTD->getCanonicalDecl())
460161755a09898c95d21bfff33707da9ca41cd53c5John McCall      return AR_accessible;
4610c01d18094100db92d38daa923c95661512db203John McCall
46293ba8579c341d5329175f1413cdc3b35a36592d2John McCall    // If the context isn't dependent, it can't be a dependent match.
46393ba8579c341d5329175f1413cdc3b35a36592d2John McCall    if (!EC.isDependent())
46493ba8579c341d5329175f1413cdc3b35a36592d2John McCall      continue;
46593ba8579c341d5329175f1413cdc3b35a36592d2John McCall
4660c01d18094100db92d38daa923c95661512db203John McCall    // If the template names don't match, it can't be a dependent
4673e4c6c4c79a03f5cb0c4671d7c282d623c6dc35eRichard Smith    // match.
4683e4c6c4c79a03f5cb0c4671d7c282d623c6dc35eRichard Smith    if (CTD->getDeclName() != Friend->getDeclName())
4690c01d18094100db92d38daa923c95661512db203John McCall      continue;
4700c01d18094100db92d38daa923c95661512db203John McCall
4710c01d18094100db92d38daa923c95661512db203John McCall    // If the class's context can't instantiate to the friend's
4720c01d18094100db92d38daa923c95661512db203John McCall    // context, it can't be a dependent match.
4730c01d18094100db92d38daa923c95661512db203John McCall    if (!MightInstantiateTo(S, CTD->getDeclContext(),
4740c01d18094100db92d38daa923c95661512db203John McCall                            Friend->getDeclContext()))
4750c01d18094100db92d38daa923c95661512db203John McCall      continue;
4760c01d18094100db92d38daa923c95661512db203John McCall
4770c01d18094100db92d38daa923c95661512db203John McCall    // Otherwise, it's a dependent match.
478161755a09898c95d21bfff33707da9ca41cd53c5John McCall    OnFailure = AR_dependent;
479a742db0032d8f458fe229600d2082981a1fb1481John McCall  }
480a742db0032d8f458fe229600d2082981a1fb1481John McCall
4810c01d18094100db92d38daa923c95661512db203John McCall  return OnFailure;
4820c01d18094100db92d38daa923c95661512db203John McCall}
483a742db0032d8f458fe229600d2082981a1fb1481John McCall
4840c01d18094100db92d38daa923c95661512db203John McCall/// Determines whether the given friend function matches anything in
4850c01d18094100db92d38daa923c95661512db203John McCall/// the effective context.
486161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic AccessResult MatchesFriend(Sema &S,
487161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                  const EffectiveContext &EC,
488161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                  FunctionDecl *Friend) {
489161755a09898c95d21bfff33707da9ca41cd53c5John McCall  AccessResult OnFailure = AR_inaccessible;
490a742db0032d8f458fe229600d2082981a1fb1481John McCall
4915f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  for (SmallVectorImpl<FunctionDecl*>::const_iterator
4922cc2675d426af23476a9722c08c1b6c5266bd653John McCall         I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) {
4932cc2675d426af23476a9722c08c1b6c5266bd653John McCall    if (Friend == *I)
494161755a09898c95d21bfff33707da9ca41cd53c5John McCall      return AR_accessible;
4950c01d18094100db92d38daa923c95661512db203John McCall
4962cc2675d426af23476a9722c08c1b6c5266bd653John McCall    if (EC.isDependent() && MightInstantiateTo(S, *I, Friend))
497161755a09898c95d21bfff33707da9ca41cd53c5John McCall      OnFailure = AR_dependent;
4982cc2675d426af23476a9722c08c1b6c5266bd653John McCall  }
4990c01d18094100db92d38daa923c95661512db203John McCall
5002cc2675d426af23476a9722c08c1b6c5266bd653John McCall  return OnFailure;
5010c01d18094100db92d38daa923c95661512db203John McCall}
5020c01d18094100db92d38daa923c95661512db203John McCall
5030c01d18094100db92d38daa923c95661512db203John McCall/// Determines whether the given friend function template matches
5040c01d18094100db92d38daa923c95661512db203John McCall/// anything in the effective context.
505161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic AccessResult MatchesFriend(Sema &S,
506161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                  const EffectiveContext &EC,
507161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                  FunctionTemplateDecl *Friend) {
508161755a09898c95d21bfff33707da9ca41cd53c5John McCall  if (EC.Functions.empty()) return AR_inaccessible;
5092cc2675d426af23476a9722c08c1b6c5266bd653John McCall
510161755a09898c95d21bfff33707da9ca41cd53c5John McCall  AccessResult OnFailure = AR_inaccessible;
5110c01d18094100db92d38daa923c95661512db203John McCall
5125f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  for (SmallVectorImpl<FunctionDecl*>::const_iterator
5132cc2675d426af23476a9722c08c1b6c5266bd653John McCall         I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) {
514a742db0032d8f458fe229600d2082981a1fb1481John McCall
5152cc2675d426af23476a9722c08c1b6c5266bd653John McCall    FunctionTemplateDecl *FTD = (*I)->getPrimaryTemplate();
5162cc2675d426af23476a9722c08c1b6c5266bd653John McCall    if (!FTD)
5172cc2675d426af23476a9722c08c1b6c5266bd653John McCall      FTD = (*I)->getDescribedFunctionTemplate();
5182cc2675d426af23476a9722c08c1b6c5266bd653John McCall    if (!FTD)
5192cc2675d426af23476a9722c08c1b6c5266bd653John McCall      continue;
520a742db0032d8f458fe229600d2082981a1fb1481John McCall
5212cc2675d426af23476a9722c08c1b6c5266bd653John McCall    FTD = FTD->getCanonicalDecl();
522a742db0032d8f458fe229600d2082981a1fb1481John McCall
5232cc2675d426af23476a9722c08c1b6c5266bd653John McCall    if (Friend == FTD)
524161755a09898c95d21bfff33707da9ca41cd53c5John McCall      return AR_accessible;
5252cc2675d426af23476a9722c08c1b6c5266bd653John McCall
5262cc2675d426af23476a9722c08c1b6c5266bd653John McCall    if (EC.isDependent() && MightInstantiateTo(S, FTD, Friend))
527161755a09898c95d21bfff33707da9ca41cd53c5John McCall      OnFailure = AR_dependent;
5282cc2675d426af23476a9722c08c1b6c5266bd653John McCall  }
5292cc2675d426af23476a9722c08c1b6c5266bd653John McCall
5302cc2675d426af23476a9722c08c1b6c5266bd653John McCall  return OnFailure;
531a742db0032d8f458fe229600d2082981a1fb1481John McCall}
532a742db0032d8f458fe229600d2082981a1fb1481John McCall
5330c01d18094100db92d38daa923c95661512db203John McCall/// Determines whether the given friend declaration matches anything
5340c01d18094100db92d38daa923c95661512db203John McCall/// in the effective context.
535161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic AccessResult MatchesFriend(Sema &S,
536161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                  const EffectiveContext &EC,
537161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                  FriendDecl *FriendD) {
5386102ca1d490836096678d7d934f0b2b78f9293ecJohn McCall  // Whitelist accesses if there's an invalid or unsupported friend
5396102ca1d490836096678d7d934f0b2b78f9293ecJohn McCall  // declaration.
5406102ca1d490836096678d7d934f0b2b78f9293ecJohn McCall  if (FriendD->isInvalidDecl() || FriendD->isUnsupportedFriend())
541337ec3d0e8cb24a591ecbecdc0a995a167f6af01John McCall    return AR_accessible;
542337ec3d0e8cb24a591ecbecdc0a995a167f6af01John McCall
54332f2fb53d9d7c28c94d8569fd0fcf06cccee0c3dJohn McCall  if (TypeSourceInfo *T = FriendD->getFriendType())
54432f2fb53d9d7c28c94d8569fd0fcf06cccee0c3dJohn McCall    return MatchesFriend(S, EC, T->getType()->getCanonicalTypeUnqualified());
5450c01d18094100db92d38daa923c95661512db203John McCall
5460c01d18094100db92d38daa923c95661512db203John McCall  NamedDecl *Friend
5470c01d18094100db92d38daa923c95661512db203John McCall    = cast<NamedDecl>(FriendD->getFriendDecl()->getCanonicalDecl());
5480c01d18094100db92d38daa923c95661512db203John McCall
5490c01d18094100db92d38daa923c95661512db203John McCall  // FIXME: declarations with dependent or templated scope.
5500c01d18094100db92d38daa923c95661512db203John McCall
5510c01d18094100db92d38daa923c95661512db203John McCall  if (isa<ClassTemplateDecl>(Friend))
5520c01d18094100db92d38daa923c95661512db203John McCall    return MatchesFriend(S, EC, cast<ClassTemplateDecl>(Friend));
5530c01d18094100db92d38daa923c95661512db203John McCall
5540c01d18094100db92d38daa923c95661512db203John McCall  if (isa<FunctionTemplateDecl>(Friend))
5550c01d18094100db92d38daa923c95661512db203John McCall    return MatchesFriend(S, EC, cast<FunctionTemplateDecl>(Friend));
5560c01d18094100db92d38daa923c95661512db203John McCall
5570c01d18094100db92d38daa923c95661512db203John McCall  if (isa<CXXRecordDecl>(Friend))
5580c01d18094100db92d38daa923c95661512db203John McCall    return MatchesFriend(S, EC, cast<CXXRecordDecl>(Friend));
5590c01d18094100db92d38daa923c95661512db203John McCall
5600c01d18094100db92d38daa923c95661512db203John McCall  assert(isa<FunctionDecl>(Friend) && "unknown friend decl kind");
5610c01d18094100db92d38daa923c95661512db203John McCall  return MatchesFriend(S, EC, cast<FunctionDecl>(Friend));
5620c01d18094100db92d38daa923c95661512db203John McCall}
5630c01d18094100db92d38daa923c95661512db203John McCall
564161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic AccessResult GetFriendKind(Sema &S,
565161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                  const EffectiveContext &EC,
566161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                  const CXXRecordDecl *Class) {
567161755a09898c95d21bfff33707da9ca41cd53c5John McCall  AccessResult OnFailure = AR_inaccessible;
56888b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall
569d60e22e601852ae1345f01514318a0951dc09f89John McCall  // Okay, check friends.
570d60e22e601852ae1345f01514318a0951dc09f89John McCall  for (CXXRecordDecl::friend_iterator I = Class->friend_begin(),
571d60e22e601852ae1345f01514318a0951dc09f89John McCall         E = Class->friend_end(); I != E; ++I) {
572d60e22e601852ae1345f01514318a0951dc09f89John McCall    FriendDecl *Friend = *I;
573d60e22e601852ae1345f01514318a0951dc09f89John McCall
574a742db0032d8f458fe229600d2082981a1fb1481John McCall    switch (MatchesFriend(S, EC, Friend)) {
575161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case AR_accessible:
576161755a09898c95d21bfff33707da9ca41cd53c5John McCall      return AR_accessible;
57788b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall
578161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case AR_inaccessible:
579161755a09898c95d21bfff33707da9ca41cd53c5John McCall      continue;
580d60e22e601852ae1345f01514318a0951dc09f89John McCall
581161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case AR_dependent:
582161755a09898c95d21bfff33707da9ca41cd53c5John McCall      OnFailure = AR_dependent;
583a742db0032d8f458fe229600d2082981a1fb1481John McCall      break;
584a742db0032d8f458fe229600d2082981a1fb1481John McCall    }
585d60e22e601852ae1345f01514318a0951dc09f89John McCall  }
586d60e22e601852ae1345f01514318a0951dc09f89John McCall
587d60e22e601852ae1345f01514318a0951dc09f89John McCall  // That's it, give up.
58888b6c71e3f0e68d094efcf880910caf424b46cbfJohn McCall  return OnFailure;
5896b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall}
5906b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
5918c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCallnamespace {
5928c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall
5938c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall/// A helper class for checking for a friend which will grant access
5948c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall/// to a protected instance member.
5958c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCallstruct ProtectedFriendContext {
5968c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  Sema &S;
5978c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  const EffectiveContext &EC;
5988c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  const CXXRecordDecl *NamingClass;
5998c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  bool CheckDependent;
6008c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  bool EverDependent;
6018c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall
6028c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  /// The path down to the current base class.
6035f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  SmallVector<const CXXRecordDecl*, 20> CurPath;
6048c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall
6058c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  ProtectedFriendContext(Sema &S, const EffectiveContext &EC,
6068c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall                         const CXXRecordDecl *InstanceContext,
6078c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall                         const CXXRecordDecl *NamingClass)
6088c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall    : S(S), EC(EC), NamingClass(NamingClass),
6098c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall      CheckDependent(InstanceContext->isDependentContext() ||
6108c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall                     NamingClass->isDependentContext()),
6118c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall      EverDependent(false) {}
6128c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall
613326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall  /// Check classes in the current path for friendship, starting at
614326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall  /// the given index.
615326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall  bool checkFriendshipAlongPath(unsigned I) {
616326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall    assert(I < CurPath.size());
617326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall    for (unsigned E = CurPath.size(); I != E; ++I) {
618326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall      switch (GetFriendKind(S, EC, CurPath[I])) {
6198c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall      case AR_accessible:   return true;
6208c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall      case AR_inaccessible: continue;
6218c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall      case AR_dependent:    EverDependent = true; continue;
6228c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall      }
6238c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall    }
6248c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall    return false;
6258c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  }
6268c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall
6278c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  /// Perform a search starting at the given class.
628326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall  ///
629326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall  /// PrivateDepth is the index of the last (least derived) class
630326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall  /// along the current path such that a notional public member of
631326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall  /// the final class in the path would have access in that class.
632326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall  bool findFriendship(const CXXRecordDecl *Cur, unsigned PrivateDepth) {
6338c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall    // If we ever reach the naming class, check the current path for
6348c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall    // friendship.  We can also stop recursing because we obviously
6358c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall    // won't find the naming class there again.
636326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall    if (Cur == NamingClass)
637326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall      return checkFriendshipAlongPath(PrivateDepth);
6388c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall
6398c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall    if (CheckDependent && MightInstantiateTo(Cur, NamingClass))
6408c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall      EverDependent = true;
6418c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall
6428c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall    // Recurse into the base classes.
6438c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall    for (CXXRecordDecl::base_class_const_iterator
6448c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall           I = Cur->bases_begin(), E = Cur->bases_end(); I != E; ++I) {
6458c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall
646326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall      // If this is private inheritance, then a public member of the
647326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall      // base will not have any access in classes derived from Cur.
648326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall      unsigned BasePrivateDepth = PrivateDepth;
649326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall      if (I->getAccessSpecifier() == AS_private)
650326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall        BasePrivateDepth = CurPath.size() - 1;
6518c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall
6528c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall      const CXXRecordDecl *RD;
6538c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall
6548c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall      QualType T = I->getType();
6558c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall      if (const RecordType *RT = T->getAs<RecordType>()) {
6568c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall        RD = cast<CXXRecordDecl>(RT->getDecl());
6578c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall      } else if (const InjectedClassNameType *IT
6588c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall                   = T->getAs<InjectedClassNameType>()) {
6598c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall        RD = IT->getDecl();
6608c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall      } else {
6618c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall        assert(T->isDependentType() && "non-dependent base wasn't a record?");
6628c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall        EverDependent = true;
6638c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall        continue;
6648c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall      }
6658c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall
6668c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall      // Recurse.  We don't need to clean up if this returns true.
667326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall      CurPath.push_back(RD);
668326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall      if (findFriendship(RD->getCanonicalDecl(), BasePrivateDepth))
669326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall        return true;
670326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall      CurPath.pop_back();
6718c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall    }
6728c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall
6738c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall    return false;
6748c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  }
675326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall
676326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall  bool findFriendship(const CXXRecordDecl *Cur) {
677326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall    assert(CurPath.empty());
678326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall    CurPath.push_back(Cur);
679326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall    return findFriendship(Cur, 0);
680326c8c7d6e6996c82a1da55c1c3cd6cb4b89a584John McCall  }
6818c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall};
6828c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall}
6838c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall
6848c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall/// Search for a class P that EC is a friend of, under the constraint
685b9abd87283ac6e929b7e12a577663bc99e61d020John McCall///   InstanceContext <= P
686b9abd87283ac6e929b7e12a577663bc99e61d020John McCall/// if InstanceContext exists, or else
687b9abd87283ac6e929b7e12a577663bc99e61d020John McCall///   NamingClass <= P
6888c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall/// and with the additional restriction that a protected member of
689b9abd87283ac6e929b7e12a577663bc99e61d020John McCall/// NamingClass would have some natural access in P, which implicitly
690b9abd87283ac6e929b7e12a577663bc99e61d020John McCall/// imposes the constraint that P <= NamingClass.
6918c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall///
692b9abd87283ac6e929b7e12a577663bc99e61d020John McCall/// This isn't quite the condition laid out in the standard.
693b9abd87283ac6e929b7e12a577663bc99e61d020John McCall/// Instead of saying that a notional protected member of NamingClass
694b9abd87283ac6e929b7e12a577663bc99e61d020John McCall/// would have to have some natural access in P, it says the actual
695b9abd87283ac6e929b7e12a577663bc99e61d020John McCall/// target has to have some natural access in P, which opens up the
696b9abd87283ac6e929b7e12a577663bc99e61d020John McCall/// possibility that the target (which is not necessarily a member
697b9abd87283ac6e929b7e12a577663bc99e61d020John McCall/// of NamingClass) might be more accessible along some path not
698b9abd87283ac6e929b7e12a577663bc99e61d020John McCall/// passing through it.  That's really a bad idea, though, because it
6998c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall/// introduces two problems:
700b9abd87283ac6e929b7e12a577663bc99e61d020John McCall///   - Most importantly, it breaks encapsulation because you can
701b9abd87283ac6e929b7e12a577663bc99e61d020John McCall///     access a forbidden base class's members by directly subclassing
702b9abd87283ac6e929b7e12a577663bc99e61d020John McCall///     it elsewhere.
703b9abd87283ac6e929b7e12a577663bc99e61d020John McCall///   - It also makes access substantially harder to compute because it
7048c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall///     breaks the hill-climbing algorithm: knowing that the target is
7058c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall///     accessible in some base class would no longer let you change
7068c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall///     the question solely to whether the base class is accessible,
7078c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall///     because the original target might have been more accessible
7088c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall///     because of crazy subclassing.
7098c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall/// So we don't implement that.
7108c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCallstatic AccessResult GetProtectedFriendKind(Sema &S, const EffectiveContext &EC,
7118c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall                                           const CXXRecordDecl *InstanceContext,
7128c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall                                           const CXXRecordDecl *NamingClass) {
713b9abd87283ac6e929b7e12a577663bc99e61d020John McCall  assert(InstanceContext == 0 ||
714b9abd87283ac6e929b7e12a577663bc99e61d020John McCall         InstanceContext->getCanonicalDecl() == InstanceContext);
7158c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  assert(NamingClass->getCanonicalDecl() == NamingClass);
7168c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall
717b9abd87283ac6e929b7e12a577663bc99e61d020John McCall  // If we don't have an instance context, our constraints give us
718b9abd87283ac6e929b7e12a577663bc99e61d020John McCall  // that NamingClass <= P <= NamingClass, i.e. P == NamingClass.
719b9abd87283ac6e929b7e12a577663bc99e61d020John McCall  // This is just the usual friendship check.
720b9abd87283ac6e929b7e12a577663bc99e61d020John McCall  if (!InstanceContext) return GetFriendKind(S, EC, NamingClass);
721b9abd87283ac6e929b7e12a577663bc99e61d020John McCall
7228c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  ProtectedFriendContext PRC(S, EC, InstanceContext, NamingClass);
7238c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  if (PRC.findFriendship(InstanceContext)) return AR_accessible;
7248c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  if (PRC.EverDependent) return AR_dependent;
7258c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  return AR_inaccessible;
7268c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall}
7278c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall
728161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic AccessResult HasAccess(Sema &S,
729161755a09898c95d21bfff33707da9ca41cd53c5John McCall                              const EffectiveContext &EC,
730161755a09898c95d21bfff33707da9ca41cd53c5John McCall                              const CXXRecordDecl *NamingClass,
731161755a09898c95d21bfff33707da9ca41cd53c5John McCall                              AccessSpecifier Access,
732161755a09898c95d21bfff33707da9ca41cd53c5John McCall                              const AccessTarget &Target) {
733db73c684ba61fed4087af488e8610657ec638c17John McCall  assert(NamingClass->getCanonicalDecl() == NamingClass &&
734db73c684ba61fed4087af488e8610657ec638c17John McCall         "declaration should be canonicalized before being passed here");
735db73c684ba61fed4087af488e8610657ec638c17John McCall
736161755a09898c95d21bfff33707da9ca41cd53c5John McCall  if (Access == AS_public) return AR_accessible;
737db73c684ba61fed4087af488e8610657ec638c17John McCall  assert(Access == AS_private || Access == AS_protected);
738db73c684ba61fed4087af488e8610657ec638c17John McCall
739161755a09898c95d21bfff33707da9ca41cd53c5John McCall  AccessResult OnFailure = AR_inaccessible;
740161755a09898c95d21bfff33707da9ca41cd53c5John McCall
741db73c684ba61fed4087af488e8610657ec638c17John McCall  for (EffectiveContext::record_iterator
742db73c684ba61fed4087af488e8610657ec638c17John McCall         I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
743db73c684ba61fed4087af488e8610657ec638c17John McCall    // All the declarations in EC have been canonicalized, so pointer
744db73c684ba61fed4087af488e8610657ec638c17John McCall    // equality from this point on will work fine.
745db73c684ba61fed4087af488e8610657ec638c17John McCall    const CXXRecordDecl *ECRecord = *I;
746db73c684ba61fed4087af488e8610657ec638c17John McCall
747db73c684ba61fed4087af488e8610657ec638c17John McCall    // [B2] and [M2]
748161755a09898c95d21bfff33707da9ca41cd53c5John McCall    if (Access == AS_private) {
749161755a09898c95d21bfff33707da9ca41cd53c5John McCall      if (ECRecord == NamingClass)
750161755a09898c95d21bfff33707da9ca41cd53c5John McCall        return AR_accessible;
751db73c684ba61fed4087af488e8610657ec638c17John McCall
75201ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall      if (EC.isDependent() && MightInstantiateTo(ECRecord, NamingClass))
75301ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall        OnFailure = AR_dependent;
75401ebd9d1883e82c4188325900a4eb9c1e16353bbJohn McCall
755db73c684ba61fed4087af488e8610657ec638c17John McCall    // [B3] and [M3]
756161755a09898c95d21bfff33707da9ca41cd53c5John McCall    } else {
757161755a09898c95d21bfff33707da9ca41cd53c5John McCall      assert(Access == AS_protected);
758161755a09898c95d21bfff33707da9ca41cd53c5John McCall      switch (IsDerivedFromInclusive(ECRecord, NamingClass)) {
759161755a09898c95d21bfff33707da9ca41cd53c5John McCall      case AR_accessible: break;
760161755a09898c95d21bfff33707da9ca41cd53c5John McCall      case AR_inaccessible: continue;
761161755a09898c95d21bfff33707da9ca41cd53c5John McCall      case AR_dependent: OnFailure = AR_dependent; continue;
762161755a09898c95d21bfff33707da9ca41cd53c5John McCall      }
763161755a09898c95d21bfff33707da9ca41cd53c5John McCall
764161755a09898c95d21bfff33707da9ca41cd53c5John McCall      // C++ [class.protected]p1:
765161755a09898c95d21bfff33707da9ca41cd53c5John McCall      //   An additional access check beyond those described earlier in
766161755a09898c95d21bfff33707da9ca41cd53c5John McCall      //   [class.access] is applied when a non-static data member or
767161755a09898c95d21bfff33707da9ca41cd53c5John McCall      //   non-static member function is a protected member of its naming
768161755a09898c95d21bfff33707da9ca41cd53c5John McCall      //   class.  As described earlier, access to a protected member is
769161755a09898c95d21bfff33707da9ca41cd53c5John McCall      //   granted because the reference occurs in a friend or member of
770161755a09898c95d21bfff33707da9ca41cd53c5John McCall      //   some class C.  If the access is to form a pointer to member,
771161755a09898c95d21bfff33707da9ca41cd53c5John McCall      //   the nested-name-specifier shall name C or a class derived from
772161755a09898c95d21bfff33707da9ca41cd53c5John McCall      //   C. All other accesses involve a (possibly implicit) object
773161755a09898c95d21bfff33707da9ca41cd53c5John McCall      //   expression. In this case, the class of the object expression
774161755a09898c95d21bfff33707da9ca41cd53c5John McCall      //   shall be C or a class derived from C.
775161755a09898c95d21bfff33707da9ca41cd53c5John McCall      //
776b9abd87283ac6e929b7e12a577663bc99e61d020John McCall      // We interpret this as a restriction on [M3].
777b9abd87283ac6e929b7e12a577663bc99e61d020John McCall
778b9abd87283ac6e929b7e12a577663bc99e61d020John McCall      // In this part of the code, 'C' is just our context class ECRecord.
779b9abd87283ac6e929b7e12a577663bc99e61d020John McCall
780b9abd87283ac6e929b7e12a577663bc99e61d020John McCall      // These rules are different if we don't have an instance context.
781b9abd87283ac6e929b7e12a577663bc99e61d020John McCall      if (!Target.hasInstanceContext()) {
782b9abd87283ac6e929b7e12a577663bc99e61d020John McCall        // If it's not an instance member, these restrictions don't apply.
783b9abd87283ac6e929b7e12a577663bc99e61d020John McCall        if (!Target.isInstanceMember()) return AR_accessible;
784b9abd87283ac6e929b7e12a577663bc99e61d020John McCall
785b9abd87283ac6e929b7e12a577663bc99e61d020John McCall        // If it's an instance member, use the pointer-to-member rule
786b9abd87283ac6e929b7e12a577663bc99e61d020John McCall        // that the naming class has to be derived from the effective
787b9abd87283ac6e929b7e12a577663bc99e61d020John McCall        // context.
788b9abd87283ac6e929b7e12a577663bc99e61d020John McCall
789b2d899e9ae8a48c4057a48664213948934b877faFrancois Pichet        // Emulate a MSVC bug where the creation of pointer-to-member
790b2d899e9ae8a48c4057a48664213948934b877faFrancois Pichet        // to protected member of base class is allowed but only from
791b4143472c7763b84536328dee13f281df2d9040bFrancois Pichet        // static member functions.
7922d01f2c414b8ef2ae23620ce6c9d3763c8bf73bfFrancois Pichet        if (S.getLangOpts().MicrosoftMode && !EC.Functions.empty())
7932d01f2c414b8ef2ae23620ce6c9d3763c8bf73bfFrancois Pichet          if (CXXMethodDecl* MD = dyn_cast<CXXMethodDecl>(EC.Functions.front()))
7942d01f2c414b8ef2ae23620ce6c9d3763c8bf73bfFrancois Pichet            if (MD->isStatic()) return AR_accessible;
795b2d899e9ae8a48c4057a48664213948934b877faFrancois Pichet
796b9abd87283ac6e929b7e12a577663bc99e61d020John McCall        // Despite the standard's confident wording, there is a case
797b9abd87283ac6e929b7e12a577663bc99e61d020John McCall        // where you can have an instance member that's neither in a
798b9abd87283ac6e929b7e12a577663bc99e61d020John McCall        // pointer-to-member expression nor in a member access:  when
799b9abd87283ac6e929b7e12a577663bc99e61d020John McCall        // it names a field in an unevaluated context that can't be an
800b9abd87283ac6e929b7e12a577663bc99e61d020John McCall        // implicit member.  Pending clarification, we just apply the
801b9abd87283ac6e929b7e12a577663bc99e61d020John McCall        // same naming-class restriction here.
802b9abd87283ac6e929b7e12a577663bc99e61d020John McCall        //   FIXME: we're probably not correctly adding the
803b9abd87283ac6e929b7e12a577663bc99e61d020John McCall        //   protected-member restriction when we retroactively convert
804b9abd87283ac6e929b7e12a577663bc99e61d020John McCall        //   an expression to being evaluated.
805b9abd87283ac6e929b7e12a577663bc99e61d020John McCall
806b9abd87283ac6e929b7e12a577663bc99e61d020John McCall        // We know that ECRecord derives from NamingClass.  The
807b9abd87283ac6e929b7e12a577663bc99e61d020John McCall        // restriction says to check whether NamingClass derives from
808b9abd87283ac6e929b7e12a577663bc99e61d020John McCall        // ECRecord, but that's not really necessary: two distinct
809b9abd87283ac6e929b7e12a577663bc99e61d020John McCall        // classes can't be recursively derived from each other.  So
810b9abd87283ac6e929b7e12a577663bc99e61d020John McCall        // along this path, we just need to check whether the classes
811b9abd87283ac6e929b7e12a577663bc99e61d020John McCall        // are equal.
812b9abd87283ac6e929b7e12a577663bc99e61d020John McCall        if (NamingClass == ECRecord) return AR_accessible;
813b9abd87283ac6e929b7e12a577663bc99e61d020John McCall
814b9abd87283ac6e929b7e12a577663bc99e61d020John McCall        // Otherwise, this context class tells us nothing;  on to the next.
815b9abd87283ac6e929b7e12a577663bc99e61d020John McCall        continue;
816b9abd87283ac6e929b7e12a577663bc99e61d020John McCall      }
817b9abd87283ac6e929b7e12a577663bc99e61d020John McCall
818b9abd87283ac6e929b7e12a577663bc99e61d020John McCall      assert(Target.isInstanceMember());
819b9abd87283ac6e929b7e12a577663bc99e61d020John McCall
820b9abd87283ac6e929b7e12a577663bc99e61d020John McCall      const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S);
821b9abd87283ac6e929b7e12a577663bc99e61d020John McCall      if (!InstanceContext) {
822b9abd87283ac6e929b7e12a577663bc99e61d020John McCall        OnFailure = AR_dependent;
823b9abd87283ac6e929b7e12a577663bc99e61d020John McCall        continue;
824b9abd87283ac6e929b7e12a577663bc99e61d020John McCall      }
825b9abd87283ac6e929b7e12a577663bc99e61d020John McCall
826161755a09898c95d21bfff33707da9ca41cd53c5John McCall      switch (IsDerivedFromInclusive(InstanceContext, ECRecord)) {
827161755a09898c95d21bfff33707da9ca41cd53c5John McCall      case AR_accessible: return AR_accessible;
828161755a09898c95d21bfff33707da9ca41cd53c5John McCall      case AR_inaccessible: continue;
829161755a09898c95d21bfff33707da9ca41cd53c5John McCall      case AR_dependent: OnFailure = AR_dependent; continue;
830161755a09898c95d21bfff33707da9ca41cd53c5John McCall      }
831161755a09898c95d21bfff33707da9ca41cd53c5John McCall    }
832db73c684ba61fed4087af488e8610657ec638c17John McCall  }
833db73c684ba61fed4087af488e8610657ec638c17John McCall
8348c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  // [M3] and [B3] say that, if the target is protected in N, we grant
8358c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  // access if the access occurs in a friend or member of some class P
8368c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  // that's a subclass of N and where the target has some natural
8378c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  // access in P.  The 'member' aspect is easy to handle because P
8388c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  // would necessarily be one of the effective-context records, and we
8398c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  // address that above.  The 'friend' aspect is completely ridiculous
8408c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  // to implement because there are no restrictions at all on P
8418c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  // *unless* the [class.protected] restriction applies.  If it does,
8428c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  // however, we should ignore whether the naming class is a friend,
8438c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall  // and instead rely on whether any potential P is a friend.
844b9abd87283ac6e929b7e12a577663bc99e61d020John McCall  if (Access == AS_protected && Target.isInstanceMember()) {
845b9abd87283ac6e929b7e12a577663bc99e61d020John McCall    // Compute the instance context if possible.
846b9abd87283ac6e929b7e12a577663bc99e61d020John McCall    const CXXRecordDecl *InstanceContext = 0;
847b9abd87283ac6e929b7e12a577663bc99e61d020John McCall    if (Target.hasInstanceContext()) {
848b9abd87283ac6e929b7e12a577663bc99e61d020John McCall      InstanceContext = Target.resolveInstanceContext(S);
849b9abd87283ac6e929b7e12a577663bc99e61d020John McCall      if (!InstanceContext) return AR_dependent;
850b9abd87283ac6e929b7e12a577663bc99e61d020John McCall    }
851b9abd87283ac6e929b7e12a577663bc99e61d020John McCall
8528c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall    switch (GetProtectedFriendKind(S, EC, InstanceContext, NamingClass)) {
8538c77bcb072e7fd089f39fd7e079b6d767bf583faJohn McCall    case AR_accessible: return AR_accessible;
854161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case AR_inaccessible: return OnFailure;
855161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case AR_dependent: return AR_dependent;
856161755a09898c95d21bfff33707da9ca41cd53c5John McCall    }
8571797a05f97671d40929224ac030c8c16fe69938cJohn McCall    llvm_unreachable("impossible friendship kind");
858161755a09898c95d21bfff33707da9ca41cd53c5John McCall  }
859161755a09898c95d21bfff33707da9ca41cd53c5John McCall
860161755a09898c95d21bfff33707da9ca41cd53c5John McCall  switch (GetFriendKind(S, EC, NamingClass)) {
861161755a09898c95d21bfff33707da9ca41cd53c5John McCall  case AR_accessible: return AR_accessible;
862161755a09898c95d21bfff33707da9ca41cd53c5John McCall  case AR_inaccessible: return OnFailure;
863161755a09898c95d21bfff33707da9ca41cd53c5John McCall  case AR_dependent: return AR_dependent;
864161755a09898c95d21bfff33707da9ca41cd53c5John McCall  }
865161755a09898c95d21bfff33707da9ca41cd53c5John McCall
866161755a09898c95d21bfff33707da9ca41cd53c5John McCall  // Silence bogus warnings
867161755a09898c95d21bfff33707da9ca41cd53c5John McCall  llvm_unreachable("impossible friendship kind");
868db73c684ba61fed4087af488e8610657ec638c17John McCall}
869db73c684ba61fed4087af488e8610657ec638c17John McCall
8706b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// Finds the best path from the naming class to the declaring class,
8716b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// taking friend declarations into account.
8726b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall///
873db73c684ba61fed4087af488e8610657ec638c17John McCall/// C++0x [class.access.base]p5:
874db73c684ba61fed4087af488e8610657ec638c17John McCall///   A member m is accessible at the point R when named in class N if
875db73c684ba61fed4087af488e8610657ec638c17John McCall///   [M1] m as a member of N is public, or
876db73c684ba61fed4087af488e8610657ec638c17John McCall///   [M2] m as a member of N is private, and R occurs in a member or
877db73c684ba61fed4087af488e8610657ec638c17John McCall///        friend of class N, or
878db73c684ba61fed4087af488e8610657ec638c17John McCall///   [M3] m as a member of N is protected, and R occurs in a member or
879db73c684ba61fed4087af488e8610657ec638c17John McCall///        friend of class N, or in a member or friend of a class P
880db73c684ba61fed4087af488e8610657ec638c17John McCall///        derived from N, where m as a member of P is public, private,
881db73c684ba61fed4087af488e8610657ec638c17John McCall///        or protected, or
882db73c684ba61fed4087af488e8610657ec638c17John McCall///   [M4] there exists a base class B of N that is accessible at R, and
883db73c684ba61fed4087af488e8610657ec638c17John McCall///        m is accessible at R when named in class B.
884db73c684ba61fed4087af488e8610657ec638c17John McCall///
885db73c684ba61fed4087af488e8610657ec638c17John McCall/// C++0x [class.access.base]p4:
886db73c684ba61fed4087af488e8610657ec638c17John McCall///   A base class B of N is accessible at R, if
887db73c684ba61fed4087af488e8610657ec638c17John McCall///   [B1] an invented public member of B would be a public member of N, or
888db73c684ba61fed4087af488e8610657ec638c17John McCall///   [B2] R occurs in a member or friend of class N, and an invented public
889db73c684ba61fed4087af488e8610657ec638c17John McCall///        member of B would be a private or protected member of N, or
890db73c684ba61fed4087af488e8610657ec638c17John McCall///   [B3] R occurs in a member or friend of a class P derived from N, and an
891db73c684ba61fed4087af488e8610657ec638c17John McCall///        invented public member of B would be a private or protected member
892db73c684ba61fed4087af488e8610657ec638c17John McCall///        of P, or
893db73c684ba61fed4087af488e8610657ec638c17John McCall///   [B4] there exists a class S such that B is a base class of S accessible
894db73c684ba61fed4087af488e8610657ec638c17John McCall///        at R and S is a base class of N accessible at R.
895db73c684ba61fed4087af488e8610657ec638c17John McCall///
896db73c684ba61fed4087af488e8610657ec638c17John McCall/// Along a single inheritance path we can restate both of these
897db73c684ba61fed4087af488e8610657ec638c17John McCall/// iteratively:
898db73c684ba61fed4087af488e8610657ec638c17John McCall///
899db73c684ba61fed4087af488e8610657ec638c17John McCall/// First, we note that M1-4 are equivalent to B1-4 if the member is
900db73c684ba61fed4087af488e8610657ec638c17John McCall/// treated as a notional base of its declaring class with inheritance
901db73c684ba61fed4087af488e8610657ec638c17John McCall/// access equivalent to the member's access.  Therefore we need only
902db73c684ba61fed4087af488e8610657ec638c17John McCall/// ask whether a class B is accessible from a class N in context R.
903db73c684ba61fed4087af488e8610657ec638c17John McCall///
904db73c684ba61fed4087af488e8610657ec638c17John McCall/// Let B_1 .. B_n be the inheritance path in question (i.e. where
905db73c684ba61fed4087af488e8610657ec638c17John McCall/// B_1 = N, B_n = B, and for all i, B_{i+1} is a direct base class of
906db73c684ba61fed4087af488e8610657ec638c17John McCall/// B_i).  For i in 1..n, we will calculate ACAB(i), the access to the
907db73c684ba61fed4087af488e8610657ec638c17John McCall/// closest accessible base in the path:
908db73c684ba61fed4087af488e8610657ec638c17John McCall///   Access(a, b) = (* access on the base specifier from a to b *)
909db73c684ba61fed4087af488e8610657ec638c17John McCall///   Merge(a, forbidden) = forbidden
910db73c684ba61fed4087af488e8610657ec638c17John McCall///   Merge(a, private) = forbidden
911db73c684ba61fed4087af488e8610657ec638c17John McCall///   Merge(a, b) = min(a,b)
912db73c684ba61fed4087af488e8610657ec638c17John McCall///   Accessible(c, forbidden) = false
913db73c684ba61fed4087af488e8610657ec638c17John McCall///   Accessible(c, private) = (R is c) || IsFriend(c, R)
914db73c684ba61fed4087af488e8610657ec638c17John McCall///   Accessible(c, protected) = (R derived from c) || IsFriend(c, R)
915db73c684ba61fed4087af488e8610657ec638c17John McCall///   Accessible(c, public) = true
916db73c684ba61fed4087af488e8610657ec638c17John McCall///   ACAB(n) = public
917db73c684ba61fed4087af488e8610657ec638c17John McCall///   ACAB(i) =
918db73c684ba61fed4087af488e8610657ec638c17John McCall///     let AccessToBase = Merge(Access(B_i, B_{i+1}), ACAB(i+1)) in
919db73c684ba61fed4087af488e8610657ec638c17John McCall///     if Accessible(B_i, AccessToBase) then public else AccessToBase
920db73c684ba61fed4087af488e8610657ec638c17John McCall///
921db73c684ba61fed4087af488e8610657ec638c17John McCall/// B is an accessible base of N at R iff ACAB(1) = public.
922db73c684ba61fed4087af488e8610657ec638c17John McCall///
923161755a09898c95d21bfff33707da9ca41cd53c5John McCall/// \param FinalAccess the access of the "final step", or AS_public if
9247aceaf8cee77c98478e8934dc283910292711a7eJohn McCall///   there is no final step.
9256b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// \return null if friendship is dependent
9266b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallstatic CXXBasePath *FindBestPath(Sema &S,
9276b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall                                 const EffectiveContext &EC,
928161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                 AccessTarget &Target,
9297aceaf8cee77c98478e8934dc283910292711a7eJohn McCall                                 AccessSpecifier FinalAccess,
9306b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall                                 CXXBasePaths &Paths) {
9316b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  // Derive the paths to the desired base.
932161755a09898c95d21bfff33707da9ca41cd53c5John McCall  const CXXRecordDecl *Derived = Target.getNamingClass();
933161755a09898c95d21bfff33707da9ca41cd53c5John McCall  const CXXRecordDecl *Base = Target.getDeclaringClass();
934161755a09898c95d21bfff33707da9ca41cd53c5John McCall
935161755a09898c95d21bfff33707da9ca41cd53c5John McCall  // FIXME: fail correctly when there are dependent paths.
936161755a09898c95d21bfff33707da9ca41cd53c5John McCall  bool isDerived = Derived->isDerivedFrom(const_cast<CXXRecordDecl*>(Base),
937161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                          Paths);
9386b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  assert(isDerived && "derived class not actually derived from base");
9396b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  (void) isDerived;
9406b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
9416b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  CXXBasePath *BestPath = 0;
9426b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
9437aceaf8cee77c98478e8934dc283910292711a7eJohn McCall  assert(FinalAccess != AS_none && "forbidden access after declaring class");
9447aceaf8cee77c98478e8934dc283910292711a7eJohn McCall
9450c01d18094100db92d38daa923c95661512db203John McCall  bool AnyDependent = false;
9460c01d18094100db92d38daa923c95661512db203John McCall
9476b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  // Derive the friend-modified access along each path.
9486b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  for (CXXBasePaths::paths_iterator PI = Paths.begin(), PE = Paths.end();
9496b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall         PI != PE; ++PI) {
950161755a09898c95d21bfff33707da9ca41cd53c5John McCall    AccessTarget::SavedInstanceContext _ = Target.saveInstanceContext();
9516b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
9526b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    // Walk through the path backwards.
9537aceaf8cee77c98478e8934dc283910292711a7eJohn McCall    AccessSpecifier PathAccess = FinalAccess;
9546b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    CXXBasePath::iterator I = PI->end(), E = PI->begin();
9556b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    while (I != E) {
9566b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall      --I;
9576b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
9587aceaf8cee77c98478e8934dc283910292711a7eJohn McCall      assert(PathAccess != AS_none);
9597aceaf8cee77c98478e8934dc283910292711a7eJohn McCall
9607aceaf8cee77c98478e8934dc283910292711a7eJohn McCall      // If the declaration is a private member of a base class, there
9617aceaf8cee77c98478e8934dc283910292711a7eJohn McCall      // is no level of friendship in derived classes that can make it
9627aceaf8cee77c98478e8934dc283910292711a7eJohn McCall      // accessible.
9637aceaf8cee77c98478e8934dc283910292711a7eJohn McCall      if (PathAccess == AS_private) {
9647aceaf8cee77c98478e8934dc283910292711a7eJohn McCall        PathAccess = AS_none;
9657aceaf8cee77c98478e8934dc283910292711a7eJohn McCall        break;
9667aceaf8cee77c98478e8934dc283910292711a7eJohn McCall      }
9677aceaf8cee77c98478e8934dc283910292711a7eJohn McCall
968161755a09898c95d21bfff33707da9ca41cd53c5John McCall      const CXXRecordDecl *NC = I->Class->getCanonicalDecl();
969161755a09898c95d21bfff33707da9ca41cd53c5John McCall
9706b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall      AccessSpecifier BaseAccess = I->Base->getAccessSpecifier();
971db73c684ba61fed4087af488e8610657ec638c17John McCall      PathAccess = std::max(PathAccess, BaseAccess);
972161755a09898c95d21bfff33707da9ca41cd53c5John McCall
973161755a09898c95d21bfff33707da9ca41cd53c5John McCall      switch (HasAccess(S, EC, NC, PathAccess, Target)) {
974161755a09898c95d21bfff33707da9ca41cd53c5John McCall      case AR_inaccessible: break;
975161755a09898c95d21bfff33707da9ca41cd53c5John McCall      case AR_accessible:
976161755a09898c95d21bfff33707da9ca41cd53c5John McCall        PathAccess = AS_public;
977161755a09898c95d21bfff33707da9ca41cd53c5John McCall
978161755a09898c95d21bfff33707da9ca41cd53c5John McCall        // Future tests are not against members and so do not have
979161755a09898c95d21bfff33707da9ca41cd53c5John McCall        // instance context.
980161755a09898c95d21bfff33707da9ca41cd53c5John McCall        Target.suppressInstanceContext();
981161755a09898c95d21bfff33707da9ca41cd53c5John McCall        break;
982161755a09898c95d21bfff33707da9ca41cd53c5John McCall      case AR_dependent:
983db73c684ba61fed4087af488e8610657ec638c17John McCall        AnyDependent = true;
984db73c684ba61fed4087af488e8610657ec638c17John McCall        goto Next;
985c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson      }
986c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson    }
987726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl
9886b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    // Note that we modify the path's Access field to the
9896b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    // friend-modified access.
9906b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    if (BestPath == 0 || PathAccess < BestPath->Access) {
9916b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall      BestPath = &*PI;
9926b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall      BestPath->Access = PathAccess;
9930c01d18094100db92d38daa923c95661512db203John McCall
9940c01d18094100db92d38daa923c95661512db203John McCall      // Short-circuit if we found a public path.
9950c01d18094100db92d38daa923c95661512db203John McCall      if (BestPath->Access == AS_public)
9960c01d18094100db92d38daa923c95661512db203John McCall        return BestPath;
997c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson    }
9980c01d18094100db92d38daa923c95661512db203John McCall
9990c01d18094100db92d38daa923c95661512db203John McCall  Next: ;
1000c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson  }
1001c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson
10020c01d18094100db92d38daa923c95661512db203John McCall  assert((!BestPath || BestPath->Access != AS_public) &&
10030c01d18094100db92d38daa923c95661512db203John McCall         "fell out of loop with public path");
10040c01d18094100db92d38daa923c95661512db203John McCall
10050c01d18094100db92d38daa923c95661512db203John McCall  // We didn't find a public path, but at least one path was subject
10060c01d18094100db92d38daa923c95661512db203John McCall  // to dependent friendship, so delay the check.
10070c01d18094100db92d38daa923c95661512db203John McCall  if (AnyDependent)
10080c01d18094100db92d38daa923c95661512db203John McCall    return 0;
10090c01d18094100db92d38daa923c95661512db203John McCall
10106b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  return BestPath;
1011726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl}
1012726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl
1013fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall/// Given that an entity has protected natural access, check whether
1014fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall/// access might be denied because of the protected member access
1015fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall/// restriction.
1016fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall///
1017fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall/// \return true if a note was emitted
1018fe24e05a87e48fa3318b65d1a92c542107639fd9John McCallstatic bool TryDiagnoseProtectedAccess(Sema &S, const EffectiveContext &EC,
1019fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall                                       AccessTarget &Target) {
1020fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall  // Only applies to instance accesses.
1021b9abd87283ac6e929b7e12a577663bc99e61d020John McCall  if (!Target.isInstanceMember())
1022fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall    return false;
1023b9abd87283ac6e929b7e12a577663bc99e61d020John McCall
1024fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall  assert(Target.isMemberAccess());
1025fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall
1026b9abd87283ac6e929b7e12a577663bc99e61d020John McCall  const CXXRecordDecl *NamingClass = Target.getNamingClass();
1027b9abd87283ac6e929b7e12a577663bc99e61d020John McCall  NamingClass = NamingClass->getCanonicalDecl();
1028fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall
1029fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall  for (EffectiveContext::record_iterator
1030fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall         I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
1031fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall    const CXXRecordDecl *ECRecord = *I;
1032b9abd87283ac6e929b7e12a577663bc99e61d020John McCall    switch (IsDerivedFromInclusive(ECRecord, NamingClass)) {
1033fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall    case AR_accessible: break;
1034fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall    case AR_inaccessible: continue;
1035fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall    case AR_dependent: continue;
1036fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall    }
1037fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall
1038fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall    // The effective context is a subclass of the declaring class.
1039b9abd87283ac6e929b7e12a577663bc99e61d020John McCall    // Check whether the [class.protected] restriction is limiting
1040b9abd87283ac6e929b7e12a577663bc99e61d020John McCall    // access.
1041fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall
1042fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall    // To get this exactly right, this might need to be checked more
1043fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall    // holistically;  it's not necessarily the case that gaining
1044fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall    // access here would grant us access overall.
1045fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall
1046b9abd87283ac6e929b7e12a577663bc99e61d020John McCall    NamedDecl *D = Target.getTargetDecl();
1047b9abd87283ac6e929b7e12a577663bc99e61d020John McCall
1048b9abd87283ac6e929b7e12a577663bc99e61d020John McCall    // If we don't have an instance context, [class.protected] says the
1049b9abd87283ac6e929b7e12a577663bc99e61d020John McCall    // naming class has to equal the context class.
1050b9abd87283ac6e929b7e12a577663bc99e61d020John McCall    if (!Target.hasInstanceContext()) {
1051b9abd87283ac6e929b7e12a577663bc99e61d020John McCall      // If it does, the restriction doesn't apply.
1052b9abd87283ac6e929b7e12a577663bc99e61d020John McCall      if (NamingClass == ECRecord) continue;
1053b9abd87283ac6e929b7e12a577663bc99e61d020John McCall
1054b9abd87283ac6e929b7e12a577663bc99e61d020John McCall      // TODO: it would be great to have a fixit here, since this is
1055b9abd87283ac6e929b7e12a577663bc99e61d020John McCall      // such an obvious error.
1056b9abd87283ac6e929b7e12a577663bc99e61d020John McCall      S.Diag(D->getLocation(), diag::note_access_protected_restricted_noobject)
1057b9abd87283ac6e929b7e12a577663bc99e61d020John McCall        << S.Context.getTypeDeclType(ECRecord);
1058b9abd87283ac6e929b7e12a577663bc99e61d020John McCall      return true;
1059b9abd87283ac6e929b7e12a577663bc99e61d020John McCall    }
1060b9abd87283ac6e929b7e12a577663bc99e61d020John McCall
1061fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall    const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S);
1062fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall    assert(InstanceContext && "diagnosing dependent access");
1063fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall
1064fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall    switch (IsDerivedFromInclusive(InstanceContext, ECRecord)) {
1065fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall    case AR_accessible: continue;
1066fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall    case AR_dependent: continue;
1067fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall    case AR_inaccessible:
1068b9abd87283ac6e929b7e12a577663bc99e61d020John McCall      break;
1069b9abd87283ac6e929b7e12a577663bc99e61d020John McCall    }
1070b9abd87283ac6e929b7e12a577663bc99e61d020John McCall
1071b9abd87283ac6e929b7e12a577663bc99e61d020John McCall    // Okay, the restriction seems to be what's limiting us.
1072b9abd87283ac6e929b7e12a577663bc99e61d020John McCall
1073b9abd87283ac6e929b7e12a577663bc99e61d020John McCall    // Use a special diagnostic for constructors and destructors.
1074b9abd87283ac6e929b7e12a577663bc99e61d020John McCall    if (isa<CXXConstructorDecl>(D) || isa<CXXDestructorDecl>(D) ||
1075b9abd87283ac6e929b7e12a577663bc99e61d020John McCall        (isa<FunctionTemplateDecl>(D) &&
1076b9abd87283ac6e929b7e12a577663bc99e61d020John McCall         isa<CXXConstructorDecl>(
1077b9abd87283ac6e929b7e12a577663bc99e61d020John McCall                cast<FunctionTemplateDecl>(D)->getTemplatedDecl()))) {
1078b9abd87283ac6e929b7e12a577663bc99e61d020John McCall      S.Diag(D->getLocation(), diag::note_access_protected_restricted_ctordtor)
1079b9abd87283ac6e929b7e12a577663bc99e61d020John McCall        << isa<CXXDestructorDecl>(D);
1080fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall      return true;
1081fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall    }
1082b9abd87283ac6e929b7e12a577663bc99e61d020John McCall
1083b9abd87283ac6e929b7e12a577663bc99e61d020John McCall    // Otherwise, use the generic diagnostic.
1084b9abd87283ac6e929b7e12a577663bc99e61d020John McCall    S.Diag(D->getLocation(), diag::note_access_protected_restricted_object)
1085b9abd87283ac6e929b7e12a577663bc99e61d020John McCall      << S.Context.getTypeDeclType(ECRecord);
1086b9abd87283ac6e929b7e12a577663bc99e61d020John McCall    return true;
1087fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall  }
1088fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall
1089fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall  return false;
1090fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall}
1091fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall
10926b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// Diagnose the path which caused the given declaration or base class
10936b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// to become inaccessible.
10946b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallstatic void DiagnoseAccessPath(Sema &S,
10956b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall                               const EffectiveContext &EC,
1096161755a09898c95d21bfff33707da9ca41cd53c5John McCall                               AccessTarget &Entity) {
1097db73c684ba61fed4087af488e8610657ec638c17John McCall  AccessSpecifier Access = Entity.getAccess();
1098db73c684ba61fed4087af488e8610657ec638c17John McCall
1099161755a09898c95d21bfff33707da9ca41cd53c5John McCall  NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : 0);
1100161755a09898c95d21bfff33707da9ca41cd53c5John McCall  const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();
1101db73c684ba61fed4087af488e8610657ec638c17John McCall
11026b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  // Easy case: the decl's natural access determined its path access.
11036b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  // We have to check against AS_private here in case Access is AS_none,
11046b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  // indicating a non-public member of a private base class.
11056b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  if (D && (Access == D->getAccess() || D->getAccess() == AS_private)) {
1106161755a09898c95d21bfff33707da9ca41cd53c5John McCall    switch (HasAccess(S, EC, DeclaringClass, D->getAccess(), Entity)) {
1107161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case AR_inaccessible: {
1108fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall      if (Access == AS_protected &&
1109fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall          TryDiagnoseProtectedAccess(S, EC, Entity))
1110fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall        return;
1111fe24e05a87e48fa3318b65d1a92c542107639fd9John McCall
1112aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall      // Find an original declaration.
1113aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall      while (D->isOutOfLine()) {
1114aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall        NamedDecl *PrevDecl = 0;
1115162e1c1b487352434552147967c3dd296ebee2f7Richard Smith        if (VarDecl *VD = dyn_cast<VarDecl>(D))
1116ef96ee0be5f100789f451641542a69cd719144d2Douglas Gregor          PrevDecl = VD->getPreviousDecl();
1117162e1c1b487352434552147967c3dd296ebee2f7Richard Smith        else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
1118ef96ee0be5f100789f451641542a69cd719144d2Douglas Gregor          PrevDecl = FD->getPreviousDecl();
1119162e1c1b487352434552147967c3dd296ebee2f7Richard Smith        else if (TypedefNameDecl *TND = dyn_cast<TypedefNameDecl>(D))
1120ef96ee0be5f100789f451641542a69cd719144d2Douglas Gregor          PrevDecl = TND->getPreviousDecl();
1121162e1c1b487352434552147967c3dd296ebee2f7Richard Smith        else if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
1122aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall          if (isa<RecordDecl>(D) && cast<RecordDecl>(D)->isInjectedClassName())
1123aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall            break;
1124ef96ee0be5f100789f451641542a69cd719144d2Douglas Gregor          PrevDecl = TD->getPreviousDecl();
1125aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall        }
1126aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall        if (!PrevDecl) break;
1127aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall        D = PrevDecl;
1128aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall      }
1129aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall
1130aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall      CXXRecordDecl *DeclaringClass = FindDeclaringClass(D);
1131aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall      Decl *ImmediateChild;
1132aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall      if (D->getDeclContext() == DeclaringClass)
1133aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall        ImmediateChild = D;
1134aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall      else {
1135aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall        DeclContext *DC = D->getDeclContext();
1136aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall        while (DC->getParent() != DeclaringClass)
1137aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall          DC = DC->getParent();
1138aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall        ImmediateChild = cast<Decl>(DC);
1139aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall      }
1140aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall
1141aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall      // Check whether there's an AccessSpecDecl preceding this in the
1142aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall      // chain of the DeclContext.
1143aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall      bool Implicit = true;
1144aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall      for (CXXRecordDecl::decl_iterator
1145aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall             I = DeclaringClass->decls_begin(), E = DeclaringClass->decls_end();
1146aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall           I != E; ++I) {
1147aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall        if (*I == ImmediateChild) break;
1148aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall        if (isa<AccessSpecDecl>(*I)) {
1149aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall          Implicit = false;
1150aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall          break;
1151aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall        }
1152aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall      }
1153aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall
11546b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall      S.Diag(D->getLocation(), diag::note_access_natural)
11556b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall        << (unsigned) (Access == AS_protected)
1156aa56a66abb61e9f42b48ae88e43328aba10c9148John McCall        << Implicit;
11576b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall      return;
11586b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    }
1159726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl
1160161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case AR_accessible: break;
1161726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl
1162161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case AR_dependent:
1163161755a09898c95d21bfff33707da9ca41cd53c5John McCall      llvm_unreachable("can't diagnose dependent access failures");
11646b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    }
11656b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  }
1166c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson
11676b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  CXXBasePaths Paths;
1168161755a09898c95d21bfff33707da9ca41cd53c5John McCall  CXXBasePath &Path = *FindBestPath(S, EC, Entity, AS_public, Paths);
1169726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl
11706b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  CXXBasePath::iterator I = Path.end(), E = Path.begin();
11716b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  while (I != E) {
11726b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    --I;
1173c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson
11746b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    const CXXBaseSpecifier *BS = I->Base;
11756b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    AccessSpecifier BaseAccess = BS->getAccessSpecifier();
11766b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
11776b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    // If this is public inheritance, or the derived class is a friend,
11786b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    // skip this step.
11796b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    if (BaseAccess == AS_public)
11806b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall      continue;
11816b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
11826b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    switch (GetFriendKind(S, EC, I->Class)) {
1183161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case AR_accessible: continue;
1184161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case AR_inaccessible: break;
1185161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case AR_dependent:
1186161755a09898c95d21bfff33707da9ca41cd53c5John McCall      llvm_unreachable("can't diagnose dependent access failures");
11876b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    }
11886b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
11896b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    // Check whether this base specifier is the tighest point
11906b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    // constraining access.  We have to check against AS_private for
11916b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    // the same reasons as above.
11926b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    if (BaseAccess == AS_private || BaseAccess >= Access) {
11936b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
11946b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall      // We're constrained by inheritance, but we want to say
11956b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall      // "declared private here" if we're diagnosing a hierarchy
11966b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall      // conversion and this is the final step.
11976b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall      unsigned diagnostic;
11986b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall      if (D) diagnostic = diag::note_access_constrained_by_path;
11996b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall      else if (I + 1 == Path.end()) diagnostic = diag::note_access_natural;
12006b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall      else diagnostic = diag::note_access_constrained_by_path;
12016b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
12026b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall      S.Diag(BS->getSourceRange().getBegin(), diagnostic)
12036b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall        << BS->getSourceRange()
12046b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall        << (BaseAccess == AS_protected)
12056b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall        << (BS->getAccessSpecifierAsWritten() == AS_none);
120676ef658c703faf72c00f324fb9edc03169718e3eDouglas Gregor
120776ef658c703faf72c00f324fb9edc03169718e3eDouglas Gregor      if (D)
120876ef658c703faf72c00f324fb9edc03169718e3eDouglas Gregor        S.Diag(D->getLocation(), diag::note_field_decl);
120976ef658c703faf72c00f324fb9edc03169718e3eDouglas Gregor
12106b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall      return;
12116b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    }
1212c4f1e87138bfe5d3aaccff13c86b383a255bca42Anders Carlsson  }
1213726212f41bac77dc7f3352bc7047615fa0cd9e58Sebastian Redl
12146b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  llvm_unreachable("access not apparently constrained by path");
121529f006be830fbbcaa0c1cf7c7399bb5080dc7f32Anders Carlsson}
121692f883177b162928a8e632e4e3b93fafd2b26072John McCall
1217db73c684ba61fed4087af488e8610657ec638c17John McCallstatic void DiagnoseBadAccess(Sema &S, SourceLocation Loc,
1218db73c684ba61fed4087af488e8610657ec638c17John McCall                              const EffectiveContext &EC,
1219161755a09898c95d21bfff33707da9ca41cd53c5John McCall                              AccessTarget &Entity) {
1220db73c684ba61fed4087af488e8610657ec638c17John McCall  const CXXRecordDecl *NamingClass = Entity.getNamingClass();
1221161755a09898c95d21bfff33707da9ca41cd53c5John McCall  const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();
1222161755a09898c95d21bfff33707da9ca41cd53c5John McCall  NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : 0);
12236b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
122458e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall  S.Diag(Loc, Entity.getDiag())
1225db73c684ba61fed4087af488e8610657ec638c17John McCall    << (Entity.getAccess() == AS_protected)
1226db73c684ba61fed4087af488e8610657ec638c17John McCall    << (D ? D->getDeclName() : DeclarationName())
122758e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall    << S.Context.getTypeDeclType(NamingClass)
122858e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall    << S.Context.getTypeDeclType(DeclaringClass);
1229db73c684ba61fed4087af488e8610657ec638c17John McCall  DiagnoseAccessPath(S, EC, Entity);
12306b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall}
123192f883177b162928a8e632e4e3b93fafd2b26072John McCall
1232b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichet/// MSVC has a bug where if during an using declaration name lookup,
1233b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichet/// the declaration found is unaccessible (private) and that declaration
1234b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichet/// was bring into scope via another using declaration whose target
1235b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichet/// declaration is accessible (public) then no error is generated.
1236b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichet/// Example:
1237b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichet///   class A {
1238b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichet///   public:
1239b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichet///     int f();
1240b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichet///   };
1241b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichet///   class B : public A {
1242b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichet///   private:
1243b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichet///     using A::f;
1244b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichet///   };
1245b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichet///   class C : public B {
1246b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichet///   private:
1247b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichet///     using B::f;
1248b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichet///   };
1249b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichet///
1250b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichet/// Here, B::f is private so this should fail in Standard C++, but
1251b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichet/// because B::f refers to A::f which is public MSVC accepts it.
1252b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichetstatic bool IsMicrosoftUsingDeclarationAccessBug(Sema& S,
1253b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichet                                                 SourceLocation AccessLoc,
1254b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichet                                                 AccessTarget &Entity) {
1255b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichet  if (UsingShadowDecl *Shadow =
1256b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichet                         dyn_cast<UsingShadowDecl>(Entity.getTargetDecl())) {
1257b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichet    const NamedDecl *OrigDecl = Entity.getTargetDecl()->getUnderlyingDecl();
1258b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichet    if (Entity.getTargetDecl()->getAccess() == AS_private &&
1259b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichet        (OrigDecl->getAccess() == AS_public ||
1260b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichet         OrigDecl->getAccess() == AS_protected)) {
1261d7c56e1114bfe7d461786903bb720d2c6efc05a1Richard Smith      S.Diag(AccessLoc, diag::ext_ms_using_declaration_inaccessible)
1262b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichet        << Shadow->getUsingDecl()->getQualifiedNameAsString()
1263b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichet        << OrigDecl->getQualifiedNameAsString();
1264b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichet      return true;
1265b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichet    }
1266b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichet  }
1267b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichet  return false;
1268b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichet}
1269b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichet
1270db73c684ba61fed4087af488e8610657ec638c17John McCall/// Determines whether the accessed entity is accessible.  Public members
1271db73c684ba61fed4087af488e8610657ec638c17John McCall/// have been weeded out by this point.
1272161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic AccessResult IsAccessible(Sema &S,
1273161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                 const EffectiveContext &EC,
1274161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                 AccessTarget &Entity) {
1275db73c684ba61fed4087af488e8610657ec638c17John McCall  // Determine the actual naming class.
1276db73c684ba61fed4087af488e8610657ec638c17John McCall  CXXRecordDecl *NamingClass = Entity.getNamingClass();
1277db73c684ba61fed4087af488e8610657ec638c17John McCall  while (NamingClass->isAnonymousStructOrUnion())
1278db73c684ba61fed4087af488e8610657ec638c17John McCall    NamingClass = cast<CXXRecordDecl>(NamingClass->getParent());
1279db73c684ba61fed4087af488e8610657ec638c17John McCall  NamingClass = NamingClass->getCanonicalDecl();
128092f883177b162928a8e632e4e3b93fafd2b26072John McCall
1281db73c684ba61fed4087af488e8610657ec638c17John McCall  AccessSpecifier UnprivilegedAccess = Entity.getAccess();
1282db73c684ba61fed4087af488e8610657ec638c17John McCall  assert(UnprivilegedAccess != AS_public && "public access not weeded out");
128392f883177b162928a8e632e4e3b93fafd2b26072John McCall
1284db73c684ba61fed4087af488e8610657ec638c17John McCall  // Before we try to recalculate access paths, try to white-list
1285db73c684ba61fed4087af488e8610657ec638c17John McCall  // accesses which just trade in on the final step, i.e. accesses
1286db73c684ba61fed4087af488e8610657ec638c17John McCall  // which don't require [M4] or [B4]. These are by far the most
1287161755a09898c95d21bfff33707da9ca41cd53c5John McCall  // common forms of privileged access.
1288db73c684ba61fed4087af488e8610657ec638c17John McCall  if (UnprivilegedAccess != AS_none) {
1289161755a09898c95d21bfff33707da9ca41cd53c5John McCall    switch (HasAccess(S, EC, NamingClass, UnprivilegedAccess, Entity)) {
1290161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case AR_dependent:
1291db73c684ba61fed4087af488e8610657ec638c17John McCall      // This is actually an interesting policy decision.  We don't
1292db73c684ba61fed4087af488e8610657ec638c17John McCall      // *have* to delay immediately here: we can do the full access
1293db73c684ba61fed4087af488e8610657ec638c17John McCall      // calculation in the hope that friendship on some intermediate
1294db73c684ba61fed4087af488e8610657ec638c17John McCall      // class will make the declaration accessible non-dependently.
1295db73c684ba61fed4087af488e8610657ec638c17John McCall      // But that's not cheap, and odds are very good (note: assertion
1296db73c684ba61fed4087af488e8610657ec638c17John McCall      // made without data) that the friend declaration will determine
1297db73c684ba61fed4087af488e8610657ec638c17John McCall      // access.
1298161755a09898c95d21bfff33707da9ca41cd53c5John McCall      return AR_dependent;
1299db73c684ba61fed4087af488e8610657ec638c17John McCall
1300161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case AR_accessible: return AR_accessible;
1301161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case AR_inaccessible: break;
1302db73c684ba61fed4087af488e8610657ec638c17John McCall    }
1303db73c684ba61fed4087af488e8610657ec638c17John McCall  }
130492f883177b162928a8e632e4e3b93fafd2b26072John McCall
1305161755a09898c95d21bfff33707da9ca41cd53c5John McCall  AccessTarget::SavedInstanceContext _ = Entity.saveInstanceContext();
1306db73c684ba61fed4087af488e8610657ec638c17John McCall
1307db73c684ba61fed4087af488e8610657ec638c17John McCall  // We lower member accesses to base accesses by pretending that the
1308db73c684ba61fed4087af488e8610657ec638c17John McCall  // member is a base class of its declaring class.
1309db73c684ba61fed4087af488e8610657ec638c17John McCall  AccessSpecifier FinalAccess;
13106b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
13116b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  if (Entity.isMemberAccess()) {
1312db73c684ba61fed4087af488e8610657ec638c17John McCall    // Determine if the declaration is accessible from EC when named
1313db73c684ba61fed4087af488e8610657ec638c17John McCall    // in its declaring class.
13146b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    NamedDecl *Target = Entity.getTargetDecl();
1315161755a09898c95d21bfff33707da9ca41cd53c5John McCall    const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();
13166b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
1317db73c684ba61fed4087af488e8610657ec638c17John McCall    FinalAccess = Target->getAccess();
1318161755a09898c95d21bfff33707da9ca41cd53c5John McCall    switch (HasAccess(S, EC, DeclaringClass, FinalAccess, Entity)) {
1319161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case AR_accessible:
1320161755a09898c95d21bfff33707da9ca41cd53c5John McCall      FinalAccess = AS_public;
1321161755a09898c95d21bfff33707da9ca41cd53c5John McCall      break;
1322161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case AR_inaccessible: break;
1323161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case AR_dependent: return AR_dependent; // see above
13246b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    }
13252f514480c448708ec382a684cf5e035d3a827ec8John McCall
1326db73c684ba61fed4087af488e8610657ec638c17John McCall    if (DeclaringClass == NamingClass)
1327161755a09898c95d21bfff33707da9ca41cd53c5John McCall      return (FinalAccess == AS_public ? AR_accessible : AR_inaccessible);
1328161755a09898c95d21bfff33707da9ca41cd53c5John McCall
1329161755a09898c95d21bfff33707da9ca41cd53c5John McCall    Entity.suppressInstanceContext();
1330db73c684ba61fed4087af488e8610657ec638c17John McCall  } else {
1331db73c684ba61fed4087af488e8610657ec638c17John McCall    FinalAccess = AS_public;
13326b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  }
13332f514480c448708ec382a684cf5e035d3a827ec8John McCall
1334161755a09898c95d21bfff33707da9ca41cd53c5John McCall  assert(Entity.getDeclaringClass() != NamingClass);
13356b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
13366b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  // Append the declaration's access if applicable.
13376b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  CXXBasePaths Paths;
1338161755a09898c95d21bfff33707da9ca41cd53c5John McCall  CXXBasePath *Path = FindBestPath(S, EC, Entity, FinalAccess, Paths);
13390c01d18094100db92d38daa923c95661512db203John McCall  if (!Path)
1340161755a09898c95d21bfff33707da9ca41cd53c5John McCall    return AR_dependent;
134192f883177b162928a8e632e4e3b93fafd2b26072John McCall
1342db73c684ba61fed4087af488e8610657ec638c17John McCall  assert(Path->Access <= UnprivilegedAccess &&
1343db73c684ba61fed4087af488e8610657ec638c17John McCall         "access along best path worse than direct?");
1344db73c684ba61fed4087af488e8610657ec638c17John McCall  if (Path->Access == AS_public)
1345161755a09898c95d21bfff33707da9ca41cd53c5John McCall    return AR_accessible;
1346161755a09898c95d21bfff33707da9ca41cd53c5John McCall  return AR_inaccessible;
13470c01d18094100db92d38daa923c95661512db203John McCall}
13480c01d18094100db92d38daa923c95661512db203John McCall
1349161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic void DelayDependentAccess(Sema &S,
1350161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                 const EffectiveContext &EC,
1351161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                 SourceLocation Loc,
1352161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                 const AccessTarget &Entity) {
13530c01d18094100db92d38daa923c95661512db203John McCall  assert(EC.isDependent() && "delaying non-dependent access");
13547ad650f88ecbbe659f10f9f6b34a1f29ea9cf8f9John McCall  DeclContext *DC = EC.getInnerContext();
13550c01d18094100db92d38daa923c95661512db203John McCall  assert(DC->isDependentContext() && "delaying non-dependent access");
13560c01d18094100db92d38daa923c95661512db203John McCall  DependentDiagnostic::Create(S.Context, DC, DependentDiagnostic::Access,
13570c01d18094100db92d38daa923c95661512db203John McCall                              Loc,
13580c01d18094100db92d38daa923c95661512db203John McCall                              Entity.isMemberAccess(),
13590c01d18094100db92d38daa923c95661512db203John McCall                              Entity.getAccess(),
13600c01d18094100db92d38daa923c95661512db203John McCall                              Entity.getTargetDecl(),
13610c01d18094100db92d38daa923c95661512db203John McCall                              Entity.getNamingClass(),
1362161755a09898c95d21bfff33707da9ca41cd53c5John McCall                              Entity.getBaseObjectType(),
13630c01d18094100db92d38daa923c95661512db203John McCall                              Entity.getDiag());
13646b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall}
13656b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
13666b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// Checks access to an entity from the given effective context.
1367161755a09898c95d21bfff33707da9ca41cd53c5John McCallstatic AccessResult CheckEffectiveAccess(Sema &S,
1368161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                         const EffectiveContext &EC,
1369161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                         SourceLocation Loc,
1370161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                         AccessTarget &Entity) {
1371db73c684ba61fed4087af488e8610657ec638c17John McCall  assert(Entity.getAccess() != AS_public && "called for public access!");
137292f883177b162928a8e632e4e3b93fafd2b26072John McCall
13734e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie  if (S.getLangOpts().MicrosoftMode &&
1374b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichet      IsMicrosoftUsingDeclarationAccessBug(S, Loc, Entity))
1375b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichet    return AR_accessible;
1376b2ee8305f878259613b65d0f96a03f7f852977eaFrancois Pichet
1377db73c684ba61fed4087af488e8610657ec638c17John McCall  switch (IsAccessible(S, EC, Entity)) {
1378161755a09898c95d21bfff33707da9ca41cd53c5John McCall  case AR_dependent:
1379161755a09898c95d21bfff33707da9ca41cd53c5John McCall    DelayDependentAccess(S, EC, Loc, Entity);
1380161755a09898c95d21bfff33707da9ca41cd53c5John McCall    return AR_dependent;
13810c01d18094100db92d38daa923c95661512db203John McCall
1382161755a09898c95d21bfff33707da9ca41cd53c5John McCall  case AR_inaccessible:
1383db73c684ba61fed4087af488e8610657ec638c17John McCall    if (!Entity.isQuiet())
1384db73c684ba61fed4087af488e8610657ec638c17John McCall      DiagnoseBadAccess(S, Loc, EC, Entity);
1385161755a09898c95d21bfff33707da9ca41cd53c5John McCall    return AR_inaccessible;
138692f883177b162928a8e632e4e3b93fafd2b26072John McCall
1387161755a09898c95d21bfff33707da9ca41cd53c5John McCall  case AR_accessible:
1388161755a09898c95d21bfff33707da9ca41cd53c5John McCall    return AR_accessible;
1389db73c684ba61fed4087af488e8610657ec638c17John McCall  }
1390db73c684ba61fed4087af488e8610657ec638c17John McCall
1391161755a09898c95d21bfff33707da9ca41cd53c5John McCall  // silence unnecessary warning
1392161755a09898c95d21bfff33707da9ca41cd53c5John McCall  llvm_unreachable("invalid access result");
13936b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall}
139492f883177b162928a8e632e4e3b93fafd2b26072John McCall
13956b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallstatic Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc,
1396161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                      AccessTarget &Entity) {
13976b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  // If the access path is public, it's accessible everywhere.
13986b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  if (Entity.getAccess() == AS_public)
13996b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    return Sema::AR_accessible;
140092f883177b162928a8e632e4e3b93fafd2b26072John McCall
1401eee1d5434ebfa955ffc3c493aecd68bb7b3f4838John McCall  // If we're currently parsing a declaration, we may need to delay
1402eee1d5434ebfa955ffc3c493aecd68bb7b3f4838John McCall  // access control checking, because our effective context might be
1403eee1d5434ebfa955ffc3c493aecd68bb7b3f4838John McCall  // different based on what the declaration comes out as.
1404eee1d5434ebfa955ffc3c493aecd68bb7b3f4838John McCall  //
1405eee1d5434ebfa955ffc3c493aecd68bb7b3f4838John McCall  // For example, we might be parsing a declaration with a scope
1406eee1d5434ebfa955ffc3c493aecd68bb7b3f4838John McCall  // specifier, like this:
1407eee1d5434ebfa955ffc3c493aecd68bb7b3f4838John McCall  //   A::private_type A::foo() { ... }
1408eee1d5434ebfa955ffc3c493aecd68bb7b3f4838John McCall  //
1409eee1d5434ebfa955ffc3c493aecd68bb7b3f4838John McCall  // Or we might be parsing something that will turn out to be a friend:
1410eee1d5434ebfa955ffc3c493aecd68bb7b3f4838John McCall  //   void foo(A::private_type);
1411eee1d5434ebfa955ffc3c493aecd68bb7b3f4838John McCall  //   void B::foo(A::private_type);
1412eee1d5434ebfa955ffc3c493aecd68bb7b3f4838John McCall  if (S.DelayedDiagnostics.shouldDelayDiagnostics()) {
1413eee1d5434ebfa955ffc3c493aecd68bb7b3f4838John McCall    S.DelayedDiagnostics.add(DelayedDiagnostic::makeAccess(Loc, Entity));
14146b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    return Sema::AR_delayed;
141592f883177b162928a8e632e4e3b93fafd2b26072John McCall  }
141692f883177b162928a8e632e4e3b93fafd2b26072John McCall
1417161755a09898c95d21bfff33707da9ca41cd53c5John McCall  EffectiveContext EC(S.CurContext);
1418161755a09898c95d21bfff33707da9ca41cd53c5John McCall  switch (CheckEffectiveAccess(S, EC, Loc, Entity)) {
1419161755a09898c95d21bfff33707da9ca41cd53c5John McCall  case AR_accessible: return Sema::AR_accessible;
1420161755a09898c95d21bfff33707da9ca41cd53c5John McCall  case AR_inaccessible: return Sema::AR_inaccessible;
1421161755a09898c95d21bfff33707da9ca41cd53c5John McCall  case AR_dependent: return Sema::AR_dependent;
1422161755a09898c95d21bfff33707da9ca41cd53c5John McCall  }
1423161755a09898c95d21bfff33707da9ca41cd53c5John McCall  llvm_unreachable("falling off end");
142492f883177b162928a8e632e4e3b93fafd2b26072John McCall}
142592f883177b162928a8e632e4e3b93fafd2b26072John McCall
14264bfd680597862e437fcba739dce58531d0b15d6eJohn McCallvoid Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *decl) {
14274bfd680597862e437fcba739dce58531d0b15d6eJohn McCall  // Access control for names used in the declarations of functions
14284bfd680597862e437fcba739dce58531d0b15d6eJohn McCall  // and function templates should normally be evaluated in the context
14294bfd680597862e437fcba739dce58531d0b15d6eJohn McCall  // of the declaration, just in case it's a friend of something.
14304bfd680597862e437fcba739dce58531d0b15d6eJohn McCall  // However, this does not apply to local extern declarations.
14314bfd680597862e437fcba739dce58531d0b15d6eJohn McCall
14324bfd680597862e437fcba739dce58531d0b15d6eJohn McCall  DeclContext *DC = decl->getDeclContext();
14334bfd680597862e437fcba739dce58531d0b15d6eJohn McCall  if (FunctionDecl *fn = dyn_cast<FunctionDecl>(decl)) {
14344bfd680597862e437fcba739dce58531d0b15d6eJohn McCall    if (!DC->isFunctionOrMethod()) DC = fn;
14354bfd680597862e437fcba739dce58531d0b15d6eJohn McCall  } else if (FunctionTemplateDecl *fnt = dyn_cast<FunctionTemplateDecl>(decl)) {
14364bfd680597862e437fcba739dce58531d0b15d6eJohn McCall    // Never a local declaration.
14374bfd680597862e437fcba739dce58531d0b15d6eJohn McCall    DC = fnt->getTemplatedDecl();
14384bfd680597862e437fcba739dce58531d0b15d6eJohn McCall  }
14394bfd680597862e437fcba739dce58531d0b15d6eJohn McCall
1440630eb01b2568d0958118eb1a0ded02bebecb2b0fChandler Carruth  EffectiveContext EC(DC);
14412f514480c448708ec382a684cf5e035d3a827ec8John McCall
1442161755a09898c95d21bfff33707da9ca41cd53c5John McCall  AccessTarget Target(DD.getAccessData());
1443161755a09898c95d21bfff33707da9ca41cd53c5John McCall
1444161755a09898c95d21bfff33707da9ca41cd53c5John McCall  if (CheckEffectiveAccess(*this, EC, DD.Loc, Target) == ::AR_inaccessible)
14452f514480c448708ec382a684cf5e035d3a827ec8John McCall    DD.Triggered = true;
14462f514480c448708ec382a684cf5e035d3a827ec8John McCall}
14472f514480c448708ec382a684cf5e035d3a827ec8John McCall
14480c01d18094100db92d38daa923c95661512db203John McCallvoid Sema::HandleDependentAccessCheck(const DependentDiagnostic &DD,
14490c01d18094100db92d38daa923c95661512db203John McCall                        const MultiLevelTemplateArgumentList &TemplateArgs) {
14500c01d18094100db92d38daa923c95661512db203John McCall  SourceLocation Loc = DD.getAccessLoc();
14510c01d18094100db92d38daa923c95661512db203John McCall  AccessSpecifier Access = DD.getAccess();
14520c01d18094100db92d38daa923c95661512db203John McCall
14530c01d18094100db92d38daa923c95661512db203John McCall  Decl *NamingD = FindInstantiatedDecl(Loc, DD.getAccessNamingClass(),
14540c01d18094100db92d38daa923c95661512db203John McCall                                       TemplateArgs);
14550c01d18094100db92d38daa923c95661512db203John McCall  if (!NamingD) return;
14560c01d18094100db92d38daa923c95661512db203John McCall  Decl *TargetD = FindInstantiatedDecl(Loc, DD.getAccessTarget(),
14570c01d18094100db92d38daa923c95661512db203John McCall                                       TemplateArgs);
14580c01d18094100db92d38daa923c95661512db203John McCall  if (!TargetD) return;
14590c01d18094100db92d38daa923c95661512db203John McCall
14600c01d18094100db92d38daa923c95661512db203John McCall  if (DD.isAccessToMember()) {
1461161755a09898c95d21bfff33707da9ca41cd53c5John McCall    CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(NamingD);
1462161755a09898c95d21bfff33707da9ca41cd53c5John McCall    NamedDecl *TargetDecl = cast<NamedDecl>(TargetD);
1463161755a09898c95d21bfff33707da9ca41cd53c5John McCall    QualType BaseObjectType = DD.getAccessBaseObjectType();
1464161755a09898c95d21bfff33707da9ca41cd53c5John McCall    if (!BaseObjectType.isNull()) {
1465161755a09898c95d21bfff33707da9ca41cd53c5John McCall      BaseObjectType = SubstType(BaseObjectType, TemplateArgs, Loc,
1466161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                 DeclarationName());
1467161755a09898c95d21bfff33707da9ca41cd53c5John McCall      if (BaseObjectType.isNull()) return;
1468161755a09898c95d21bfff33707da9ca41cd53c5John McCall    }
1469161755a09898c95d21bfff33707da9ca41cd53c5John McCall
1470161755a09898c95d21bfff33707da9ca41cd53c5John McCall    AccessTarget Entity(Context,
1471161755a09898c95d21bfff33707da9ca41cd53c5John McCall                        AccessTarget::Member,
1472161755a09898c95d21bfff33707da9ca41cd53c5John McCall                        NamingClass,
1473161755a09898c95d21bfff33707da9ca41cd53c5John McCall                        DeclAccessPair::make(TargetDecl, Access),
1474161755a09898c95d21bfff33707da9ca41cd53c5John McCall                        BaseObjectType);
14750c01d18094100db92d38daa923c95661512db203John McCall    Entity.setDiag(DD.getDiagnostic());
14760c01d18094100db92d38daa923c95661512db203John McCall    CheckAccess(*this, Loc, Entity);
14770c01d18094100db92d38daa923c95661512db203John McCall  } else {
1478161755a09898c95d21bfff33707da9ca41cd53c5John McCall    AccessTarget Entity(Context,
1479161755a09898c95d21bfff33707da9ca41cd53c5John McCall                        AccessTarget::Base,
1480161755a09898c95d21bfff33707da9ca41cd53c5John McCall                        cast<CXXRecordDecl>(TargetD),
1481161755a09898c95d21bfff33707da9ca41cd53c5John McCall                        cast<CXXRecordDecl>(NamingD),
1482161755a09898c95d21bfff33707da9ca41cd53c5John McCall                        Access);
14830c01d18094100db92d38daa923c95661512db203John McCall    Entity.setDiag(DD.getDiagnostic());
14840c01d18094100db92d38daa923c95661512db203John McCall    CheckAccess(*this, Loc, Entity);
14850c01d18094100db92d38daa923c95661512db203John McCall  }
14860c01d18094100db92d38daa923c95661512db203John McCall}
14870c01d18094100db92d38daa923c95661512db203John McCall
14886b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallSema::AccessResult Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E,
14899aa472c45d2bd81b7b52c225e8acc560d716db97John McCall                                                     DeclAccessPair Found) {
14904e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie  if (!getLangOpts().AccessControl ||
149158e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall      !E->getNamingClass() ||
14929aa472c45d2bd81b7b52c225e8acc560d716db97John McCall      Found.getAccess() == AS_public)
14936b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    return AR_accessible;
1494c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall
1495161755a09898c95d21bfff33707da9ca41cd53c5John McCall  AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(),
1496161755a09898c95d21bfff33707da9ca41cd53c5John McCall                      Found, QualType());
149758e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall  Entity.setDiag(diag::err_access) << E->getSourceRange();
149858e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall
149958e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall  return CheckAccess(*this, E->getNameLoc(), Entity);
1500c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall}
1501c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall
1502c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall/// Perform access-control checking on a previously-unresolved member
1503c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall/// access which has now been resolved to a member.
15046b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallSema::AccessResult Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E,
15059aa472c45d2bd81b7b52c225e8acc560d716db97John McCall                                                     DeclAccessPair Found) {
15064e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie  if (!getLangOpts().AccessControl ||
15079aa472c45d2bd81b7b52c225e8acc560d716db97John McCall      Found.getAccess() == AS_public)
15086b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    return AR_accessible;
1509c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall
1510161755a09898c95d21bfff33707da9ca41cd53c5John McCall  QualType BaseType = E->getBaseType();
1511161755a09898c95d21bfff33707da9ca41cd53c5John McCall  if (E->isArrow())
1512161755a09898c95d21bfff33707da9ca41cd53c5John McCall    BaseType = BaseType->getAs<PointerType>()->getPointeeType();
1513161755a09898c95d21bfff33707da9ca41cd53c5John McCall
1514161755a09898c95d21bfff33707da9ca41cd53c5John McCall  AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(),
1515161755a09898c95d21bfff33707da9ca41cd53c5John McCall                      Found, BaseType);
151658e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall  Entity.setDiag(diag::err_access) << E->getSourceRange();
151758e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall
151858e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall  return CheckAccess(*this, E->getMemberLoc(), Entity);
1519c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall}
1520c373d48502ca7683ab55385f5bd624d778eb288dJohn McCall
152112d8d80fb0f8d9cddecb34da0f37b0dc9fcaf5e6John McCall/// Is the given special member function accessible for the purposes of
152212d8d80fb0f8d9cddecb34da0f37b0dc9fcaf5e6John McCall/// deciding whether to define a special member function as deleted?
152312d8d80fb0f8d9cddecb34da0f37b0dc9fcaf5e6John McCallbool Sema::isSpecialMemberAccessibleForDeletion(CXXMethodDecl *decl,
152412d8d80fb0f8d9cddecb34da0f37b0dc9fcaf5e6John McCall                                                AccessSpecifier access,
152512d8d80fb0f8d9cddecb34da0f37b0dc9fcaf5e6John McCall                                                QualType objectType) {
152612d8d80fb0f8d9cddecb34da0f37b0dc9fcaf5e6John McCall  // Fast path.
152712d8d80fb0f8d9cddecb34da0f37b0dc9fcaf5e6John McCall  if (access == AS_public || !getLangOpts().AccessControl) return true;
152812d8d80fb0f8d9cddecb34da0f37b0dc9fcaf5e6John McCall
152912d8d80fb0f8d9cddecb34da0f37b0dc9fcaf5e6John McCall  AccessTarget entity(Context, AccessTarget::Member, decl->getParent(),
153012d8d80fb0f8d9cddecb34da0f37b0dc9fcaf5e6John McCall                      DeclAccessPair::make(decl, access), objectType);
153112d8d80fb0f8d9cddecb34da0f37b0dc9fcaf5e6John McCall
153212d8d80fb0f8d9cddecb34da0f37b0dc9fcaf5e6John McCall  // Suppress diagnostics.
153312d8d80fb0f8d9cddecb34da0f37b0dc9fcaf5e6John McCall  entity.setDiag(PDiag());
153412d8d80fb0f8d9cddecb34da0f37b0dc9fcaf5e6John McCall
153512d8d80fb0f8d9cddecb34da0f37b0dc9fcaf5e6John McCall  switch (CheckAccess(*this, SourceLocation(), entity)) {
153612d8d80fb0f8d9cddecb34da0f37b0dc9fcaf5e6John McCall  case AR_accessible: return true;
153712d8d80fb0f8d9cddecb34da0f37b0dc9fcaf5e6John McCall  case AR_inaccessible: return false;
153812d8d80fb0f8d9cddecb34da0f37b0dc9fcaf5e6John McCall  case AR_dependent: llvm_unreachable("dependent for =delete computation");
153912d8d80fb0f8d9cddecb34da0f37b0dc9fcaf5e6John McCall  case AR_delayed: llvm_unreachable("cannot delay =delete computation");
154012d8d80fb0f8d9cddecb34da0f37b0dc9fcaf5e6John McCall  }
154112d8d80fb0f8d9cddecb34da0f37b0dc9fcaf5e6John McCall  llvm_unreachable("bad access result");
154212d8d80fb0f8d9cddecb34da0f37b0dc9fcaf5e6John McCall}
154312d8d80fb0f8d9cddecb34da0f37b0dc9fcaf5e6John McCall
15446b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallSema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc,
154558e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall                                               CXXDestructorDecl *Dtor,
1546b9abd87283ac6e929b7e12a577663bc99e61d020John McCall                                               const PartialDiagnostic &PDiag,
1547b9abd87283ac6e929b7e12a577663bc99e61d020John McCall                                               QualType ObjectTy) {
15484e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie  if (!getLangOpts().AccessControl)
15496b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    return AR_accessible;
15504f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall
155158e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall  // There's never a path involved when checking implicit destructor access.
15524f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall  AccessSpecifier Access = Dtor->getAccess();
15534f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall  if (Access == AS_public)
15546b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    return AR_accessible;
15554f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall
155658e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall  CXXRecordDecl *NamingClass = Dtor->getParent();
1557b9abd87283ac6e929b7e12a577663bc99e61d020John McCall  if (ObjectTy.isNull()) ObjectTy = Context.getTypeDeclType(NamingClass);
1558b9abd87283ac6e929b7e12a577663bc99e61d020John McCall
1559161755a09898c95d21bfff33707da9ca41cd53c5John McCall  AccessTarget Entity(Context, AccessTarget::Member, NamingClass,
1560161755a09898c95d21bfff33707da9ca41cd53c5John McCall                      DeclAccessPair::make(Dtor, Access),
1561b9abd87283ac6e929b7e12a577663bc99e61d020John McCall                      ObjectTy);
156258e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall  Entity.setDiag(PDiag); // TODO: avoid copy
156358e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall
156458e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall  return CheckAccess(*this, Loc, Entity);
15654f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall}
15664f9506a27cb6b865bf38beea48eadfa9dc93f510John McCall
1567b13b737a2450167c82e148590e8019b839ce6b98John McCall/// Checks access to a constructor.
15686b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallSema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc,
156957d12fd4a2bc739c4a4d62a364b7f08cd483c59eJeffrey Yasskin                                                CXXConstructorDecl *Constructor,
157057d12fd4a2bc739c4a4d62a364b7f08cd483c59eJeffrey Yasskin                                                const InitializedEntity &Entity,
157157d12fd4a2bc739c4a4d62a364b7f08cd483c59eJeffrey Yasskin                                                AccessSpecifier Access,
157257d12fd4a2bc739c4a4d62a364b7f08cd483c59eJeffrey Yasskin                                                bool IsCopyBindingRefToTemp) {
1573b9abd87283ac6e929b7e12a577663bc99e61d020John McCall  if (!getLangOpts().AccessControl || Access == AS_public)
15746b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    return AR_accessible;
1575b13b737a2450167c82e148590e8019b839ce6b98John McCall
1576b320e0c322fb71d6235ebca9ec22940a97bdcdc7Sean Hunt  PartialDiagnostic PD(PDiag());
15779a68a67c6ae4982001815cc04f69b8781058263aAnders Carlsson  switch (Entity.getKind()) {
15789a68a67c6ae4982001815cc04f69b8781058263aAnders Carlsson  default:
1579b320e0c322fb71d6235ebca9ec22940a97bdcdc7Sean Hunt    PD = PDiag(IsCopyBindingRefToTemp
1580b320e0c322fb71d6235ebca9ec22940a97bdcdc7Sean Hunt                 ? diag::ext_rvalue_to_reference_access_ctor
1581b320e0c322fb71d6235ebca9ec22940a97bdcdc7Sean Hunt                 : diag::err_access_ctor);
1582b320e0c322fb71d6235ebca9ec22940a97bdcdc7Sean Hunt
15839a68a67c6ae4982001815cc04f69b8781058263aAnders Carlsson    break;
15849a68a67c6ae4982001815cc04f69b8781058263aAnders Carlsson
15853b8c53b619c1c3d77632734d227566071459b9f5Anders Carlsson  case InitializedEntity::EK_Base:
1586b320e0c322fb71d6235ebca9ec22940a97bdcdc7Sean Hunt    PD = PDiag(diag::err_access_base_ctor);
1587b320e0c322fb71d6235ebca9ec22940a97bdcdc7Sean Hunt    PD << Entity.isInheritedVirtualBase()
1588b320e0c322fb71d6235ebca9ec22940a97bdcdc7Sean Hunt       << Entity.getBaseSpecifier()->getType() << getSpecialMember(Constructor);
15899a68a67c6ae4982001815cc04f69b8781058263aAnders Carlsson    break;
15903b8c53b619c1c3d77632734d227566071459b9f5Anders Carlsson
1591b99c666a940e93bcfcaeddc01515c94472e28a20Anders Carlsson  case InitializedEntity::EK_Member: {
1592b99c666a940e93bcfcaeddc01515c94472e28a20Anders Carlsson    const FieldDecl *Field = cast<FieldDecl>(Entity.getDecl());
1593b320e0c322fb71d6235ebca9ec22940a97bdcdc7Sean Hunt    PD = PDiag(diag::err_access_field_ctor);
1594b320e0c322fb71d6235ebca9ec22940a97bdcdc7Sean Hunt    PD << Field->getType() << getSpecialMember(Constructor);
1595b99c666a940e93bcfcaeddc01515c94472e28a20Anders Carlsson    break;
1596b99c666a940e93bcfcaeddc01515c94472e28a20Anders Carlsson  }
159758e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall
15984773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor  case InitializedEntity::EK_LambdaCapture: {
15994773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor    const VarDecl *Var = Entity.getCapturedVar();
16004773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor    PD = PDiag(diag::err_access_lambda_capture);
16014773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor    PD << Var->getName() << Entity.getType() << getSpecialMember(Constructor);
16024773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor    break;
16034773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor  }
16044773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor
1605711f34adb886cce8ba86c7b1b6513a1eaaf63bb5Anders Carlsson  }
1606711f34adb886cce8ba86c7b1b6513a1eaaf63bb5Anders Carlsson
1607b9abd87283ac6e929b7e12a577663bc99e61d020John McCall  return CheckConstructorAccess(UseLoc, Constructor, Entity, Access, PD);
1608b320e0c322fb71d6235ebca9ec22940a97bdcdc7Sean Hunt}
1609b320e0c322fb71d6235ebca9ec22940a97bdcdc7Sean Hunt
1610b320e0c322fb71d6235ebca9ec22940a97bdcdc7Sean Hunt/// Checks access to a constructor.
1611b320e0c322fb71d6235ebca9ec22940a97bdcdc7Sean HuntSema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc,
1612b320e0c322fb71d6235ebca9ec22940a97bdcdc7Sean Hunt                                                CXXConstructorDecl *Constructor,
1613b9abd87283ac6e929b7e12a577663bc99e61d020John McCall                                                const InitializedEntity &Entity,
1614b320e0c322fb71d6235ebca9ec22940a97bdcdc7Sean Hunt                                                AccessSpecifier Access,
1615b9abd87283ac6e929b7e12a577663bc99e61d020John McCall                                                const PartialDiagnostic &PD) {
16164e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie  if (!getLangOpts().AccessControl ||
1617b320e0c322fb71d6235ebca9ec22940a97bdcdc7Sean Hunt      Access == AS_public)
1618b320e0c322fb71d6235ebca9ec22940a97bdcdc7Sean Hunt    return AR_accessible;
1619b320e0c322fb71d6235ebca9ec22940a97bdcdc7Sean Hunt
1620b320e0c322fb71d6235ebca9ec22940a97bdcdc7Sean Hunt  CXXRecordDecl *NamingClass = Constructor->getParent();
1621b9abd87283ac6e929b7e12a577663bc99e61d020John McCall
1622b9abd87283ac6e929b7e12a577663bc99e61d020John McCall  // Initializing a base sub-object is an instance method call on an
1623b9abd87283ac6e929b7e12a577663bc99e61d020John McCall  // object of the derived class.  Otherwise, we have an instance method
1624b9abd87283ac6e929b7e12a577663bc99e61d020John McCall  // call on an object of the constructed type.
1625b9abd87283ac6e929b7e12a577663bc99e61d020John McCall  CXXRecordDecl *ObjectClass;
1626b9abd87283ac6e929b7e12a577663bc99e61d020John McCall  if (Entity.getKind() == InitializedEntity::EK_Base) {
1627b9abd87283ac6e929b7e12a577663bc99e61d020John McCall    ObjectClass = cast<CXXConstructorDecl>(CurContext)->getParent();
1628b9abd87283ac6e929b7e12a577663bc99e61d020John McCall  } else {
1629b9abd87283ac6e929b7e12a577663bc99e61d020John McCall    ObjectClass = NamingClass;
1630b9abd87283ac6e929b7e12a577663bc99e61d020John McCall  }
1631b9abd87283ac6e929b7e12a577663bc99e61d020John McCall
1632b320e0c322fb71d6235ebca9ec22940a97bdcdc7Sean Hunt  AccessTarget AccessEntity(Context, AccessTarget::Member, NamingClass,
1633b320e0c322fb71d6235ebca9ec22940a97bdcdc7Sean Hunt                            DeclAccessPair::make(Constructor, Access),
1634b9abd87283ac6e929b7e12a577663bc99e61d020John McCall                            Context.getTypeDeclType(ObjectClass));
1635b320e0c322fb71d6235ebca9ec22940a97bdcdc7Sean Hunt  AccessEntity.setDiag(PD);
1636b320e0c322fb71d6235ebca9ec22940a97bdcdc7Sean Hunt
16379a68a67c6ae4982001815cc04f69b8781058263aAnders Carlsson  return CheckAccess(*this, UseLoc, AccessEntity);
1638b9abd87283ac6e929b7e12a577663bc99e61d020John McCall}
1639b13b737a2450167c82e148590e8019b839ce6b98John McCall
164090c8c57bcd84083df85f76aac2aa62acb85eb077John McCall/// Checks access to an overloaded operator new or delete.
164190c8c57bcd84083df85f76aac2aa62acb85eb077John McCallSema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc,
164290c8c57bcd84083df85f76aac2aa62acb85eb077John McCall                                               SourceRange PlacementRange,
164390c8c57bcd84083df85f76aac2aa62acb85eb077John McCall                                               CXXRecordDecl *NamingClass,
1644cb45a0f42964ab5fa1474b25abcc1ae3a8bd0ab8Sean Hunt                                               DeclAccessPair Found,
1645cb45a0f42964ab5fa1474b25abcc1ae3a8bd0ab8Sean Hunt                                               bool Diagnose) {
16464e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie  if (!getLangOpts().AccessControl ||
164790c8c57bcd84083df85f76aac2aa62acb85eb077John McCall      !NamingClass ||
16489aa472c45d2bd81b7b52c225e8acc560d716db97John McCall      Found.getAccess() == AS_public)
164990c8c57bcd84083df85f76aac2aa62acb85eb077John McCall    return AR_accessible;
165090c8c57bcd84083df85f76aac2aa62acb85eb077John McCall
1651161755a09898c95d21bfff33707da9ca41cd53c5John McCall  AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
1652161755a09898c95d21bfff33707da9ca41cd53c5John McCall                      QualType());
1653cb45a0f42964ab5fa1474b25abcc1ae3a8bd0ab8Sean Hunt  if (Diagnose)
1654cb45a0f42964ab5fa1474b25abcc1ae3a8bd0ab8Sean Hunt    Entity.setDiag(diag::err_access)
1655cb45a0f42964ab5fa1474b25abcc1ae3a8bd0ab8Sean Hunt      << PlacementRange;
165690c8c57bcd84083df85f76aac2aa62acb85eb077John McCall
165790c8c57bcd84083df85f76aac2aa62acb85eb077John McCall  return CheckAccess(*this, OpLoc, Entity);
165890c8c57bcd84083df85f76aac2aa62acb85eb077John McCall}
165990c8c57bcd84083df85f76aac2aa62acb85eb077John McCall
1660b13b737a2450167c82e148590e8019b839ce6b98John McCall/// Checks access to an overloaded member operator, including
1661b13b737a2450167c82e148590e8019b839ce6b98John McCall/// conversion operators.
16626b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallSema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc,
16636b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall                                                   Expr *ObjectExpr,
166458e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall                                                   Expr *ArgExpr,
16659aa472c45d2bd81b7b52c225e8acc560d716db97John McCall                                                   DeclAccessPair Found) {
16664e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie  if (!getLangOpts().AccessControl ||
16679aa472c45d2bd81b7b52c225e8acc560d716db97John McCall      Found.getAccess() == AS_public)
16686b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    return AR_accessible;
16695357b615364c17ea024c757354c58ae2a520d216John McCall
1670ca82a82082edc982a1fb5fcfef2dd2c8cf9bc824John McCall  const RecordType *RT = ObjectExpr->getType()->castAs<RecordType>();
16715357b615364c17ea024c757354c58ae2a520d216John McCall  CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(RT->getDecl());
16725357b615364c17ea024c757354c58ae2a520d216John McCall
1673161755a09898c95d21bfff33707da9ca41cd53c5John McCall  AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
1674161755a09898c95d21bfff33707da9ca41cd53c5John McCall                      ObjectExpr->getType());
167558e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall  Entity.setDiag(diag::err_access)
167658e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall    << ObjectExpr->getSourceRange()
167758e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall    << (ArgExpr ? ArgExpr->getSourceRange() : SourceRange());
167858e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall
167958e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall  return CheckAccess(*this, OpLoc, Entity);
16806b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall}
16815357b615364c17ea024c757354c58ae2a520d216John McCall
16821f2e1a96bec2ba6418ae7f2d2b525a3575203b6aJohn McCall/// Checks access to the target of a friend declaration.
16831f2e1a96bec2ba6418ae7f2d2b525a3575203b6aJohn McCallSema::AccessResult Sema::CheckFriendAccess(NamedDecl *target) {
16841f2e1a96bec2ba6418ae7f2d2b525a3575203b6aJohn McCall  assert(isa<CXXMethodDecl>(target) ||
16851f2e1a96bec2ba6418ae7f2d2b525a3575203b6aJohn McCall         (isa<FunctionTemplateDecl>(target) &&
16861f2e1a96bec2ba6418ae7f2d2b525a3575203b6aJohn McCall          isa<CXXMethodDecl>(cast<FunctionTemplateDecl>(target)
16871f2e1a96bec2ba6418ae7f2d2b525a3575203b6aJohn McCall                               ->getTemplatedDecl())));
16881f2e1a96bec2ba6418ae7f2d2b525a3575203b6aJohn McCall
16891f2e1a96bec2ba6418ae7f2d2b525a3575203b6aJohn McCall  // Friendship lookup is a redeclaration lookup, so there's never an
16901f2e1a96bec2ba6418ae7f2d2b525a3575203b6aJohn McCall  // inheritance path modifying access.
16911f2e1a96bec2ba6418ae7f2d2b525a3575203b6aJohn McCall  AccessSpecifier access = target->getAccess();
16921f2e1a96bec2ba6418ae7f2d2b525a3575203b6aJohn McCall
16931f2e1a96bec2ba6418ae7f2d2b525a3575203b6aJohn McCall  if (!getLangOpts().AccessControl || access == AS_public)
16941f2e1a96bec2ba6418ae7f2d2b525a3575203b6aJohn McCall    return AR_accessible;
16951f2e1a96bec2ba6418ae7f2d2b525a3575203b6aJohn McCall
16961f2e1a96bec2ba6418ae7f2d2b525a3575203b6aJohn McCall  CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(target);
16971f2e1a96bec2ba6418ae7f2d2b525a3575203b6aJohn McCall  if (!method)
16981f2e1a96bec2ba6418ae7f2d2b525a3575203b6aJohn McCall    method = cast<CXXMethodDecl>(
16991f2e1a96bec2ba6418ae7f2d2b525a3575203b6aJohn McCall                     cast<FunctionTemplateDecl>(target)->getTemplatedDecl());
17001f2e1a96bec2ba6418ae7f2d2b525a3575203b6aJohn McCall  assert(method->getQualifier());
17011f2e1a96bec2ba6418ae7f2d2b525a3575203b6aJohn McCall
17021f2e1a96bec2ba6418ae7f2d2b525a3575203b6aJohn McCall  AccessTarget entity(Context, AccessTarget::Member,
17031f2e1a96bec2ba6418ae7f2d2b525a3575203b6aJohn McCall                      cast<CXXRecordDecl>(target->getDeclContext()),
17041f2e1a96bec2ba6418ae7f2d2b525a3575203b6aJohn McCall                      DeclAccessPair::make(target, access),
17051f2e1a96bec2ba6418ae7f2d2b525a3575203b6aJohn McCall                      /*no instance context*/ QualType());
17061f2e1a96bec2ba6418ae7f2d2b525a3575203b6aJohn McCall  entity.setDiag(diag::err_access_friend_function)
17071f2e1a96bec2ba6418ae7f2d2b525a3575203b6aJohn McCall    << method->getQualifierLoc().getSourceRange();
17081f2e1a96bec2ba6418ae7f2d2b525a3575203b6aJohn McCall
17091f2e1a96bec2ba6418ae7f2d2b525a3575203b6aJohn McCall  // We need to bypass delayed-diagnostics because we might be called
17101f2e1a96bec2ba6418ae7f2d2b525a3575203b6aJohn McCall  // while the ParsingDeclarator is active.
17111f2e1a96bec2ba6418ae7f2d2b525a3575203b6aJohn McCall  EffectiveContext EC(CurContext);
17121f2e1a96bec2ba6418ae7f2d2b525a3575203b6aJohn McCall  switch (CheckEffectiveAccess(*this, EC, target->getLocation(), entity)) {
17131f2e1a96bec2ba6418ae7f2d2b525a3575203b6aJohn McCall  case AR_accessible: return Sema::AR_accessible;
17141f2e1a96bec2ba6418ae7f2d2b525a3575203b6aJohn McCall  case AR_inaccessible: return Sema::AR_inaccessible;
17151f2e1a96bec2ba6418ae7f2d2b525a3575203b6aJohn McCall  case AR_dependent: return Sema::AR_dependent;
17161f2e1a96bec2ba6418ae7f2d2b525a3575203b6aJohn McCall  }
17171f2e1a96bec2ba6418ae7f2d2b525a3575203b6aJohn McCall  llvm_unreachable("falling off end");
17181f2e1a96bec2ba6418ae7f2d2b525a3575203b6aJohn McCall}
17191f2e1a96bec2ba6418ae7f2d2b525a3575203b6aJohn McCall
17206bb8017bb9e828d118e15e59d71c66bba323c364John McCallSema::AccessResult Sema::CheckAddressOfMemberAccess(Expr *OvlExpr,
17216bb8017bb9e828d118e15e59d71c66bba323c364John McCall                                                    DeclAccessPair Found) {
17224e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie  if (!getLangOpts().AccessControl ||
1723e2f5ba9d80cfadbb3e1dafb9f375eb526f669b85John McCall      Found.getAccess() == AS_none ||
17246bb8017bb9e828d118e15e59d71c66bba323c364John McCall      Found.getAccess() == AS_public)
17256bb8017bb9e828d118e15e59d71c66bba323c364John McCall    return AR_accessible;
17266bb8017bb9e828d118e15e59d71c66bba323c364John McCall
17279c72c6088d591ace8503b842d39448c2040f3033John McCall  OverloadExpr *Ovl = OverloadExpr::find(OvlExpr).Expression;
1728e9ee23edd17c4bb7f271e67f8790792b4de677fcJohn McCall  CXXRecordDecl *NamingClass = Ovl->getNamingClass();
17296bb8017bb9e828d118e15e59d71c66bba323c364John McCall
1730161755a09898c95d21bfff33707da9ca41cd53c5John McCall  AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
1731b9abd87283ac6e929b7e12a577663bc99e61d020John McCall                      /*no instance context*/ QualType());
17326bb8017bb9e828d118e15e59d71c66bba323c364John McCall  Entity.setDiag(diag::err_access)
17336bb8017bb9e828d118e15e59d71c66bba323c364John McCall    << Ovl->getSourceRange();
17346bb8017bb9e828d118e15e59d71c66bba323c364John McCall
17356bb8017bb9e828d118e15e59d71c66bba323c364John McCall  return CheckAccess(*this, Ovl->getNameLoc(), Entity);
17366bb8017bb9e828d118e15e59d71c66bba323c364John McCall}
17376bb8017bb9e828d118e15e59d71c66bba323c364John McCall
17386b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// Checks access for a hierarchy conversion.
17396b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall///
17406b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// \param ForceCheck true if this check should be performed even if access
17416b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall///     control is disabled;  some things rely on this for semantics
17426b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall/// \param ForceUnprivileged true if this check should proceed as if the
17436b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall///     context had no special privileges
17446b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallSema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc,
17456b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall                                              QualType Base,
17466b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall                                              QualType Derived,
17476b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall                                              const CXXBasePath &Path,
174858e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall                                              unsigned DiagID,
17496b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall                                              bool ForceCheck,
175058e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall                                              bool ForceUnprivileged) {
17514e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie  if (!ForceCheck && !getLangOpts().AccessControl)
17526b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    return AR_accessible;
17536b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
17546b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  if (Path.Access == AS_public)
17556b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall    return AR_accessible;
17566b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
17576b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  CXXRecordDecl *BaseD, *DerivedD;
17586b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  BaseD = cast<CXXRecordDecl>(Base->getAs<RecordType>()->getDecl());
17596b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  DerivedD = cast<CXXRecordDecl>(Derived->getAs<RecordType>()->getDecl());
176058e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall
1761161755a09898c95d21bfff33707da9ca41cd53c5John McCall  AccessTarget Entity(Context, AccessTarget::Base, BaseD, DerivedD,
1762161755a09898c95d21bfff33707da9ca41cd53c5John McCall                      Path.Access);
176358e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall  if (DiagID)
176458e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall    Entity.setDiag(DiagID) << Derived << Base;
17656b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
1766161755a09898c95d21bfff33707da9ca41cd53c5John McCall  if (ForceUnprivileged) {
1767161755a09898c95d21bfff33707da9ca41cd53c5John McCall    switch (CheckEffectiveAccess(*this, EffectiveContext(),
1768161755a09898c95d21bfff33707da9ca41cd53c5John McCall                                 AccessLoc, Entity)) {
1769161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case ::AR_accessible: return Sema::AR_accessible;
1770161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case ::AR_inaccessible: return Sema::AR_inaccessible;
1771161755a09898c95d21bfff33707da9ca41cd53c5John McCall    case ::AR_dependent: return Sema::AR_dependent;
1772161755a09898c95d21bfff33707da9ca41cd53c5John McCall    }
1773161755a09898c95d21bfff33707da9ca41cd53c5John McCall    llvm_unreachable("unexpected result from CheckEffectiveAccess");
1774161755a09898c95d21bfff33707da9ca41cd53c5John McCall  }
177558e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall  return CheckAccess(*this, AccessLoc, Entity);
17765357b615364c17ea024c757354c58ae2a520d216John McCall}
17775357b615364c17ea024c757354c58ae2a520d216John McCall
177892f883177b162928a8e632e4e3b93fafd2b26072John McCall/// Checks access to all the declarations in the given result set.
17796b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCallvoid Sema::CheckLookupAccess(const LookupResult &R) {
17804e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie  assert(getLangOpts().AccessControl
17816b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall         && "performing access check without access control");
17826b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall  assert(R.getNamingClass() && "performing access check without naming class");
17836b2accb4793e16b2e93a8c2589f5df702231f17aJohn McCall
178458e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall  for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
178558e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall    if (I.getAccess() != AS_public) {
1786161755a09898c95d21bfff33707da9ca41cd53c5John McCall      AccessTarget Entity(Context, AccessedEntity::Member,
1787161755a09898c95d21bfff33707da9ca41cd53c5John McCall                          R.getNamingClass(), I.getPair(),
178824dd9ad9001d1aa16223de135d7e4ed34e94b207Erik Verbruggen                          R.getBaseObjectType());
178958e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall      Entity.setDiag(diag::err_access);
179058e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall      CheckAccess(*this, R.getNameLoc(), Entity);
179158e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall    }
179258e6f34e4d2c668562e1c391162ee9de7b05fbb2John McCall  }
179392f883177b162928a8e632e4e3b93fafd2b26072John McCall}
1794926c4b486a08f698cd3a367fd6f1a3a07604358dChandler Carruth
1795d12059673dcef32bc2b6bae5321654d33863afe6Erik Verbruggen/// Checks access to Decl from the given class. The check will take access
1796d12059673dcef32bc2b6bae5321654d33863afe6Erik Verbruggen/// specifiers into account, but no member access expressions and such.
1797d12059673dcef32bc2b6bae5321654d33863afe6Erik Verbruggen///
1798d12059673dcef32bc2b6bae5321654d33863afe6Erik Verbruggen/// \param Decl the declaration to check if it can be accessed
17991ddbd89bb397988dd1a4e96d8d8c2c7705a2af75Dmitri Gribenko/// \param Ctx the class/context from which to start the search
1800d12059673dcef32bc2b6bae5321654d33863afe6Erik Verbruggen/// \return true if the Decl is accessible from the Class, false otherwise.
180117015eff2b3166e445377b15913474b472775e7cDouglas Gregorbool Sema::IsSimplyAccessible(NamedDecl *Decl, DeclContext *Ctx) {
180217015eff2b3166e445377b15913474b472775e7cDouglas Gregor  if (CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(Ctx)) {
1803a885dce496f2a9e30650f74607efe11856a76a34Douglas Gregor    if (!Decl->isCXXClassMember())
180417015eff2b3166e445377b15913474b472775e7cDouglas Gregor      return true;
1805d12059673dcef32bc2b6bae5321654d33863afe6Erik Verbruggen
180617015eff2b3166e445377b15913474b472775e7cDouglas Gregor    QualType qType = Class->getTypeForDecl()->getCanonicalTypeInternal();
180717015eff2b3166e445377b15913474b472775e7cDouglas Gregor    AccessTarget Entity(Context, AccessedEntity::Member, Class,
180817015eff2b3166e445377b15913474b472775e7cDouglas Gregor                        DeclAccessPair::make(Decl, Decl->getAccess()),
180917015eff2b3166e445377b15913474b472775e7cDouglas Gregor                        qType);
181017015eff2b3166e445377b15913474b472775e7cDouglas Gregor    if (Entity.getAccess() == AS_public)
181117015eff2b3166e445377b15913474b472775e7cDouglas Gregor      return true;
1812d12059673dcef32bc2b6bae5321654d33863afe6Erik Verbruggen
181317015eff2b3166e445377b15913474b472775e7cDouglas Gregor    EffectiveContext EC(CurContext);
181417015eff2b3166e445377b15913474b472775e7cDouglas Gregor    return ::IsAccessible(*this, EC, Entity) != ::AR_inaccessible;
181517015eff2b3166e445377b15913474b472775e7cDouglas Gregor  }
181617015eff2b3166e445377b15913474b472775e7cDouglas Gregor
1817f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor  if (ObjCIvarDecl *Ivar = dyn_cast<ObjCIvarDecl>(Decl)) {
1818f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor    // @public and @package ivars are always accessible.
1819f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor    if (Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Public ||
1820f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor        Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Package)
1821f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor      return true;
1822f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor
1823f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor
1824f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor
1825f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor    // If we are inside a class or category implementation, determine the
1826f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor    // interface we're in.
1827f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor    ObjCInterfaceDecl *ClassOfMethodDecl = 0;
1828f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor    if (ObjCMethodDecl *MD = getCurMethodDecl())
1829f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor      ClassOfMethodDecl =  MD->getClassInterface();
1830f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor    else if (FunctionDecl *FD = getCurFunctionDecl()) {
1831f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor      if (ObjCImplDecl *Impl
1832f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor            = dyn_cast<ObjCImplDecl>(FD->getLexicalDeclContext())) {
1833f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor        if (ObjCImplementationDecl *IMPD
1834f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor              = dyn_cast<ObjCImplementationDecl>(Impl))
1835f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor          ClassOfMethodDecl = IMPD->getClassInterface();
1836f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor        else if (ObjCCategoryImplDecl* CatImplClass
1837f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor                   = dyn_cast<ObjCCategoryImplDecl>(Impl))
1838f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor          ClassOfMethodDecl = CatImplClass->getClassInterface();
1839f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor      }
1840f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor    }
1841f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor
1842f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor    // If we're not in an interface, this ivar is inaccessible.
1843f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor    if (!ClassOfMethodDecl)
1844f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor      return false;
1845f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor
1846f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor    // If we're inside the same interface that owns the ivar, we're fine.
184760ef308e51c71b760d7f598c1b763ceb7b768148Douglas Gregor    if (declaresSameEntity(ClassOfMethodDecl, Ivar->getContainingInterface()))
1848f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor      return true;
1849f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor
1850f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor    // If the ivar is private, it's inaccessible.
1851f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor    if (Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Private)
1852f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor      return false;
1853f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor
1854f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor    return Ivar->getContainingInterface()->isSuperClassOf(ClassOfMethodDecl);
1855f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor  }
1856f3c02869a7a50ebdc963d0456fd075368b5b5a3fDouglas Gregor
185717015eff2b3166e445377b15913474b472775e7cDouglas Gregor  return true;
1858d12059673dcef32bc2b6bae5321654d33863afe6Erik Verbruggen}
1859