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