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