SemaAccess.cpp revision 263508
1168404Spjd//===---- SemaAccess.cpp - C++ Access Control -------------------*- C++ -*-===//
2168404Spjd//
3168404Spjd//                     The LLVM Compiler Infrastructure
4168404Spjd//
5168404Spjd// This file is distributed under the University of Illinois Open Source
6168404Spjd// License. See LICENSE.TXT for details.
7168404Spjd//
8168404Spjd//===----------------------------------------------------------------------===//
9168404Spjd//
10168404Spjd// This file provides Sema routines for C++ access control semantics.
11168404Spjd//
12168404Spjd//===----------------------------------------------------------------------===//
13168404Spjd
14168404Spjd#include "clang/Sema/SemaInternal.h"
15168404Spjd#include "clang/AST/ASTContext.h"
16168404Spjd#include "clang/AST/CXXInheritance.h"
17168404Spjd#include "clang/AST/DeclCXX.h"
18168404Spjd#include "clang/AST/DeclFriend.h"
19168404Spjd#include "clang/AST/DeclObjC.h"
20168404Spjd#include "clang/AST/DependentDiagnostic.h"
21168404Spjd#include "clang/AST/ExprCXX.h"
22185029Spjd#include "clang/Sema/DelayedDiagnostic.h"
23168404Spjd#include "clang/Sema/Initialization.h"
24168404Spjd#include "clang/Sema/Lookup.h"
25168404Spjd
26168404Spjdusing namespace clang;
27168404Spjdusing namespace sema;
28168404Spjd
29168404Spjd/// A copy of Sema's enum without AR_delayed.
30168404Spjdenum AccessResult {
31168404Spjd  AR_accessible,
32168404Spjd  AR_inaccessible,
33168404Spjd  AR_dependent
34168404Spjd};
35168404Spjd
36168404Spjd/// SetMemberAccessSpecifier - Set the access specifier of a member.
37168404Spjd/// Returns true on error (when the previous member decl access specifier
38168404Spjd/// is different from the new member decl access specifier).
39168404Spjdbool Sema::SetMemberAccessSpecifier(NamedDecl *MemberDecl,
40168404Spjd                                    NamedDecl *PrevMemberDecl,
41168404Spjd                                    AccessSpecifier LexicalAS) {
42168404Spjd  if (!PrevMemberDecl) {
43168404Spjd    // Use the lexical access specifier.
44168404Spjd    MemberDecl->setAccess(LexicalAS);
45168404Spjd    return false;
46168404Spjd  }
47168404Spjd
48168404Spjd  // C++ [class.access.spec]p3: When a member is redeclared its access
49168404Spjd  // specifier must be same as its initial declaration.
50168404Spjd  if (LexicalAS != AS_none && LexicalAS != PrevMemberDecl->getAccess()) {
51168404Spjd    Diag(MemberDecl->getLocation(),
52168404Spjd         diag::err_class_redeclared_with_different_access)
53168404Spjd      << MemberDecl << LexicalAS;
54168404Spjd    Diag(PrevMemberDecl->getLocation(), diag::note_previous_access_declaration)
55168404Spjd      << PrevMemberDecl << PrevMemberDecl->getAccess();
56168404Spjd
57168404Spjd    MemberDecl->setAccess(LexicalAS);
58168404Spjd    return true;
59168404Spjd  }
60168404Spjd
61168404Spjd  MemberDecl->setAccess(PrevMemberDecl->getAccess());
62168404Spjd  return false;
63168404Spjd}
64168404Spjd
65168404Spjdstatic CXXRecordDecl *FindDeclaringClass(NamedDecl *D) {
66168404Spjd  DeclContext *DC = D->getDeclContext();
67168404Spjd
68168404Spjd  // This can only happen at top: enum decls only "publish" their
69168404Spjd  // immediate members.
70168404Spjd  if (isa<EnumDecl>(DC))
71169028Spjd    DC = cast<EnumDecl>(DC)->getDeclContext();
72168404Spjd
73168404Spjd  CXXRecordDecl *DeclaringClass = cast<CXXRecordDecl>(DC);
74168404Spjd  while (DeclaringClass->isAnonymousStructOrUnion())
75168404Spjd    DeclaringClass = cast<CXXRecordDecl>(DeclaringClass->getDeclContext());
76168404Spjd  return DeclaringClass;
77168404Spjd}
78168404Spjd
79168404Spjdnamespace {
80168404Spjdstruct EffectiveContext {
81168404Spjd  EffectiveContext() : Inner(0), Dependent(false) {}
82168404Spjd
83168404Spjd  explicit EffectiveContext(DeclContext *DC)
84168404Spjd    : Inner(DC),
85168404Spjd      Dependent(DC->isDependentContext()) {
86168404Spjd
87168404Spjd    // C++11 [class.access.nest]p1:
88168404Spjd    //   A nested class is a member and as such has the same access
89168404Spjd    //   rights as any other member.
90168404Spjd    // C++11 [class.access]p2:
91168404Spjd    //   A member of a class can also access all the names to which
92168404Spjd    //   the class has access.  A local class of a member function
93168404Spjd    //   may access the same names that the member function itself
94168404Spjd    //   may access.
95168404Spjd    // This almost implies that the privileges of nesting are transitive.
96168404Spjd    // Technically it says nothing about the local classes of non-member
97168404Spjd    // functions (which can gain privileges through friendship), but we
98168404Spjd    // take that as an oversight.
99168404Spjd    while (true) {
100168404Spjd      // We want to add canonical declarations to the EC lists for
101168404Spjd      // simplicity of checking, but we need to walk up through the
102168404Spjd      // actual current DC chain.  Otherwise, something like a local
103168404Spjd      // extern or friend which happens to be the canonical
104168404Spjd      // declaration will really mess us up.
105168404Spjd
106168404Spjd      if (isa<CXXRecordDecl>(DC)) {
107168404Spjd        CXXRecordDecl *Record = cast<CXXRecordDecl>(DC);
108168404Spjd        Records.push_back(Record->getCanonicalDecl());
109168404Spjd        DC = Record->getDeclContext();
110168404Spjd      } else if (isa<FunctionDecl>(DC)) {
111168404Spjd        FunctionDecl *Function = cast<FunctionDecl>(DC);
112168404Spjd        Functions.push_back(Function->getCanonicalDecl());
113168404Spjd        if (Function->getFriendObjectKind())
114168404Spjd          DC = Function->getLexicalDeclContext();
115168404Spjd        else
116168404Spjd          DC = Function->getDeclContext();
117168404Spjd      } else if (DC->isFileContext()) {
118168404Spjd        break;
119168404Spjd      } else {
120168404Spjd        DC = DC->getParent();
121168404Spjd      }
122168404Spjd    }
123168404Spjd  }
124168404Spjd
125168404Spjd  bool isDependent() const { return Dependent; }
126168404Spjd
127168404Spjd  bool includesClass(const CXXRecordDecl *R) const {
128168404Spjd    R = R->getCanonicalDecl();
129168404Spjd    return std::find(Records.begin(), Records.end(), R)
130168404Spjd             != Records.end();
131168404Spjd  }
132168404Spjd
133168404Spjd  /// Retrieves the innermost "useful" context.  Can be null if we're
134168404Spjd  /// doing access-control without privileges.
135168404Spjd  DeclContext *getInnerContext() const {
136168404Spjd    return Inner;
137168404Spjd  }
138168404Spjd
139168404Spjd  typedef SmallVectorImpl<CXXRecordDecl*>::const_iterator record_iterator;
140168404Spjd
141168404Spjd  DeclContext *Inner;
142168404Spjd  SmallVector<FunctionDecl*, 4> Functions;
143168404Spjd  SmallVector<CXXRecordDecl*, 4> Records;
144168404Spjd  bool Dependent;
145168404Spjd};
146168404Spjd
147168404Spjd/// Like sema::AccessedEntity, but kindly lets us scribble all over
148168404Spjd/// it.
149168404Spjdstruct AccessTarget : public AccessedEntity {
150168404Spjd  AccessTarget(const AccessedEntity &Entity)
151168404Spjd    : AccessedEntity(Entity) {
152168404Spjd    initialize();
153168404Spjd  }
154168404Spjd
155168404Spjd  AccessTarget(ASTContext &Context,
156168404Spjd               MemberNonce _,
157168404Spjd               CXXRecordDecl *NamingClass,
158168404Spjd               DeclAccessPair FoundDecl,
159168404Spjd               QualType BaseObjectType)
160168404Spjd    : AccessedEntity(Context.getDiagAllocator(), Member, NamingClass,
161168404Spjd                     FoundDecl, BaseObjectType) {
162168404Spjd    initialize();
163168404Spjd  }
164168404Spjd
165168404Spjd  AccessTarget(ASTContext &Context,
166168404Spjd               BaseNonce _,
167168404Spjd               CXXRecordDecl *BaseClass,
168168404Spjd               CXXRecordDecl *DerivedClass,
169168404Spjd               AccessSpecifier Access)
170168404Spjd    : AccessedEntity(Context.getDiagAllocator(), Base, BaseClass, DerivedClass,
171168404Spjd                     Access) {
172168404Spjd    initialize();
173168404Spjd  }
174168404Spjd
175185029Spjd  bool isInstanceMember() const {
176185029Spjd    return (isMemberAccess() && getTargetDecl()->isCXXInstanceMember());
177185029Spjd  }
178185029Spjd
179185029Spjd  bool hasInstanceContext() const {
180168404Spjd    return HasInstanceContext;
181168404Spjd  }
182168404Spjd
183168404Spjd  class SavedInstanceContext {
184168404Spjd  public:
185168404Spjd    ~SavedInstanceContext() {
186168404Spjd      Target.HasInstanceContext = Has;
187168404Spjd    }
188168404Spjd
189168404Spjd  private:
190185029Spjd    friend struct AccessTarget;
191185029Spjd    explicit SavedInstanceContext(AccessTarget &Target)
192168404Spjd      : Target(Target), Has(Target.HasInstanceContext) {}
193168404Spjd    AccessTarget &Target;
194185029Spjd    bool Has;
195185029Spjd  };
196168404Spjd
197168404Spjd  SavedInstanceContext saveInstanceContext() {
198168404Spjd    return SavedInstanceContext(*this);
199185029Spjd  }
200185029Spjd
201185029Spjd  void suppressInstanceContext() {
202185029Spjd    HasInstanceContext = false;
203185029Spjd  }
204168404Spjd
205168404Spjd  const CXXRecordDecl *resolveInstanceContext(Sema &S) const {
206168404Spjd    assert(HasInstanceContext);
207168404Spjd    if (CalculatedInstanceContext)
208168404Spjd      return InstanceContext;
209168404Spjd
210168404Spjd    CalculatedInstanceContext = true;
211168404Spjd    DeclContext *IC = S.computeDeclContext(getBaseObjectType());
212168404Spjd    InstanceContext = (IC ? cast<CXXRecordDecl>(IC)->getCanonicalDecl() : 0);
213168404Spjd    return InstanceContext;
214168404Spjd  }
215168404Spjd
216168404Spjd  const CXXRecordDecl *getDeclaringClass() const {
217168404Spjd    return DeclaringClass;
218168404Spjd  }
219168404Spjd
220168404Spjd  /// The "effective" naming class is the canonical non-anonymous
221168404Spjd  /// class containing the actual naming class.
222168404Spjd  const CXXRecordDecl *getEffectiveNamingClass() const {
223168404Spjd    const CXXRecordDecl *namingClass = getNamingClass();
224168404Spjd    while (namingClass->isAnonymousStructOrUnion())
225168404Spjd      namingClass = cast<CXXRecordDecl>(namingClass->getParent());
226168404Spjd    return namingClass->getCanonicalDecl();
227168404Spjd  }
228168404Spjd
229168404Spjdprivate:
230168404Spjd  void initialize() {
231168404Spjd    HasInstanceContext = (isMemberAccess() &&
232168404Spjd                          !getBaseObjectType().isNull() &&
233168404Spjd                          getTargetDecl()->isCXXInstanceMember());
234168404Spjd    CalculatedInstanceContext = false;
235168404Spjd    InstanceContext = 0;
236168404Spjd
237168404Spjd    if (isMemberAccess())
238168404Spjd      DeclaringClass = FindDeclaringClass(getTargetDecl());
239168404Spjd    else
240168404Spjd      DeclaringClass = getBaseClass();
241168404Spjd    DeclaringClass = DeclaringClass->getCanonicalDecl();
242168404Spjd  }
243168404Spjd
244168404Spjd  bool HasInstanceContext : 1;
245168404Spjd  mutable bool CalculatedInstanceContext : 1;
246168404Spjd  mutable const CXXRecordDecl *InstanceContext;
247168404Spjd  const CXXRecordDecl *DeclaringClass;
248168404Spjd};
249168404Spjd
250168404Spjd}
251168404Spjd
252168404Spjd/// Checks whether one class might instantiate to the other.
253168404Spjdstatic bool MightInstantiateTo(const CXXRecordDecl *From,
254168404Spjd                               const CXXRecordDecl *To) {
255168404Spjd  // Declaration names are always preserved by instantiation.
256168404Spjd  if (From->getDeclName() != To->getDeclName())
257168404Spjd    return false;
258168404Spjd
259168404Spjd  const DeclContext *FromDC = From->getDeclContext()->getPrimaryContext();
260168404Spjd  const DeclContext *ToDC = To->getDeclContext()->getPrimaryContext();
261168404Spjd  if (FromDC == ToDC) return true;
262168404Spjd  if (FromDC->isFileContext() || ToDC->isFileContext()) return false;
263168404Spjd
264168404Spjd  // Be conservative.
265168404Spjd  return true;
266168404Spjd}
267168404Spjd
268168404Spjd/// Checks whether one class is derived from another, inclusively.
269168404Spjd/// Properly indicates when it couldn't be determined due to
270168404Spjd/// dependence.
271168404Spjd///
272168404Spjd/// This should probably be donated to AST or at least Sema.
273168404Spjdstatic AccessResult IsDerivedFromInclusive(const CXXRecordDecl *Derived,
274168404Spjd                                           const CXXRecordDecl *Target) {
275168404Spjd  assert(Derived->getCanonicalDecl() == Derived);
276168404Spjd  assert(Target->getCanonicalDecl() == Target);
277168404Spjd
278168404Spjd  if (Derived == Target) return AR_accessible;
279168404Spjd
280168404Spjd  bool CheckDependent = Derived->isDependentContext();
281168404Spjd  if (CheckDependent && MightInstantiateTo(Derived, Target))
282168404Spjd    return AR_dependent;
283168404Spjd
284168404Spjd  AccessResult OnFailure = AR_inaccessible;
285168404Spjd  SmallVector<const CXXRecordDecl*, 8> Queue; // actually a stack
286168404Spjd
287168404Spjd  while (true) {
288168404Spjd    if (Derived->isDependentContext() && !Derived->hasDefinition())
289168404Spjd      return AR_dependent;
290168404Spjd
291168404Spjd    for (CXXRecordDecl::base_class_const_iterator
292168404Spjd           I = Derived->bases_begin(), E = Derived->bases_end(); I != E; ++I) {
293168404Spjd
294168404Spjd      const CXXRecordDecl *RD;
295168404Spjd
296168404Spjd      QualType T = I->getType();
297168404Spjd      if (const RecordType *RT = T->getAs<RecordType>()) {
298185029Spjd        RD = cast<CXXRecordDecl>(RT->getDecl());
299185029Spjd      } else if (const InjectedClassNameType *IT
300168404Spjd                   = T->getAs<InjectedClassNameType>()) {
301168404Spjd        RD = IT->getDecl();
302168404Spjd      } else {
303168404Spjd        assert(T->isDependentType() && "non-dependent base wasn't a record?");
304168404Spjd        OnFailure = AR_dependent;
305168404Spjd        continue;
306168404Spjd      }
307168404Spjd
308168404Spjd      RD = RD->getCanonicalDecl();
309168404Spjd      if (RD == Target) return AR_accessible;
310168404Spjd      if (CheckDependent && MightInstantiateTo(RD, Target))
311168404Spjd        OnFailure = AR_dependent;
312168404Spjd
313168404Spjd      Queue.push_back(RD);
314168404Spjd    }
315168404Spjd
316168404Spjd    if (Queue.empty()) break;
317168404Spjd
318168404Spjd    Derived = Queue.pop_back_val();
319168404Spjd  }
320168404Spjd
321168404Spjd  return OnFailure;
322168404Spjd}
323168404Spjd
324168404Spjd
325168404Spjdstatic bool MightInstantiateTo(Sema &S, DeclContext *Context,
326168404Spjd                               DeclContext *Friend) {
327168404Spjd  if (Friend == Context)
328168404Spjd    return true;
329168404Spjd
330168404Spjd  assert(!Friend->isDependentContext() &&
331168404Spjd         "can't handle friends with dependent contexts here");
332168404Spjd
333168404Spjd  if (!Context->isDependentContext())
334168404Spjd    return false;
335168404Spjd
336168404Spjd  if (Friend->isFileContext())
337168404Spjd    return false;
338168404Spjd
339168404Spjd  // TODO: this is very conservative
340168404Spjd  return true;
341168404Spjd}
342168404Spjd
343168404Spjd// Asks whether the type in 'context' can ever instantiate to the type
344168404Spjd// in 'friend'.
345168404Spjdstatic bool MightInstantiateTo(Sema &S, CanQualType Context, CanQualType Friend) {
346168404Spjd  if (Friend == Context)
347168404Spjd    return true;
348168404Spjd
349168404Spjd  if (!Friend->isDependentType() && !Context->isDependentType())
350168404Spjd    return false;
351168404Spjd
352168404Spjd  // TODO: this is very conservative.
353168404Spjd  return true;
354168404Spjd}
355168404Spjd
356168404Spjdstatic bool MightInstantiateTo(Sema &S,
357168404Spjd                               FunctionDecl *Context,
358168404Spjd                               FunctionDecl *Friend) {
359168404Spjd  if (Context->getDeclName() != Friend->getDeclName())
360168404Spjd    return false;
361168404Spjd
362168404Spjd  if (!MightInstantiateTo(S,
363168404Spjd                          Context->getDeclContext(),
364168404Spjd                          Friend->getDeclContext()))
365168404Spjd    return false;
366168404Spjd
367168404Spjd  CanQual<FunctionProtoType> FriendTy
368168404Spjd    = S.Context.getCanonicalType(Friend->getType())
369168404Spjd         ->getAs<FunctionProtoType>();
370168404Spjd  CanQual<FunctionProtoType> ContextTy
371168404Spjd    = S.Context.getCanonicalType(Context->getType())
372168404Spjd         ->getAs<FunctionProtoType>();
373168404Spjd
374168404Spjd  // There isn't any way that I know of to add qualifiers
375168404Spjd  // during instantiation.
376168404Spjd  if (FriendTy.getQualifiers() != ContextTy.getQualifiers())
377168404Spjd    return false;
378168404Spjd
379168404Spjd  if (FriendTy->getNumArgs() != ContextTy->getNumArgs())
380168404Spjd    return false;
381168404Spjd
382168404Spjd  if (!MightInstantiateTo(S,
383168404Spjd                          ContextTy->getResultType(),
384168404Spjd                          FriendTy->getResultType()))
385168404Spjd    return false;
386168404Spjd
387168404Spjd  for (unsigned I = 0, E = FriendTy->getNumArgs(); I != E; ++I)
388168404Spjd    if (!MightInstantiateTo(S,
389168404Spjd                            ContextTy->getArgType(I),
390168404Spjd                            FriendTy->getArgType(I)))
391168404Spjd      return false;
392168404Spjd
393168404Spjd  return true;
394168404Spjd}
395168404Spjd
396168404Spjdstatic bool MightInstantiateTo(Sema &S,
397168404Spjd                               FunctionTemplateDecl *Context,
398168404Spjd                               FunctionTemplateDecl *Friend) {
399168404Spjd  return MightInstantiateTo(S,
400168404Spjd                            Context->getTemplatedDecl(),
401168404Spjd                            Friend->getTemplatedDecl());
402168404Spjd}
403168404Spjd
404168404Spjdstatic AccessResult MatchesFriend(Sema &S,
405168404Spjd                                  const EffectiveContext &EC,
406168404Spjd                                  const CXXRecordDecl *Friend) {
407168404Spjd  if (EC.includesClass(Friend))
408168404Spjd    return AR_accessible;
409168404Spjd
410168404Spjd  if (EC.isDependent()) {
411168404Spjd    CanQualType FriendTy
412168404Spjd      = S.Context.getCanonicalType(S.Context.getTypeDeclType(Friend));
413168404Spjd
414168404Spjd    for (EffectiveContext::record_iterator
415168404Spjd           I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
416168404Spjd      CanQualType ContextTy
417168404Spjd        = S.Context.getCanonicalType(S.Context.getTypeDeclType(*I));
418168404Spjd      if (MightInstantiateTo(S, ContextTy, FriendTy))
419168404Spjd        return AR_dependent;
420168404Spjd    }
421168404Spjd  }
422168404Spjd
423168404Spjd  return AR_inaccessible;
424168404Spjd}
425168404Spjd
426168404Spjdstatic AccessResult MatchesFriend(Sema &S,
427168404Spjd                                  const EffectiveContext &EC,
428168404Spjd                                  CanQualType Friend) {
429168404Spjd  if (const RecordType *RT = Friend->getAs<RecordType>())
430168404Spjd    return MatchesFriend(S, EC, cast<CXXRecordDecl>(RT->getDecl()));
431168404Spjd
432168404Spjd  // TODO: we can do better than this
433168404Spjd  if (Friend->isDependentType())
434168404Spjd    return AR_dependent;
435168404Spjd
436168404Spjd  return AR_inaccessible;
437168404Spjd}
438168404Spjd
439185029Spjd/// Determines whether the given friend class template matches
440185029Spjd/// anything in the effective context.
441185029Spjdstatic AccessResult MatchesFriend(Sema &S,
442185029Spjd                                  const EffectiveContext &EC,
443185029Spjd                                  ClassTemplateDecl *Friend) {
444185029Spjd  AccessResult OnFailure = AR_inaccessible;
445185029Spjd
446185029Spjd  // Check whether the friend is the template of a class in the
447185029Spjd  // context chain.
448185029Spjd  for (SmallVectorImpl<CXXRecordDecl*>::const_iterator
449168404Spjd         I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
450168404Spjd    CXXRecordDecl *Record = *I;
451168404Spjd
452168404Spjd    // Figure out whether the current class has a template:
453168404Spjd    ClassTemplateDecl *CTD;
454168404Spjd
455168404Spjd    // A specialization of the template...
456168404Spjd    if (isa<ClassTemplateSpecializationDecl>(Record)) {
457168404Spjd      CTD = cast<ClassTemplateSpecializationDecl>(Record)
458168404Spjd        ->getSpecializedTemplate();
459168404Spjd
460168404Spjd    // ... or the template pattern itself.
461168404Spjd    } else {
462168404Spjd      CTD = Record->getDescribedClassTemplate();
463168404Spjd      if (!CTD) continue;
464168404Spjd    }
465168404Spjd
466168404Spjd    // It's a match.
467168404Spjd    if (Friend == CTD->getCanonicalDecl())
468168404Spjd      return AR_accessible;
469168404Spjd
470168404Spjd    // If the context isn't dependent, it can't be a dependent match.
471168404Spjd    if (!EC.isDependent())
472185029Spjd      continue;
473168404Spjd
474185029Spjd    // If the template names don't match, it can't be a dependent
475185029Spjd    // match.
476185029Spjd    if (CTD->getDeclName() != Friend->getDeclName())
477185029Spjd      continue;
478185029Spjd
479185029Spjd    // If the class's context can't instantiate to the friend's
480185029Spjd    // context, it can't be a dependent match.
481185029Spjd    if (!MightInstantiateTo(S, CTD->getDeclContext(),
482185029Spjd                            Friend->getDeclContext()))
483185029Spjd      continue;
484185029Spjd
485185029Spjd    // Otherwise, it's a dependent match.
486185029Spjd    OnFailure = AR_dependent;
487185029Spjd  }
488168404Spjd
489168404Spjd  return OnFailure;
490185029Spjd}
491185029Spjd
492185029Spjd/// Determines whether the given friend function matches anything in
493185029Spjd/// the effective context.
494185029Spjdstatic AccessResult MatchesFriend(Sema &S,
495185029Spjd                                  const EffectiveContext &EC,
496185029Spjd                                  FunctionDecl *Friend) {
497185029Spjd  AccessResult OnFailure = AR_inaccessible;
498185029Spjd
499185029Spjd  for (SmallVectorImpl<FunctionDecl*>::const_iterator
500185029Spjd         I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) {
501185029Spjd    if (Friend == *I)
502185029Spjd      return AR_accessible;
503168404Spjd
504168404Spjd    if (EC.isDependent() && MightInstantiateTo(S, *I, Friend))
505200724Sdelphij      OnFailure = AR_dependent;
506200724Sdelphij  }
507200724Sdelphij
508200724Sdelphij  return OnFailure;
509200724Sdelphij}
510200724Sdelphij
511200724Sdelphij/// Determines whether the given friend function template matches
512200724Sdelphij/// anything in the effective context.
513200724Sdelphijstatic AccessResult MatchesFriend(Sema &S,
514200724Sdelphij                                  const EffectiveContext &EC,
515200724Sdelphij                                  FunctionTemplateDecl *Friend) {
516200724Sdelphij  if (EC.Functions.empty()) return AR_inaccessible;
517200724Sdelphij
518200724Sdelphij  AccessResult OnFailure = AR_inaccessible;
519200724Sdelphij
520200724Sdelphij  for (SmallVectorImpl<FunctionDecl*>::const_iterator
521200724Sdelphij         I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) {
522200724Sdelphij
523200724Sdelphij    FunctionTemplateDecl *FTD = (*I)->getPrimaryTemplate();
524168404Spjd    if (!FTD)
525168404Spjd      FTD = (*I)->getDescribedFunctionTemplate();
526168404Spjd    if (!FTD)
527168404Spjd      continue;
528168404Spjd
529168404Spjd    FTD = FTD->getCanonicalDecl();
530168404Spjd
531168404Spjd    if (Friend == FTD)
532168404Spjd      return AR_accessible;
533168404Spjd
534185029Spjd    if (EC.isDependent() && MightInstantiateTo(S, FTD, Friend))
535168404Spjd      OnFailure = AR_dependent;
536185029Spjd  }
537168404Spjd
538168404Spjd  return OnFailure;
539168404Spjd}
540168404Spjd
541168404Spjd/// Determines whether the given friend declaration matches anything
542168404Spjd/// in the effective context.
543168404Spjdstatic AccessResult MatchesFriend(Sema &S,
544200724Sdelphij                                  const EffectiveContext &EC,
545200724Sdelphij                                  FriendDecl *FriendD) {
546200724Sdelphij  // Whitelist accesses if there's an invalid or unsupported friend
547200724Sdelphij  // declaration.
548200724Sdelphij  if (FriendD->isInvalidDecl() || FriendD->isUnsupportedFriend())
549200724Sdelphij    return AR_accessible;
550200724Sdelphij
551200724Sdelphij  if (TypeSourceInfo *T = FriendD->getFriendType())
552200724Sdelphij    return MatchesFriend(S, EC, T->getType()->getCanonicalTypeUnqualified());
553200724Sdelphij
554200724Sdelphij  NamedDecl *Friend
555200724Sdelphij    = cast<NamedDecl>(FriendD->getFriendDecl()->getCanonicalDecl());
556200724Sdelphij
557200724Sdelphij  // FIXME: declarations with dependent or templated scope.
558200724Sdelphij
559168404Spjd  if (isa<ClassTemplateDecl>(Friend))
560168404Spjd    return MatchesFriend(S, EC, cast<ClassTemplateDecl>(Friend));
561168404Spjd
562168404Spjd  if (isa<FunctionTemplateDecl>(Friend))
563168404Spjd    return MatchesFriend(S, EC, cast<FunctionTemplateDecl>(Friend));
564168404Spjd
565168404Spjd  if (isa<CXXRecordDecl>(Friend))
566168404Spjd    return MatchesFriend(S, EC, cast<CXXRecordDecl>(Friend));
567168404Spjd
568168404Spjd  assert(isa<FunctionDecl>(Friend) && "unknown friend decl kind");
569168404Spjd  return MatchesFriend(S, EC, cast<FunctionDecl>(Friend));
570168404Spjd}
571168404Spjd
572168404Spjdstatic AccessResult GetFriendKind(Sema &S,
573168404Spjd                                  const EffectiveContext &EC,
574168404Spjd                                  const CXXRecordDecl *Class) {
575168404Spjd  AccessResult OnFailure = AR_inaccessible;
576168404Spjd
577168404Spjd  // Okay, check friends.
578185029Spjd  for (CXXRecordDecl::friend_iterator I = Class->friend_begin(),
579185029Spjd         E = Class->friend_end(); I != E; ++I) {
580185029Spjd    FriendDecl *Friend = *I;
581185029Spjd
582185029Spjd    switch (MatchesFriend(S, EC, Friend)) {
583185029Spjd    case AR_accessible:
584185029Spjd      return AR_accessible;
585185029Spjd
586168404Spjd    case AR_inaccessible:
587185029Spjd      continue;
588185029Spjd
589185029Spjd    case AR_dependent:
590185029Spjd      OnFailure = AR_dependent;
591185029Spjd      break;
592185029Spjd    }
593185029Spjd  }
594185029Spjd
595168404Spjd  // That's it, give up.
596185029Spjd  return OnFailure;
597185029Spjd}
598185029Spjd
599185029Spjdnamespace {
600185029Spjd
601168404Spjd/// A helper class for checking for a friend which will grant access
602185029Spjd/// to a protected instance member.
603185029Spjdstruct ProtectedFriendContext {
604185029Spjd  Sema &S;
605185029Spjd  const EffectiveContext &EC;
606185029Spjd  const CXXRecordDecl *NamingClass;
607185029Spjd  bool CheckDependent;
608168404Spjd  bool EverDependent;
609185029Spjd
610185029Spjd  /// The path down to the current base class.
611185029Spjd  SmallVector<const CXXRecordDecl*, 20> CurPath;
612185029Spjd
613185029Spjd  ProtectedFriendContext(Sema &S, const EffectiveContext &EC,
614185029Spjd                         const CXXRecordDecl *InstanceContext,
615185029Spjd                         const CXXRecordDecl *NamingClass)
616185029Spjd    : S(S), EC(EC), NamingClass(NamingClass),
617185029Spjd      CheckDependent(InstanceContext->isDependentContext() ||
618185029Spjd                     NamingClass->isDependentContext()),
619185029Spjd      EverDependent(false) {}
620185029Spjd
621185029Spjd  /// Check classes in the current path for friendship, starting at
622185029Spjd  /// the given index.
623168404Spjd  bool checkFriendshipAlongPath(unsigned I) {
624168404Spjd    assert(I < CurPath.size());
625185029Spjd    for (unsigned E = CurPath.size(); I != E; ++I) {
626185029Spjd      switch (GetFriendKind(S, EC, CurPath[I])) {
627185029Spjd      case AR_accessible:   return true;
628185029Spjd      case AR_inaccessible: continue;
629185029Spjd      case AR_dependent:    EverDependent = true; continue;
630185029Spjd      }
631185029Spjd    }
632185029Spjd    return false;
633185029Spjd  }
634185029Spjd
635185029Spjd  /// Perform a search starting at the given class.
636185029Spjd  ///
637185029Spjd  /// PrivateDepth is the index of the last (least derived) class
638185029Spjd  /// along the current path such that a notional public member of
639185029Spjd  /// the final class in the path would have access in that class.
640185029Spjd  bool findFriendship(const CXXRecordDecl *Cur, unsigned PrivateDepth) {
641185029Spjd    // If we ever reach the naming class, check the current path for
642185029Spjd    // friendship.  We can also stop recursing because we obviously
643185029Spjd    // won't find the naming class there again.
644185029Spjd    if (Cur == NamingClass)
645185029Spjd      return checkFriendshipAlongPath(PrivateDepth);
646185029Spjd
647185029Spjd    if (CheckDependent && MightInstantiateTo(Cur, NamingClass))
648185029Spjd      EverDependent = true;
649185029Spjd
650185029Spjd    // Recurse into the base classes.
651185029Spjd    for (CXXRecordDecl::base_class_const_iterator
652185029Spjd           I = Cur->bases_begin(), E = Cur->bases_end(); I != E; ++I) {
653185029Spjd
654185029Spjd      // If this is private inheritance, then a public member of the
655185029Spjd      // base will not have any access in classes derived from Cur.
656185029Spjd      unsigned BasePrivateDepth = PrivateDepth;
657185029Spjd      if (I->getAccessSpecifier() == AS_private)
658185029Spjd        BasePrivateDepth = CurPath.size() - 1;
659185029Spjd
660185029Spjd      const CXXRecordDecl *RD;
661185029Spjd
662185029Spjd      QualType T = I->getType();
663185029Spjd      if (const RecordType *RT = T->getAs<RecordType>()) {
664185029Spjd        RD = cast<CXXRecordDecl>(RT->getDecl());
665185029Spjd      } else if (const InjectedClassNameType *IT
666185029Spjd                   = T->getAs<InjectedClassNameType>()) {
667185029Spjd        RD = IT->getDecl();
668185029Spjd      } else {
669168404Spjd        assert(T->isDependentType() && "non-dependent base wasn't a record?");
670185029Spjd        EverDependent = true;
671168404Spjd        continue;
672185029Spjd      }
673185029Spjd
674185029Spjd      // Recurse.  We don't need to clean up if this returns true.
675185029Spjd      CurPath.push_back(RD);
676185029Spjd      if (findFriendship(RD->getCanonicalDecl(), BasePrivateDepth))
677168404Spjd        return true;
678185029Spjd      CurPath.pop_back();
679185029Spjd    }
680168404Spjd
681185029Spjd    return false;
682168404Spjd  }
683185029Spjd
684185029Spjd  bool findFriendship(const CXXRecordDecl *Cur) {
685185029Spjd    assert(CurPath.empty());
686185029Spjd    CurPath.push_back(Cur);
687185029Spjd    return findFriendship(Cur, 0);
688185029Spjd  }
689185029Spjd};
690185029Spjd}
691185029Spjd
692185029Spjd/// Search for a class P that EC is a friend of, under the constraint
693185029Spjd///   InstanceContext <= P
694185029Spjd/// if InstanceContext exists, or else
695185029Spjd///   NamingClass <= P
696185029Spjd/// and with the additional restriction that a protected member of
697185029Spjd/// NamingClass would have some natural access in P, which implicitly
698168404Spjd/// imposes the constraint that P <= NamingClass.
699168404Spjd///
700168404Spjd/// This isn't quite the condition laid out in the standard.
701168404Spjd/// Instead of saying that a notional protected member of NamingClass
702168404Spjd/// would have to have some natural access in P, it says the actual
703168404Spjd/// target has to have some natural access in P, which opens up the
704185029Spjd/// possibility that the target (which is not necessarily a member
705185029Spjd/// of NamingClass) might be more accessible along some path not
706185029Spjd/// passing through it.  That's really a bad idea, though, because it
707185029Spjd/// introduces two problems:
708168404Spjd///   - Most importantly, it breaks encapsulation because you can
709168404Spjd///     access a forbidden base class's members by directly subclassing
710168404Spjd///     it elsewhere.
711185029Spjd///   - It also makes access substantially harder to compute because it
712185029Spjd///     breaks the hill-climbing algorithm: knowing that the target is
713185029Spjd///     accessible in some base class would no longer let you change
714185029Spjd///     the question solely to whether the base class is accessible,
715185029Spjd///     because the original target might have been more accessible
716185029Spjd///     because of crazy subclassing.
717185029Spjd/// So we don't implement that.
718185029Spjdstatic AccessResult GetProtectedFriendKind(Sema &S, const EffectiveContext &EC,
719185029Spjd                                           const CXXRecordDecl *InstanceContext,
720185029Spjd                                           const CXXRecordDecl *NamingClass) {
721185029Spjd  assert(InstanceContext == 0 ||
722185029Spjd         InstanceContext->getCanonicalDecl() == InstanceContext);
723185029Spjd  assert(NamingClass->getCanonicalDecl() == NamingClass);
724185029Spjd
725185029Spjd  // If we don't have an instance context, our constraints give us
726185029Spjd  // that NamingClass <= P <= NamingClass, i.e. P == NamingClass.
727168404Spjd  // This is just the usual friendship check.
728168404Spjd  if (!InstanceContext) return GetFriendKind(S, EC, NamingClass);
729168404Spjd
730168404Spjd  ProtectedFriendContext PRC(S, EC, InstanceContext, NamingClass);
731168404Spjd  if (PRC.findFriendship(InstanceContext)) return AR_accessible;
732168404Spjd  if (PRC.EverDependent) return AR_dependent;
733185029Spjd  return AR_inaccessible;
734185029Spjd}
735185029Spjd
736168404Spjdstatic AccessResult HasAccess(Sema &S,
737168404Spjd                              const EffectiveContext &EC,
738168404Spjd                              const CXXRecordDecl *NamingClass,
739168404Spjd                              AccessSpecifier Access,
740168404Spjd                              const AccessTarget &Target) {
741168404Spjd  assert(NamingClass->getCanonicalDecl() == NamingClass &&
742168404Spjd         "declaration should be canonicalized before being passed here");
743168404Spjd
744168404Spjd  if (Access == AS_public) return AR_accessible;
745168404Spjd  assert(Access == AS_private || Access == AS_protected);
746168404Spjd
747185029Spjd  AccessResult OnFailure = AR_inaccessible;
748185029Spjd
749185029Spjd  for (EffectiveContext::record_iterator
750185029Spjd         I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
751185029Spjd    // All the declarations in EC have been canonicalized, so pointer
752185029Spjd    // equality from this point on will work fine.
753185029Spjd    const CXXRecordDecl *ECRecord = *I;
754185029Spjd
755185029Spjd    // [B2] and [M2]
756168404Spjd    if (Access == AS_private) {
757168404Spjd      if (ECRecord == NamingClass)
758168404Spjd        return AR_accessible;
759168404Spjd
760168404Spjd      if (EC.isDependent() && MightInstantiateTo(ECRecord, NamingClass))
761168404Spjd        OnFailure = AR_dependent;
762168404Spjd
763168404Spjd    // [B3] and [M3]
764168404Spjd    } else {
765168404Spjd      assert(Access == AS_protected);
766185029Spjd      switch (IsDerivedFromInclusive(ECRecord, NamingClass)) {
767168404Spjd      case AR_accessible: break;
768168404Spjd      case AR_inaccessible: continue;
769168404Spjd      case AR_dependent: OnFailure = AR_dependent; continue;
770168404Spjd      }
771168404Spjd
772168404Spjd      // C++ [class.protected]p1:
773168404Spjd      //   An additional access check beyond those described earlier in
774168404Spjd      //   [class.access] is applied when a non-static data member or
775168404Spjd      //   non-static member function is a protected member of its naming
776168404Spjd      //   class.  As described earlier, access to a protected member is
777168404Spjd      //   granted because the reference occurs in a friend or member of
778168404Spjd      //   some class C.  If the access is to form a pointer to member,
779168404Spjd      //   the nested-name-specifier shall name C or a class derived from
780168404Spjd      //   C. All other accesses involve a (possibly implicit) object
781168404Spjd      //   expression. In this case, the class of the object expression
782168404Spjd      //   shall be C or a class derived from C.
783168404Spjd      //
784168404Spjd      // We interpret this as a restriction on [M3].
785168404Spjd
786168404Spjd      // In this part of the code, 'C' is just our context class ECRecord.
787168404Spjd
788168404Spjd      // These rules are different if we don't have an instance context.
789168404Spjd      if (!Target.hasInstanceContext()) {
790185029Spjd        // If it's not an instance member, these restrictions don't apply.
791168404Spjd        if (!Target.isInstanceMember()) return AR_accessible;
792185029Spjd
793168404Spjd        // If it's an instance member, use the pointer-to-member rule
794168404Spjd        // that the naming class has to be derived from the effective
795168404Spjd        // context.
796168404Spjd
797168404Spjd        // Emulate a MSVC bug where the creation of pointer-to-member
798168404Spjd        // to protected member of base class is allowed but only from
799168404Spjd        // static member functions.
800168404Spjd        if (S.getLangOpts().MicrosoftMode && !EC.Functions.empty())
801168404Spjd          if (CXXMethodDecl* MD = dyn_cast<CXXMethodDecl>(EC.Functions.front()))
802168404Spjd            if (MD->isStatic()) return AR_accessible;
803168404Spjd
804168404Spjd        // Despite the standard's confident wording, there is a case
805168404Spjd        // where you can have an instance member that's neither in a
806168404Spjd        // pointer-to-member expression nor in a member access:  when
807168404Spjd        // it names a field in an unevaluated context that can't be an
808168404Spjd        // implicit member.  Pending clarification, we just apply the
809168404Spjd        // same naming-class restriction here.
810168404Spjd        //   FIXME: we're probably not correctly adding the
811168404Spjd        //   protected-member restriction when we retroactively convert
812168404Spjd        //   an expression to being evaluated.
813168404Spjd
814168404Spjd        // We know that ECRecord derives from NamingClass.  The
815168404Spjd        // restriction says to check whether NamingClass derives from
816168404Spjd        // ECRecord, but that's not really necessary: two distinct
817168404Spjd        // classes can't be recursively derived from each other.  So
818168404Spjd        // along this path, we just need to check whether the classes
819168404Spjd        // are equal.
820168404Spjd        if (NamingClass == ECRecord) return AR_accessible;
821168404Spjd
822168404Spjd        // Otherwise, this context class tells us nothing;  on to the next.
823168404Spjd        continue;
824168404Spjd      }
825168404Spjd
826168404Spjd      assert(Target.isInstanceMember());
827168404Spjd
828168404Spjd      const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S);
829168404Spjd      if (!InstanceContext) {
830168404Spjd        OnFailure = AR_dependent;
831168404Spjd        continue;
832168404Spjd      }
833168404Spjd
834168404Spjd      switch (IsDerivedFromInclusive(InstanceContext, ECRecord)) {
835168404Spjd      case AR_accessible: return AR_accessible;
836168404Spjd      case AR_inaccessible: continue;
837168404Spjd      case AR_dependent: OnFailure = AR_dependent; continue;
838168404Spjd      }
839168404Spjd    }
840168404Spjd  }
841168404Spjd
842168404Spjd  // [M3] and [B3] say that, if the target is protected in N, we grant
843168404Spjd  // access if the access occurs in a friend or member of some class P
844168404Spjd  // that's a subclass of N and where the target has some natural
845168404Spjd  // access in P.  The 'member' aspect is easy to handle because P
846168404Spjd  // would necessarily be one of the effective-context records, and we
847168404Spjd  // address that above.  The 'friend' aspect is completely ridiculous
848168404Spjd  // to implement because there are no restrictions at all on P
849168404Spjd  // *unless* the [class.protected] restriction applies.  If it does,
850168404Spjd  // however, we should ignore whether the naming class is a friend,
851168404Spjd  // and instead rely on whether any potential P is a friend.
852168404Spjd  if (Access == AS_protected && Target.isInstanceMember()) {
853168404Spjd    // Compute the instance context if possible.
854168404Spjd    const CXXRecordDecl *InstanceContext = 0;
855168404Spjd    if (Target.hasInstanceContext()) {
856168404Spjd      InstanceContext = Target.resolveInstanceContext(S);
857168404Spjd      if (!InstanceContext) return AR_dependent;
858168404Spjd    }
859168404Spjd
860168404Spjd    switch (GetProtectedFriendKind(S, EC, InstanceContext, NamingClass)) {
861168404Spjd    case AR_accessible: return AR_accessible;
862168404Spjd    case AR_inaccessible: return OnFailure;
863168404Spjd    case AR_dependent: return AR_dependent;
864168404Spjd    }
865168404Spjd    llvm_unreachable("impossible friendship kind");
866168404Spjd  }
867168404Spjd
868168404Spjd  switch (GetFriendKind(S, EC, NamingClass)) {
869168404Spjd  case AR_accessible: return AR_accessible;
870168404Spjd  case AR_inaccessible: return OnFailure;
871168404Spjd  case AR_dependent: return AR_dependent;
872168404Spjd  }
873168404Spjd
874168404Spjd  // Silence bogus warnings
875168404Spjd  llvm_unreachable("impossible friendship kind");
876168404Spjd}
877168404Spjd
878168404Spjd/// Finds the best path from the naming class to the declaring class,
879168404Spjd/// taking friend declarations into account.
880168404Spjd///
881168404Spjd/// C++0x [class.access.base]p5:
882168404Spjd///   A member m is accessible at the point R when named in class N if
883168404Spjd///   [M1] m as a member of N is public, or
884168404Spjd///   [M2] m as a member of N is private, and R occurs in a member or
885168404Spjd///        friend of class N, or
886168404Spjd///   [M3] m as a member of N is protected, and R occurs in a member or
887168404Spjd///        friend of class N, or in a member or friend of a class P
888168404Spjd///        derived from N, where m as a member of P is public, private,
889168404Spjd///        or protected, or
890168404Spjd///   [M4] there exists a base class B of N that is accessible at R, and
891168404Spjd///        m is accessible at R when named in class B.
892185029Spjd///
893185029Spjd/// C++0x [class.access.base]p4:
894168404Spjd///   A base class B of N is accessible at R, if
895168404Spjd///   [B1] an invented public member of B would be a public member of N, or
896168404Spjd///   [B2] R occurs in a member or friend of class N, and an invented public
897168404Spjd///        member of B would be a private or protected member of N, or
898168404Spjd///   [B3] R occurs in a member or friend of a class P derived from N, and an
899168404Spjd///        invented public member of B would be a private or protected member
900168404Spjd///        of P, or
901168404Spjd///   [B4] there exists a class S such that B is a base class of S accessible
902168404Spjd///        at R and S is a base class of N accessible at R.
903168404Spjd///
904168404Spjd/// Along a single inheritance path we can restate both of these
905168404Spjd/// iteratively:
906168404Spjd///
907168404Spjd/// First, we note that M1-4 are equivalent to B1-4 if the member is
908168404Spjd/// treated as a notional base of its declaring class with inheritance
909168404Spjd/// access equivalent to the member's access.  Therefore we need only
910168404Spjd/// ask whether a class B is accessible from a class N in context R.
911168404Spjd///
912168404Spjd/// Let B_1 .. B_n be the inheritance path in question (i.e. where
913168404Spjd/// B_1 = N, B_n = B, and for all i, B_{i+1} is a direct base class of
914168404Spjd/// B_i).  For i in 1..n, we will calculate ACAB(i), the access to the
915168404Spjd/// closest accessible base in the path:
916168404Spjd///   Access(a, b) = (* access on the base specifier from a to b *)
917168404Spjd///   Merge(a, forbidden) = forbidden
918168404Spjd///   Merge(a, private) = forbidden
919168404Spjd///   Merge(a, b) = min(a,b)
920168404Spjd///   Accessible(c, forbidden) = false
921168404Spjd///   Accessible(c, private) = (R is c) || IsFriend(c, R)
922168404Spjd///   Accessible(c, protected) = (R derived from c) || IsFriend(c, R)
923168404Spjd///   Accessible(c, public) = true
924168404Spjd///   ACAB(n) = public
925168404Spjd///   ACAB(i) =
926168404Spjd///     let AccessToBase = Merge(Access(B_i, B_{i+1}), ACAB(i+1)) in
927168404Spjd///     if Accessible(B_i, AccessToBase) then public else AccessToBase
928168404Spjd///
929168404Spjd/// B is an accessible base of N at R iff ACAB(1) = public.
930168404Spjd///
931168404Spjd/// \param FinalAccess the access of the "final step", or AS_public if
932168404Spjd///   there is no final step.
933168404Spjd/// \return null if friendship is dependent
934168404Spjdstatic CXXBasePath *FindBestPath(Sema &S,
935168404Spjd                                 const EffectiveContext &EC,
936168404Spjd                                 AccessTarget &Target,
937168404Spjd                                 AccessSpecifier FinalAccess,
938168404Spjd                                 CXXBasePaths &Paths) {
939168404Spjd  // Derive the paths to the desired base.
940168404Spjd  const CXXRecordDecl *Derived = Target.getNamingClass();
941168404Spjd  const CXXRecordDecl *Base = Target.getDeclaringClass();
942168404Spjd
943168404Spjd  // FIXME: fail correctly when there are dependent paths.
944168404Spjd  bool isDerived = Derived->isDerivedFrom(const_cast<CXXRecordDecl*>(Base),
945168404Spjd                                          Paths);
946168404Spjd  assert(isDerived && "derived class not actually derived from base");
947168404Spjd  (void) isDerived;
948168404Spjd
949168404Spjd  CXXBasePath *BestPath = 0;
950168404Spjd
951168404Spjd  assert(FinalAccess != AS_none && "forbidden access after declaring class");
952168404Spjd
953168404Spjd  bool AnyDependent = false;
954168404Spjd
955168404Spjd  // Derive the friend-modified access along each path.
956168404Spjd  for (CXXBasePaths::paths_iterator PI = Paths.begin(), PE = Paths.end();
957168404Spjd         PI != PE; ++PI) {
958168404Spjd    AccessTarget::SavedInstanceContext _ = Target.saveInstanceContext();
959168404Spjd
960168404Spjd    // Walk through the path backwards.
961168404Spjd    AccessSpecifier PathAccess = FinalAccess;
962168404Spjd    CXXBasePath::iterator I = PI->end(), E = PI->begin();
963168404Spjd    while (I != E) {
964168404Spjd      --I;
965168404Spjd
966168404Spjd      assert(PathAccess != AS_none);
967168404Spjd
968168404Spjd      // If the declaration is a private member of a base class, there
969168404Spjd      // is no level of friendship in derived classes that can make it
970168404Spjd      // accessible.
971168404Spjd      if (PathAccess == AS_private) {
972168404Spjd        PathAccess = AS_none;
973168404Spjd        break;
974168404Spjd      }
975168404Spjd
976168404Spjd      const CXXRecordDecl *NC = I->Class->getCanonicalDecl();
977168404Spjd
978168404Spjd      AccessSpecifier BaseAccess = I->Base->getAccessSpecifier();
979168404Spjd      PathAccess = std::max(PathAccess, BaseAccess);
980168404Spjd
981168404Spjd      switch (HasAccess(S, EC, NC, PathAccess, Target)) {
982168404Spjd      case AR_inaccessible: break;
983168404Spjd      case AR_accessible:
984168404Spjd        PathAccess = AS_public;
985168404Spjd
986168404Spjd        // Future tests are not against members and so do not have
987168404Spjd        // instance context.
988168404Spjd        Target.suppressInstanceContext();
989185029Spjd        break;
990168404Spjd      case AR_dependent:
991168404Spjd        AnyDependent = true;
992168404Spjd        goto Next;
993168404Spjd      }
994168404Spjd    }
995168404Spjd
996168404Spjd    // Note that we modify the path's Access field to the
997168404Spjd    // friend-modified access.
998185029Spjd    if (BestPath == 0 || PathAccess < BestPath->Access) {
999168404Spjd      BestPath = &*PI;
1000168404Spjd      BestPath->Access = PathAccess;
1001168404Spjd
1002168404Spjd      // Short-circuit if we found a public path.
1003168404Spjd      if (BestPath->Access == AS_public)
1004168404Spjd        return BestPath;
1005168404Spjd    }
1006168404Spjd
1007168404Spjd  Next: ;
1008168404Spjd  }
1009168404Spjd
1010168404Spjd  assert((!BestPath || BestPath->Access != AS_public) &&
1011168404Spjd         "fell out of loop with public path");
1012168404Spjd
1013185029Spjd  // We didn't find a public path, but at least one path was subject
1014168404Spjd  // to dependent friendship, so delay the check.
1015168404Spjd  if (AnyDependent)
1016168404Spjd    return 0;
1017168404Spjd
1018168404Spjd  return BestPath;
1019168404Spjd}
1020168404Spjd
1021168404Spjd/// Given that an entity has protected natural access, check whether
1022168404Spjd/// access might be denied because of the protected member access
1023168404Spjd/// restriction.
1024168404Spjd///
1025168404Spjd/// \return true if a note was emitted
1026168404Spjdstatic bool TryDiagnoseProtectedAccess(Sema &S, const EffectiveContext &EC,
1027168404Spjd                                       AccessTarget &Target) {
1028168404Spjd  // Only applies to instance accesses.
1029168404Spjd  if (!Target.isInstanceMember())
1030168404Spjd    return false;
1031168404Spjd
1032168404Spjd  assert(Target.isMemberAccess());
1033168404Spjd
1034168404Spjd  const CXXRecordDecl *NamingClass = Target.getEffectiveNamingClass();
1035168404Spjd
1036168404Spjd  for (EffectiveContext::record_iterator
1037168404Spjd         I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
1038168404Spjd    const CXXRecordDecl *ECRecord = *I;
1039168404Spjd    switch (IsDerivedFromInclusive(ECRecord, NamingClass)) {
1040168404Spjd    case AR_accessible: break;
1041168404Spjd    case AR_inaccessible: continue;
1042168404Spjd    case AR_dependent: continue;
1043168404Spjd    }
1044168404Spjd
1045168404Spjd    // The effective context is a subclass of the declaring class.
1046168404Spjd    // Check whether the [class.protected] restriction is limiting
1047168404Spjd    // access.
1048168404Spjd
1049185029Spjd    // To get this exactly right, this might need to be checked more
1050168404Spjd    // holistically;  it's not necessarily the case that gaining
1051168404Spjd    // access here would grant us access overall.
1052168404Spjd
1053168404Spjd    NamedDecl *D = Target.getTargetDecl();
1054168404Spjd
1055168404Spjd    // If we don't have an instance context, [class.protected] says the
1056168404Spjd    // naming class has to equal the context class.
1057168404Spjd    if (!Target.hasInstanceContext()) {
1058168404Spjd      // If it does, the restriction doesn't apply.
1059168404Spjd      if (NamingClass == ECRecord) continue;
1060168404Spjd
1061168404Spjd      // TODO: it would be great to have a fixit here, since this is
1062168404Spjd      // such an obvious error.
1063168404Spjd      S.Diag(D->getLocation(), diag::note_access_protected_restricted_noobject)
1064168404Spjd        << S.Context.getTypeDeclType(ECRecord);
1065168404Spjd      return true;
1066168404Spjd    }
1067168404Spjd
1068168404Spjd    const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S);
1069168404Spjd    assert(InstanceContext && "diagnosing dependent access");
1070168404Spjd
1071168404Spjd    switch (IsDerivedFromInclusive(InstanceContext, ECRecord)) {
1072168404Spjd    case AR_accessible: continue;
1073168404Spjd    case AR_dependent: continue;
1074168404Spjd    case AR_inaccessible:
1075168404Spjd      break;
1076168404Spjd    }
1077168404Spjd
1078191900Skmacy    // Okay, the restriction seems to be what's limiting us.
1079168404Spjd
1080168404Spjd    // Use a special diagnostic for constructors and destructors.
1081168404Spjd    if (isa<CXXConstructorDecl>(D) || isa<CXXDestructorDecl>(D) ||
1082168404Spjd        (isa<FunctionTemplateDecl>(D) &&
1083185029Spjd         isa<CXXConstructorDecl>(
1084168404Spjd                cast<FunctionTemplateDecl>(D)->getTemplatedDecl()))) {
1085168404Spjd      S.Diag(D->getLocation(), diag::note_access_protected_restricted_ctordtor)
1086168404Spjd        << isa<CXXDestructorDecl>(D);
1087168404Spjd      return true;
1088168404Spjd    }
1089168404Spjd
1090168404Spjd    // Otherwise, use the generic diagnostic.
1091168404Spjd    S.Diag(D->getLocation(), diag::note_access_protected_restricted_object)
1092168404Spjd      << S.Context.getTypeDeclType(ECRecord);
1093185029Spjd    return true;
1094168404Spjd  }
1095168404Spjd
1096168404Spjd  return false;
1097168404Spjd}
1098168404Spjd
1099168404Spjd/// We are unable to access a given declaration due to its direct
1100168404Spjd/// access control;  diagnose that.
1101168404Spjdstatic void diagnoseBadDirectAccess(Sema &S,
1102168404Spjd                                    const EffectiveContext &EC,
1103168404Spjd                                    AccessTarget &entity) {
1104168404Spjd  assert(entity.isMemberAccess());
1105168404Spjd  NamedDecl *D = entity.getTargetDecl();
1106168404Spjd
1107168404Spjd  if (D->getAccess() == AS_protected &&
1108168404Spjd      TryDiagnoseProtectedAccess(S, EC, entity))
1109168404Spjd    return;
1110168404Spjd
1111168404Spjd  // Find an original declaration.
1112168404Spjd  while (D->isOutOfLine()) {
1113168404Spjd    NamedDecl *PrevDecl = 0;
1114168404Spjd    if (VarDecl *VD = dyn_cast<VarDecl>(D))
1115168404Spjd      PrevDecl = VD->getPreviousDecl();
1116168404Spjd    else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
1117168404Spjd      PrevDecl = FD->getPreviousDecl();
1118168404Spjd    else if (TypedefNameDecl *TND = dyn_cast<TypedefNameDecl>(D))
1119168404Spjd      PrevDecl = TND->getPreviousDecl();
1120168404Spjd    else if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
1121168404Spjd      if (isa<RecordDecl>(D) && cast<RecordDecl>(D)->isInjectedClassName())
1122168404Spjd        break;
1123168404Spjd      PrevDecl = TD->getPreviousDecl();
1124168404Spjd    }
1125168404Spjd    if (!PrevDecl) break;
1126168404Spjd    D = PrevDecl;
1127168404Spjd  }
1128168404Spjd
1129168404Spjd  CXXRecordDecl *DeclaringClass = FindDeclaringClass(D);
1130168404Spjd  Decl *ImmediateChild;
1131168404Spjd  if (D->getDeclContext() == DeclaringClass)
1132168404Spjd    ImmediateChild = D;
1133168404Spjd  else {
1134168404Spjd    DeclContext *DC = D->getDeclContext();
1135168404Spjd    while (DC->getParent() != DeclaringClass)
1136168404Spjd      DC = DC->getParent();
1137168404Spjd    ImmediateChild = cast<Decl>(DC);
1138168404Spjd  }
1139168404Spjd
1140168404Spjd  // Check whether there's an AccessSpecDecl preceding this in the
1141168404Spjd  // chain of the DeclContext.
1142168404Spjd  bool isImplicit = true;
1143168404Spjd  for (CXXRecordDecl::decl_iterator
1144168404Spjd         I = DeclaringClass->decls_begin(), E = DeclaringClass->decls_end();
1145168404Spjd       I != E; ++I) {
1146168404Spjd    if (*I == ImmediateChild) break;
1147168404Spjd    if (isa<AccessSpecDecl>(*I)) {
1148168404Spjd      isImplicit = false;
1149168404Spjd      break;
1150168404Spjd    }
1151168404Spjd  }
1152185029Spjd
1153168404Spjd  S.Diag(D->getLocation(), diag::note_access_natural)
1154168404Spjd    << (unsigned) (D->getAccess() == AS_protected)
1155168404Spjd    << isImplicit;
1156168404Spjd}
1157168404Spjd
1158168404Spjd/// Diagnose the path which caused the given declaration or base class
1159168404Spjd/// to become inaccessible.
1160168404Spjdstatic void DiagnoseAccessPath(Sema &S,
1161168404Spjd                               const EffectiveContext &EC,
1162168404Spjd                               AccessTarget &entity) {
1163168404Spjd  // Save the instance context to preserve invariants.
1164185029Spjd  AccessTarget::SavedInstanceContext _ = entity.saveInstanceContext();
1165168404Spjd
1166168404Spjd  // This basically repeats the main algorithm but keeps some more
1167168404Spjd  // information.
1168168404Spjd
1169168404Spjd  // The natural access so far.
1170168404Spjd  AccessSpecifier accessSoFar = AS_public;
1171168404Spjd
1172168404Spjd  // Check whether we have special rights to the declaring class.
1173168404Spjd  if (entity.isMemberAccess()) {
1174168404Spjd    NamedDecl *D = entity.getTargetDecl();
1175168404Spjd    accessSoFar = D->getAccess();
1176168404Spjd    const CXXRecordDecl *declaringClass = entity.getDeclaringClass();
1177168404Spjd
1178168404Spjd    switch (HasAccess(S, EC, declaringClass, accessSoFar, entity)) {
1179168404Spjd    // If the declaration is accessible when named in its declaring
1180168404Spjd    // class, then we must be constrained by the path.
1181168404Spjd    case AR_accessible:
1182168404Spjd      accessSoFar = AS_public;
1183168404Spjd      entity.suppressInstanceContext();
1184168404Spjd      break;
1185168404Spjd
1186168404Spjd    case AR_inaccessible:
1187168404Spjd      if (accessSoFar == AS_private ||
1188168404Spjd          declaringClass == entity.getEffectiveNamingClass())
1189168404Spjd        return diagnoseBadDirectAccess(S, EC, entity);
1190168404Spjd      break;
1191168404Spjd
1192168404Spjd    case AR_dependent:
1193168404Spjd      llvm_unreachable("cannot diagnose dependent access");
1194168404Spjd    }
1195168404Spjd  }
1196168404Spjd
1197168404Spjd  CXXBasePaths paths;
1198185029Spjd  CXXBasePath &path = *FindBestPath(S, EC, entity, accessSoFar, paths);
1199168404Spjd  assert(path.Access != AS_public);
1200185029Spjd
1201168404Spjd  CXXBasePath::iterator i = path.end(), e = path.begin();
1202168404Spjd  CXXBasePath::iterator constrainingBase = i;
1203168404Spjd  while (i != e) {
1204168404Spjd    --i;
1205168404Spjd
1206168404Spjd    assert(accessSoFar != AS_none && accessSoFar != AS_private);
1207168404Spjd
1208168404Spjd    // Is the entity accessible when named in the deriving class, as
1209168404Spjd    // modified by the base specifier?
1210168404Spjd    const CXXRecordDecl *derivingClass = i->Class->getCanonicalDecl();
1211168404Spjd    const CXXBaseSpecifier *base = i->Base;
1212168404Spjd
1213168404Spjd    // If the access to this base is worse than the access we have to
1214168404Spjd    // the declaration, remember it.
1215168404Spjd    AccessSpecifier baseAccess = base->getAccessSpecifier();
1216168404Spjd    if (baseAccess > accessSoFar) {
1217168404Spjd      constrainingBase = i;
1218168404Spjd      accessSoFar = baseAccess;
1219168404Spjd    }
1220168404Spjd
1221168404Spjd    switch (HasAccess(S, EC, derivingClass, accessSoFar, entity)) {
1222168404Spjd    case AR_inaccessible: break;
1223168404Spjd    case AR_accessible:
1224168404Spjd      accessSoFar = AS_public;
1225168404Spjd      entity.suppressInstanceContext();
1226168404Spjd      constrainingBase = 0;
1227168404Spjd      break;
1228168404Spjd    case AR_dependent:
1229168404Spjd      llvm_unreachable("cannot diagnose dependent access");
1230168404Spjd    }
1231168404Spjd
1232168404Spjd    // If this was private inheritance, but we don't have access to
1233168404Spjd    // the deriving class, we're done.
1234168404Spjd    if (accessSoFar == AS_private) {
1235168404Spjd      assert(baseAccess == AS_private);
1236168404Spjd      assert(constrainingBase == i);
1237168404Spjd      break;
1238168404Spjd    }
1239168404Spjd  }
1240168404Spjd
1241168404Spjd  // If we don't have a constraining base, the access failure must be
1242168404Spjd  // due to the original declaration.
1243168404Spjd  if (constrainingBase == path.end())
1244168404Spjd    return diagnoseBadDirectAccess(S, EC, entity);
1245168404Spjd
1246168404Spjd  // We're constrained by inheritance, but we want to say
1247168404Spjd  // "declared private here" if we're diagnosing a hierarchy
1248168404Spjd  // conversion and this is the final step.
1249168404Spjd  unsigned diagnostic;
1250168404Spjd  if (entity.isMemberAccess() ||
1251168404Spjd      constrainingBase + 1 != path.end()) {
1252168404Spjd    diagnostic = diag::note_access_constrained_by_path;
1253168404Spjd  } else {
1254168404Spjd    diagnostic = diag::note_access_natural;
1255168404Spjd  }
1256168404Spjd
1257168404Spjd  const CXXBaseSpecifier *base = constrainingBase->Base;
1258168404Spjd
1259168404Spjd  S.Diag(base->getSourceRange().getBegin(), diagnostic)
1260168404Spjd    << base->getSourceRange()
1261168404Spjd    << (base->getAccessSpecifier() == AS_protected)
1262168404Spjd    << (base->getAccessSpecifierAsWritten() == AS_none);
1263168404Spjd
1264168404Spjd  if (entity.isMemberAccess())
1265168404Spjd    S.Diag(entity.getTargetDecl()->getLocation(), diag::note_field_decl);
1266168404Spjd}
1267168404Spjd
1268168404Spjdstatic void DiagnoseBadAccess(Sema &S, SourceLocation Loc,
1269168404Spjd                              const EffectiveContext &EC,
1270168404Spjd                              AccessTarget &Entity) {
1271168404Spjd  const CXXRecordDecl *NamingClass = Entity.getNamingClass();
1272168404Spjd  const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();
1273168404Spjd  NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : 0);
1274168404Spjd
1275168404Spjd  S.Diag(Loc, Entity.getDiag())
1276168404Spjd    << (Entity.getAccess() == AS_protected)
1277168404Spjd    << (D ? D->getDeclName() : DeclarationName())
1278168404Spjd    << S.Context.getTypeDeclType(NamingClass)
1279168404Spjd    << S.Context.getTypeDeclType(DeclaringClass);
1280168404Spjd  DiagnoseAccessPath(S, EC, Entity);
1281168404Spjd}
1282168404Spjd
1283168404Spjd/// MSVC has a bug where if during an using declaration name lookup,
1284168404Spjd/// the declaration found is unaccessible (private) and that declaration
1285168404Spjd/// was bring into scope via another using declaration whose target
1286168404Spjd/// declaration is accessible (public) then no error is generated.
1287168404Spjd/// Example:
1288168404Spjd///   class A {
1289168404Spjd///   public:
1290168404Spjd///     int f();
1291168404Spjd///   };
1292168404Spjd///   class B : public A {
1293168404Spjd///   private:
1294168404Spjd///     using A::f;
1295168404Spjd///   };
1296168404Spjd///   class C : public B {
1297168404Spjd///   private:
1298168404Spjd///     using B::f;
1299168404Spjd///   };
1300168404Spjd///
1301168404Spjd/// Here, B::f is private so this should fail in Standard C++, but
1302168404Spjd/// because B::f refers to A::f which is public MSVC accepts it.
1303168404Spjdstatic bool IsMicrosoftUsingDeclarationAccessBug(Sema& S,
1304168404Spjd                                                 SourceLocation AccessLoc,
1305168404Spjd                                                 AccessTarget &Entity) {
1306168404Spjd  if (UsingShadowDecl *Shadow =
1307168404Spjd                         dyn_cast<UsingShadowDecl>(Entity.getTargetDecl())) {
1308168404Spjd    const NamedDecl *OrigDecl = Entity.getTargetDecl()->getUnderlyingDecl();
1309168404Spjd    if (Entity.getTargetDecl()->getAccess() == AS_private &&
1310168404Spjd        (OrigDecl->getAccess() == AS_public ||
1311168404Spjd         OrigDecl->getAccess() == AS_protected)) {
1312168404Spjd      S.Diag(AccessLoc, diag::ext_ms_using_declaration_inaccessible)
1313168404Spjd        << Shadow->getUsingDecl()->getQualifiedNameAsString()
1314168404Spjd        << OrigDecl->getQualifiedNameAsString();
1315168404Spjd      return true;
1316168404Spjd    }
1317168404Spjd  }
1318168404Spjd  return false;
1319168404Spjd}
1320168404Spjd
1321168404Spjd/// Determines whether the accessed entity is accessible.  Public members
1322168404Spjd/// have been weeded out by this point.
1323168404Spjdstatic AccessResult IsAccessible(Sema &S,
1324168404Spjd                                 const EffectiveContext &EC,
1325168404Spjd                                 AccessTarget &Entity) {
1326168404Spjd  // Determine the actual naming class.
1327168404Spjd  const CXXRecordDecl *NamingClass = Entity.getEffectiveNamingClass();
1328168404Spjd
1329168404Spjd  AccessSpecifier UnprivilegedAccess = Entity.getAccess();
1330168404Spjd  assert(UnprivilegedAccess != AS_public && "public access not weeded out");
1331168404Spjd
1332168404Spjd  // Before we try to recalculate access paths, try to white-list
1333168404Spjd  // accesses which just trade in on the final step, i.e. accesses
1334168404Spjd  // which don't require [M4] or [B4]. These are by far the most
1335168404Spjd  // common forms of privileged access.
1336168404Spjd  if (UnprivilegedAccess != AS_none) {
1337168404Spjd    switch (HasAccess(S, EC, NamingClass, UnprivilegedAccess, Entity)) {
1338168404Spjd    case AR_dependent:
1339168404Spjd      // This is actually an interesting policy decision.  We don't
1340168404Spjd      // *have* to delay immediately here: we can do the full access
1341168404Spjd      // calculation in the hope that friendship on some intermediate
1342185029Spjd      // class will make the declaration accessible non-dependently.
1343168404Spjd      // But that's not cheap, and odds are very good (note: assertion
1344185029Spjd      // made without data) that the friend declaration will determine
1345185029Spjd      // access.
1346185029Spjd      return AR_dependent;
1347185029Spjd
1348185029Spjd    case AR_accessible: return AR_accessible;
1349185029Spjd    case AR_inaccessible: break;
1350168404Spjd    }
1351168404Spjd  }
1352168404Spjd
1353168404Spjd  AccessTarget::SavedInstanceContext _ = Entity.saveInstanceContext();
1354168404Spjd
1355168404Spjd  // We lower member accesses to base accesses by pretending that the
1356168404Spjd  // member is a base class of its declaring class.
1357168404Spjd  AccessSpecifier FinalAccess;
1358168404Spjd
1359168404Spjd  if (Entity.isMemberAccess()) {
1360168404Spjd    // Determine if the declaration is accessible from EC when named
1361168404Spjd    // in its declaring class.
1362168404Spjd    NamedDecl *Target = Entity.getTargetDecl();
1363168404Spjd    const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();
1364168404Spjd
1365168404Spjd    FinalAccess = Target->getAccess();
1366168404Spjd    switch (HasAccess(S, EC, DeclaringClass, FinalAccess, Entity)) {
1367168404Spjd    case AR_accessible:
1368185029Spjd      // Target is accessible at EC when named in its declaring class.
1369185029Spjd      // We can now hill-climb and simply check whether the declaring
1370168404Spjd      // class is accessible as a base of the naming class.  This is
1371168404Spjd      // equivalent to checking the access of a notional public
1372168404Spjd      // member with no instance context.
1373168404Spjd      FinalAccess = AS_public;
1374168404Spjd      Entity.suppressInstanceContext();
1375185029Spjd      break;
1376185029Spjd    case AR_inaccessible: break;
1377185029Spjd    case AR_dependent: return AR_dependent; // see above
1378168404Spjd    }
1379168404Spjd
1380168404Spjd    if (DeclaringClass == NamingClass)
1381168404Spjd      return (FinalAccess == AS_public ? AR_accessible : AR_inaccessible);
1382168404Spjd  } else {
1383168404Spjd    FinalAccess = AS_public;
1384168404Spjd  }
1385168404Spjd
1386168404Spjd  assert(Entity.getDeclaringClass() != NamingClass);
1387168404Spjd
1388168404Spjd  // Append the declaration's access if applicable.
1389168404Spjd  CXXBasePaths Paths;
1390168404Spjd  CXXBasePath *Path = FindBestPath(S, EC, Entity, FinalAccess, Paths);
1391168404Spjd  if (!Path)
1392168404Spjd    return AR_dependent;
1393168404Spjd
1394168404Spjd  assert(Path->Access <= UnprivilegedAccess &&
1395168404Spjd         "access along best path worse than direct?");
1396168404Spjd  if (Path->Access == AS_public)
1397168404Spjd    return AR_accessible;
1398168404Spjd  return AR_inaccessible;
1399168404Spjd}
1400168404Spjd
1401168404Spjdstatic void DelayDependentAccess(Sema &S,
1402168404Spjd                                 const EffectiveContext &EC,
1403168404Spjd                                 SourceLocation Loc,
1404168404Spjd                                 const AccessTarget &Entity) {
1405168404Spjd  assert(EC.isDependent() && "delaying non-dependent access");
1406168404Spjd  DeclContext *DC = EC.getInnerContext();
1407168404Spjd  assert(DC->isDependentContext() && "delaying non-dependent access");
1408168404Spjd  DependentDiagnostic::Create(S.Context, DC, DependentDiagnostic::Access,
1409168404Spjd                              Loc,
1410168404Spjd                              Entity.isMemberAccess(),
1411168404Spjd                              Entity.getAccess(),
1412168404Spjd                              Entity.getTargetDecl(),
1413168404Spjd                              Entity.getNamingClass(),
1414168404Spjd                              Entity.getBaseObjectType(),
1415168404Spjd                              Entity.getDiag());
1416168404Spjd}
1417168404Spjd
1418168404Spjd/// Checks access to an entity from the given effective context.
1419168404Spjdstatic AccessResult CheckEffectiveAccess(Sema &S,
1420168404Spjd                                         const EffectiveContext &EC,
1421168404Spjd                                         SourceLocation Loc,
1422168404Spjd                                         AccessTarget &Entity) {
1423168404Spjd  assert(Entity.getAccess() != AS_public && "called for public access!");
1424168404Spjd
1425168404Spjd  if (S.getLangOpts().MicrosoftMode &&
1426168404Spjd      IsMicrosoftUsingDeclarationAccessBug(S, Loc, Entity))
1427168404Spjd    return AR_accessible;
1428168404Spjd
1429168404Spjd  switch (IsAccessible(S, EC, Entity)) {
1430168404Spjd  case AR_dependent:
1431168404Spjd    DelayDependentAccess(S, EC, Loc, Entity);
1432168404Spjd    return AR_dependent;
1433168404Spjd
1434168404Spjd  case AR_inaccessible:
1435168404Spjd    if (!Entity.isQuiet())
1436200724Sdelphij      DiagnoseBadAccess(S, Loc, EC, Entity);
1437168404Spjd    return AR_inaccessible;
1438168404Spjd
1439168404Spjd  case AR_accessible:
1440168404Spjd    return AR_accessible;
1441168404Spjd  }
1442168404Spjd
1443168404Spjd  // silence unnecessary warning
1444168404Spjd  llvm_unreachable("invalid access result");
1445168404Spjd}
1446168404Spjd
1447168404Spjdstatic Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc,
1448168404Spjd                                      AccessTarget &Entity) {
1449168404Spjd  // If the access path is public, it's accessible everywhere.
1450168404Spjd  if (Entity.getAccess() == AS_public)
1451168404Spjd    return Sema::AR_accessible;
1452168404Spjd
1453168404Spjd  // If we're currently parsing a declaration, we may need to delay
1454168404Spjd  // access control checking, because our effective context might be
1455168404Spjd  // different based on what the declaration comes out as.
1456168404Spjd  //
1457168404Spjd  // For example, we might be parsing a declaration with a scope
1458168404Spjd  // specifier, like this:
1459168404Spjd  //   A::private_type A::foo() { ... }
1460168404Spjd  //
1461168404Spjd  // Or we might be parsing something that will turn out to be a friend:
1462168404Spjd  //   void foo(A::private_type);
1463168404Spjd  //   void B::foo(A::private_type);
1464168404Spjd  if (S.DelayedDiagnostics.shouldDelayDiagnostics()) {
1465168404Spjd    S.DelayedDiagnostics.add(DelayedDiagnostic::makeAccess(Loc, Entity));
1466168404Spjd    return Sema::AR_delayed;
1467168404Spjd  }
1468168404Spjd
1469168404Spjd  EffectiveContext EC(S.CurContext);
1470168404Spjd  switch (CheckEffectiveAccess(S, EC, Loc, Entity)) {
1471168404Spjd  case AR_accessible: return Sema::AR_accessible;
1472168404Spjd  case AR_inaccessible: return Sema::AR_inaccessible;
1473168404Spjd  case AR_dependent: return Sema::AR_dependent;
1474168404Spjd  }
1475168404Spjd  llvm_unreachable("falling off end");
1476168404Spjd}
1477168404Spjd
1478168404Spjdvoid Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *D) {
1479168404Spjd  // Access control for names used in the declarations of functions
1480168404Spjd  // and function templates should normally be evaluated in the context
1481168404Spjd  // of the declaration, just in case it's a friend of something.
1482168404Spjd  // However, this does not apply to local extern declarations.
1483168404Spjd
1484168404Spjd  DeclContext *DC = D->getDeclContext();
1485185029Spjd  if (FunctionDecl *FN = dyn_cast<FunctionDecl>(D)) {
1486168404Spjd    if (D->getLexicalDeclContext()->isFunctionOrMethod())
1487168404Spjd      DC = D->getLexicalDeclContext();
1488168404Spjd    else
1489168404Spjd      DC = FN;
1490168404Spjd  } else if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D)) {
1491168404Spjd    DC = cast<DeclContext>(TD->getTemplatedDecl());
1492168404Spjd  }
1493168404Spjd
1494168404Spjd  EffectiveContext EC(DC);
1495168404Spjd
1496168404Spjd  AccessTarget Target(DD.getAccessData());
1497168404Spjd
1498168404Spjd  if (CheckEffectiveAccess(*this, EC, DD.Loc, Target) == ::AR_inaccessible)
1499168404Spjd    DD.Triggered = true;
1500168404Spjd}
1501168404Spjd
1502168404Spjdvoid Sema::HandleDependentAccessCheck(const DependentDiagnostic &DD,
1503168404Spjd                        const MultiLevelTemplateArgumentList &TemplateArgs) {
1504168404Spjd  SourceLocation Loc = DD.getAccessLoc();
1505168404Spjd  AccessSpecifier Access = DD.getAccess();
1506168404Spjd
1507168404Spjd  Decl *NamingD = FindInstantiatedDecl(Loc, DD.getAccessNamingClass(),
1508168404Spjd                                       TemplateArgs);
1509168404Spjd  if (!NamingD) return;
1510168404Spjd  Decl *TargetD = FindInstantiatedDecl(Loc, DD.getAccessTarget(),
1511185029Spjd                                       TemplateArgs);
1512185029Spjd  if (!TargetD) return;
1513185029Spjd
1514168404Spjd  if (DD.isAccessToMember()) {
1515168404Spjd    CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(NamingD);
1516168404Spjd    NamedDecl *TargetDecl = cast<NamedDecl>(TargetD);
1517168404Spjd    QualType BaseObjectType = DD.getAccessBaseObjectType();
1518168404Spjd    if (!BaseObjectType.isNull()) {
1519168404Spjd      BaseObjectType = SubstType(BaseObjectType, TemplateArgs, Loc,
1520168404Spjd                                 DeclarationName());
1521168404Spjd      if (BaseObjectType.isNull()) return;
1522168404Spjd    }
1523168404Spjd
1524168404Spjd    AccessTarget Entity(Context,
1525168404Spjd                        AccessTarget::Member,
1526168404Spjd                        NamingClass,
1527168404Spjd                        DeclAccessPair::make(TargetDecl, Access),
1528168404Spjd                        BaseObjectType);
1529168404Spjd    Entity.setDiag(DD.getDiagnostic());
1530168404Spjd    CheckAccess(*this, Loc, Entity);
1531168404Spjd  } else {
1532168404Spjd    AccessTarget Entity(Context,
1533168404Spjd                        AccessTarget::Base,
1534168404Spjd                        cast<CXXRecordDecl>(TargetD),
1535168404Spjd                        cast<CXXRecordDecl>(NamingD),
1536168404Spjd                        Access);
1537168404Spjd    Entity.setDiag(DD.getDiagnostic());
1538168404Spjd    CheckAccess(*this, Loc, Entity);
1539168404Spjd  }
1540168404Spjd}
1541168404Spjd
1542168404SpjdSema::AccessResult Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E,
1543168404Spjd                                                     DeclAccessPair Found) {
1544168404Spjd  if (!getLangOpts().AccessControl ||
1545168404Spjd      !E->getNamingClass() ||
1546168404Spjd      Found.getAccess() == AS_public)
1547168404Spjd    return AR_accessible;
1548168404Spjd
1549168404Spjd  AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(),
1550168404Spjd                      Found, QualType());
1551168404Spjd  Entity.setDiag(diag::err_access) << E->getSourceRange();
1552168404Spjd
1553168404Spjd  return CheckAccess(*this, E->getNameLoc(), Entity);
1554168404Spjd}
1555168404Spjd
1556168404Spjd/// Perform access-control checking on a previously-unresolved member
1557168404Spjd/// access which has now been resolved to a member.
1558168404SpjdSema::AccessResult Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E,
1559168404Spjd                                                     DeclAccessPair Found) {
1560168404Spjd  if (!getLangOpts().AccessControl ||
1561168404Spjd      Found.getAccess() == AS_public)
1562168404Spjd    return AR_accessible;
1563168404Spjd
1564168404Spjd  QualType BaseType = E->getBaseType();
1565168404Spjd  if (E->isArrow())
1566168404Spjd    BaseType = BaseType->getAs<PointerType>()->getPointeeType();
1567168404Spjd
1568168404Spjd  AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(),
1569168404Spjd                      Found, BaseType);
1570168404Spjd  Entity.setDiag(diag::err_access) << E->getSourceRange();
1571168404Spjd
1572168404Spjd  return CheckAccess(*this, E->getMemberLoc(), Entity);
1573168404Spjd}
1574168404Spjd
1575168404Spjd/// Is the given special member function accessible for the purposes of
1576168404Spjd/// deciding whether to define a special member function as deleted?
1577168404Spjdbool Sema::isSpecialMemberAccessibleForDeletion(CXXMethodDecl *decl,
1578168404Spjd                                                AccessSpecifier access,
1579168404Spjd                                                QualType objectType) {
1580168404Spjd  // Fast path.
1581168404Spjd  if (access == AS_public || !getLangOpts().AccessControl) return true;
1582168404Spjd
1583168404Spjd  AccessTarget entity(Context, AccessTarget::Member, decl->getParent(),
1584168404Spjd                      DeclAccessPair::make(decl, access), objectType);
1585168404Spjd
1586168404Spjd  // Suppress diagnostics.
1587168404Spjd  entity.setDiag(PDiag());
1588185029Spjd
1589185029Spjd  switch (CheckAccess(*this, SourceLocation(), entity)) {
1590168404Spjd  case AR_accessible: return true;
1591168404Spjd  case AR_inaccessible: return false;
1592168404Spjd  case AR_dependent: llvm_unreachable("dependent for =delete computation");
1593185029Spjd  case AR_delayed: llvm_unreachable("cannot delay =delete computation");
1594168404Spjd  }
1595168404Spjd  llvm_unreachable("bad access result");
1596168404Spjd}
1597168404Spjd
1598168404SpjdSema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc,
1599168404Spjd                                               CXXDestructorDecl *Dtor,
1600168404Spjd                                               const PartialDiagnostic &PDiag,
1601168404Spjd                                               QualType ObjectTy) {
1602168404Spjd  if (!getLangOpts().AccessControl)
1603168404Spjd    return AR_accessible;
1604168404Spjd
1605168404Spjd  // There's never a path involved when checking implicit destructor access.
1606168404Spjd  AccessSpecifier Access = Dtor->getAccess();
1607168404Spjd  if (Access == AS_public)
1608168404Spjd    return AR_accessible;
1609168404Spjd
1610168404Spjd  CXXRecordDecl *NamingClass = Dtor->getParent();
1611168404Spjd  if (ObjectTy.isNull()) ObjectTy = Context.getTypeDeclType(NamingClass);
1612168404Spjd
1613168404Spjd  AccessTarget Entity(Context, AccessTarget::Member, NamingClass,
1614168404Spjd                      DeclAccessPair::make(Dtor, Access),
1615168404Spjd                      ObjectTy);
1616185029Spjd  Entity.setDiag(PDiag); // TODO: avoid copy
1617185029Spjd
1618168404Spjd  return CheckAccess(*this, Loc, Entity);
1619168404Spjd}
1620168404Spjd
1621168404Spjd/// Checks access to a constructor.
1622168404SpjdSema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc,
1623168404Spjd                                                CXXConstructorDecl *Constructor,
1624168404Spjd                                                const InitializedEntity &Entity,
1625168404Spjd                                                AccessSpecifier Access,
1626168404Spjd                                                bool IsCopyBindingRefToTemp) {
1627168404Spjd  if (!getLangOpts().AccessControl || Access == AS_public)
1628168404Spjd    return AR_accessible;
1629168404Spjd
1630168404Spjd  PartialDiagnostic PD(PDiag());
1631168404Spjd  switch (Entity.getKind()) {
1632168404Spjd  default:
1633168404Spjd    PD = PDiag(IsCopyBindingRefToTemp
1634168404Spjd                 ? diag::ext_rvalue_to_reference_access_ctor
1635168404Spjd                 : diag::err_access_ctor);
1636168404Spjd
1637185029Spjd    break;
1638185029Spjd
1639185029Spjd  case InitializedEntity::EK_Base:
1640168404Spjd    PD = PDiag(diag::err_access_base_ctor);
1641168404Spjd    PD << Entity.isInheritedVirtualBase()
1642168404Spjd       << Entity.getBaseSpecifier()->getType() << getSpecialMember(Constructor);
1643168404Spjd    break;
1644168404Spjd
1645168404Spjd  case InitializedEntity::EK_Member: {
1646168404Spjd    const FieldDecl *Field = cast<FieldDecl>(Entity.getDecl());
1647168404Spjd    PD = PDiag(diag::err_access_field_ctor);
1648168404Spjd    PD << Field->getType() << getSpecialMember(Constructor);
1649168404Spjd    break;
1650168404Spjd  }
1651168404Spjd
1652168404Spjd  case InitializedEntity::EK_LambdaCapture: {
1653168404Spjd    StringRef VarName = Entity.getCapturedVarName();
1654168404Spjd    PD = PDiag(diag::err_access_lambda_capture);
1655168404Spjd    PD << VarName << Entity.getType() << getSpecialMember(Constructor);
1656185029Spjd    break;
1657185029Spjd  }
1658168404Spjd
1659168404Spjd  }
1660168404Spjd
1661168404Spjd  return CheckConstructorAccess(UseLoc, Constructor, Entity, Access, PD);
1662168404Spjd}
1663200724Sdelphij
1664168404Spjd/// Checks access to a constructor.
1665168404SpjdSema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc,
1666168404Spjd                                                CXXConstructorDecl *Constructor,
1667168404Spjd                                                const InitializedEntity &Entity,
1668168404Spjd                                                AccessSpecifier Access,
1669168404Spjd                                                const PartialDiagnostic &PD) {
1670168404Spjd  if (!getLangOpts().AccessControl ||
1671185029Spjd      Access == AS_public)
1672168404Spjd    return AR_accessible;
1673168404Spjd
1674168404Spjd  CXXRecordDecl *NamingClass = Constructor->getParent();
1675168404Spjd
1676168404Spjd  // Initializing a base sub-object is an instance method call on an
1677168404Spjd  // object of the derived class.  Otherwise, we have an instance method
1678168404Spjd  // call on an object of the constructed type.
1679168404Spjd  CXXRecordDecl *ObjectClass;
1680168404Spjd  if (Entity.getKind() == InitializedEntity::EK_Base) {
1681168404Spjd    ObjectClass = cast<CXXConstructorDecl>(CurContext)->getParent();
1682168404Spjd  } else {
1683174049Sjb    ObjectClass = NamingClass;
1684168404Spjd  }
1685168404Spjd
1686168404Spjd  AccessTarget AccessEntity(Context, AccessTarget::Member, NamingClass,
1687168404Spjd                            DeclAccessPair::make(Constructor, Access),
1688168404Spjd                            Context.getTypeDeclType(ObjectClass));
1689168404Spjd  AccessEntity.setDiag(PD);
1690185029Spjd
1691168404Spjd  return CheckAccess(*this, UseLoc, AccessEntity);
1692168404Spjd}
1693168404Spjd
1694168404Spjd/// Checks access to an overloaded operator new or delete.
1695168404SpjdSema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc,
1696168404Spjd                                               SourceRange PlacementRange,
1697168404Spjd                                               CXXRecordDecl *NamingClass,
1698168404Spjd                                               DeclAccessPair Found,
1699168404Spjd                                               bool Diagnose) {
1700168404Spjd  if (!getLangOpts().AccessControl ||
1701168404Spjd      !NamingClass ||
1702168404Spjd      Found.getAccess() == AS_public)
1703168404Spjd    return AR_accessible;
1704168404Spjd
1705168404Spjd  AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
1706168404Spjd                      QualType());
1707168404Spjd  if (Diagnose)
1708168404Spjd    Entity.setDiag(diag::err_access)
1709168404Spjd      << PlacementRange;
1710168404Spjd
1711168404Spjd  return CheckAccess(*this, OpLoc, Entity);
1712168404Spjd}
1713168404Spjd
1714168404Spjd/// \brief Checks access to a member.
1715168404SpjdSema::AccessResult Sema::CheckMemberAccess(SourceLocation UseLoc,
1716168404Spjd                                           CXXRecordDecl *NamingClass,
1717168404Spjd                                           DeclAccessPair Found) {
1718168404Spjd  if (!getLangOpts().AccessControl ||
1719168404Spjd      !NamingClass ||
1720168404Spjd      Found.getAccess() == AS_public)
1721168404Spjd    return AR_accessible;
1722168404Spjd
1723168404Spjd  AccessTarget Entity(Context, AccessTarget::Member, NamingClass,
1724168404Spjd                      Found, QualType());
1725168404Spjd
1726168404Spjd  return CheckAccess(*this, UseLoc, Entity);
1727168404Spjd}
1728168404Spjd
1729168404Spjd/// Checks access to an overloaded member operator, including
1730168404Spjd/// conversion operators.
1731168404SpjdSema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc,
1732168404Spjd                                                   Expr *ObjectExpr,
1733168404Spjd                                                   Expr *ArgExpr,
1734168404Spjd                                                   DeclAccessPair Found) {
1735168404Spjd  if (!getLangOpts().AccessControl ||
1736      Found.getAccess() == AS_public)
1737    return AR_accessible;
1738
1739  const RecordType *RT = ObjectExpr->getType()->castAs<RecordType>();
1740  CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(RT->getDecl());
1741
1742  AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
1743                      ObjectExpr->getType());
1744  Entity.setDiag(diag::err_access)
1745    << ObjectExpr->getSourceRange()
1746    << (ArgExpr ? ArgExpr->getSourceRange() : SourceRange());
1747
1748  return CheckAccess(*this, OpLoc, Entity);
1749}
1750
1751/// Checks access to the target of a friend declaration.
1752Sema::AccessResult Sema::CheckFriendAccess(NamedDecl *target) {
1753  assert(isa<CXXMethodDecl>(target) ||
1754         (isa<FunctionTemplateDecl>(target) &&
1755          isa<CXXMethodDecl>(cast<FunctionTemplateDecl>(target)
1756                               ->getTemplatedDecl())));
1757
1758  // Friendship lookup is a redeclaration lookup, so there's never an
1759  // inheritance path modifying access.
1760  AccessSpecifier access = target->getAccess();
1761
1762  if (!getLangOpts().AccessControl || access == AS_public)
1763    return AR_accessible;
1764
1765  CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(target);
1766  if (!method)
1767    method = cast<CXXMethodDecl>(
1768                     cast<FunctionTemplateDecl>(target)->getTemplatedDecl());
1769  assert(method->getQualifier());
1770
1771  AccessTarget entity(Context, AccessTarget::Member,
1772                      cast<CXXRecordDecl>(target->getDeclContext()),
1773                      DeclAccessPair::make(target, access),
1774                      /*no instance context*/ QualType());
1775  entity.setDiag(diag::err_access_friend_function)
1776    << method->getQualifierLoc().getSourceRange();
1777
1778  // We need to bypass delayed-diagnostics because we might be called
1779  // while the ParsingDeclarator is active.
1780  EffectiveContext EC(CurContext);
1781  switch (CheckEffectiveAccess(*this, EC, target->getLocation(), entity)) {
1782  case AR_accessible: return Sema::AR_accessible;
1783  case AR_inaccessible: return Sema::AR_inaccessible;
1784  case AR_dependent: return Sema::AR_dependent;
1785  }
1786  llvm_unreachable("falling off end");
1787}
1788
1789Sema::AccessResult Sema::CheckAddressOfMemberAccess(Expr *OvlExpr,
1790                                                    DeclAccessPair Found) {
1791  if (!getLangOpts().AccessControl ||
1792      Found.getAccess() == AS_none ||
1793      Found.getAccess() == AS_public)
1794    return AR_accessible;
1795
1796  OverloadExpr *Ovl = OverloadExpr::find(OvlExpr).Expression;
1797  CXXRecordDecl *NamingClass = Ovl->getNamingClass();
1798
1799  AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
1800                      /*no instance context*/ QualType());
1801  Entity.setDiag(diag::err_access)
1802    << Ovl->getSourceRange();
1803
1804  return CheckAccess(*this, Ovl->getNameLoc(), Entity);
1805}
1806
1807/// Checks access for a hierarchy conversion.
1808///
1809/// \param ForceCheck true if this check should be performed even if access
1810///     control is disabled;  some things rely on this for semantics
1811/// \param ForceUnprivileged true if this check should proceed as if the
1812///     context had no special privileges
1813Sema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc,
1814                                              QualType Base,
1815                                              QualType Derived,
1816                                              const CXXBasePath &Path,
1817                                              unsigned DiagID,
1818                                              bool ForceCheck,
1819                                              bool ForceUnprivileged) {
1820  if (!ForceCheck && !getLangOpts().AccessControl)
1821    return AR_accessible;
1822
1823  if (Path.Access == AS_public)
1824    return AR_accessible;
1825
1826  CXXRecordDecl *BaseD, *DerivedD;
1827  BaseD = cast<CXXRecordDecl>(Base->getAs<RecordType>()->getDecl());
1828  DerivedD = cast<CXXRecordDecl>(Derived->getAs<RecordType>()->getDecl());
1829
1830  AccessTarget Entity(Context, AccessTarget::Base, BaseD, DerivedD,
1831                      Path.Access);
1832  if (DiagID)
1833    Entity.setDiag(DiagID) << Derived << Base;
1834
1835  if (ForceUnprivileged) {
1836    switch (CheckEffectiveAccess(*this, EffectiveContext(),
1837                                 AccessLoc, Entity)) {
1838    case ::AR_accessible: return Sema::AR_accessible;
1839    case ::AR_inaccessible: return Sema::AR_inaccessible;
1840    case ::AR_dependent: return Sema::AR_dependent;
1841    }
1842    llvm_unreachable("unexpected result from CheckEffectiveAccess");
1843  }
1844  return CheckAccess(*this, AccessLoc, Entity);
1845}
1846
1847/// Checks access to all the declarations in the given result set.
1848void Sema::CheckLookupAccess(const LookupResult &R) {
1849  assert(getLangOpts().AccessControl
1850         && "performing access check without access control");
1851  assert(R.getNamingClass() && "performing access check without naming class");
1852
1853  for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
1854    if (I.getAccess() != AS_public) {
1855      AccessTarget Entity(Context, AccessedEntity::Member,
1856                          R.getNamingClass(), I.getPair(),
1857                          R.getBaseObjectType());
1858      Entity.setDiag(diag::err_access);
1859      CheckAccess(*this, R.getNameLoc(), Entity);
1860    }
1861  }
1862}
1863
1864/// Checks access to Decl from the given class. The check will take access
1865/// specifiers into account, but no member access expressions and such.
1866///
1867/// \param Decl the declaration to check if it can be accessed
1868/// \param Ctx the class/context from which to start the search
1869/// \return true if the Decl is accessible from the Class, false otherwise.
1870bool Sema::IsSimplyAccessible(NamedDecl *Decl, DeclContext *Ctx) {
1871  if (CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(Ctx)) {
1872    if (!Decl->isCXXClassMember())
1873      return true;
1874
1875    QualType qType = Class->getTypeForDecl()->getCanonicalTypeInternal();
1876    AccessTarget Entity(Context, AccessedEntity::Member, Class,
1877                        DeclAccessPair::make(Decl, Decl->getAccess()),
1878                        qType);
1879    if (Entity.getAccess() == AS_public)
1880      return true;
1881
1882    EffectiveContext EC(CurContext);
1883    return ::IsAccessible(*this, EC, Entity) != ::AR_inaccessible;
1884  }
1885
1886  if (ObjCIvarDecl *Ivar = dyn_cast<ObjCIvarDecl>(Decl)) {
1887    // @public and @package ivars are always accessible.
1888    if (Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Public ||
1889        Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Package)
1890      return true;
1891
1892    // If we are inside a class or category implementation, determine the
1893    // interface we're in.
1894    ObjCInterfaceDecl *ClassOfMethodDecl = 0;
1895    if (ObjCMethodDecl *MD = getCurMethodDecl())
1896      ClassOfMethodDecl =  MD->getClassInterface();
1897    else if (FunctionDecl *FD = getCurFunctionDecl()) {
1898      if (ObjCImplDecl *Impl
1899            = dyn_cast<ObjCImplDecl>(FD->getLexicalDeclContext())) {
1900        if (ObjCImplementationDecl *IMPD
1901              = dyn_cast<ObjCImplementationDecl>(Impl))
1902          ClassOfMethodDecl = IMPD->getClassInterface();
1903        else if (ObjCCategoryImplDecl* CatImplClass
1904                   = dyn_cast<ObjCCategoryImplDecl>(Impl))
1905          ClassOfMethodDecl = CatImplClass->getClassInterface();
1906      }
1907    }
1908
1909    // If we're not in an interface, this ivar is inaccessible.
1910    if (!ClassOfMethodDecl)
1911      return false;
1912
1913    // If we're inside the same interface that owns the ivar, we're fine.
1914    if (declaresSameEntity(ClassOfMethodDecl, Ivar->getContainingInterface()))
1915      return true;
1916
1917    // If the ivar is private, it's inaccessible.
1918    if (Ivar->getCanonicalAccessControl() == ObjCIvarDecl::Private)
1919      return false;
1920
1921    return Ivar->getContainingInterface()->isSuperClassOf(ClassOfMethodDecl);
1922  }
1923
1924  return true;
1925}
1926