SemaAccess.cpp revision 263508
1//===---- SemaAccess.cpp - C++ Access Control -------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file provides Sema routines for C++ access control semantics.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Sema/SemaInternal.h"
15#include "clang/AST/ASTContext.h"
16#include "clang/AST/CXXInheritance.h"
17#include "clang/AST/DeclCXX.h"
18#include "clang/AST/DeclFriend.h"
19#include "clang/AST/DeclObjC.h"
20#include "clang/AST/DependentDiagnostic.h"
21#include "clang/AST/ExprCXX.h"
22#include "clang/Sema/DelayedDiagnostic.h"
23#include "clang/Sema/Initialization.h"
24#include "clang/Sema/Lookup.h"
25
26using namespace clang;
27using namespace sema;
28
29/// A copy of Sema's enum without AR_delayed.
30enum AccessResult {
31  AR_accessible,
32  AR_inaccessible,
33  AR_dependent
34};
35
36/// SetMemberAccessSpecifier - Set the access specifier of a member.
37/// Returns true on error (when the previous member decl access specifier
38/// is different from the new member decl access specifier).
39bool Sema::SetMemberAccessSpecifier(NamedDecl *MemberDecl,
40                                    NamedDecl *PrevMemberDecl,
41                                    AccessSpecifier LexicalAS) {
42  if (!PrevMemberDecl) {
43    // Use the lexical access specifier.
44    MemberDecl->setAccess(LexicalAS);
45    return false;
46  }
47
48  // C++ [class.access.spec]p3: When a member is redeclared its access
49  // specifier must be same as its initial declaration.
50  if (LexicalAS != AS_none && LexicalAS != PrevMemberDecl->getAccess()) {
51    Diag(MemberDecl->getLocation(),
52         diag::err_class_redeclared_with_different_access)
53      << MemberDecl << LexicalAS;
54    Diag(PrevMemberDecl->getLocation(), diag::note_previous_access_declaration)
55      << PrevMemberDecl << PrevMemberDecl->getAccess();
56
57    MemberDecl->setAccess(LexicalAS);
58    return true;
59  }
60
61  MemberDecl->setAccess(PrevMemberDecl->getAccess());
62  return false;
63}
64
65static CXXRecordDecl *FindDeclaringClass(NamedDecl *D) {
66  DeclContext *DC = D->getDeclContext();
67
68  // This can only happen at top: enum decls only "publish" their
69  // immediate members.
70  if (isa<EnumDecl>(DC))
71    DC = cast<EnumDecl>(DC)->getDeclContext();
72
73  CXXRecordDecl *DeclaringClass = cast<CXXRecordDecl>(DC);
74  while (DeclaringClass->isAnonymousStructOrUnion())
75    DeclaringClass = cast<CXXRecordDecl>(DeclaringClass->getDeclContext());
76  return DeclaringClass;
77}
78
79namespace {
80struct EffectiveContext {
81  EffectiveContext() : Inner(0), Dependent(false) {}
82
83  explicit EffectiveContext(DeclContext *DC)
84    : Inner(DC),
85      Dependent(DC->isDependentContext()) {
86
87    // C++11 [class.access.nest]p1:
88    //   A nested class is a member and as such has the same access
89    //   rights as any other member.
90    // C++11 [class.access]p2:
91    //   A member of a class can also access all the names to which
92    //   the class has access.  A local class of a member function
93    //   may access the same names that the member function itself
94    //   may access.
95    // This almost implies that the privileges of nesting are transitive.
96    // Technically it says nothing about the local classes of non-member
97    // functions (which can gain privileges through friendship), but we
98    // take that as an oversight.
99    while (true) {
100      // We want to add canonical declarations to the EC lists for
101      // simplicity of checking, but we need to walk up through the
102      // actual current DC chain.  Otherwise, something like a local
103      // extern or friend which happens to be the canonical
104      // declaration will really mess us up.
105
106      if (isa<CXXRecordDecl>(DC)) {
107        CXXRecordDecl *Record = cast<CXXRecordDecl>(DC);
108        Records.push_back(Record->getCanonicalDecl());
109        DC = Record->getDeclContext();
110      } else if (isa<FunctionDecl>(DC)) {
111        FunctionDecl *Function = cast<FunctionDecl>(DC);
112        Functions.push_back(Function->getCanonicalDecl());
113        if (Function->getFriendObjectKind())
114          DC = Function->getLexicalDeclContext();
115        else
116          DC = Function->getDeclContext();
117      } else if (DC->isFileContext()) {
118        break;
119      } else {
120        DC = DC->getParent();
121      }
122    }
123  }
124
125  bool isDependent() const { return Dependent; }
126
127  bool includesClass(const CXXRecordDecl *R) const {
128    R = R->getCanonicalDecl();
129    return std::find(Records.begin(), Records.end(), R)
130             != Records.end();
131  }
132
133  /// Retrieves the innermost "useful" context.  Can be null if we're
134  /// doing access-control without privileges.
135  DeclContext *getInnerContext() const {
136    return Inner;
137  }
138
139  typedef SmallVectorImpl<CXXRecordDecl*>::const_iterator record_iterator;
140
141  DeclContext *Inner;
142  SmallVector<FunctionDecl*, 4> Functions;
143  SmallVector<CXXRecordDecl*, 4> Records;
144  bool Dependent;
145};
146
147/// Like sema::AccessedEntity, but kindly lets us scribble all over
148/// it.
149struct AccessTarget : public AccessedEntity {
150  AccessTarget(const AccessedEntity &Entity)
151    : AccessedEntity(Entity) {
152    initialize();
153  }
154
155  AccessTarget(ASTContext &Context,
156               MemberNonce _,
157               CXXRecordDecl *NamingClass,
158               DeclAccessPair FoundDecl,
159               QualType BaseObjectType)
160    : AccessedEntity(Context.getDiagAllocator(), Member, NamingClass,
161                     FoundDecl, BaseObjectType) {
162    initialize();
163  }
164
165  AccessTarget(ASTContext &Context,
166               BaseNonce _,
167               CXXRecordDecl *BaseClass,
168               CXXRecordDecl *DerivedClass,
169               AccessSpecifier Access)
170    : AccessedEntity(Context.getDiagAllocator(), Base, BaseClass, DerivedClass,
171                     Access) {
172    initialize();
173  }
174
175  bool isInstanceMember() const {
176    return (isMemberAccess() && getTargetDecl()->isCXXInstanceMember());
177  }
178
179  bool hasInstanceContext() const {
180    return HasInstanceContext;
181  }
182
183  class SavedInstanceContext {
184  public:
185    ~SavedInstanceContext() {
186      Target.HasInstanceContext = Has;
187    }
188
189  private:
190    friend struct AccessTarget;
191    explicit SavedInstanceContext(AccessTarget &Target)
192      : Target(Target), Has(Target.HasInstanceContext) {}
193    AccessTarget &Target;
194    bool Has;
195  };
196
197  SavedInstanceContext saveInstanceContext() {
198    return SavedInstanceContext(*this);
199  }
200
201  void suppressInstanceContext() {
202    HasInstanceContext = false;
203  }
204
205  const CXXRecordDecl *resolveInstanceContext(Sema &S) const {
206    assert(HasInstanceContext);
207    if (CalculatedInstanceContext)
208      return InstanceContext;
209
210    CalculatedInstanceContext = true;
211    DeclContext *IC = S.computeDeclContext(getBaseObjectType());
212    InstanceContext = (IC ? cast<CXXRecordDecl>(IC)->getCanonicalDecl() : 0);
213    return InstanceContext;
214  }
215
216  const CXXRecordDecl *getDeclaringClass() const {
217    return DeclaringClass;
218  }
219
220  /// The "effective" naming class is the canonical non-anonymous
221  /// class containing the actual naming class.
222  const CXXRecordDecl *getEffectiveNamingClass() const {
223    const CXXRecordDecl *namingClass = getNamingClass();
224    while (namingClass->isAnonymousStructOrUnion())
225      namingClass = cast<CXXRecordDecl>(namingClass->getParent());
226    return namingClass->getCanonicalDecl();
227  }
228
229private:
230  void initialize() {
231    HasInstanceContext = (isMemberAccess() &&
232                          !getBaseObjectType().isNull() &&
233                          getTargetDecl()->isCXXInstanceMember());
234    CalculatedInstanceContext = false;
235    InstanceContext = 0;
236
237    if (isMemberAccess())
238      DeclaringClass = FindDeclaringClass(getTargetDecl());
239    else
240      DeclaringClass = getBaseClass();
241    DeclaringClass = DeclaringClass->getCanonicalDecl();
242  }
243
244  bool HasInstanceContext : 1;
245  mutable bool CalculatedInstanceContext : 1;
246  mutable const CXXRecordDecl *InstanceContext;
247  const CXXRecordDecl *DeclaringClass;
248};
249
250}
251
252/// Checks whether one class might instantiate to the other.
253static bool MightInstantiateTo(const CXXRecordDecl *From,
254                               const CXXRecordDecl *To) {
255  // Declaration names are always preserved by instantiation.
256  if (From->getDeclName() != To->getDeclName())
257    return false;
258
259  const DeclContext *FromDC = From->getDeclContext()->getPrimaryContext();
260  const DeclContext *ToDC = To->getDeclContext()->getPrimaryContext();
261  if (FromDC == ToDC) return true;
262  if (FromDC->isFileContext() || ToDC->isFileContext()) return false;
263
264  // Be conservative.
265  return true;
266}
267
268/// Checks whether one class is derived from another, inclusively.
269/// Properly indicates when it couldn't be determined due to
270/// dependence.
271///
272/// This should probably be donated to AST or at least Sema.
273static AccessResult IsDerivedFromInclusive(const CXXRecordDecl *Derived,
274                                           const CXXRecordDecl *Target) {
275  assert(Derived->getCanonicalDecl() == Derived);
276  assert(Target->getCanonicalDecl() == Target);
277
278  if (Derived == Target) return AR_accessible;
279
280  bool CheckDependent = Derived->isDependentContext();
281  if (CheckDependent && MightInstantiateTo(Derived, Target))
282    return AR_dependent;
283
284  AccessResult OnFailure = AR_inaccessible;
285  SmallVector<const CXXRecordDecl*, 8> Queue; // actually a stack
286
287  while (true) {
288    if (Derived->isDependentContext() && !Derived->hasDefinition())
289      return AR_dependent;
290
291    for (CXXRecordDecl::base_class_const_iterator
292           I = Derived->bases_begin(), E = Derived->bases_end(); I != E; ++I) {
293
294      const CXXRecordDecl *RD;
295
296      QualType T = I->getType();
297      if (const RecordType *RT = T->getAs<RecordType>()) {
298        RD = cast<CXXRecordDecl>(RT->getDecl());
299      } else if (const InjectedClassNameType *IT
300                   = T->getAs<InjectedClassNameType>()) {
301        RD = IT->getDecl();
302      } else {
303        assert(T->isDependentType() && "non-dependent base wasn't a record?");
304        OnFailure = AR_dependent;
305        continue;
306      }
307
308      RD = RD->getCanonicalDecl();
309      if (RD == Target) return AR_accessible;
310      if (CheckDependent && MightInstantiateTo(RD, Target))
311        OnFailure = AR_dependent;
312
313      Queue.push_back(RD);
314    }
315
316    if (Queue.empty()) break;
317
318    Derived = Queue.pop_back_val();
319  }
320
321  return OnFailure;
322}
323
324
325static bool MightInstantiateTo(Sema &S, DeclContext *Context,
326                               DeclContext *Friend) {
327  if (Friend == Context)
328    return true;
329
330  assert(!Friend->isDependentContext() &&
331         "can't handle friends with dependent contexts here");
332
333  if (!Context->isDependentContext())
334    return false;
335
336  if (Friend->isFileContext())
337    return false;
338
339  // TODO: this is very conservative
340  return true;
341}
342
343// Asks whether the type in 'context' can ever instantiate to the type
344// in 'friend'.
345static bool MightInstantiateTo(Sema &S, CanQualType Context, CanQualType Friend) {
346  if (Friend == Context)
347    return true;
348
349  if (!Friend->isDependentType() && !Context->isDependentType())
350    return false;
351
352  // TODO: this is very conservative.
353  return true;
354}
355
356static bool MightInstantiateTo(Sema &S,
357                               FunctionDecl *Context,
358                               FunctionDecl *Friend) {
359  if (Context->getDeclName() != Friend->getDeclName())
360    return false;
361
362  if (!MightInstantiateTo(S,
363                          Context->getDeclContext(),
364                          Friend->getDeclContext()))
365    return false;
366
367  CanQual<FunctionProtoType> FriendTy
368    = S.Context.getCanonicalType(Friend->getType())
369         ->getAs<FunctionProtoType>();
370  CanQual<FunctionProtoType> ContextTy
371    = S.Context.getCanonicalType(Context->getType())
372         ->getAs<FunctionProtoType>();
373
374  // There isn't any way that I know of to add qualifiers
375  // during instantiation.
376  if (FriendTy.getQualifiers() != ContextTy.getQualifiers())
377    return false;
378
379  if (FriendTy->getNumArgs() != ContextTy->getNumArgs())
380    return false;
381
382  if (!MightInstantiateTo(S,
383                          ContextTy->getResultType(),
384                          FriendTy->getResultType()))
385    return false;
386
387  for (unsigned I = 0, E = FriendTy->getNumArgs(); I != E; ++I)
388    if (!MightInstantiateTo(S,
389                            ContextTy->getArgType(I),
390                            FriendTy->getArgType(I)))
391      return false;
392
393  return true;
394}
395
396static bool MightInstantiateTo(Sema &S,
397                               FunctionTemplateDecl *Context,
398                               FunctionTemplateDecl *Friend) {
399  return MightInstantiateTo(S,
400                            Context->getTemplatedDecl(),
401                            Friend->getTemplatedDecl());
402}
403
404static AccessResult MatchesFriend(Sema &S,
405                                  const EffectiveContext &EC,
406                                  const CXXRecordDecl *Friend) {
407  if (EC.includesClass(Friend))
408    return AR_accessible;
409
410  if (EC.isDependent()) {
411    CanQualType FriendTy
412      = S.Context.getCanonicalType(S.Context.getTypeDeclType(Friend));
413
414    for (EffectiveContext::record_iterator
415           I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
416      CanQualType ContextTy
417        = S.Context.getCanonicalType(S.Context.getTypeDeclType(*I));
418      if (MightInstantiateTo(S, ContextTy, FriendTy))
419        return AR_dependent;
420    }
421  }
422
423  return AR_inaccessible;
424}
425
426static AccessResult MatchesFriend(Sema &S,
427                                  const EffectiveContext &EC,
428                                  CanQualType Friend) {
429  if (const RecordType *RT = Friend->getAs<RecordType>())
430    return MatchesFriend(S, EC, cast<CXXRecordDecl>(RT->getDecl()));
431
432  // TODO: we can do better than this
433  if (Friend->isDependentType())
434    return AR_dependent;
435
436  return AR_inaccessible;
437}
438
439/// Determines whether the given friend class template matches
440/// anything in the effective context.
441static AccessResult MatchesFriend(Sema &S,
442                                  const EffectiveContext &EC,
443                                  ClassTemplateDecl *Friend) {
444  AccessResult OnFailure = AR_inaccessible;
445
446  // Check whether the friend is the template of a class in the
447  // context chain.
448  for (SmallVectorImpl<CXXRecordDecl*>::const_iterator
449         I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
450    CXXRecordDecl *Record = *I;
451
452    // Figure out whether the current class has a template:
453    ClassTemplateDecl *CTD;
454
455    // A specialization of the template...
456    if (isa<ClassTemplateSpecializationDecl>(Record)) {
457      CTD = cast<ClassTemplateSpecializationDecl>(Record)
458        ->getSpecializedTemplate();
459
460    // ... or the template pattern itself.
461    } else {
462      CTD = Record->getDescribedClassTemplate();
463      if (!CTD) continue;
464    }
465
466    // It's a match.
467    if (Friend == CTD->getCanonicalDecl())
468      return AR_accessible;
469
470    // If the context isn't dependent, it can't be a dependent match.
471    if (!EC.isDependent())
472      continue;
473
474    // If the template names don't match, it can't be a dependent
475    // match.
476    if (CTD->getDeclName() != Friend->getDeclName())
477      continue;
478
479    // If the class's context can't instantiate to the friend's
480    // context, it can't be a dependent match.
481    if (!MightInstantiateTo(S, CTD->getDeclContext(),
482                            Friend->getDeclContext()))
483      continue;
484
485    // Otherwise, it's a dependent match.
486    OnFailure = AR_dependent;
487  }
488
489  return OnFailure;
490}
491
492/// Determines whether the given friend function matches anything in
493/// the effective context.
494static AccessResult MatchesFriend(Sema &S,
495                                  const EffectiveContext &EC,
496                                  FunctionDecl *Friend) {
497  AccessResult OnFailure = AR_inaccessible;
498
499  for (SmallVectorImpl<FunctionDecl*>::const_iterator
500         I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) {
501    if (Friend == *I)
502      return AR_accessible;
503
504    if (EC.isDependent() && MightInstantiateTo(S, *I, Friend))
505      OnFailure = AR_dependent;
506  }
507
508  return OnFailure;
509}
510
511/// Determines whether the given friend function template matches
512/// anything in the effective context.
513static AccessResult MatchesFriend(Sema &S,
514                                  const EffectiveContext &EC,
515                                  FunctionTemplateDecl *Friend) {
516  if (EC.Functions.empty()) return AR_inaccessible;
517
518  AccessResult OnFailure = AR_inaccessible;
519
520  for (SmallVectorImpl<FunctionDecl*>::const_iterator
521         I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) {
522
523    FunctionTemplateDecl *FTD = (*I)->getPrimaryTemplate();
524    if (!FTD)
525      FTD = (*I)->getDescribedFunctionTemplate();
526    if (!FTD)
527      continue;
528
529    FTD = FTD->getCanonicalDecl();
530
531    if (Friend == FTD)
532      return AR_accessible;
533
534    if (EC.isDependent() && MightInstantiateTo(S, FTD, Friend))
535      OnFailure = AR_dependent;
536  }
537
538  return OnFailure;
539}
540
541/// Determines whether the given friend declaration matches anything
542/// in the effective context.
543static AccessResult MatchesFriend(Sema &S,
544                                  const EffectiveContext &EC,
545                                  FriendDecl *FriendD) {
546  // Whitelist accesses if there's an invalid or unsupported friend
547  // declaration.
548  if (FriendD->isInvalidDecl() || FriendD->isUnsupportedFriend())
549    return AR_accessible;
550
551  if (TypeSourceInfo *T = FriendD->getFriendType())
552    return MatchesFriend(S, EC, T->getType()->getCanonicalTypeUnqualified());
553
554  NamedDecl *Friend
555    = cast<NamedDecl>(FriendD->getFriendDecl()->getCanonicalDecl());
556
557  // FIXME: declarations with dependent or templated scope.
558
559  if (isa<ClassTemplateDecl>(Friend))
560    return MatchesFriend(S, EC, cast<ClassTemplateDecl>(Friend));
561
562  if (isa<FunctionTemplateDecl>(Friend))
563    return MatchesFriend(S, EC, cast<FunctionTemplateDecl>(Friend));
564
565  if (isa<CXXRecordDecl>(Friend))
566    return MatchesFriend(S, EC, cast<CXXRecordDecl>(Friend));
567
568  assert(isa<FunctionDecl>(Friend) && "unknown friend decl kind");
569  return MatchesFriend(S, EC, cast<FunctionDecl>(Friend));
570}
571
572static AccessResult GetFriendKind(Sema &S,
573                                  const EffectiveContext &EC,
574                                  const CXXRecordDecl *Class) {
575  AccessResult OnFailure = AR_inaccessible;
576
577  // Okay, check friends.
578  for (CXXRecordDecl::friend_iterator I = Class->friend_begin(),
579         E = Class->friend_end(); I != E; ++I) {
580    FriendDecl *Friend = *I;
581
582    switch (MatchesFriend(S, EC, Friend)) {
583    case AR_accessible:
584      return AR_accessible;
585
586    case AR_inaccessible:
587      continue;
588
589    case AR_dependent:
590      OnFailure = AR_dependent;
591      break;
592    }
593  }
594
595  // That's it, give up.
596  return OnFailure;
597}
598
599namespace {
600
601/// A helper class for checking for a friend which will grant access
602/// to a protected instance member.
603struct ProtectedFriendContext {
604  Sema &S;
605  const EffectiveContext &EC;
606  const CXXRecordDecl *NamingClass;
607  bool CheckDependent;
608  bool EverDependent;
609
610  /// The path down to the current base class.
611  SmallVector<const CXXRecordDecl*, 20> CurPath;
612
613  ProtectedFriendContext(Sema &S, const EffectiveContext &EC,
614                         const CXXRecordDecl *InstanceContext,
615                         const CXXRecordDecl *NamingClass)
616    : S(S), EC(EC), NamingClass(NamingClass),
617      CheckDependent(InstanceContext->isDependentContext() ||
618                     NamingClass->isDependentContext()),
619      EverDependent(false) {}
620
621  /// Check classes in the current path for friendship, starting at
622  /// the given index.
623  bool checkFriendshipAlongPath(unsigned I) {
624    assert(I < CurPath.size());
625    for (unsigned E = CurPath.size(); I != E; ++I) {
626      switch (GetFriendKind(S, EC, CurPath[I])) {
627      case AR_accessible:   return true;
628      case AR_inaccessible: continue;
629      case AR_dependent:    EverDependent = true; continue;
630      }
631    }
632    return false;
633  }
634
635  /// Perform a search starting at the given class.
636  ///
637  /// PrivateDepth is the index of the last (least derived) class
638  /// along the current path such that a notional public member of
639  /// the final class in the path would have access in that class.
640  bool findFriendship(const CXXRecordDecl *Cur, unsigned PrivateDepth) {
641    // If we ever reach the naming class, check the current path for
642    // friendship.  We can also stop recursing because we obviously
643    // won't find the naming class there again.
644    if (Cur == NamingClass)
645      return checkFriendshipAlongPath(PrivateDepth);
646
647    if (CheckDependent && MightInstantiateTo(Cur, NamingClass))
648      EverDependent = true;
649
650    // Recurse into the base classes.
651    for (CXXRecordDecl::base_class_const_iterator
652           I = Cur->bases_begin(), E = Cur->bases_end(); I != E; ++I) {
653
654      // If this is private inheritance, then a public member of the
655      // base will not have any access in classes derived from Cur.
656      unsigned BasePrivateDepth = PrivateDepth;
657      if (I->getAccessSpecifier() == AS_private)
658        BasePrivateDepth = CurPath.size() - 1;
659
660      const CXXRecordDecl *RD;
661
662      QualType T = I->getType();
663      if (const RecordType *RT = T->getAs<RecordType>()) {
664        RD = cast<CXXRecordDecl>(RT->getDecl());
665      } else if (const InjectedClassNameType *IT
666                   = T->getAs<InjectedClassNameType>()) {
667        RD = IT->getDecl();
668      } else {
669        assert(T->isDependentType() && "non-dependent base wasn't a record?");
670        EverDependent = true;
671        continue;
672      }
673
674      // Recurse.  We don't need to clean up if this returns true.
675      CurPath.push_back(RD);
676      if (findFriendship(RD->getCanonicalDecl(), BasePrivateDepth))
677        return true;
678      CurPath.pop_back();
679    }
680
681    return false;
682  }
683
684  bool findFriendship(const CXXRecordDecl *Cur) {
685    assert(CurPath.empty());
686    CurPath.push_back(Cur);
687    return findFriendship(Cur, 0);
688  }
689};
690}
691
692/// Search for a class P that EC is a friend of, under the constraint
693///   InstanceContext <= P
694/// if InstanceContext exists, or else
695///   NamingClass <= P
696/// and with the additional restriction that a protected member of
697/// NamingClass would have some natural access in P, which implicitly
698/// imposes the constraint that P <= NamingClass.
699///
700/// This isn't quite the condition laid out in the standard.
701/// Instead of saying that a notional protected member of NamingClass
702/// would have to have some natural access in P, it says the actual
703/// target has to have some natural access in P, which opens up the
704/// possibility that the target (which is not necessarily a member
705/// of NamingClass) might be more accessible along some path not
706/// passing through it.  That's really a bad idea, though, because it
707/// introduces two problems:
708///   - Most importantly, it breaks encapsulation because you can
709///     access a forbidden base class's members by directly subclassing
710///     it elsewhere.
711///   - It also makes access substantially harder to compute because it
712///     breaks the hill-climbing algorithm: knowing that the target is
713///     accessible in some base class would no longer let you change
714///     the question solely to whether the base class is accessible,
715///     because the original target might have been more accessible
716///     because of crazy subclassing.
717/// So we don't implement that.
718static AccessResult GetProtectedFriendKind(Sema &S, const EffectiveContext &EC,
719                                           const CXXRecordDecl *InstanceContext,
720                                           const CXXRecordDecl *NamingClass) {
721  assert(InstanceContext == 0 ||
722         InstanceContext->getCanonicalDecl() == InstanceContext);
723  assert(NamingClass->getCanonicalDecl() == NamingClass);
724
725  // If we don't have an instance context, our constraints give us
726  // that NamingClass <= P <= NamingClass, i.e. P == NamingClass.
727  // This is just the usual friendship check.
728  if (!InstanceContext) return GetFriendKind(S, EC, NamingClass);
729
730  ProtectedFriendContext PRC(S, EC, InstanceContext, NamingClass);
731  if (PRC.findFriendship(InstanceContext)) return AR_accessible;
732  if (PRC.EverDependent) return AR_dependent;
733  return AR_inaccessible;
734}
735
736static AccessResult HasAccess(Sema &S,
737                              const EffectiveContext &EC,
738                              const CXXRecordDecl *NamingClass,
739                              AccessSpecifier Access,
740                              const AccessTarget &Target) {
741  assert(NamingClass->getCanonicalDecl() == NamingClass &&
742         "declaration should be canonicalized before being passed here");
743
744  if (Access == AS_public) return AR_accessible;
745  assert(Access == AS_private || Access == AS_protected);
746
747  AccessResult OnFailure = AR_inaccessible;
748
749  for (EffectiveContext::record_iterator
750         I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
751    // All the declarations in EC have been canonicalized, so pointer
752    // equality from this point on will work fine.
753    const CXXRecordDecl *ECRecord = *I;
754
755    // [B2] and [M2]
756    if (Access == AS_private) {
757      if (ECRecord == NamingClass)
758        return AR_accessible;
759
760      if (EC.isDependent() && MightInstantiateTo(ECRecord, NamingClass))
761        OnFailure = AR_dependent;
762
763    // [B3] and [M3]
764    } else {
765      assert(Access == AS_protected);
766      switch (IsDerivedFromInclusive(ECRecord, NamingClass)) {
767      case AR_accessible: break;
768      case AR_inaccessible: continue;
769      case AR_dependent: OnFailure = AR_dependent; continue;
770      }
771
772      // C++ [class.protected]p1:
773      //   An additional access check beyond those described earlier in
774      //   [class.access] is applied when a non-static data member or
775      //   non-static member function is a protected member of its naming
776      //   class.  As described earlier, access to a protected member is
777      //   granted because the reference occurs in a friend or member of
778      //   some class C.  If the access is to form a pointer to member,
779      //   the nested-name-specifier shall name C or a class derived from
780      //   C. All other accesses involve a (possibly implicit) object
781      //   expression. In this case, the class of the object expression
782      //   shall be C or a class derived from C.
783      //
784      // We interpret this as a restriction on [M3].
785
786      // In this part of the code, 'C' is just our context class ECRecord.
787
788      // These rules are different if we don't have an instance context.
789      if (!Target.hasInstanceContext()) {
790        // If it's not an instance member, these restrictions don't apply.
791        if (!Target.isInstanceMember()) return AR_accessible;
792
793        // If it's an instance member, use the pointer-to-member rule
794        // that the naming class has to be derived from the effective
795        // context.
796
797        // Emulate a MSVC bug where the creation of pointer-to-member
798        // to protected member of base class is allowed but only from
799        // static member functions.
800        if (S.getLangOpts().MicrosoftMode && !EC.Functions.empty())
801          if (CXXMethodDecl* MD = dyn_cast<CXXMethodDecl>(EC.Functions.front()))
802            if (MD->isStatic()) return AR_accessible;
803
804        // Despite the standard's confident wording, there is a case
805        // where you can have an instance member that's neither in a
806        // pointer-to-member expression nor in a member access:  when
807        // it names a field in an unevaluated context that can't be an
808        // implicit member.  Pending clarification, we just apply the
809        // same naming-class restriction here.
810        //   FIXME: we're probably not correctly adding the
811        //   protected-member restriction when we retroactively convert
812        //   an expression to being evaluated.
813
814        // We know that ECRecord derives from NamingClass.  The
815        // restriction says to check whether NamingClass derives from
816        // ECRecord, but that's not really necessary: two distinct
817        // classes can't be recursively derived from each other.  So
818        // along this path, we just need to check whether the classes
819        // are equal.
820        if (NamingClass == ECRecord) return AR_accessible;
821
822        // Otherwise, this context class tells us nothing;  on to the next.
823        continue;
824      }
825
826      assert(Target.isInstanceMember());
827
828      const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S);
829      if (!InstanceContext) {
830        OnFailure = AR_dependent;
831        continue;
832      }
833
834      switch (IsDerivedFromInclusive(InstanceContext, ECRecord)) {
835      case AR_accessible: return AR_accessible;
836      case AR_inaccessible: continue;
837      case AR_dependent: OnFailure = AR_dependent; continue;
838      }
839    }
840  }
841
842  // [M3] and [B3] say that, if the target is protected in N, we grant
843  // access if the access occurs in a friend or member of some class P
844  // that's a subclass of N and where the target has some natural
845  // access in P.  The 'member' aspect is easy to handle because P
846  // would necessarily be one of the effective-context records, and we
847  // address that above.  The 'friend' aspect is completely ridiculous
848  // to implement because there are no restrictions at all on P
849  // *unless* the [class.protected] restriction applies.  If it does,
850  // however, we should ignore whether the naming class is a friend,
851  // and instead rely on whether any potential P is a friend.
852  if (Access == AS_protected && Target.isInstanceMember()) {
853    // Compute the instance context if possible.
854    const CXXRecordDecl *InstanceContext = 0;
855    if (Target.hasInstanceContext()) {
856      InstanceContext = Target.resolveInstanceContext(S);
857      if (!InstanceContext) return AR_dependent;
858    }
859
860    switch (GetProtectedFriendKind(S, EC, InstanceContext, NamingClass)) {
861    case AR_accessible: return AR_accessible;
862    case AR_inaccessible: return OnFailure;
863    case AR_dependent: return AR_dependent;
864    }
865    llvm_unreachable("impossible friendship kind");
866  }
867
868  switch (GetFriendKind(S, EC, NamingClass)) {
869  case AR_accessible: return AR_accessible;
870  case AR_inaccessible: return OnFailure;
871  case AR_dependent: return AR_dependent;
872  }
873
874  // Silence bogus warnings
875  llvm_unreachable("impossible friendship kind");
876}
877
878/// Finds the best path from the naming class to the declaring class,
879/// taking friend declarations into account.
880///
881/// C++0x [class.access.base]p5:
882///   A member m is accessible at the point R when named in class N if
883///   [M1] m as a member of N is public, or
884///   [M2] m as a member of N is private, and R occurs in a member or
885///        friend of class N, or
886///   [M3] m as a member of N is protected, and R occurs in a member or
887///        friend of class N, or in a member or friend of a class P
888///        derived from N, where m as a member of P is public, private,
889///        or protected, or
890///   [M4] there exists a base class B of N that is accessible at R, and
891///        m is accessible at R when named in class B.
892///
893/// C++0x [class.access.base]p4:
894///   A base class B of N is accessible at R, if
895///   [B1] an invented public member of B would be a public member of N, or
896///   [B2] R occurs in a member or friend of class N, and an invented public
897///        member of B would be a private or protected member of N, or
898///   [B3] R occurs in a member or friend of a class P derived from N, and an
899///        invented public member of B would be a private or protected member
900///        of P, or
901///   [B4] there exists a class S such that B is a base class of S accessible
902///        at R and S is a base class of N accessible at R.
903///
904/// Along a single inheritance path we can restate both of these
905/// iteratively:
906///
907/// First, we note that M1-4 are equivalent to B1-4 if the member is
908/// treated as a notional base of its declaring class with inheritance
909/// access equivalent to the member's access.  Therefore we need only
910/// ask whether a class B is accessible from a class N in context R.
911///
912/// Let B_1 .. B_n be the inheritance path in question (i.e. where
913/// B_1 = N, B_n = B, and for all i, B_{i+1} is a direct base class of
914/// B_i).  For i in 1..n, we will calculate ACAB(i), the access to the
915/// closest accessible base in the path:
916///   Access(a, b) = (* access on the base specifier from a to b *)
917///   Merge(a, forbidden) = forbidden
918///   Merge(a, private) = forbidden
919///   Merge(a, b) = min(a,b)
920///   Accessible(c, forbidden) = false
921///   Accessible(c, private) = (R is c) || IsFriend(c, R)
922///   Accessible(c, protected) = (R derived from c) || IsFriend(c, R)
923///   Accessible(c, public) = true
924///   ACAB(n) = public
925///   ACAB(i) =
926///     let AccessToBase = Merge(Access(B_i, B_{i+1}), ACAB(i+1)) in
927///     if Accessible(B_i, AccessToBase) then public else AccessToBase
928///
929/// B is an accessible base of N at R iff ACAB(1) = public.
930///
931/// \param FinalAccess the access of the "final step", or AS_public if
932///   there is no final step.
933/// \return null if friendship is dependent
934static CXXBasePath *FindBestPath(Sema &S,
935                                 const EffectiveContext &EC,
936                                 AccessTarget &Target,
937                                 AccessSpecifier FinalAccess,
938                                 CXXBasePaths &Paths) {
939  // Derive the paths to the desired base.
940  const CXXRecordDecl *Derived = Target.getNamingClass();
941  const CXXRecordDecl *Base = Target.getDeclaringClass();
942
943  // FIXME: fail correctly when there are dependent paths.
944  bool isDerived = Derived->isDerivedFrom(const_cast<CXXRecordDecl*>(Base),
945                                          Paths);
946  assert(isDerived && "derived class not actually derived from base");
947  (void) isDerived;
948
949  CXXBasePath *BestPath = 0;
950
951  assert(FinalAccess != AS_none && "forbidden access after declaring class");
952
953  bool AnyDependent = false;
954
955  // Derive the friend-modified access along each path.
956  for (CXXBasePaths::paths_iterator PI = Paths.begin(), PE = Paths.end();
957         PI != PE; ++PI) {
958    AccessTarget::SavedInstanceContext _ = Target.saveInstanceContext();
959
960    // Walk through the path backwards.
961    AccessSpecifier PathAccess = FinalAccess;
962    CXXBasePath::iterator I = PI->end(), E = PI->begin();
963    while (I != E) {
964      --I;
965
966      assert(PathAccess != AS_none);
967
968      // If the declaration is a private member of a base class, there
969      // is no level of friendship in derived classes that can make it
970      // accessible.
971      if (PathAccess == AS_private) {
972        PathAccess = AS_none;
973        break;
974      }
975
976      const CXXRecordDecl *NC = I->Class->getCanonicalDecl();
977
978      AccessSpecifier BaseAccess = I->Base->getAccessSpecifier();
979      PathAccess = std::max(PathAccess, BaseAccess);
980
981      switch (HasAccess(S, EC, NC, PathAccess, Target)) {
982      case AR_inaccessible: break;
983      case AR_accessible:
984        PathAccess = AS_public;
985
986        // Future tests are not against members and so do not have
987        // instance context.
988        Target.suppressInstanceContext();
989        break;
990      case AR_dependent:
991        AnyDependent = true;
992        goto Next;
993      }
994    }
995
996    // Note that we modify the path's Access field to the
997    // friend-modified access.
998    if (BestPath == 0 || PathAccess < BestPath->Access) {
999      BestPath = &*PI;
1000      BestPath->Access = PathAccess;
1001
1002      // Short-circuit if we found a public path.
1003      if (BestPath->Access == AS_public)
1004        return BestPath;
1005    }
1006
1007  Next: ;
1008  }
1009
1010  assert((!BestPath || BestPath->Access != AS_public) &&
1011         "fell out of loop with public path");
1012
1013  // We didn't find a public path, but at least one path was subject
1014  // to dependent friendship, so delay the check.
1015  if (AnyDependent)
1016    return 0;
1017
1018  return BestPath;
1019}
1020
1021/// Given that an entity has protected natural access, check whether
1022/// access might be denied because of the protected member access
1023/// restriction.
1024///
1025/// \return true if a note was emitted
1026static bool TryDiagnoseProtectedAccess(Sema &S, const EffectiveContext &EC,
1027                                       AccessTarget &Target) {
1028  // Only applies to instance accesses.
1029  if (!Target.isInstanceMember())
1030    return false;
1031
1032  assert(Target.isMemberAccess());
1033
1034  const CXXRecordDecl *NamingClass = Target.getEffectiveNamingClass();
1035
1036  for (EffectiveContext::record_iterator
1037         I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
1038    const CXXRecordDecl *ECRecord = *I;
1039    switch (IsDerivedFromInclusive(ECRecord, NamingClass)) {
1040    case AR_accessible: break;
1041    case AR_inaccessible: continue;
1042    case AR_dependent: continue;
1043    }
1044
1045    // The effective context is a subclass of the declaring class.
1046    // Check whether the [class.protected] restriction is limiting
1047    // access.
1048
1049    // To get this exactly right, this might need to be checked more
1050    // holistically;  it's not necessarily the case that gaining
1051    // access here would grant us access overall.
1052
1053    NamedDecl *D = Target.getTargetDecl();
1054
1055    // If we don't have an instance context, [class.protected] says the
1056    // naming class has to equal the context class.
1057    if (!Target.hasInstanceContext()) {
1058      // If it does, the restriction doesn't apply.
1059      if (NamingClass == ECRecord) continue;
1060
1061      // TODO: it would be great to have a fixit here, since this is
1062      // such an obvious error.
1063      S.Diag(D->getLocation(), diag::note_access_protected_restricted_noobject)
1064        << S.Context.getTypeDeclType(ECRecord);
1065      return true;
1066    }
1067
1068    const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S);
1069    assert(InstanceContext && "diagnosing dependent access");
1070
1071    switch (IsDerivedFromInclusive(InstanceContext, ECRecord)) {
1072    case AR_accessible: continue;
1073    case AR_dependent: continue;
1074    case AR_inaccessible:
1075      break;
1076    }
1077
1078    // Okay, the restriction seems to be what's limiting us.
1079
1080    // Use a special diagnostic for constructors and destructors.
1081    if (isa<CXXConstructorDecl>(D) || isa<CXXDestructorDecl>(D) ||
1082        (isa<FunctionTemplateDecl>(D) &&
1083         isa<CXXConstructorDecl>(
1084                cast<FunctionTemplateDecl>(D)->getTemplatedDecl()))) {
1085      S.Diag(D->getLocation(), diag::note_access_protected_restricted_ctordtor)
1086        << isa<CXXDestructorDecl>(D);
1087      return true;
1088    }
1089
1090    // Otherwise, use the generic diagnostic.
1091    S.Diag(D->getLocation(), diag::note_access_protected_restricted_object)
1092      << S.Context.getTypeDeclType(ECRecord);
1093    return true;
1094  }
1095
1096  return false;
1097}
1098
1099/// We are unable to access a given declaration due to its direct
1100/// access control;  diagnose that.
1101static void diagnoseBadDirectAccess(Sema &S,
1102                                    const EffectiveContext &EC,
1103                                    AccessTarget &entity) {
1104  assert(entity.isMemberAccess());
1105  NamedDecl *D = entity.getTargetDecl();
1106
1107  if (D->getAccess() == AS_protected &&
1108      TryDiagnoseProtectedAccess(S, EC, entity))
1109    return;
1110
1111  // Find an original declaration.
1112  while (D->isOutOfLine()) {
1113    NamedDecl *PrevDecl = 0;
1114    if (VarDecl *VD = dyn_cast<VarDecl>(D))
1115      PrevDecl = VD->getPreviousDecl();
1116    else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
1117      PrevDecl = FD->getPreviousDecl();
1118    else if (TypedefNameDecl *TND = dyn_cast<TypedefNameDecl>(D))
1119      PrevDecl = TND->getPreviousDecl();
1120    else if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
1121      if (isa<RecordDecl>(D) && cast<RecordDecl>(D)->isInjectedClassName())
1122        break;
1123      PrevDecl = TD->getPreviousDecl();
1124    }
1125    if (!PrevDecl) break;
1126    D = PrevDecl;
1127  }
1128
1129  CXXRecordDecl *DeclaringClass = FindDeclaringClass(D);
1130  Decl *ImmediateChild;
1131  if (D->getDeclContext() == DeclaringClass)
1132    ImmediateChild = D;
1133  else {
1134    DeclContext *DC = D->getDeclContext();
1135    while (DC->getParent() != DeclaringClass)
1136      DC = DC->getParent();
1137    ImmediateChild = cast<Decl>(DC);
1138  }
1139
1140  // Check whether there's an AccessSpecDecl preceding this in the
1141  // chain of the DeclContext.
1142  bool isImplicit = true;
1143  for (CXXRecordDecl::decl_iterator
1144         I = DeclaringClass->decls_begin(), E = DeclaringClass->decls_end();
1145       I != E; ++I) {
1146    if (*I == ImmediateChild) break;
1147    if (isa<AccessSpecDecl>(*I)) {
1148      isImplicit = false;
1149      break;
1150    }
1151  }
1152
1153  S.Diag(D->getLocation(), diag::note_access_natural)
1154    << (unsigned) (D->getAccess() == AS_protected)
1155    << isImplicit;
1156}
1157
1158/// Diagnose the path which caused the given declaration or base class
1159/// to become inaccessible.
1160static void DiagnoseAccessPath(Sema &S,
1161                               const EffectiveContext &EC,
1162                               AccessTarget &entity) {
1163  // Save the instance context to preserve invariants.
1164  AccessTarget::SavedInstanceContext _ = entity.saveInstanceContext();
1165
1166  // This basically repeats the main algorithm but keeps some more
1167  // information.
1168
1169  // The natural access so far.
1170  AccessSpecifier accessSoFar = AS_public;
1171
1172  // Check whether we have special rights to the declaring class.
1173  if (entity.isMemberAccess()) {
1174    NamedDecl *D = entity.getTargetDecl();
1175    accessSoFar = D->getAccess();
1176    const CXXRecordDecl *declaringClass = entity.getDeclaringClass();
1177
1178    switch (HasAccess(S, EC, declaringClass, accessSoFar, entity)) {
1179    // If the declaration is accessible when named in its declaring
1180    // class, then we must be constrained by the path.
1181    case AR_accessible:
1182      accessSoFar = AS_public;
1183      entity.suppressInstanceContext();
1184      break;
1185
1186    case AR_inaccessible:
1187      if (accessSoFar == AS_private ||
1188          declaringClass == entity.getEffectiveNamingClass())
1189        return diagnoseBadDirectAccess(S, EC, entity);
1190      break;
1191
1192    case AR_dependent:
1193      llvm_unreachable("cannot diagnose dependent access");
1194    }
1195  }
1196
1197  CXXBasePaths paths;
1198  CXXBasePath &path = *FindBestPath(S, EC, entity, accessSoFar, paths);
1199  assert(path.Access != AS_public);
1200
1201  CXXBasePath::iterator i = path.end(), e = path.begin();
1202  CXXBasePath::iterator constrainingBase = i;
1203  while (i != e) {
1204    --i;
1205
1206    assert(accessSoFar != AS_none && accessSoFar != AS_private);
1207
1208    // Is the entity accessible when named in the deriving class, as
1209    // modified by the base specifier?
1210    const CXXRecordDecl *derivingClass = i->Class->getCanonicalDecl();
1211    const CXXBaseSpecifier *base = i->Base;
1212
1213    // If the access to this base is worse than the access we have to
1214    // the declaration, remember it.
1215    AccessSpecifier baseAccess = base->getAccessSpecifier();
1216    if (baseAccess > accessSoFar) {
1217      constrainingBase = i;
1218      accessSoFar = baseAccess;
1219    }
1220
1221    switch (HasAccess(S, EC, derivingClass, accessSoFar, entity)) {
1222    case AR_inaccessible: break;
1223    case AR_accessible:
1224      accessSoFar = AS_public;
1225      entity.suppressInstanceContext();
1226      constrainingBase = 0;
1227      break;
1228    case AR_dependent:
1229      llvm_unreachable("cannot diagnose dependent access");
1230    }
1231
1232    // If this was private inheritance, but we don't have access to
1233    // the deriving class, we're done.
1234    if (accessSoFar == AS_private) {
1235      assert(baseAccess == AS_private);
1236      assert(constrainingBase == i);
1237      break;
1238    }
1239  }
1240
1241  // If we don't have a constraining base, the access failure must be
1242  // due to the original declaration.
1243  if (constrainingBase == path.end())
1244    return diagnoseBadDirectAccess(S, EC, entity);
1245
1246  // We're constrained by inheritance, but we want to say
1247  // "declared private here" if we're diagnosing a hierarchy
1248  // conversion and this is the final step.
1249  unsigned diagnostic;
1250  if (entity.isMemberAccess() ||
1251      constrainingBase + 1 != path.end()) {
1252    diagnostic = diag::note_access_constrained_by_path;
1253  } else {
1254    diagnostic = diag::note_access_natural;
1255  }
1256
1257  const CXXBaseSpecifier *base = constrainingBase->Base;
1258
1259  S.Diag(base->getSourceRange().getBegin(), diagnostic)
1260    << base->getSourceRange()
1261    << (base->getAccessSpecifier() == AS_protected)
1262    << (base->getAccessSpecifierAsWritten() == AS_none);
1263
1264  if (entity.isMemberAccess())
1265    S.Diag(entity.getTargetDecl()->getLocation(), diag::note_field_decl);
1266}
1267
1268static void DiagnoseBadAccess(Sema &S, SourceLocation Loc,
1269                              const EffectiveContext &EC,
1270                              AccessTarget &Entity) {
1271  const CXXRecordDecl *NamingClass = Entity.getNamingClass();
1272  const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();
1273  NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : 0);
1274
1275  S.Diag(Loc, Entity.getDiag())
1276    << (Entity.getAccess() == AS_protected)
1277    << (D ? D->getDeclName() : DeclarationName())
1278    << S.Context.getTypeDeclType(NamingClass)
1279    << S.Context.getTypeDeclType(DeclaringClass);
1280  DiagnoseAccessPath(S, EC, Entity);
1281}
1282
1283/// MSVC has a bug where if during an using declaration name lookup,
1284/// the declaration found is unaccessible (private) and that declaration
1285/// was bring into scope via another using declaration whose target
1286/// declaration is accessible (public) then no error is generated.
1287/// Example:
1288///   class A {
1289///   public:
1290///     int f();
1291///   };
1292///   class B : public A {
1293///   private:
1294///     using A::f;
1295///   };
1296///   class C : public B {
1297///   private:
1298///     using B::f;
1299///   };
1300///
1301/// Here, B::f is private so this should fail in Standard C++, but
1302/// because B::f refers to A::f which is public MSVC accepts it.
1303static bool IsMicrosoftUsingDeclarationAccessBug(Sema& S,
1304                                                 SourceLocation AccessLoc,
1305                                                 AccessTarget &Entity) {
1306  if (UsingShadowDecl *Shadow =
1307                         dyn_cast<UsingShadowDecl>(Entity.getTargetDecl())) {
1308    const NamedDecl *OrigDecl = Entity.getTargetDecl()->getUnderlyingDecl();
1309    if (Entity.getTargetDecl()->getAccess() == AS_private &&
1310        (OrigDecl->getAccess() == AS_public ||
1311         OrigDecl->getAccess() == AS_protected)) {
1312      S.Diag(AccessLoc, diag::ext_ms_using_declaration_inaccessible)
1313        << Shadow->getUsingDecl()->getQualifiedNameAsString()
1314        << OrigDecl->getQualifiedNameAsString();
1315      return true;
1316    }
1317  }
1318  return false;
1319}
1320
1321/// Determines whether the accessed entity is accessible.  Public members
1322/// have been weeded out by this point.
1323static AccessResult IsAccessible(Sema &S,
1324                                 const EffectiveContext &EC,
1325                                 AccessTarget &Entity) {
1326  // Determine the actual naming class.
1327  const CXXRecordDecl *NamingClass = Entity.getEffectiveNamingClass();
1328
1329  AccessSpecifier UnprivilegedAccess = Entity.getAccess();
1330  assert(UnprivilegedAccess != AS_public && "public access not weeded out");
1331
1332  // Before we try to recalculate access paths, try to white-list
1333  // accesses which just trade in on the final step, i.e. accesses
1334  // which don't require [M4] or [B4]. These are by far the most
1335  // common forms of privileged access.
1336  if (UnprivilegedAccess != AS_none) {
1337    switch (HasAccess(S, EC, NamingClass, UnprivilegedAccess, Entity)) {
1338    case AR_dependent:
1339      // This is actually an interesting policy decision.  We don't
1340      // *have* to delay immediately here: we can do the full access
1341      // calculation in the hope that friendship on some intermediate
1342      // class will make the declaration accessible non-dependently.
1343      // But that's not cheap, and odds are very good (note: assertion
1344      // made without data) that the friend declaration will determine
1345      // access.
1346      return AR_dependent;
1347
1348    case AR_accessible: return AR_accessible;
1349    case AR_inaccessible: break;
1350    }
1351  }
1352
1353  AccessTarget::SavedInstanceContext _ = Entity.saveInstanceContext();
1354
1355  // We lower member accesses to base accesses by pretending that the
1356  // member is a base class of its declaring class.
1357  AccessSpecifier FinalAccess;
1358
1359  if (Entity.isMemberAccess()) {
1360    // Determine if the declaration is accessible from EC when named
1361    // in its declaring class.
1362    NamedDecl *Target = Entity.getTargetDecl();
1363    const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();
1364
1365    FinalAccess = Target->getAccess();
1366    switch (HasAccess(S, EC, DeclaringClass, FinalAccess, Entity)) {
1367    case AR_accessible:
1368      // Target is accessible at EC when named in its declaring class.
1369      // We can now hill-climb and simply check whether the declaring
1370      // class is accessible as a base of the naming class.  This is
1371      // equivalent to checking the access of a notional public
1372      // member with no instance context.
1373      FinalAccess = AS_public;
1374      Entity.suppressInstanceContext();
1375      break;
1376    case AR_inaccessible: break;
1377    case AR_dependent: return AR_dependent; // see above
1378    }
1379
1380    if (DeclaringClass == NamingClass)
1381      return (FinalAccess == AS_public ? AR_accessible : AR_inaccessible);
1382  } else {
1383    FinalAccess = AS_public;
1384  }
1385
1386  assert(Entity.getDeclaringClass() != NamingClass);
1387
1388  // Append the declaration's access if applicable.
1389  CXXBasePaths Paths;
1390  CXXBasePath *Path = FindBestPath(S, EC, Entity, FinalAccess, Paths);
1391  if (!Path)
1392    return AR_dependent;
1393
1394  assert(Path->Access <= UnprivilegedAccess &&
1395         "access along best path worse than direct?");
1396  if (Path->Access == AS_public)
1397    return AR_accessible;
1398  return AR_inaccessible;
1399}
1400
1401static void DelayDependentAccess(Sema &S,
1402                                 const EffectiveContext &EC,
1403                                 SourceLocation Loc,
1404                                 const AccessTarget &Entity) {
1405  assert(EC.isDependent() && "delaying non-dependent access");
1406  DeclContext *DC = EC.getInnerContext();
1407  assert(DC->isDependentContext() && "delaying non-dependent access");
1408  DependentDiagnostic::Create(S.Context, DC, DependentDiagnostic::Access,
1409                              Loc,
1410                              Entity.isMemberAccess(),
1411                              Entity.getAccess(),
1412                              Entity.getTargetDecl(),
1413                              Entity.getNamingClass(),
1414                              Entity.getBaseObjectType(),
1415                              Entity.getDiag());
1416}
1417
1418/// Checks access to an entity from the given effective context.
1419static AccessResult CheckEffectiveAccess(Sema &S,
1420                                         const EffectiveContext &EC,
1421                                         SourceLocation Loc,
1422                                         AccessTarget &Entity) {
1423  assert(Entity.getAccess() != AS_public && "called for public access!");
1424
1425  if (S.getLangOpts().MicrosoftMode &&
1426      IsMicrosoftUsingDeclarationAccessBug(S, Loc, Entity))
1427    return AR_accessible;
1428
1429  switch (IsAccessible(S, EC, Entity)) {
1430  case AR_dependent:
1431    DelayDependentAccess(S, EC, Loc, Entity);
1432    return AR_dependent;
1433
1434  case AR_inaccessible:
1435    if (!Entity.isQuiet())
1436      DiagnoseBadAccess(S, Loc, EC, Entity);
1437    return AR_inaccessible;
1438
1439  case AR_accessible:
1440    return AR_accessible;
1441  }
1442
1443  // silence unnecessary warning
1444  llvm_unreachable("invalid access result");
1445}
1446
1447static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc,
1448                                      AccessTarget &Entity) {
1449  // If the access path is public, it's accessible everywhere.
1450  if (Entity.getAccess() == AS_public)
1451    return Sema::AR_accessible;
1452
1453  // If we're currently parsing a declaration, we may need to delay
1454  // access control checking, because our effective context might be
1455  // different based on what the declaration comes out as.
1456  //
1457  // For example, we might be parsing a declaration with a scope
1458  // specifier, like this:
1459  //   A::private_type A::foo() { ... }
1460  //
1461  // Or we might be parsing something that will turn out to be a friend:
1462  //   void foo(A::private_type);
1463  //   void B::foo(A::private_type);
1464  if (S.DelayedDiagnostics.shouldDelayDiagnostics()) {
1465    S.DelayedDiagnostics.add(DelayedDiagnostic::makeAccess(Loc, Entity));
1466    return Sema::AR_delayed;
1467  }
1468
1469  EffectiveContext EC(S.CurContext);
1470  switch (CheckEffectiveAccess(S, EC, Loc, Entity)) {
1471  case AR_accessible: return Sema::AR_accessible;
1472  case AR_inaccessible: return Sema::AR_inaccessible;
1473  case AR_dependent: return Sema::AR_dependent;
1474  }
1475  llvm_unreachable("falling off end");
1476}
1477
1478void Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *D) {
1479  // Access control for names used in the declarations of functions
1480  // and function templates should normally be evaluated in the context
1481  // of the declaration, just in case it's a friend of something.
1482  // However, this does not apply to local extern declarations.
1483
1484  DeclContext *DC = D->getDeclContext();
1485  if (FunctionDecl *FN = dyn_cast<FunctionDecl>(D)) {
1486    if (D->getLexicalDeclContext()->isFunctionOrMethod())
1487      DC = D->getLexicalDeclContext();
1488    else
1489      DC = FN;
1490  } else if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D)) {
1491    DC = cast<DeclContext>(TD->getTemplatedDecl());
1492  }
1493
1494  EffectiveContext EC(DC);
1495
1496  AccessTarget Target(DD.getAccessData());
1497
1498  if (CheckEffectiveAccess(*this, EC, DD.Loc, Target) == ::AR_inaccessible)
1499    DD.Triggered = true;
1500}
1501
1502void Sema::HandleDependentAccessCheck(const DependentDiagnostic &DD,
1503                        const MultiLevelTemplateArgumentList &TemplateArgs) {
1504  SourceLocation Loc = DD.getAccessLoc();
1505  AccessSpecifier Access = DD.getAccess();
1506
1507  Decl *NamingD = FindInstantiatedDecl(Loc, DD.getAccessNamingClass(),
1508                                       TemplateArgs);
1509  if (!NamingD) return;
1510  Decl *TargetD = FindInstantiatedDecl(Loc, DD.getAccessTarget(),
1511                                       TemplateArgs);
1512  if (!TargetD) return;
1513
1514  if (DD.isAccessToMember()) {
1515    CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(NamingD);
1516    NamedDecl *TargetDecl = cast<NamedDecl>(TargetD);
1517    QualType BaseObjectType = DD.getAccessBaseObjectType();
1518    if (!BaseObjectType.isNull()) {
1519      BaseObjectType = SubstType(BaseObjectType, TemplateArgs, Loc,
1520                                 DeclarationName());
1521      if (BaseObjectType.isNull()) return;
1522    }
1523
1524    AccessTarget Entity(Context,
1525                        AccessTarget::Member,
1526                        NamingClass,
1527                        DeclAccessPair::make(TargetDecl, Access),
1528                        BaseObjectType);
1529    Entity.setDiag(DD.getDiagnostic());
1530    CheckAccess(*this, Loc, Entity);
1531  } else {
1532    AccessTarget Entity(Context,
1533                        AccessTarget::Base,
1534                        cast<CXXRecordDecl>(TargetD),
1535                        cast<CXXRecordDecl>(NamingD),
1536                        Access);
1537    Entity.setDiag(DD.getDiagnostic());
1538    CheckAccess(*this, Loc, Entity);
1539  }
1540}
1541
1542Sema::AccessResult Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E,
1543                                                     DeclAccessPair Found) {
1544  if (!getLangOpts().AccessControl ||
1545      !E->getNamingClass() ||
1546      Found.getAccess() == AS_public)
1547    return AR_accessible;
1548
1549  AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(),
1550                      Found, QualType());
1551  Entity.setDiag(diag::err_access) << E->getSourceRange();
1552
1553  return CheckAccess(*this, E->getNameLoc(), Entity);
1554}
1555
1556/// Perform access-control checking on a previously-unresolved member
1557/// access which has now been resolved to a member.
1558Sema::AccessResult Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E,
1559                                                     DeclAccessPair Found) {
1560  if (!getLangOpts().AccessControl ||
1561      Found.getAccess() == AS_public)
1562    return AR_accessible;
1563
1564  QualType BaseType = E->getBaseType();
1565  if (E->isArrow())
1566    BaseType = BaseType->getAs<PointerType>()->getPointeeType();
1567
1568  AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(),
1569                      Found, BaseType);
1570  Entity.setDiag(diag::err_access) << E->getSourceRange();
1571
1572  return CheckAccess(*this, E->getMemberLoc(), Entity);
1573}
1574
1575/// Is the given special member function accessible for the purposes of
1576/// deciding whether to define a special member function as deleted?
1577bool Sema::isSpecialMemberAccessibleForDeletion(CXXMethodDecl *decl,
1578                                                AccessSpecifier access,
1579                                                QualType objectType) {
1580  // Fast path.
1581  if (access == AS_public || !getLangOpts().AccessControl) return true;
1582
1583  AccessTarget entity(Context, AccessTarget::Member, decl->getParent(),
1584                      DeclAccessPair::make(decl, access), objectType);
1585
1586  // Suppress diagnostics.
1587  entity.setDiag(PDiag());
1588
1589  switch (CheckAccess(*this, SourceLocation(), entity)) {
1590  case AR_accessible: return true;
1591  case AR_inaccessible: return false;
1592  case AR_dependent: llvm_unreachable("dependent for =delete computation");
1593  case AR_delayed: llvm_unreachable("cannot delay =delete computation");
1594  }
1595  llvm_unreachable("bad access result");
1596}
1597
1598Sema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc,
1599                                               CXXDestructorDecl *Dtor,
1600                                               const PartialDiagnostic &PDiag,
1601                                               QualType ObjectTy) {
1602  if (!getLangOpts().AccessControl)
1603    return AR_accessible;
1604
1605  // There's never a path involved when checking implicit destructor access.
1606  AccessSpecifier Access = Dtor->getAccess();
1607  if (Access == AS_public)
1608    return AR_accessible;
1609
1610  CXXRecordDecl *NamingClass = Dtor->getParent();
1611  if (ObjectTy.isNull()) ObjectTy = Context.getTypeDeclType(NamingClass);
1612
1613  AccessTarget Entity(Context, AccessTarget::Member, NamingClass,
1614                      DeclAccessPair::make(Dtor, Access),
1615                      ObjectTy);
1616  Entity.setDiag(PDiag); // TODO: avoid copy
1617
1618  return CheckAccess(*this, Loc, Entity);
1619}
1620
1621/// Checks access to a constructor.
1622Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc,
1623                                                CXXConstructorDecl *Constructor,
1624                                                const InitializedEntity &Entity,
1625                                                AccessSpecifier Access,
1626                                                bool IsCopyBindingRefToTemp) {
1627  if (!getLangOpts().AccessControl || Access == AS_public)
1628    return AR_accessible;
1629
1630  PartialDiagnostic PD(PDiag());
1631  switch (Entity.getKind()) {
1632  default:
1633    PD = PDiag(IsCopyBindingRefToTemp
1634                 ? diag::ext_rvalue_to_reference_access_ctor
1635                 : diag::err_access_ctor);
1636
1637    break;
1638
1639  case InitializedEntity::EK_Base:
1640    PD = PDiag(diag::err_access_base_ctor);
1641    PD << Entity.isInheritedVirtualBase()
1642       << Entity.getBaseSpecifier()->getType() << getSpecialMember(Constructor);
1643    break;
1644
1645  case InitializedEntity::EK_Member: {
1646    const FieldDecl *Field = cast<FieldDecl>(Entity.getDecl());
1647    PD = PDiag(diag::err_access_field_ctor);
1648    PD << Field->getType() << getSpecialMember(Constructor);
1649    break;
1650  }
1651
1652  case InitializedEntity::EK_LambdaCapture: {
1653    StringRef VarName = Entity.getCapturedVarName();
1654    PD = PDiag(diag::err_access_lambda_capture);
1655    PD << VarName << Entity.getType() << getSpecialMember(Constructor);
1656    break;
1657  }
1658
1659  }
1660
1661  return CheckConstructorAccess(UseLoc, Constructor, Entity, Access, PD);
1662}
1663
1664/// Checks access to a constructor.
1665Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc,
1666                                                CXXConstructorDecl *Constructor,
1667                                                const InitializedEntity &Entity,
1668                                                AccessSpecifier Access,
1669                                                const PartialDiagnostic &PD) {
1670  if (!getLangOpts().AccessControl ||
1671      Access == AS_public)
1672    return AR_accessible;
1673
1674  CXXRecordDecl *NamingClass = Constructor->getParent();
1675
1676  // Initializing a base sub-object is an instance method call on an
1677  // object of the derived class.  Otherwise, we have an instance method
1678  // call on an object of the constructed type.
1679  CXXRecordDecl *ObjectClass;
1680  if (Entity.getKind() == InitializedEntity::EK_Base) {
1681    ObjectClass = cast<CXXConstructorDecl>(CurContext)->getParent();
1682  } else {
1683    ObjectClass = NamingClass;
1684  }
1685
1686  AccessTarget AccessEntity(Context, AccessTarget::Member, NamingClass,
1687                            DeclAccessPair::make(Constructor, Access),
1688                            Context.getTypeDeclType(ObjectClass));
1689  AccessEntity.setDiag(PD);
1690
1691  return CheckAccess(*this, UseLoc, AccessEntity);
1692}
1693
1694/// Checks access to an overloaded operator new or delete.
1695Sema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc,
1696                                               SourceRange PlacementRange,
1697                                               CXXRecordDecl *NamingClass,
1698                                               DeclAccessPair Found,
1699                                               bool Diagnose) {
1700  if (!getLangOpts().AccessControl ||
1701      !NamingClass ||
1702      Found.getAccess() == AS_public)
1703    return AR_accessible;
1704
1705  AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
1706                      QualType());
1707  if (Diagnose)
1708    Entity.setDiag(diag::err_access)
1709      << PlacementRange;
1710
1711  return CheckAccess(*this, OpLoc, Entity);
1712}
1713
1714/// \brief Checks access to a member.
1715Sema::AccessResult Sema::CheckMemberAccess(SourceLocation UseLoc,
1716                                           CXXRecordDecl *NamingClass,
1717                                           DeclAccessPair Found) {
1718  if (!getLangOpts().AccessControl ||
1719      !NamingClass ||
1720      Found.getAccess() == AS_public)
1721    return AR_accessible;
1722
1723  AccessTarget Entity(Context, AccessTarget::Member, NamingClass,
1724                      Found, QualType());
1725
1726  return CheckAccess(*this, UseLoc, Entity);
1727}
1728
1729/// Checks access to an overloaded member operator, including
1730/// conversion operators.
1731Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc,
1732                                                   Expr *ObjectExpr,
1733                                                   Expr *ArgExpr,
1734                                                   DeclAccessPair Found) {
1735  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