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