SemaAccess.cpp revision e737f5041a36d0befb39ffeed8d50ba15916d3da
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/Sema.h"
15#include "clang/Sema/Initialization.h"
16#include "clang/Sema/Lookup.h"
17#include "clang/AST/ASTContext.h"
18#include "clang/AST/CXXInheritance.h"
19#include "clang/AST/DeclCXX.h"
20#include "clang/AST/DeclFriend.h"
21#include "clang/AST/DependentDiagnostic.h"
22#include "clang/AST/ExprCXX.h"
23
24using namespace clang;
25
26/// A copy of Sema's enum without AR_delayed.
27enum AccessResult {
28  AR_accessible,
29  AR_inaccessible,
30  AR_dependent
31};
32
33/// SetMemberAccessSpecifier - Set the access specifier of a member.
34/// Returns true on error (when the previous member decl access specifier
35/// is different from the new member decl access specifier).
36bool Sema::SetMemberAccessSpecifier(NamedDecl *MemberDecl,
37                                    NamedDecl *PrevMemberDecl,
38                                    AccessSpecifier LexicalAS) {
39  if (!PrevMemberDecl) {
40    // Use the lexical access specifier.
41    MemberDecl->setAccess(LexicalAS);
42    return false;
43  }
44
45  // C++ [class.access.spec]p3: When a member is redeclared its access
46  // specifier must be same as its initial declaration.
47  if (LexicalAS != AS_none && LexicalAS != PrevMemberDecl->getAccess()) {
48    Diag(MemberDecl->getLocation(),
49         diag::err_class_redeclared_with_different_access)
50      << MemberDecl << LexicalAS;
51    Diag(PrevMemberDecl->getLocation(), diag::note_previous_access_declaration)
52      << PrevMemberDecl << PrevMemberDecl->getAccess();
53
54    MemberDecl->setAccess(LexicalAS);
55    return true;
56  }
57
58  MemberDecl->setAccess(PrevMemberDecl->getAccess());
59  return false;
60}
61
62static CXXRecordDecl *FindDeclaringClass(NamedDecl *D) {
63  DeclContext *DC = D->getDeclContext();
64
65  // This can only happen at top: enum decls only "publish" their
66  // immediate members.
67  if (isa<EnumDecl>(DC))
68    DC = cast<EnumDecl>(DC)->getDeclContext();
69
70  CXXRecordDecl *DeclaringClass = cast<CXXRecordDecl>(DC);
71  while (DeclaringClass->isAnonymousStructOrUnion())
72    DeclaringClass = cast<CXXRecordDecl>(DeclaringClass->getDeclContext());
73  return DeclaringClass;
74}
75
76namespace {
77struct EffectiveContext {
78  EffectiveContext() : Inner(0), Dependent(false) {}
79
80  explicit EffectiveContext(DeclContext *DC)
81    : Inner(DC),
82      Dependent(DC->isDependentContext()) {
83
84    // C++ [class.access.nest]p1:
85    //   A nested class is a member and as such has the same access
86    //   rights as any other member.
87    // C++ [class.access]p2:
88    //   A member of a class can also access all the names to which
89    //   the class has access.  A local class of a member function
90    //   may access the same names that the member function itself
91    //   may access.
92    // This almost implies that the privileges of nesting are transitive.
93    // Technically it says nothing about the local classes of non-member
94    // functions (which can gain privileges through friendship), but we
95    // take that as an oversight.
96    while (true) {
97      if (isa<CXXRecordDecl>(DC)) {
98        CXXRecordDecl *Record = cast<CXXRecordDecl>(DC)->getCanonicalDecl();
99        Records.push_back(Record);
100        DC = Record->getDeclContext();
101      } else if (isa<FunctionDecl>(DC)) {
102        FunctionDecl *Function = cast<FunctionDecl>(DC)->getCanonicalDecl();
103        Functions.push_back(Function);
104        DC = Function->getDeclContext();
105      } else if (DC->isFileContext()) {
106        break;
107      } else {
108        DC = DC->getParent();
109      }
110    }
111  }
112
113  bool isDependent() const { return Dependent; }
114
115  bool includesClass(const CXXRecordDecl *R) const {
116    R = R->getCanonicalDecl();
117    return std::find(Records.begin(), Records.end(), R)
118             != Records.end();
119  }
120
121  /// Retrieves the innermost "useful" context.  Can be null if we're
122  /// doing access-control without privileges.
123  DeclContext *getInnerContext() const {
124    return Inner;
125  }
126
127  typedef llvm::SmallVectorImpl<CXXRecordDecl*>::const_iterator record_iterator;
128
129  DeclContext *Inner;
130  llvm::SmallVector<FunctionDecl*, 4> Functions;
131  llvm::SmallVector<CXXRecordDecl*, 4> Records;
132  bool Dependent;
133};
134
135/// Like Sema's AccessedEntity, but kindly lets us scribble all over
136/// it.
137struct AccessTarget : public Sema::AccessedEntity {
138  AccessTarget(const Sema::AccessedEntity &Entity)
139    : AccessedEntity(Entity) {
140    initialize();
141  }
142
143  AccessTarget(ASTContext &Context,
144               MemberNonce _,
145               CXXRecordDecl *NamingClass,
146               DeclAccessPair FoundDecl,
147               QualType BaseObjectType)
148    : AccessedEntity(Context, Member, NamingClass, FoundDecl, BaseObjectType) {
149    initialize();
150  }
151
152  AccessTarget(ASTContext &Context,
153               BaseNonce _,
154               CXXRecordDecl *BaseClass,
155               CXXRecordDecl *DerivedClass,
156               AccessSpecifier Access)
157    : AccessedEntity(Context, Base, BaseClass, DerivedClass, Access) {
158    initialize();
159  }
160
161  bool hasInstanceContext() const {
162    return HasInstanceContext;
163  }
164
165  class SavedInstanceContext {
166  public:
167    ~SavedInstanceContext() {
168      Target.HasInstanceContext = Has;
169    }
170
171  private:
172    friend struct AccessTarget;
173    explicit SavedInstanceContext(AccessTarget &Target)
174      : Target(Target), Has(Target.HasInstanceContext) {}
175    AccessTarget &Target;
176    bool Has;
177  };
178
179  SavedInstanceContext saveInstanceContext() {
180    return SavedInstanceContext(*this);
181  }
182
183  void suppressInstanceContext() {
184    HasInstanceContext = false;
185  }
186
187  const CXXRecordDecl *resolveInstanceContext(Sema &S) const {
188    assert(HasInstanceContext);
189    if (CalculatedInstanceContext)
190      return InstanceContext;
191
192    CalculatedInstanceContext = true;
193    DeclContext *IC = S.computeDeclContext(getBaseObjectType());
194    InstanceContext = (IC ? cast<CXXRecordDecl>(IC)->getCanonicalDecl() : 0);
195    return InstanceContext;
196  }
197
198  const CXXRecordDecl *getDeclaringClass() const {
199    return DeclaringClass;
200  }
201
202private:
203  void initialize() {
204    HasInstanceContext = (isMemberAccess() &&
205                          !getBaseObjectType().isNull() &&
206                          getTargetDecl()->isCXXInstanceMember());
207    CalculatedInstanceContext = false;
208    InstanceContext = 0;
209
210    if (isMemberAccess())
211      DeclaringClass = FindDeclaringClass(getTargetDecl());
212    else
213      DeclaringClass = getBaseClass();
214    DeclaringClass = DeclaringClass->getCanonicalDecl();
215  }
216
217  bool HasInstanceContext : 1;
218  mutable bool CalculatedInstanceContext : 1;
219  mutable const CXXRecordDecl *InstanceContext;
220  const CXXRecordDecl *DeclaringClass;
221};
222
223}
224
225/// Checks whether one class might instantiate to the other.
226static bool MightInstantiateTo(const CXXRecordDecl *From,
227                               const CXXRecordDecl *To) {
228  // Declaration names are always preserved by instantiation.
229  if (From->getDeclName() != To->getDeclName())
230    return false;
231
232  const DeclContext *FromDC = From->getDeclContext()->getPrimaryContext();
233  const DeclContext *ToDC = To->getDeclContext()->getPrimaryContext();
234  if (FromDC == ToDC) return true;
235  if (FromDC->isFileContext() || ToDC->isFileContext()) return false;
236
237  // Be conservative.
238  return true;
239}
240
241/// Checks whether one class is derived from another, inclusively.
242/// Properly indicates when it couldn't be determined due to
243/// dependence.
244///
245/// This should probably be donated to AST or at least Sema.
246static AccessResult IsDerivedFromInclusive(const CXXRecordDecl *Derived,
247                                           const CXXRecordDecl *Target) {
248  assert(Derived->getCanonicalDecl() == Derived);
249  assert(Target->getCanonicalDecl() == Target);
250
251  if (Derived == Target) return AR_accessible;
252
253  bool CheckDependent = Derived->isDependentContext();
254  if (CheckDependent && MightInstantiateTo(Derived, Target))
255    return AR_dependent;
256
257  AccessResult OnFailure = AR_inaccessible;
258  llvm::SmallVector<const CXXRecordDecl*, 8> Queue; // actually a stack
259
260  while (true) {
261    for (CXXRecordDecl::base_class_const_iterator
262           I = Derived->bases_begin(), E = Derived->bases_end(); I != E; ++I) {
263
264      const CXXRecordDecl *RD;
265
266      QualType T = I->getType();
267      if (const RecordType *RT = T->getAs<RecordType>()) {
268        RD = cast<CXXRecordDecl>(RT->getDecl());
269      } else if (const InjectedClassNameType *IT
270                   = T->getAs<InjectedClassNameType>()) {
271        RD = IT->getDecl();
272      } else {
273        assert(T->isDependentType() && "non-dependent base wasn't a record?");
274        OnFailure = AR_dependent;
275        continue;
276      }
277
278      RD = RD->getCanonicalDecl();
279      if (RD == Target) return AR_accessible;
280      if (CheckDependent && MightInstantiateTo(RD, Target))
281        OnFailure = AR_dependent;
282
283      Queue.push_back(RD);
284    }
285
286    if (Queue.empty()) break;
287
288    Derived = Queue.back();
289    Queue.pop_back();
290  }
291
292  return OnFailure;
293}
294
295
296static bool MightInstantiateTo(Sema &S, DeclContext *Context,
297                               DeclContext *Friend) {
298  if (Friend == Context)
299    return true;
300
301  assert(!Friend->isDependentContext() &&
302         "can't handle friends with dependent contexts here");
303
304  if (!Context->isDependentContext())
305    return false;
306
307  if (Friend->isFileContext())
308    return false;
309
310  // TODO: this is very conservative
311  return true;
312}
313
314// Asks whether the type in 'context' can ever instantiate to the type
315// in 'friend'.
316static bool MightInstantiateTo(Sema &S, CanQualType Context, CanQualType Friend) {
317  if (Friend == Context)
318    return true;
319
320  if (!Friend->isDependentType() && !Context->isDependentType())
321    return false;
322
323  // TODO: this is very conservative.
324  return true;
325}
326
327static bool MightInstantiateTo(Sema &S,
328                               FunctionDecl *Context,
329                               FunctionDecl *Friend) {
330  if (Context->getDeclName() != Friend->getDeclName())
331    return false;
332
333  if (!MightInstantiateTo(S,
334                          Context->getDeclContext(),
335                          Friend->getDeclContext()))
336    return false;
337
338  CanQual<FunctionProtoType> FriendTy
339    = S.Context.getCanonicalType(Friend->getType())
340         ->getAs<FunctionProtoType>();
341  CanQual<FunctionProtoType> ContextTy
342    = S.Context.getCanonicalType(Context->getType())
343         ->getAs<FunctionProtoType>();
344
345  // There isn't any way that I know of to add qualifiers
346  // during instantiation.
347  if (FriendTy.getQualifiers() != ContextTy.getQualifiers())
348    return false;
349
350  if (FriendTy->getNumArgs() != ContextTy->getNumArgs())
351    return false;
352
353  if (!MightInstantiateTo(S,
354                          ContextTy->getResultType(),
355                          FriendTy->getResultType()))
356    return false;
357
358  for (unsigned I = 0, E = FriendTy->getNumArgs(); I != E; ++I)
359    if (!MightInstantiateTo(S,
360                            ContextTy->getArgType(I),
361                            FriendTy->getArgType(I)))
362      return false;
363
364  return true;
365}
366
367static bool MightInstantiateTo(Sema &S,
368                               FunctionTemplateDecl *Context,
369                               FunctionTemplateDecl *Friend) {
370  return MightInstantiateTo(S,
371                            Context->getTemplatedDecl(),
372                            Friend->getTemplatedDecl());
373}
374
375static AccessResult MatchesFriend(Sema &S,
376                                  const EffectiveContext &EC,
377                                  const CXXRecordDecl *Friend) {
378  if (EC.includesClass(Friend))
379    return AR_accessible;
380
381  if (EC.isDependent()) {
382    CanQualType FriendTy
383      = S.Context.getCanonicalType(S.Context.getTypeDeclType(Friend));
384
385    for (EffectiveContext::record_iterator
386           I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
387      CanQualType ContextTy
388        = S.Context.getCanonicalType(S.Context.getTypeDeclType(*I));
389      if (MightInstantiateTo(S, ContextTy, FriendTy))
390        return AR_dependent;
391    }
392  }
393
394  return AR_inaccessible;
395}
396
397static AccessResult MatchesFriend(Sema &S,
398                                  const EffectiveContext &EC,
399                                  CanQualType Friend) {
400  if (const RecordType *RT = Friend->getAs<RecordType>())
401    return MatchesFriend(S, EC, cast<CXXRecordDecl>(RT->getDecl()));
402
403  // TODO: we can do better than this
404  if (Friend->isDependentType())
405    return AR_dependent;
406
407  return AR_inaccessible;
408}
409
410/// Determines whether the given friend class template matches
411/// anything in the effective context.
412static AccessResult MatchesFriend(Sema &S,
413                                  const EffectiveContext &EC,
414                                  ClassTemplateDecl *Friend) {
415  AccessResult OnFailure = AR_inaccessible;
416
417  // Check whether the friend is the template of a class in the
418  // context chain.
419  for (llvm::SmallVectorImpl<CXXRecordDecl*>::const_iterator
420         I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
421    CXXRecordDecl *Record = *I;
422
423    // Figure out whether the current class has a template:
424    ClassTemplateDecl *CTD;
425
426    // A specialization of the template...
427    if (isa<ClassTemplateSpecializationDecl>(Record)) {
428      CTD = cast<ClassTemplateSpecializationDecl>(Record)
429        ->getSpecializedTemplate();
430
431    // ... or the template pattern itself.
432    } else {
433      CTD = Record->getDescribedClassTemplate();
434      if (!CTD) continue;
435    }
436
437    // It's a match.
438    if (Friend == CTD->getCanonicalDecl())
439      return AR_accessible;
440
441    // If the context isn't dependent, it can't be a dependent match.
442    if (!EC.isDependent())
443      continue;
444
445    // If the template names don't match, it can't be a dependent
446    // match.  This isn't true in C++0x because of template aliases.
447    if (!S.LangOpts.CPlusPlus0x && CTD->getDeclName() != Friend->getDeclName())
448      continue;
449
450    // If the class's context can't instantiate to the friend's
451    // context, it can't be a dependent match.
452    if (!MightInstantiateTo(S, CTD->getDeclContext(),
453                            Friend->getDeclContext()))
454      continue;
455
456    // Otherwise, it's a dependent match.
457    OnFailure = AR_dependent;
458  }
459
460  return OnFailure;
461}
462
463/// Determines whether the given friend function matches anything in
464/// the effective context.
465static AccessResult MatchesFriend(Sema &S,
466                                  const EffectiveContext &EC,
467                                  FunctionDecl *Friend) {
468  AccessResult OnFailure = AR_inaccessible;
469
470  for (llvm::SmallVectorImpl<FunctionDecl*>::const_iterator
471         I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) {
472    if (Friend == *I)
473      return AR_accessible;
474
475    if (EC.isDependent() && MightInstantiateTo(S, *I, Friend))
476      OnFailure = AR_dependent;
477  }
478
479  return OnFailure;
480}
481
482/// Determines whether the given friend function template matches
483/// anything in the effective context.
484static AccessResult MatchesFriend(Sema &S,
485                                  const EffectiveContext &EC,
486                                  FunctionTemplateDecl *Friend) {
487  if (EC.Functions.empty()) return AR_inaccessible;
488
489  AccessResult OnFailure = AR_inaccessible;
490
491  for (llvm::SmallVectorImpl<FunctionDecl*>::const_iterator
492         I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) {
493
494    FunctionTemplateDecl *FTD = (*I)->getPrimaryTemplate();
495    if (!FTD)
496      FTD = (*I)->getDescribedFunctionTemplate();
497    if (!FTD)
498      continue;
499
500    FTD = FTD->getCanonicalDecl();
501
502    if (Friend == FTD)
503      return AR_accessible;
504
505    if (EC.isDependent() && MightInstantiateTo(S, FTD, Friend))
506      OnFailure = AR_dependent;
507  }
508
509  return OnFailure;
510}
511
512/// Determines whether the given friend declaration matches anything
513/// in the effective context.
514static AccessResult MatchesFriend(Sema &S,
515                                  const EffectiveContext &EC,
516                                  FriendDecl *FriendD) {
517  if (TypeSourceInfo *T = FriendD->getFriendType())
518    return MatchesFriend(S, EC, T->getType()->getCanonicalTypeUnqualified());
519
520  NamedDecl *Friend
521    = cast<NamedDecl>(FriendD->getFriendDecl()->getCanonicalDecl());
522
523  // FIXME: declarations with dependent or templated scope.
524
525  if (isa<ClassTemplateDecl>(Friend))
526    return MatchesFriend(S, EC, cast<ClassTemplateDecl>(Friend));
527
528  if (isa<FunctionTemplateDecl>(Friend))
529    return MatchesFriend(S, EC, cast<FunctionTemplateDecl>(Friend));
530
531  if (isa<CXXRecordDecl>(Friend))
532    return MatchesFriend(S, EC, cast<CXXRecordDecl>(Friend));
533
534  assert(isa<FunctionDecl>(Friend) && "unknown friend decl kind");
535  return MatchesFriend(S, EC, cast<FunctionDecl>(Friend));
536}
537
538static AccessResult GetFriendKind(Sema &S,
539                                  const EffectiveContext &EC,
540                                  const CXXRecordDecl *Class) {
541  AccessResult OnFailure = AR_inaccessible;
542
543  // Okay, check friends.
544  for (CXXRecordDecl::friend_iterator I = Class->friend_begin(),
545         E = Class->friend_end(); I != E; ++I) {
546    FriendDecl *Friend = *I;
547
548    switch (MatchesFriend(S, EC, Friend)) {
549    case AR_accessible:
550      return AR_accessible;
551
552    case AR_inaccessible:
553      continue;
554
555    case AR_dependent:
556      OnFailure = AR_dependent;
557      break;
558    }
559  }
560
561  // That's it, give up.
562  return OnFailure;
563}
564
565static AccessResult HasAccess(Sema &S,
566                              const EffectiveContext &EC,
567                              const CXXRecordDecl *NamingClass,
568                              AccessSpecifier Access,
569                              const AccessTarget &Target) {
570  assert(NamingClass->getCanonicalDecl() == NamingClass &&
571         "declaration should be canonicalized before being passed here");
572
573  if (Access == AS_public) return AR_accessible;
574  assert(Access == AS_private || Access == AS_protected);
575
576  AccessResult OnFailure = AR_inaccessible;
577
578  for (EffectiveContext::record_iterator
579         I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
580    // All the declarations in EC have been canonicalized, so pointer
581    // equality from this point on will work fine.
582    const CXXRecordDecl *ECRecord = *I;
583
584    // [B2] and [M2]
585    if (Access == AS_private) {
586      if (ECRecord == NamingClass)
587        return AR_accessible;
588
589      if (EC.isDependent() && MightInstantiateTo(ECRecord, NamingClass))
590        OnFailure = AR_dependent;
591
592    // [B3] and [M3]
593    } else {
594      assert(Access == AS_protected);
595      switch (IsDerivedFromInclusive(ECRecord, NamingClass)) {
596      case AR_accessible: break;
597      case AR_inaccessible: continue;
598      case AR_dependent: OnFailure = AR_dependent; continue;
599      }
600
601      if (!Target.hasInstanceContext())
602        return AR_accessible;
603
604      const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S);
605      if (!InstanceContext) {
606        OnFailure = AR_dependent;
607        continue;
608      }
609
610      // C++ [class.protected]p1:
611      //   An additional access check beyond those described earlier in
612      //   [class.access] is applied when a non-static data member or
613      //   non-static member function is a protected member of its naming
614      //   class.  As described earlier, access to a protected member is
615      //   granted because the reference occurs in a friend or member of
616      //   some class C.  If the access is to form a pointer to member,
617      //   the nested-name-specifier shall name C or a class derived from
618      //   C. All other accesses involve a (possibly implicit) object
619      //   expression. In this case, the class of the object expression
620      //   shall be C or a class derived from C.
621      //
622      // We interpret this as a restriction on [M3].  Most of the
623      // conditions are encoded by not having any instance context.
624      switch (IsDerivedFromInclusive(InstanceContext, ECRecord)) {
625      case AR_accessible: return AR_accessible;
626      case AR_inaccessible: continue;
627      case AR_dependent: OnFailure = AR_dependent; continue;
628      }
629    }
630  }
631
632  if (!NamingClass->hasFriends())
633    return OnFailure;
634
635  // Don't consider friends if we're under the [class.protected]
636  // restriction, above.
637  if (Access == AS_protected && Target.hasInstanceContext()) {
638    const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S);
639    if (!InstanceContext) return AR_dependent;
640
641    switch (IsDerivedFromInclusive(InstanceContext, NamingClass)) {
642    case AR_accessible: break;
643    case AR_inaccessible: return OnFailure;
644    case AR_dependent: return AR_dependent;
645    }
646  }
647
648  switch (GetFriendKind(S, EC, NamingClass)) {
649  case AR_accessible: return AR_accessible;
650  case AR_inaccessible: return OnFailure;
651  case AR_dependent: return AR_dependent;
652  }
653
654  // Silence bogus warnings
655  llvm_unreachable("impossible friendship kind");
656  return OnFailure;
657}
658
659/// Finds the best path from the naming class to the declaring class,
660/// taking friend declarations into account.
661///
662/// C++0x [class.access.base]p5:
663///   A member m is accessible at the point R when named in class N if
664///   [M1] m as a member of N is public, or
665///   [M2] m as a member of N is private, and R occurs in a member or
666///        friend of class N, or
667///   [M3] m as a member of N is protected, and R occurs in a member or
668///        friend of class N, or in a member or friend of a class P
669///        derived from N, where m as a member of P is public, private,
670///        or protected, or
671///   [M4] there exists a base class B of N that is accessible at R, and
672///        m is accessible at R when named in class B.
673///
674/// C++0x [class.access.base]p4:
675///   A base class B of N is accessible at R, if
676///   [B1] an invented public member of B would be a public member of N, or
677///   [B2] R occurs in a member or friend of class N, and an invented public
678///        member of B would be a private or protected member of N, or
679///   [B3] R occurs in a member or friend of a class P derived from N, and an
680///        invented public member of B would be a private or protected member
681///        of P, or
682///   [B4] there exists a class S such that B is a base class of S accessible
683///        at R and S is a base class of N accessible at R.
684///
685/// Along a single inheritance path we can restate both of these
686/// iteratively:
687///
688/// First, we note that M1-4 are equivalent to B1-4 if the member is
689/// treated as a notional base of its declaring class with inheritance
690/// access equivalent to the member's access.  Therefore we need only
691/// ask whether a class B is accessible from a class N in context R.
692///
693/// Let B_1 .. B_n be the inheritance path in question (i.e. where
694/// B_1 = N, B_n = B, and for all i, B_{i+1} is a direct base class of
695/// B_i).  For i in 1..n, we will calculate ACAB(i), the access to the
696/// closest accessible base in the path:
697///   Access(a, b) = (* access on the base specifier from a to b *)
698///   Merge(a, forbidden) = forbidden
699///   Merge(a, private) = forbidden
700///   Merge(a, b) = min(a,b)
701///   Accessible(c, forbidden) = false
702///   Accessible(c, private) = (R is c) || IsFriend(c, R)
703///   Accessible(c, protected) = (R derived from c) || IsFriend(c, R)
704///   Accessible(c, public) = true
705///   ACAB(n) = public
706///   ACAB(i) =
707///     let AccessToBase = Merge(Access(B_i, B_{i+1}), ACAB(i+1)) in
708///     if Accessible(B_i, AccessToBase) then public else AccessToBase
709///
710/// B is an accessible base of N at R iff ACAB(1) = public.
711///
712/// \param FinalAccess the access of the "final step", or AS_public if
713///   there is no final step.
714/// \return null if friendship is dependent
715static CXXBasePath *FindBestPath(Sema &S,
716                                 const EffectiveContext &EC,
717                                 AccessTarget &Target,
718                                 AccessSpecifier FinalAccess,
719                                 CXXBasePaths &Paths) {
720  // Derive the paths to the desired base.
721  const CXXRecordDecl *Derived = Target.getNamingClass();
722  const CXXRecordDecl *Base = Target.getDeclaringClass();
723
724  // FIXME: fail correctly when there are dependent paths.
725  bool isDerived = Derived->isDerivedFrom(const_cast<CXXRecordDecl*>(Base),
726                                          Paths);
727  assert(isDerived && "derived class not actually derived from base");
728  (void) isDerived;
729
730  CXXBasePath *BestPath = 0;
731
732  assert(FinalAccess != AS_none && "forbidden access after declaring class");
733
734  bool AnyDependent = false;
735
736  // Derive the friend-modified access along each path.
737  for (CXXBasePaths::paths_iterator PI = Paths.begin(), PE = Paths.end();
738         PI != PE; ++PI) {
739    AccessTarget::SavedInstanceContext _ = Target.saveInstanceContext();
740
741    // Walk through the path backwards.
742    AccessSpecifier PathAccess = FinalAccess;
743    CXXBasePath::iterator I = PI->end(), E = PI->begin();
744    while (I != E) {
745      --I;
746
747      assert(PathAccess != AS_none);
748
749      // If the declaration is a private member of a base class, there
750      // is no level of friendship in derived classes that can make it
751      // accessible.
752      if (PathAccess == AS_private) {
753        PathAccess = AS_none;
754        break;
755      }
756
757      const CXXRecordDecl *NC = I->Class->getCanonicalDecl();
758
759      AccessSpecifier BaseAccess = I->Base->getAccessSpecifier();
760      PathAccess = std::max(PathAccess, BaseAccess);
761
762      switch (HasAccess(S, EC, NC, PathAccess, Target)) {
763      case AR_inaccessible: break;
764      case AR_accessible:
765        PathAccess = AS_public;
766
767        // Future tests are not against members and so do not have
768        // instance context.
769        Target.suppressInstanceContext();
770        break;
771      case AR_dependent:
772        AnyDependent = true;
773        goto Next;
774      }
775    }
776
777    // Note that we modify the path's Access field to the
778    // friend-modified access.
779    if (BestPath == 0 || PathAccess < BestPath->Access) {
780      BestPath = &*PI;
781      BestPath->Access = PathAccess;
782
783      // Short-circuit if we found a public path.
784      if (BestPath->Access == AS_public)
785        return BestPath;
786    }
787
788  Next: ;
789  }
790
791  assert((!BestPath || BestPath->Access != AS_public) &&
792         "fell out of loop with public path");
793
794  // We didn't find a public path, but at least one path was subject
795  // to dependent friendship, so delay the check.
796  if (AnyDependent)
797    return 0;
798
799  return BestPath;
800}
801
802/// Diagnose the path which caused the given declaration or base class
803/// to become inaccessible.
804static void DiagnoseAccessPath(Sema &S,
805                               const EffectiveContext &EC,
806                               AccessTarget &Entity) {
807  AccessSpecifier Access = Entity.getAccess();
808  const CXXRecordDecl *NamingClass = Entity.getNamingClass();
809  NamingClass = NamingClass->getCanonicalDecl();
810
811  NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : 0);
812  const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();
813
814  // Easy case: the decl's natural access determined its path access.
815  // We have to check against AS_private here in case Access is AS_none,
816  // indicating a non-public member of a private base class.
817  if (D && (Access == D->getAccess() || D->getAccess() == AS_private)) {
818    switch (HasAccess(S, EC, DeclaringClass, D->getAccess(), Entity)) {
819    case AR_inaccessible: {
820      S.Diag(D->getLocation(), diag::note_access_natural)
821        << (unsigned) (Access == AS_protected)
822        << /*FIXME: not implicitly*/ 0;
823      return;
824    }
825
826    case AR_accessible: break;
827
828    case AR_dependent:
829      llvm_unreachable("can't diagnose dependent access failures");
830      return;
831    }
832  }
833
834  CXXBasePaths Paths;
835  CXXBasePath &Path = *FindBestPath(S, EC, Entity, AS_public, Paths);
836
837  CXXBasePath::iterator I = Path.end(), E = Path.begin();
838  while (I != E) {
839    --I;
840
841    const CXXBaseSpecifier *BS = I->Base;
842    AccessSpecifier BaseAccess = BS->getAccessSpecifier();
843
844    // If this is public inheritance, or the derived class is a friend,
845    // skip this step.
846    if (BaseAccess == AS_public)
847      continue;
848
849    switch (GetFriendKind(S, EC, I->Class)) {
850    case AR_accessible: continue;
851    case AR_inaccessible: break;
852    case AR_dependent:
853      llvm_unreachable("can't diagnose dependent access failures");
854    }
855
856    // Check whether this base specifier is the tighest point
857    // constraining access.  We have to check against AS_private for
858    // the same reasons as above.
859    if (BaseAccess == AS_private || BaseAccess >= Access) {
860
861      // We're constrained by inheritance, but we want to say
862      // "declared private here" if we're diagnosing a hierarchy
863      // conversion and this is the final step.
864      unsigned diagnostic;
865      if (D) diagnostic = diag::note_access_constrained_by_path;
866      else if (I + 1 == Path.end()) diagnostic = diag::note_access_natural;
867      else diagnostic = diag::note_access_constrained_by_path;
868
869      S.Diag(BS->getSourceRange().getBegin(), diagnostic)
870        << BS->getSourceRange()
871        << (BaseAccess == AS_protected)
872        << (BS->getAccessSpecifierAsWritten() == AS_none);
873
874      if (D)
875        S.Diag(D->getLocation(), diag::note_field_decl);
876
877      return;
878    }
879  }
880
881  llvm_unreachable("access not apparently constrained by path");
882}
883
884static void DiagnoseBadAccess(Sema &S, SourceLocation Loc,
885                              const EffectiveContext &EC,
886                              AccessTarget &Entity) {
887  const CXXRecordDecl *NamingClass = Entity.getNamingClass();
888  const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();
889  NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : 0);
890
891  S.Diag(Loc, Entity.getDiag())
892    << (Entity.getAccess() == AS_protected)
893    << (D ? D->getDeclName() : DeclarationName())
894    << S.Context.getTypeDeclType(NamingClass)
895    << S.Context.getTypeDeclType(DeclaringClass);
896  DiagnoseAccessPath(S, EC, Entity);
897}
898
899/// Determines whether the accessed entity is accessible.  Public members
900/// have been weeded out by this point.
901static AccessResult IsAccessible(Sema &S,
902                                 const EffectiveContext &EC,
903                                 AccessTarget &Entity) {
904  // Determine the actual naming class.
905  CXXRecordDecl *NamingClass = Entity.getNamingClass();
906  while (NamingClass->isAnonymousStructOrUnion())
907    NamingClass = cast<CXXRecordDecl>(NamingClass->getParent());
908  NamingClass = NamingClass->getCanonicalDecl();
909
910  AccessSpecifier UnprivilegedAccess = Entity.getAccess();
911  assert(UnprivilegedAccess != AS_public && "public access not weeded out");
912
913  // Before we try to recalculate access paths, try to white-list
914  // accesses which just trade in on the final step, i.e. accesses
915  // which don't require [M4] or [B4]. These are by far the most
916  // common forms of privileged access.
917  if (UnprivilegedAccess != AS_none) {
918    switch (HasAccess(S, EC, NamingClass, UnprivilegedAccess, Entity)) {
919    case AR_dependent:
920      // This is actually an interesting policy decision.  We don't
921      // *have* to delay immediately here: we can do the full access
922      // calculation in the hope that friendship on some intermediate
923      // class will make the declaration accessible non-dependently.
924      // But that's not cheap, and odds are very good (note: assertion
925      // made without data) that the friend declaration will determine
926      // access.
927      return AR_dependent;
928
929    case AR_accessible: return AR_accessible;
930    case AR_inaccessible: break;
931    }
932  }
933
934  AccessTarget::SavedInstanceContext _ = Entity.saveInstanceContext();
935
936  // We lower member accesses to base accesses by pretending that the
937  // member is a base class of its declaring class.
938  AccessSpecifier FinalAccess;
939
940  if (Entity.isMemberAccess()) {
941    // Determine if the declaration is accessible from EC when named
942    // in its declaring class.
943    NamedDecl *Target = Entity.getTargetDecl();
944    const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();
945
946    FinalAccess = Target->getAccess();
947    switch (HasAccess(S, EC, DeclaringClass, FinalAccess, Entity)) {
948    case AR_accessible:
949      FinalAccess = AS_public;
950      break;
951    case AR_inaccessible: break;
952    case AR_dependent: return AR_dependent; // see above
953    }
954
955    if (DeclaringClass == NamingClass)
956      return (FinalAccess == AS_public ? AR_accessible : AR_inaccessible);
957
958    Entity.suppressInstanceContext();
959  } else {
960    FinalAccess = AS_public;
961  }
962
963  assert(Entity.getDeclaringClass() != NamingClass);
964
965  // Append the declaration's access if applicable.
966  CXXBasePaths Paths;
967  CXXBasePath *Path = FindBestPath(S, EC, Entity, FinalAccess, Paths);
968  if (!Path)
969    return AR_dependent;
970
971  assert(Path->Access <= UnprivilegedAccess &&
972         "access along best path worse than direct?");
973  if (Path->Access == AS_public)
974    return AR_accessible;
975  return AR_inaccessible;
976}
977
978static void DelayDependentAccess(Sema &S,
979                                 const EffectiveContext &EC,
980                                 SourceLocation Loc,
981                                 const AccessTarget &Entity) {
982  assert(EC.isDependent() && "delaying non-dependent access");
983  DeclContext *DC = EC.getInnerContext();
984  assert(DC->isDependentContext() && "delaying non-dependent access");
985  DependentDiagnostic::Create(S.Context, DC, DependentDiagnostic::Access,
986                              Loc,
987                              Entity.isMemberAccess(),
988                              Entity.getAccess(),
989                              Entity.getTargetDecl(),
990                              Entity.getNamingClass(),
991                              Entity.getBaseObjectType(),
992                              Entity.getDiag());
993}
994
995/// Checks access to an entity from the given effective context.
996static AccessResult CheckEffectiveAccess(Sema &S,
997                                         const EffectiveContext &EC,
998                                         SourceLocation Loc,
999                                         AccessTarget &Entity) {
1000  assert(Entity.getAccess() != AS_public && "called for public access!");
1001
1002  switch (IsAccessible(S, EC, Entity)) {
1003  case AR_dependent:
1004    DelayDependentAccess(S, EC, Loc, Entity);
1005    return AR_dependent;
1006
1007  case AR_inaccessible:
1008    if (!Entity.isQuiet())
1009      DiagnoseBadAccess(S, Loc, EC, Entity);
1010    return AR_inaccessible;
1011
1012  case AR_accessible:
1013    return AR_accessible;
1014  }
1015
1016  // silence unnecessary warning
1017  llvm_unreachable("invalid access result");
1018  return AR_accessible;
1019}
1020
1021static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc,
1022                                      AccessTarget &Entity) {
1023  // If the access path is public, it's accessible everywhere.
1024  if (Entity.getAccess() == AS_public)
1025    return Sema::AR_accessible;
1026
1027  if (S.SuppressAccessChecking)
1028    return Sema::AR_accessible;
1029
1030  // If we're currently parsing a top-level declaration, delay
1031  // diagnostics.  This is the only case where parsing a declaration
1032  // can actually change our effective context for the purposes of
1033  // access control.
1034  if (S.CurContext->isFileContext() && S.ParsingDeclDepth) {
1035    S.DelayedDiagnostics.push_back(
1036        Sema::DelayedDiagnostic::makeAccess(Loc, Entity));
1037    return Sema::AR_delayed;
1038  }
1039
1040  EffectiveContext EC(S.CurContext);
1041  switch (CheckEffectiveAccess(S, EC, Loc, Entity)) {
1042  case AR_accessible: return Sema::AR_accessible;
1043  case AR_inaccessible: return Sema::AR_inaccessible;
1044  case AR_dependent: return Sema::AR_dependent;
1045  }
1046  llvm_unreachable("falling off end");
1047  return Sema::AR_accessible;
1048}
1049
1050void Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *Ctx) {
1051  // Pretend we did this from the context of the newly-parsed
1052  // declaration. If that declaration itself forms a declaration context,
1053  // include it in the effective context so that parameters and return types of
1054  // befriended functions have that function's access priveledges.
1055  DeclContext *DC = Ctx->getDeclContext();
1056  if (isa<FunctionDecl>(Ctx))
1057    DC = cast<DeclContext>(Ctx);
1058  else if (FunctionTemplateDecl *FnTpl = dyn_cast<FunctionTemplateDecl>(Ctx))
1059    DC = cast<DeclContext>(FnTpl->getTemplatedDecl());
1060  EffectiveContext EC(DC);
1061
1062  AccessTarget Target(DD.getAccessData());
1063
1064  if (CheckEffectiveAccess(*this, EC, DD.Loc, Target) == ::AR_inaccessible)
1065    DD.Triggered = true;
1066}
1067
1068void Sema::HandleDependentAccessCheck(const DependentDiagnostic &DD,
1069                        const MultiLevelTemplateArgumentList &TemplateArgs) {
1070  SourceLocation Loc = DD.getAccessLoc();
1071  AccessSpecifier Access = DD.getAccess();
1072
1073  Decl *NamingD = FindInstantiatedDecl(Loc, DD.getAccessNamingClass(),
1074                                       TemplateArgs);
1075  if (!NamingD) return;
1076  Decl *TargetD = FindInstantiatedDecl(Loc, DD.getAccessTarget(),
1077                                       TemplateArgs);
1078  if (!TargetD) return;
1079
1080  if (DD.isAccessToMember()) {
1081    CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(NamingD);
1082    NamedDecl *TargetDecl = cast<NamedDecl>(TargetD);
1083    QualType BaseObjectType = DD.getAccessBaseObjectType();
1084    if (!BaseObjectType.isNull()) {
1085      BaseObjectType = SubstType(BaseObjectType, TemplateArgs, Loc,
1086                                 DeclarationName());
1087      if (BaseObjectType.isNull()) return;
1088    }
1089
1090    AccessTarget Entity(Context,
1091                        AccessTarget::Member,
1092                        NamingClass,
1093                        DeclAccessPair::make(TargetDecl, Access),
1094                        BaseObjectType);
1095    Entity.setDiag(DD.getDiagnostic());
1096    CheckAccess(*this, Loc, Entity);
1097  } else {
1098    AccessTarget Entity(Context,
1099                        AccessTarget::Base,
1100                        cast<CXXRecordDecl>(TargetD),
1101                        cast<CXXRecordDecl>(NamingD),
1102                        Access);
1103    Entity.setDiag(DD.getDiagnostic());
1104    CheckAccess(*this, Loc, Entity);
1105  }
1106}
1107
1108Sema::AccessResult Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E,
1109                                                     DeclAccessPair Found) {
1110  if (!getLangOptions().AccessControl ||
1111      !E->getNamingClass() ||
1112      Found.getAccess() == AS_public)
1113    return AR_accessible;
1114
1115  AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(),
1116                      Found, QualType());
1117  Entity.setDiag(diag::err_access) << E->getSourceRange();
1118
1119  return CheckAccess(*this, E->getNameLoc(), Entity);
1120}
1121
1122/// Perform access-control checking on a previously-unresolved member
1123/// access which has now been resolved to a member.
1124Sema::AccessResult Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E,
1125                                                     DeclAccessPair Found) {
1126  if (!getLangOptions().AccessControl ||
1127      Found.getAccess() == AS_public)
1128    return AR_accessible;
1129
1130  QualType BaseType = E->getBaseType();
1131  if (E->isArrow())
1132    BaseType = BaseType->getAs<PointerType>()->getPointeeType();
1133
1134  AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(),
1135                      Found, BaseType);
1136  Entity.setDiag(diag::err_access) << E->getSourceRange();
1137
1138  return CheckAccess(*this, E->getMemberLoc(), Entity);
1139}
1140
1141Sema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc,
1142                                               CXXDestructorDecl *Dtor,
1143                                               const PartialDiagnostic &PDiag) {
1144  if (!getLangOptions().AccessControl)
1145    return AR_accessible;
1146
1147  // There's never a path involved when checking implicit destructor access.
1148  AccessSpecifier Access = Dtor->getAccess();
1149  if (Access == AS_public)
1150    return AR_accessible;
1151
1152  CXXRecordDecl *NamingClass = Dtor->getParent();
1153  AccessTarget Entity(Context, AccessTarget::Member, NamingClass,
1154                      DeclAccessPair::make(Dtor, Access),
1155                      QualType());
1156  Entity.setDiag(PDiag); // TODO: avoid copy
1157
1158  return CheckAccess(*this, Loc, Entity);
1159}
1160
1161/// Checks access to a constructor.
1162Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc,
1163                                                CXXConstructorDecl *Constructor,
1164                                                const InitializedEntity &Entity,
1165                                                AccessSpecifier Access,
1166                                                bool IsCopyBindingRefToTemp) {
1167  if (!getLangOptions().AccessControl ||
1168      Access == AS_public)
1169    return AR_accessible;
1170
1171  CXXRecordDecl *NamingClass = Constructor->getParent();
1172  AccessTarget AccessEntity(Context, AccessTarget::Member, NamingClass,
1173                            DeclAccessPair::make(Constructor, Access),
1174                            QualType());
1175  switch (Entity.getKind()) {
1176  default:
1177    AccessEntity.setDiag(IsCopyBindingRefToTemp
1178                         ? diag::ext_rvalue_to_reference_access_ctor
1179                         : diag::err_access_ctor);
1180    break;
1181
1182  case InitializedEntity::EK_Base:
1183    AccessEntity.setDiag(PDiag(diag::err_access_base)
1184                          << Entity.isInheritedVirtualBase()
1185                          << Entity.getBaseSpecifier()->getType()
1186                          << getSpecialMember(Constructor));
1187    break;
1188
1189  case InitializedEntity::EK_Member: {
1190    const FieldDecl *Field = cast<FieldDecl>(Entity.getDecl());
1191    AccessEntity.setDiag(PDiag(diag::err_access_field)
1192                          << Field->getType()
1193                          << getSpecialMember(Constructor));
1194    break;
1195  }
1196
1197  }
1198
1199  return CheckAccess(*this, UseLoc, AccessEntity);
1200}
1201
1202/// Checks direct (i.e. non-inherited) access to an arbitrary class
1203/// member.
1204Sema::AccessResult Sema::CheckDirectMemberAccess(SourceLocation UseLoc,
1205                                                 NamedDecl *Target,
1206                                           const PartialDiagnostic &Diag) {
1207  AccessSpecifier Access = Target->getAccess();
1208  if (!getLangOptions().AccessControl ||
1209      Access == AS_public)
1210    return AR_accessible;
1211
1212  CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(Target->getDeclContext());
1213  AccessTarget Entity(Context, AccessTarget::Member, NamingClass,
1214                      DeclAccessPair::make(Target, Access),
1215                      QualType());
1216  Entity.setDiag(Diag);
1217  return CheckAccess(*this, UseLoc, Entity);
1218}
1219
1220
1221/// Checks access to an overloaded operator new or delete.
1222Sema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc,
1223                                               SourceRange PlacementRange,
1224                                               CXXRecordDecl *NamingClass,
1225                                               DeclAccessPair Found) {
1226  if (!getLangOptions().AccessControl ||
1227      !NamingClass ||
1228      Found.getAccess() == AS_public)
1229    return AR_accessible;
1230
1231  AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
1232                      QualType());
1233  Entity.setDiag(diag::err_access)
1234    << PlacementRange;
1235
1236  return CheckAccess(*this, OpLoc, Entity);
1237}
1238
1239/// Checks access to an overloaded member operator, including
1240/// conversion operators.
1241Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc,
1242                                                   Expr *ObjectExpr,
1243                                                   Expr *ArgExpr,
1244                                                   DeclAccessPair Found) {
1245  if (!getLangOptions().AccessControl ||
1246      Found.getAccess() == AS_public)
1247    return AR_accessible;
1248
1249  const RecordType *RT = ObjectExpr->getType()->getAs<RecordType>();
1250  assert(RT && "found member operator but object expr not of record type");
1251  CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(RT->getDecl());
1252
1253  AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
1254                      ObjectExpr->getType());
1255  Entity.setDiag(diag::err_access)
1256    << ObjectExpr->getSourceRange()
1257    << (ArgExpr ? ArgExpr->getSourceRange() : SourceRange());
1258
1259  return CheckAccess(*this, OpLoc, Entity);
1260}
1261
1262Sema::AccessResult Sema::CheckAddressOfMemberAccess(Expr *OvlExpr,
1263                                                    DeclAccessPair Found) {
1264  if (!getLangOptions().AccessControl ||
1265      Found.getAccess() == AS_none ||
1266      Found.getAccess() == AS_public)
1267    return AR_accessible;
1268
1269  OverloadExpr *Ovl = OverloadExpr::find(OvlExpr).getPointer();
1270  CXXRecordDecl *NamingClass = Ovl->getNamingClass();
1271
1272  AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
1273                      Context.getTypeDeclType(NamingClass));
1274  Entity.setDiag(diag::err_access)
1275    << Ovl->getSourceRange();
1276
1277  return CheckAccess(*this, Ovl->getNameLoc(), Entity);
1278}
1279
1280/// Checks access for a hierarchy conversion.
1281///
1282/// \param IsBaseToDerived whether this is a base-to-derived conversion (true)
1283///     or a derived-to-base conversion (false)
1284/// \param ForceCheck true if this check should be performed even if access
1285///     control is disabled;  some things rely on this for semantics
1286/// \param ForceUnprivileged true if this check should proceed as if the
1287///     context had no special privileges
1288/// \param ADK controls the kind of diagnostics that are used
1289Sema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc,
1290                                              QualType Base,
1291                                              QualType Derived,
1292                                              const CXXBasePath &Path,
1293                                              unsigned DiagID,
1294                                              bool ForceCheck,
1295                                              bool ForceUnprivileged) {
1296  if (!ForceCheck && !getLangOptions().AccessControl)
1297    return AR_accessible;
1298
1299  if (Path.Access == AS_public)
1300    return AR_accessible;
1301
1302  CXXRecordDecl *BaseD, *DerivedD;
1303  BaseD = cast<CXXRecordDecl>(Base->getAs<RecordType>()->getDecl());
1304  DerivedD = cast<CXXRecordDecl>(Derived->getAs<RecordType>()->getDecl());
1305
1306  AccessTarget Entity(Context, AccessTarget::Base, BaseD, DerivedD,
1307                      Path.Access);
1308  if (DiagID)
1309    Entity.setDiag(DiagID) << Derived << Base;
1310
1311  if (ForceUnprivileged) {
1312    switch (CheckEffectiveAccess(*this, EffectiveContext(),
1313                                 AccessLoc, Entity)) {
1314    case ::AR_accessible: return Sema::AR_accessible;
1315    case ::AR_inaccessible: return Sema::AR_inaccessible;
1316    case ::AR_dependent: return Sema::AR_dependent;
1317    }
1318    llvm_unreachable("unexpected result from CheckEffectiveAccess");
1319  }
1320  return CheckAccess(*this, AccessLoc, Entity);
1321}
1322
1323/// Checks access to all the declarations in the given result set.
1324void Sema::CheckLookupAccess(const LookupResult &R) {
1325  assert(getLangOptions().AccessControl
1326         && "performing access check without access control");
1327  assert(R.getNamingClass() && "performing access check without naming class");
1328
1329  for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
1330    if (I.getAccess() != AS_public) {
1331      AccessTarget Entity(Context, AccessedEntity::Member,
1332                          R.getNamingClass(), I.getPair(),
1333                          R.getBaseObjectType());
1334      Entity.setDiag(diag::err_access);
1335
1336      CheckAccess(*this, R.getNameLoc(), Entity);
1337    }
1338  }
1339}
1340
1341void Sema::ActOnStartSuppressingAccessChecks() {
1342  assert(!SuppressAccessChecking &&
1343         "Tried to start access check suppression when already started.");
1344  SuppressAccessChecking = true;
1345}
1346
1347void Sema::ActOnStopSuppressingAccessChecks() {
1348  assert(SuppressAccessChecking &&
1349         "Tried to stop access check suprression when already stopped.");
1350  SuppressAccessChecking = false;
1351}
1352