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