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