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