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