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