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