blob: 5b1a9d880a910f4715a025f9e25dd89b559c1886 [file] [log] [blame]
Anders Carlsson29f006b2009-03-27 05:05:05 +00001//===---- SemaAccess.cpp - C++ Access Control -------------------*- C++ -*-===//
Anders Carlsson60d6b0d2009-03-27 04:43:36 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file provides Sema routines for C++ access control semantics.
11//
12//===----------------------------------------------------------------------===//
Anders Carlssonc60e8882009-03-27 04:54:36 +000013
14#include "Sema.h"
John McCall92f88312010-01-23 00:46:32 +000015#include "Lookup.h"
Anders Carlssonc4f1e872009-03-27 06:03:27 +000016#include "clang/AST/ASTContext.h"
Douglas Gregora8f32e02009-10-06 17:59:45 +000017#include "clang/AST/CXXInheritance.h"
18#include "clang/AST/DeclCXX.h"
John McCalld60e22e2010-03-12 01:19:31 +000019#include "clang/AST/DeclFriend.h"
John McCall0c01d182010-03-24 05:22:00 +000020#include "clang/AST/DependentDiagnostic.h"
John McCallc373d482010-01-27 01:50:18 +000021#include "clang/AST/ExprCXX.h"
22
Anders Carlssonc60e8882009-03-27 04:54:36 +000023using namespace clang;
24
Anders Carlsson29f006b2009-03-27 05:05:05 +000025/// SetMemberAccessSpecifier - Set the access specifier of a member.
26/// Returns true on error (when the previous member decl access specifier
27/// is different from the new member decl access specifier).
Mike Stump1eb44332009-09-09 15:08:12 +000028bool Sema::SetMemberAccessSpecifier(NamedDecl *MemberDecl,
Anders Carlssonc60e8882009-03-27 04:54:36 +000029 NamedDecl *PrevMemberDecl,
30 AccessSpecifier LexicalAS) {
31 if (!PrevMemberDecl) {
32 // Use the lexical access specifier.
33 MemberDecl->setAccess(LexicalAS);
34 return false;
35 }
Mike Stump1eb44332009-09-09 15:08:12 +000036
Anders Carlssonc60e8882009-03-27 04:54:36 +000037 // C++ [class.access.spec]p3: When a member is redeclared its access
38 // specifier must be same as its initial declaration.
39 if (LexicalAS != AS_none && LexicalAS != PrevMemberDecl->getAccess()) {
Mike Stump1eb44332009-09-09 15:08:12 +000040 Diag(MemberDecl->getLocation(),
41 diag::err_class_redeclared_with_different_access)
Anders Carlssonc60e8882009-03-27 04:54:36 +000042 << MemberDecl << LexicalAS;
43 Diag(PrevMemberDecl->getLocation(), diag::note_previous_access_declaration)
44 << PrevMemberDecl << PrevMemberDecl->getAccess();
John McCall44e067b2009-12-23 00:37:40 +000045
46 MemberDecl->setAccess(LexicalAS);
Anders Carlssonc60e8882009-03-27 04:54:36 +000047 return true;
48 }
Mike Stump1eb44332009-09-09 15:08:12 +000049
Anders Carlssonc60e8882009-03-27 04:54:36 +000050 MemberDecl->setAccess(PrevMemberDecl->getAccess());
51 return false;
52}
Anders Carlsson29f006b2009-03-27 05:05:05 +000053
John McCall6b2accb2010-02-10 09:31:12 +000054namespace {
55struct EffectiveContext {
John McCall7ad650f2010-03-24 07:46:06 +000056 EffectiveContext() : Inner(0), Function(0), Dependent(false) {}
Anders Carlssonc4f1e872009-03-27 06:03:27 +000057
John McCall7ad650f2010-03-24 07:46:06 +000058 explicit EffectiveContext(DeclContext *DC)
59 : Inner(DC),
60 Dependent(DC->isDependentContext()) {
John McCall0c01d182010-03-24 05:22:00 +000061
John McCall6b2accb2010-02-10 09:31:12 +000062 if (isa<FunctionDecl>(DC)) {
John McCalld60e22e2010-03-12 01:19:31 +000063 Function = cast<FunctionDecl>(DC)->getCanonicalDecl();
John McCall6b2accb2010-02-10 09:31:12 +000064 DC = Function->getDeclContext();
65 } else
66 Function = 0;
John McCall88b6c712010-03-17 04:58:56 +000067
68 // C++ [class.access.nest]p1:
69 // A nested class is a member and as such has the same access
70 // rights as any other member.
71 // C++ [class.access]p2:
72 // A member of a class can also access all the names to which
73 // the class has access.
74 // This implies that the privileges of nesting are transitive.
75 while (isa<CXXRecordDecl>(DC)) {
76 CXXRecordDecl *Record = cast<CXXRecordDecl>(DC)->getCanonicalDecl();
77 Records.push_back(Record);
78 DC = Record->getDeclContext();
79 }
Anders Carlssonc4f1e872009-03-27 06:03:27 +000080 }
Sebastian Redl726212f2009-07-18 14:32:15 +000081
John McCall0c01d182010-03-24 05:22:00 +000082 bool isDependent() const { return Dependent; }
83
John McCall88b6c712010-03-17 04:58:56 +000084 bool includesClass(const CXXRecordDecl *R) const {
85 R = R->getCanonicalDecl();
86 return std::find(Records.begin(), Records.end(), R)
87 != Records.end();
John McCall6b2accb2010-02-10 09:31:12 +000088 }
89
John McCall7ad650f2010-03-24 07:46:06 +000090 /// Retrieves the innermost "useful" context. Can be null if we're
91 /// doing access-control without privileges.
92 DeclContext *getInnerContext() const {
93 return Inner;
John McCall0c01d182010-03-24 05:22:00 +000094 }
95
96 typedef llvm::SmallVectorImpl<CXXRecordDecl*>::const_iterator record_iterator;
97
John McCall7ad650f2010-03-24 07:46:06 +000098 DeclContext *Inner;
John McCall88b6c712010-03-17 04:58:56 +000099 llvm::SmallVector<CXXRecordDecl*, 4> Records;
John McCall6b2accb2010-02-10 09:31:12 +0000100 FunctionDecl *Function;
John McCall0c01d182010-03-24 05:22:00 +0000101 bool Dependent;
John McCall6b2accb2010-02-10 09:31:12 +0000102};
Anders Carlsson29f006b2009-03-27 05:05:05 +0000103}
John McCall92f88312010-01-23 00:46:32 +0000104
John McCall6b2accb2010-02-10 09:31:12 +0000105static CXXRecordDecl *FindDeclaringClass(NamedDecl *D) {
106 CXXRecordDecl *DeclaringClass = cast<CXXRecordDecl>(D->getDeclContext());
107 while (DeclaringClass->isAnonymousStructOrUnion())
108 DeclaringClass = cast<CXXRecordDecl>(DeclaringClass->getDeclContext());
109 return DeclaringClass;
110}
111
John McCall0c01d182010-03-24 05:22:00 +0000112static bool MightInstantiateTo(Sema &S, DeclContext *Context,
113 DeclContext *Friend) {
114 if (Friend == Context)
115 return true;
116
117 assert(!Friend->isDependentContext() &&
118 "can't handle friends with dependent contexts here");
119
120 if (!Context->isDependentContext())
121 return false;
122
123 if (Friend->isFileContext())
124 return false;
125
126 // TODO: this is very conservative
127 return true;
128}
129
130// Asks whether the type in 'context' can ever instantiate to the type
131// in 'friend'.
132static bool MightInstantiateTo(Sema &S, CanQualType Context, CanQualType Friend) {
133 if (Friend == Context)
134 return true;
135
136 if (!Friend->isDependentType() && !Context->isDependentType())
137 return false;
138
139 // TODO: this is very conservative.
140 return true;
141}
142
143static bool MightInstantiateTo(Sema &S,
144 FunctionDecl *Context,
145 FunctionDecl *Friend) {
146 if (Context->getDeclName() != Friend->getDeclName())
147 return false;
148
149 if (!MightInstantiateTo(S,
150 Context->getDeclContext(),
151 Friend->getDeclContext()))
152 return false;
153
154 CanQual<FunctionProtoType> FriendTy
155 = S.Context.getCanonicalType(Friend->getType())
156 ->getAs<FunctionProtoType>();
157 CanQual<FunctionProtoType> ContextTy
158 = S.Context.getCanonicalType(Context->getType())
159 ->getAs<FunctionProtoType>();
160
161 // There isn't any way that I know of to add qualifiers
162 // during instantiation.
163 if (FriendTy.getQualifiers() != ContextTy.getQualifiers())
164 return false;
165
166 if (FriendTy->getNumArgs() != ContextTy->getNumArgs())
167 return false;
168
169 if (!MightInstantiateTo(S,
170 ContextTy->getResultType(),
171 FriendTy->getResultType()))
172 return false;
173
174 for (unsigned I = 0, E = FriendTy->getNumArgs(); I != E; ++I)
175 if (!MightInstantiateTo(S,
176 ContextTy->getArgType(I),
177 FriendTy->getArgType(I)))
178 return false;
179
180 return true;
181}
182
183static bool MightInstantiateTo(Sema &S,
184 FunctionTemplateDecl *Context,
185 FunctionTemplateDecl *Friend) {
186 return MightInstantiateTo(S,
187 Context->getTemplatedDecl(),
188 Friend->getTemplatedDecl());
189}
190
John McCalla742db02010-03-17 20:01:29 +0000191static Sema::AccessResult MatchesFriend(Sema &S,
192 const EffectiveContext &EC,
193 const CXXRecordDecl *Friend) {
John McCalla742db02010-03-17 20:01:29 +0000194 if (EC.includesClass(Friend))
195 return Sema::AR_accessible;
196
John McCall0c01d182010-03-24 05:22:00 +0000197 if (EC.isDependent()) {
198 CanQualType FriendTy
199 = S.Context.getCanonicalType(S.Context.getTypeDeclType(Friend));
200
201 for (EffectiveContext::record_iterator
202 I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
203 CanQualType ContextTy
204 = S.Context.getCanonicalType(S.Context.getTypeDeclType(*I));
205 if (MightInstantiateTo(S, ContextTy, FriendTy))
206 return Sema::AR_dependent;
207 }
208 }
209
John McCalla742db02010-03-17 20:01:29 +0000210 return Sema::AR_inaccessible;
211}
212
213static Sema::AccessResult MatchesFriend(Sema &S,
214 const EffectiveContext &EC,
John McCall0c01d182010-03-24 05:22:00 +0000215 CanQualType Friend) {
216 if (const RecordType *RT = Friend->getAs<RecordType>())
217 return MatchesFriend(S, EC, cast<CXXRecordDecl>(RT->getDecl()));
John McCalla742db02010-03-17 20:01:29 +0000218
John McCall0c01d182010-03-24 05:22:00 +0000219 // TODO: we can do better than this
220 if (Friend->isDependentType())
221 return Sema::AR_dependent;
John McCalla742db02010-03-17 20:01:29 +0000222
John McCall0c01d182010-03-24 05:22:00 +0000223 return Sema::AR_inaccessible;
224}
225
226/// Determines whether the given friend class template matches
227/// anything in the effective context.
228static Sema::AccessResult MatchesFriend(Sema &S,
229 const EffectiveContext &EC,
230 ClassTemplateDecl *Friend) {
231 Sema::AccessResult OnFailure = Sema::AR_inaccessible;
232
233 for (llvm::SmallVectorImpl<CXXRecordDecl*>::const_iterator
234 I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
235 CXXRecordDecl *Record = *I;
236
237 // Check whether the friend is the template of a class in the
238 // context chain. To do that, we need to figure out whether the
239 // current class has a template:
240 ClassTemplateDecl *CTD;
241
242 // A specialization of the template...
243 if (isa<ClassTemplateSpecializationDecl>(Record)) {
244 CTD = cast<ClassTemplateSpecializationDecl>(Record)
245 ->getSpecializedTemplate();
246
247 // ... or the template pattern itself.
248 } else {
249 CTD = Record->getDescribedClassTemplate();
250 if (!CTD) continue;
251 }
252
253 // It's a match.
254 if (Friend == CTD->getCanonicalDecl())
255 return Sema::AR_accessible;
256
257 // If the template names don't match, it can't be a dependent
258 // match. This isn't true in C++0x because of template aliases.
259 if (!S.LangOpts.CPlusPlus0x && CTD->getDeclName() != Friend->getDeclName())
260 continue;
261
262 // If the class's context can't instantiate to the friend's
263 // context, it can't be a dependent match.
264 if (!MightInstantiateTo(S, CTD->getDeclContext(),
265 Friend->getDeclContext()))
266 continue;
267
268 // Otherwise, it's a dependent match.
269 OnFailure = Sema::AR_dependent;
John McCalla742db02010-03-17 20:01:29 +0000270 }
271
John McCall0c01d182010-03-24 05:22:00 +0000272 return OnFailure;
273}
274
275/// Determines whether the given friend function matches anything in
276/// the effective context.
277static Sema::AccessResult MatchesFriend(Sema &S,
278 const EffectiveContext &EC,
279 FunctionDecl *Friend) {
280 if (!EC.Function)
281 return Sema::AR_inaccessible;
282
283 if (Friend == EC.Function)
284 return Sema::AR_accessible;
285
286 if (EC.isDependent() && MightInstantiateTo(S, EC.Function, Friend))
287 return Sema::AR_dependent;
288
289 return Sema::AR_inaccessible;
290}
291
292/// Determines whether the given friend function template matches
293/// anything in the effective context.
294static Sema::AccessResult MatchesFriend(Sema &S,
295 const EffectiveContext &EC,
296 FunctionTemplateDecl *Friend) {
297 if (!EC.Function) return Sema::AR_inaccessible;
298
299 FunctionTemplateDecl *FTD = EC.Function->getPrimaryTemplate();
300 if (!FTD)
301 FTD = EC.Function->getDescribedFunctionTemplate();
302 if (!FTD)
303 return Sema::AR_inaccessible;
304
305 if (Friend == FTD->getCanonicalDecl())
306 return Sema::AR_accessible;
307
308 if (MightInstantiateTo(S, FTD, Friend))
309 return Sema::AR_dependent;
310
311 return Sema::AR_inaccessible;
312}
313
314/// Determines whether the given friend declaration matches anything
315/// in the effective context.
316static Sema::AccessResult MatchesFriend(Sema &S,
317 const EffectiveContext &EC,
318 FriendDecl *FriendD) {
319 if (Type *T = FriendD->getFriendType())
320 return MatchesFriend(S, EC, T->getCanonicalTypeUnqualified());
321
322 NamedDecl *Friend
323 = cast<NamedDecl>(FriendD->getFriendDecl()->getCanonicalDecl());
John McCalla742db02010-03-17 20:01:29 +0000324
325 // FIXME: declarations with dependent or templated scope.
326
John McCall0c01d182010-03-24 05:22:00 +0000327 if (isa<ClassTemplateDecl>(Friend))
328 return MatchesFriend(S, EC, cast<ClassTemplateDecl>(Friend));
John McCalla742db02010-03-17 20:01:29 +0000329
John McCall0c01d182010-03-24 05:22:00 +0000330 if (isa<FunctionTemplateDecl>(Friend))
331 return MatchesFriend(S, EC, cast<FunctionTemplateDecl>(Friend));
John McCalla742db02010-03-17 20:01:29 +0000332
John McCall0c01d182010-03-24 05:22:00 +0000333 if (isa<CXXRecordDecl>(Friend))
334 return MatchesFriend(S, EC, cast<CXXRecordDecl>(Friend));
John McCalla742db02010-03-17 20:01:29 +0000335
John McCall0c01d182010-03-24 05:22:00 +0000336 assert(isa<FunctionDecl>(Friend) && "unknown friend decl kind");
337 return MatchesFriend(S, EC, cast<FunctionDecl>(Friend));
John McCalla742db02010-03-17 20:01:29 +0000338}
339
John McCall6b2accb2010-02-10 09:31:12 +0000340static Sema::AccessResult GetFriendKind(Sema &S,
341 const EffectiveContext &EC,
342 const CXXRecordDecl *Class) {
John McCalld60e22e2010-03-12 01:19:31 +0000343 // A class always has access to its own members.
John McCall88b6c712010-03-17 04:58:56 +0000344 if (EC.includesClass(Class))
John McCall6b2accb2010-02-10 09:31:12 +0000345 return Sema::AR_accessible;
346
John McCall88b6c712010-03-17 04:58:56 +0000347 Sema::AccessResult OnFailure = Sema::AR_inaccessible;
348
John McCalld60e22e2010-03-12 01:19:31 +0000349 // Okay, check friends.
350 for (CXXRecordDecl::friend_iterator I = Class->friend_begin(),
351 E = Class->friend_end(); I != E; ++I) {
352 FriendDecl *Friend = *I;
353
John McCalla742db02010-03-17 20:01:29 +0000354 switch (MatchesFriend(S, EC, Friend)) {
355 case Sema::AR_accessible:
356 return Sema::AR_accessible;
John McCalld60e22e2010-03-12 01:19:31 +0000357
John McCalla742db02010-03-17 20:01:29 +0000358 case Sema::AR_inaccessible:
359 break;
John McCall88b6c712010-03-17 04:58:56 +0000360
John McCalla742db02010-03-17 20:01:29 +0000361 case Sema::AR_dependent:
362 OnFailure = Sema::AR_dependent;
363 break;
364
365 case Sema::AR_delayed:
366 llvm_unreachable("cannot get delayed answer from MatchesFriend");
John McCalld60e22e2010-03-12 01:19:31 +0000367 }
John McCalld60e22e2010-03-12 01:19:31 +0000368 }
369
370 // That's it, give up.
John McCall88b6c712010-03-17 04:58:56 +0000371 return OnFailure;
John McCall6b2accb2010-02-10 09:31:12 +0000372}
373
374/// Finds the best path from the naming class to the declaring class,
375/// taking friend declarations into account.
376///
John McCall7aceaf82010-03-18 23:49:19 +0000377/// \param FinalAccess the access of the "final step", or AS_none if
378/// there is no final step.
John McCall6b2accb2010-02-10 09:31:12 +0000379/// \return null if friendship is dependent
380static CXXBasePath *FindBestPath(Sema &S,
381 const EffectiveContext &EC,
382 CXXRecordDecl *Derived,
383 CXXRecordDecl *Base,
John McCall7aceaf82010-03-18 23:49:19 +0000384 AccessSpecifier FinalAccess,
John McCall6b2accb2010-02-10 09:31:12 +0000385 CXXBasePaths &Paths) {
386 // Derive the paths to the desired base.
387 bool isDerived = Derived->isDerivedFrom(Base, Paths);
388 assert(isDerived && "derived class not actually derived from base");
389 (void) isDerived;
390
391 CXXBasePath *BestPath = 0;
392
John McCall7aceaf82010-03-18 23:49:19 +0000393 assert(FinalAccess != AS_none && "forbidden access after declaring class");
394
John McCall0c01d182010-03-24 05:22:00 +0000395 bool AnyDependent = false;
396
John McCall6b2accb2010-02-10 09:31:12 +0000397 // Derive the friend-modified access along each path.
398 for (CXXBasePaths::paths_iterator PI = Paths.begin(), PE = Paths.end();
399 PI != PE; ++PI) {
400
401 // Walk through the path backwards.
John McCall7aceaf82010-03-18 23:49:19 +0000402 AccessSpecifier PathAccess = FinalAccess;
John McCall6b2accb2010-02-10 09:31:12 +0000403 CXXBasePath::iterator I = PI->end(), E = PI->begin();
404 while (I != E) {
405 --I;
406
John McCall7aceaf82010-03-18 23:49:19 +0000407 assert(PathAccess != AS_none);
408
409 // If the declaration is a private member of a base class, there
410 // is no level of friendship in derived classes that can make it
411 // accessible.
412 if (PathAccess == AS_private) {
413 PathAccess = AS_none;
414 break;
415 }
416
John McCall6b2accb2010-02-10 09:31:12 +0000417 AccessSpecifier BaseAccess = I->Base->getAccessSpecifier();
418 if (BaseAccess != AS_public) {
419 switch (GetFriendKind(S, EC, I->Class)) {
John McCall7aceaf82010-03-18 23:49:19 +0000420 case Sema::AR_inaccessible:
421 PathAccess = CXXRecordDecl::MergeAccess(BaseAccess, PathAccess);
422 break;
423 case Sema::AR_accessible:
424 PathAccess = AS_public;
425 break;
426 case Sema::AR_dependent:
John McCall0c01d182010-03-24 05:22:00 +0000427 AnyDependent = true;
428 goto Next;
John McCall6b2accb2010-02-10 09:31:12 +0000429 case Sema::AR_delayed:
430 llvm_unreachable("friend resolution is never delayed"); break;
431 }
432 }
John McCall6b2accb2010-02-10 09:31:12 +0000433 }
434
435 // Note that we modify the path's Access field to the
436 // friend-modified access.
437 if (BestPath == 0 || PathAccess < BestPath->Access) {
438 BestPath = &*PI;
439 BestPath->Access = PathAccess;
John McCall0c01d182010-03-24 05:22:00 +0000440
441 // Short-circuit if we found a public path.
442 if (BestPath->Access == AS_public)
443 return BestPath;
John McCall6b2accb2010-02-10 09:31:12 +0000444 }
John McCall0c01d182010-03-24 05:22:00 +0000445
446 Next: ;
John McCall6b2accb2010-02-10 09:31:12 +0000447 }
448
John McCall0c01d182010-03-24 05:22:00 +0000449 assert((!BestPath || BestPath->Access != AS_public) &&
450 "fell out of loop with public path");
451
452 // We didn't find a public path, but at least one path was subject
453 // to dependent friendship, so delay the check.
454 if (AnyDependent)
455 return 0;
456
John McCall6b2accb2010-02-10 09:31:12 +0000457 return BestPath;
458}
459
460/// Diagnose the path which caused the given declaration or base class
461/// to become inaccessible.
462static void DiagnoseAccessPath(Sema &S,
463 const EffectiveContext &EC,
464 CXXRecordDecl *NamingClass,
465 CXXRecordDecl *DeclaringClass,
466 NamedDecl *D, AccessSpecifier Access) {
John McCall92f88312010-01-23 00:46:32 +0000467 // Easy case: the decl's natural access determined its path access.
John McCall6b2accb2010-02-10 09:31:12 +0000468 // We have to check against AS_private here in case Access is AS_none,
469 // indicating a non-public member of a private base class.
470 //
471 // DependentFriend should be impossible here.
472 if (D && (Access == D->getAccess() || D->getAccess() == AS_private)) {
473 switch (GetFriendKind(S, EC, DeclaringClass)) {
474 case Sema::AR_inaccessible: {
475 S.Diag(D->getLocation(), diag::note_access_natural)
476 << (unsigned) (Access == AS_protected)
477 << /*FIXME: not implicitly*/ 0;
478 return;
479 }
480
481 case Sema::AR_accessible: break;
482
483 case Sema::AR_dependent:
484 case Sema::AR_delayed:
485 llvm_unreachable("dependent/delayed not allowed");
486 return;
487 }
488 }
489
490 CXXBasePaths Paths;
John McCall7aceaf82010-03-18 23:49:19 +0000491 CXXBasePath &Path = *FindBestPath(S, EC, NamingClass, DeclaringClass,
492 AS_public, Paths);
John McCall6b2accb2010-02-10 09:31:12 +0000493
494 CXXBasePath::iterator I = Path.end(), E = Path.begin();
495 while (I != E) {
496 --I;
497
498 const CXXBaseSpecifier *BS = I->Base;
499 AccessSpecifier BaseAccess = BS->getAccessSpecifier();
500
501 // If this is public inheritance, or the derived class is a friend,
502 // skip this step.
503 if (BaseAccess == AS_public)
504 continue;
505
506 switch (GetFriendKind(S, EC, I->Class)) {
507 case Sema::AR_accessible: continue;
508 case Sema::AR_inaccessible: break;
509
510 case Sema::AR_dependent:
511 case Sema::AR_delayed:
512 llvm_unreachable("dependent friendship, should not be diagnosing");
513 }
514
515 // Check whether this base specifier is the tighest point
516 // constraining access. We have to check against AS_private for
517 // the same reasons as above.
518 if (BaseAccess == AS_private || BaseAccess >= Access) {
519
520 // We're constrained by inheritance, but we want to say
521 // "declared private here" if we're diagnosing a hierarchy
522 // conversion and this is the final step.
523 unsigned diagnostic;
524 if (D) diagnostic = diag::note_access_constrained_by_path;
525 else if (I + 1 == Path.end()) diagnostic = diag::note_access_natural;
526 else diagnostic = diag::note_access_constrained_by_path;
527
528 S.Diag(BS->getSourceRange().getBegin(), diagnostic)
529 << BS->getSourceRange()
530 << (BaseAccess == AS_protected)
531 << (BS->getAccessSpecifierAsWritten() == AS_none);
532 return;
533 }
534 }
535
536 llvm_unreachable("access not apparently constrained by path");
537}
538
539/// Diagnose an inaccessible class member.
540static void DiagnoseInaccessibleMember(Sema &S, SourceLocation Loc,
541 const EffectiveContext &EC,
542 CXXRecordDecl *NamingClass,
543 AccessSpecifier Access,
544 const Sema::AccessedEntity &Entity) {
545 NamedDecl *D = Entity.getTargetDecl();
546 CXXRecordDecl *DeclaringClass = FindDeclaringClass(D);
547
John McCall58e6f342010-03-16 05:22:47 +0000548 S.Diag(Loc, Entity.getDiag())
549 << (Access == AS_protected)
550 << D->getDeclName()
551 << S.Context.getTypeDeclType(NamingClass)
552 << S.Context.getTypeDeclType(DeclaringClass);
John McCall6b2accb2010-02-10 09:31:12 +0000553 DiagnoseAccessPath(S, EC, NamingClass, DeclaringClass, D, Access);
554}
555
556/// Diagnose an inaccessible hierarchy conversion.
557static void DiagnoseInaccessibleBase(Sema &S, SourceLocation Loc,
558 const EffectiveContext &EC,
559 AccessSpecifier Access,
John McCall58e6f342010-03-16 05:22:47 +0000560 const Sema::AccessedEntity &Entity) {
561 S.Diag(Loc, Entity.getDiag())
562 << (Access == AS_protected)
563 << DeclarationName()
564 << S.Context.getTypeDeclType(Entity.getDerivedClass())
565 << S.Context.getTypeDeclType(Entity.getBaseClass());
John McCall6b2accb2010-02-10 09:31:12 +0000566 DiagnoseAccessPath(S, EC, Entity.getDerivedClass(),
567 Entity.getBaseClass(), 0, Access);
568}
569
John McCall58e6f342010-03-16 05:22:47 +0000570static void DiagnoseBadAccess(Sema &S, SourceLocation Loc,
John McCall6b2accb2010-02-10 09:31:12 +0000571 const EffectiveContext &EC,
572 CXXRecordDecl *NamingClass,
573 AccessSpecifier Access,
John McCall58e6f342010-03-16 05:22:47 +0000574 const Sema::AccessedEntity &Entity) {
John McCall6b2accb2010-02-10 09:31:12 +0000575 if (Entity.isMemberAccess())
576 DiagnoseInaccessibleMember(S, Loc, EC, NamingClass, Access, Entity);
577 else
John McCall58e6f342010-03-16 05:22:47 +0000578 DiagnoseInaccessibleBase(S, Loc, EC, Access, Entity);
John McCall6b2accb2010-02-10 09:31:12 +0000579}
580
581
582/// Try to elevate access using friend declarations. This is
583/// potentially quite expensive.
John McCall0c01d182010-03-24 05:22:00 +0000584///
585/// \return true if elevation was dependent
586static bool TryElevateAccess(Sema &S,
John McCall6b2accb2010-02-10 09:31:12 +0000587 const EffectiveContext &EC,
588 const Sema::AccessedEntity &Entity,
589 AccessSpecifier &Access) {
590 CXXRecordDecl *DeclaringClass;
591 if (Entity.isMemberAccess()) {
592 DeclaringClass = FindDeclaringClass(Entity.getTargetDecl());
593 } else {
594 DeclaringClass = Entity.getBaseClass();
595 }
596 CXXRecordDecl *NamingClass = Entity.getNamingClass();
597
598 // Adjust the declaration of the referred entity.
John McCall7aceaf82010-03-18 23:49:19 +0000599 AccessSpecifier DeclAccess = AS_public;
John McCall6b2accb2010-02-10 09:31:12 +0000600 if (Entity.isMemberAccess()) {
601 NamedDecl *Target = Entity.getTargetDecl();
602
603 DeclAccess = Target->getAccess();
604 if (DeclAccess != AS_public) {
605 switch (GetFriendKind(S, EC, DeclaringClass)) {
606 case Sema::AR_accessible: DeclAccess = AS_public; break;
607 case Sema::AR_inaccessible: break;
John McCall0c01d182010-03-24 05:22:00 +0000608 case Sema::AR_dependent: return true;
John McCall6b2accb2010-02-10 09:31:12 +0000609 case Sema::AR_delayed: llvm_unreachable("friend status is never delayed");
610 }
611 }
612
613 if (DeclaringClass == NamingClass) {
614 Access = DeclAccess;
John McCall0c01d182010-03-24 05:22:00 +0000615 return false;
John McCall6b2accb2010-02-10 09:31:12 +0000616 }
617 }
618
619 assert(DeclaringClass != NamingClass);
620
621 // Append the declaration's access if applicable.
622 CXXBasePaths Paths;
623 CXXBasePath *Path = FindBestPath(S, EC, Entity.getNamingClass(),
John McCall7aceaf82010-03-18 23:49:19 +0000624 DeclaringClass, DeclAccess, Paths);
John McCall0c01d182010-03-24 05:22:00 +0000625 if (!Path)
626 return true;
John McCall92f88312010-01-23 00:46:32 +0000627
John McCall7aceaf82010-03-18 23:49:19 +0000628 // Grab the access along the best path (note that this includes the
629 // final-step access).
John McCall6b2accb2010-02-10 09:31:12 +0000630 AccessSpecifier NewAccess = Path->Access;
John McCall6b2accb2010-02-10 09:31:12 +0000631 assert(NewAccess <= Access && "access along best path worse than direct?");
632 Access = NewAccess;
John McCall0c01d182010-03-24 05:22:00 +0000633 return false;
634}
635
636static void DelayAccess(Sema &S,
637 const EffectiveContext &EC,
638 SourceLocation Loc,
639 const Sema::AccessedEntity &Entity) {
640 assert(EC.isDependent() && "delaying non-dependent access");
John McCall7ad650f2010-03-24 07:46:06 +0000641 DeclContext *DC = EC.getInnerContext();
John McCall0c01d182010-03-24 05:22:00 +0000642 assert(DC->isDependentContext() && "delaying non-dependent access");
643 DependentDiagnostic::Create(S.Context, DC, DependentDiagnostic::Access,
644 Loc,
645 Entity.isMemberAccess(),
646 Entity.getAccess(),
647 Entity.getTargetDecl(),
648 Entity.getNamingClass(),
649 Entity.getDiag());
John McCall92f88312010-01-23 00:46:32 +0000650}
651
John McCall6b2accb2010-02-10 09:31:12 +0000652/// Checks access to an entity from the given effective context.
653static Sema::AccessResult CheckEffectiveAccess(Sema &S,
654 const EffectiveContext &EC,
655 SourceLocation Loc,
John McCall58e6f342010-03-16 05:22:47 +0000656 Sema::AccessedEntity const &Entity) {
John McCall6b2accb2010-02-10 09:31:12 +0000657 AccessSpecifier Access = Entity.getAccess();
John McCall88b6c712010-03-17 04:58:56 +0000658 assert(Access != AS_public && "called for public access!");
John McCall92f88312010-01-23 00:46:32 +0000659
John McCall88b6c712010-03-17 04:58:56 +0000660 // Find a non-anonymous naming class. For records with access,
661 // there should always be one of these.
John McCall6b2accb2010-02-10 09:31:12 +0000662 CXXRecordDecl *NamingClass = Entity.getNamingClass();
John McCall92f88312010-01-23 00:46:32 +0000663 while (NamingClass->isAnonymousStructOrUnion())
John McCall58e6f342010-03-16 05:22:47 +0000664 NamingClass = cast<CXXRecordDecl>(NamingClass->getParent());
John McCall92f88312010-01-23 00:46:32 +0000665
John McCall88b6c712010-03-17 04:58:56 +0000666 // White-list accesses from classes with privileges equivalent to the
667 // naming class --- but only if the access path isn't forbidden
668 // (i.e. an access of a private member from a subclass).
669 if (Access != AS_none && EC.includesClass(NamingClass))
John McCall6b2accb2010-02-10 09:31:12 +0000670 return Sema::AR_accessible;
John McCall88b6c712010-03-17 04:58:56 +0000671
672 // Try to elevate access.
John McCall88b6c712010-03-17 04:58:56 +0000673 // TODO: on some code, it might be better to do the protected check
674 // without trying to elevate first.
John McCall0c01d182010-03-24 05:22:00 +0000675 if (TryElevateAccess(S, EC, Entity, Access)) {
676 DelayAccess(S, EC, Loc, Entity);
677 return Sema::AR_dependent;
678 }
679
John McCall88b6c712010-03-17 04:58:56 +0000680 if (Access == AS_public) return Sema::AR_accessible;
John McCall92f88312010-01-23 00:46:32 +0000681
682 // Protected access.
683 if (Access == AS_protected) {
684 // FIXME: implement [class.protected]p1
John McCall88b6c712010-03-17 04:58:56 +0000685 for (llvm::SmallVectorImpl<CXXRecordDecl*>::const_iterator
686 I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I)
687 if ((*I)->isDerivedFrom(NamingClass))
688 return Sema::AR_accessible;
John McCall92f88312010-01-23 00:46:32 +0000689
John McCall88b6c712010-03-17 04:58:56 +0000690 // FIXME: delay if we can't decide class derivation yet.
John McCall92f88312010-01-23 00:46:32 +0000691 }
692
John McCall6b2accb2010-02-10 09:31:12 +0000693 // Okay, that's it, reject it.
John McCall58e6f342010-03-16 05:22:47 +0000694 if (!Entity.isQuiet())
695 DiagnoseBadAccess(S, Loc, EC, NamingClass, Access, Entity);
John McCall6b2accb2010-02-10 09:31:12 +0000696 return Sema::AR_inaccessible;
697}
John McCall92f88312010-01-23 00:46:32 +0000698
John McCall6b2accb2010-02-10 09:31:12 +0000699static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc,
John McCall58e6f342010-03-16 05:22:47 +0000700 const Sema::AccessedEntity &Entity) {
John McCall6b2accb2010-02-10 09:31:12 +0000701 // If the access path is public, it's accessible everywhere.
702 if (Entity.getAccess() == AS_public)
703 return Sema::AR_accessible;
John McCall92f88312010-01-23 00:46:32 +0000704
John McCall6b2accb2010-02-10 09:31:12 +0000705 // If we're currently parsing a top-level declaration, delay
706 // diagnostics. This is the only case where parsing a declaration
707 // can actually change our effective context for the purposes of
708 // access control.
709 if (S.CurContext->isFileContext() && S.ParsingDeclDepth) {
John McCall6b2accb2010-02-10 09:31:12 +0000710 S.DelayedDiagnostics.push_back(
711 Sema::DelayedDiagnostic::makeAccess(Loc, Entity));
712 return Sema::AR_delayed;
John McCall92f88312010-01-23 00:46:32 +0000713 }
714
John McCall6b2accb2010-02-10 09:31:12 +0000715 return CheckEffectiveAccess(S, EffectiveContext(S.CurContext),
John McCall58e6f342010-03-16 05:22:47 +0000716 Loc, Entity);
John McCall92f88312010-01-23 00:46:32 +0000717}
718
John McCall2f514482010-01-27 03:50:35 +0000719void Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *Ctx) {
John McCall2f514482010-01-27 03:50:35 +0000720 // Pretend we did this from the context of the newly-parsed
721 // declaration.
John McCall6b2accb2010-02-10 09:31:12 +0000722 EffectiveContext EC(Ctx->getDeclContext());
John McCall2f514482010-01-27 03:50:35 +0000723
John McCall58e6f342010-03-16 05:22:47 +0000724 if (CheckEffectiveAccess(*this, EC, DD.Loc, DD.getAccessData()))
John McCall2f514482010-01-27 03:50:35 +0000725 DD.Triggered = true;
726}
727
John McCall0c01d182010-03-24 05:22:00 +0000728void Sema::HandleDependentAccessCheck(const DependentDiagnostic &DD,
729 const MultiLevelTemplateArgumentList &TemplateArgs) {
730 SourceLocation Loc = DD.getAccessLoc();
731 AccessSpecifier Access = DD.getAccess();
732
733 Decl *NamingD = FindInstantiatedDecl(Loc, DD.getAccessNamingClass(),
734 TemplateArgs);
735 if (!NamingD) return;
736 Decl *TargetD = FindInstantiatedDecl(Loc, DD.getAccessTarget(),
737 TemplateArgs);
738 if (!TargetD) return;
739
740 if (DD.isAccessToMember()) {
741 AccessedEntity Entity(AccessedEntity::Member,
742 cast<CXXRecordDecl>(NamingD),
743 Access,
744 cast<NamedDecl>(TargetD));
745 Entity.setDiag(DD.getDiagnostic());
746 CheckAccess(*this, Loc, Entity);
747 } else {
748 AccessedEntity Entity(AccessedEntity::Base,
749 cast<CXXRecordDecl>(TargetD),
750 cast<CXXRecordDecl>(NamingD),
751 Access);
752 Entity.setDiag(DD.getDiagnostic());
753 CheckAccess(*this, Loc, Entity);
754 }
755}
756
John McCall6b2accb2010-02-10 09:31:12 +0000757Sema::AccessResult Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E,
John McCall9aa472c2010-03-19 07:35:19 +0000758 DeclAccessPair Found) {
John McCall58e6f342010-03-16 05:22:47 +0000759 if (!getLangOptions().AccessControl ||
760 !E->getNamingClass() ||
John McCall9aa472c2010-03-19 07:35:19 +0000761 Found.getAccess() == AS_public)
John McCall6b2accb2010-02-10 09:31:12 +0000762 return AR_accessible;
John McCallc373d482010-01-27 01:50:18 +0000763
John McCall9aa472c2010-03-19 07:35:19 +0000764 AccessedEntity Entity(AccessedEntity::Member, E->getNamingClass(), Found);
John McCall58e6f342010-03-16 05:22:47 +0000765 Entity.setDiag(diag::err_access) << E->getSourceRange();
766
767 return CheckAccess(*this, E->getNameLoc(), Entity);
John McCallc373d482010-01-27 01:50:18 +0000768}
769
770/// Perform access-control checking on a previously-unresolved member
771/// access which has now been resolved to a member.
John McCall6b2accb2010-02-10 09:31:12 +0000772Sema::AccessResult Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E,
John McCall9aa472c2010-03-19 07:35:19 +0000773 DeclAccessPair Found) {
John McCall58e6f342010-03-16 05:22:47 +0000774 if (!getLangOptions().AccessControl ||
John McCall9aa472c2010-03-19 07:35:19 +0000775 Found.getAccess() == AS_public)
John McCall6b2accb2010-02-10 09:31:12 +0000776 return AR_accessible;
John McCallc373d482010-01-27 01:50:18 +0000777
John McCall9aa472c2010-03-19 07:35:19 +0000778 AccessedEntity Entity(AccessedEntity::Member, E->getNamingClass(), Found);
John McCall58e6f342010-03-16 05:22:47 +0000779 Entity.setDiag(diag::err_access) << E->getSourceRange();
780
781 return CheckAccess(*this, E->getMemberLoc(), Entity);
John McCallc373d482010-01-27 01:50:18 +0000782}
783
John McCall6b2accb2010-02-10 09:31:12 +0000784Sema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc,
John McCall58e6f342010-03-16 05:22:47 +0000785 CXXDestructorDecl *Dtor,
786 const PartialDiagnostic &PDiag) {
John McCall4f9506a2010-02-02 08:45:54 +0000787 if (!getLangOptions().AccessControl)
John McCall6b2accb2010-02-10 09:31:12 +0000788 return AR_accessible;
John McCall4f9506a2010-02-02 08:45:54 +0000789
John McCall58e6f342010-03-16 05:22:47 +0000790 // There's never a path involved when checking implicit destructor access.
John McCall4f9506a2010-02-02 08:45:54 +0000791 AccessSpecifier Access = Dtor->getAccess();
792 if (Access == AS_public)
John McCall6b2accb2010-02-10 09:31:12 +0000793 return AR_accessible;
John McCall4f9506a2010-02-02 08:45:54 +0000794
John McCall58e6f342010-03-16 05:22:47 +0000795 CXXRecordDecl *NamingClass = Dtor->getParent();
John McCall9aa472c2010-03-19 07:35:19 +0000796 AccessedEntity Entity(AccessedEntity::Member, NamingClass,
797 DeclAccessPair::make(Dtor, Access));
John McCall58e6f342010-03-16 05:22:47 +0000798 Entity.setDiag(PDiag); // TODO: avoid copy
799
800 return CheckAccess(*this, Loc, Entity);
John McCall4f9506a2010-02-02 08:45:54 +0000801}
802
John McCallb13b7372010-02-01 03:16:54 +0000803/// Checks access to a constructor.
John McCall6b2accb2010-02-10 09:31:12 +0000804Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc,
John McCallb13b7372010-02-01 03:16:54 +0000805 CXXConstructorDecl *Constructor,
806 AccessSpecifier Access) {
John McCall58e6f342010-03-16 05:22:47 +0000807 if (!getLangOptions().AccessControl ||
808 Access == AS_public)
John McCall6b2accb2010-02-10 09:31:12 +0000809 return AR_accessible;
John McCallb13b7372010-02-01 03:16:54 +0000810
John McCall6b2accb2010-02-10 09:31:12 +0000811 CXXRecordDecl *NamingClass = Constructor->getParent();
John McCall9aa472c2010-03-19 07:35:19 +0000812 AccessedEntity Entity(AccessedEntity::Member, NamingClass,
813 DeclAccessPair::make(Constructor, Access));
John McCall58e6f342010-03-16 05:22:47 +0000814 Entity.setDiag(diag::err_access_ctor);
815
816 return CheckAccess(*this, UseLoc, Entity);
John McCallb13b7372010-02-01 03:16:54 +0000817}
818
John McCallb0207482010-03-16 06:11:48 +0000819/// Checks direct (i.e. non-inherited) access to an arbitrary class
820/// member.
821Sema::AccessResult Sema::CheckDirectMemberAccess(SourceLocation UseLoc,
822 NamedDecl *Target,
823 const PartialDiagnostic &Diag) {
824 AccessSpecifier Access = Target->getAccess();
825 if (!getLangOptions().AccessControl ||
826 Access == AS_public)
827 return AR_accessible;
828
829 CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(Target->getDeclContext());
John McCall9aa472c2010-03-19 07:35:19 +0000830 AccessedEntity Entity(AccessedEntity::Member, NamingClass,
831 DeclAccessPair::make(Target, Access));
John McCallb0207482010-03-16 06:11:48 +0000832 Entity.setDiag(Diag);
833 return CheckAccess(*this, UseLoc, Entity);
834}
835
836
John McCall90c8c572010-03-18 08:19:33 +0000837/// Checks access to an overloaded operator new or delete.
838Sema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc,
839 SourceRange PlacementRange,
840 CXXRecordDecl *NamingClass,
John McCall9aa472c2010-03-19 07:35:19 +0000841 DeclAccessPair Found) {
John McCall90c8c572010-03-18 08:19:33 +0000842 if (!getLangOptions().AccessControl ||
843 !NamingClass ||
John McCall9aa472c2010-03-19 07:35:19 +0000844 Found.getAccess() == AS_public)
John McCall90c8c572010-03-18 08:19:33 +0000845 return AR_accessible;
846
John McCall9aa472c2010-03-19 07:35:19 +0000847 AccessedEntity Entity(AccessedEntity::Member, NamingClass, Found);
John McCall90c8c572010-03-18 08:19:33 +0000848 Entity.setDiag(diag::err_access)
849 << PlacementRange;
850
851 return CheckAccess(*this, OpLoc, Entity);
852}
853
John McCallb13b7372010-02-01 03:16:54 +0000854/// Checks access to an overloaded member operator, including
855/// conversion operators.
John McCall6b2accb2010-02-10 09:31:12 +0000856Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc,
857 Expr *ObjectExpr,
John McCall58e6f342010-03-16 05:22:47 +0000858 Expr *ArgExpr,
John McCall9aa472c2010-03-19 07:35:19 +0000859 DeclAccessPair Found) {
John McCall58e6f342010-03-16 05:22:47 +0000860 if (!getLangOptions().AccessControl ||
John McCall9aa472c2010-03-19 07:35:19 +0000861 Found.getAccess() == AS_public)
John McCall6b2accb2010-02-10 09:31:12 +0000862 return AR_accessible;
John McCall5357b612010-01-28 01:42:12 +0000863
864 const RecordType *RT = ObjectExpr->getType()->getAs<RecordType>();
865 assert(RT && "found member operator but object expr not of record type");
866 CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(RT->getDecl());
867
John McCall9aa472c2010-03-19 07:35:19 +0000868 AccessedEntity Entity(AccessedEntity::Member, NamingClass, Found);
John McCall58e6f342010-03-16 05:22:47 +0000869 Entity.setDiag(diag::err_access)
870 << ObjectExpr->getSourceRange()
871 << (ArgExpr ? ArgExpr->getSourceRange() : SourceRange());
872
873 return CheckAccess(*this, OpLoc, Entity);
John McCall6b2accb2010-02-10 09:31:12 +0000874}
John McCall5357b612010-01-28 01:42:12 +0000875
John McCall6b2accb2010-02-10 09:31:12 +0000876/// Checks access for a hierarchy conversion.
877///
878/// \param IsBaseToDerived whether this is a base-to-derived conversion (true)
879/// or a derived-to-base conversion (false)
880/// \param ForceCheck true if this check should be performed even if access
881/// control is disabled; some things rely on this for semantics
882/// \param ForceUnprivileged true if this check should proceed as if the
883/// context had no special privileges
884/// \param ADK controls the kind of diagnostics that are used
885Sema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc,
John McCall6b2accb2010-02-10 09:31:12 +0000886 QualType Base,
887 QualType Derived,
888 const CXXBasePath &Path,
John McCall58e6f342010-03-16 05:22:47 +0000889 unsigned DiagID,
John McCall6b2accb2010-02-10 09:31:12 +0000890 bool ForceCheck,
John McCall58e6f342010-03-16 05:22:47 +0000891 bool ForceUnprivileged) {
John McCall6b2accb2010-02-10 09:31:12 +0000892 if (!ForceCheck && !getLangOptions().AccessControl)
893 return AR_accessible;
John McCall5357b612010-01-28 01:42:12 +0000894
John McCall6b2accb2010-02-10 09:31:12 +0000895 if (Path.Access == AS_public)
896 return AR_accessible;
John McCall5357b612010-01-28 01:42:12 +0000897
John McCall6b2accb2010-02-10 09:31:12 +0000898 CXXRecordDecl *BaseD, *DerivedD;
899 BaseD = cast<CXXRecordDecl>(Base->getAs<RecordType>()->getDecl());
900 DerivedD = cast<CXXRecordDecl>(Derived->getAs<RecordType>()->getDecl());
John McCall58e6f342010-03-16 05:22:47 +0000901
902 AccessedEntity Entity(AccessedEntity::Base, BaseD, DerivedD, Path.Access);
903 if (DiagID)
904 Entity.setDiag(DiagID) << Derived << Base;
John McCall6b2accb2010-02-10 09:31:12 +0000905
906 if (ForceUnprivileged)
John McCall58e6f342010-03-16 05:22:47 +0000907 return CheckEffectiveAccess(*this, EffectiveContext(), AccessLoc, Entity);
908 return CheckAccess(*this, AccessLoc, Entity);
John McCall5357b612010-01-28 01:42:12 +0000909}
910
John McCall92f88312010-01-23 00:46:32 +0000911/// Checks access to all the declarations in the given result set.
John McCall6b2accb2010-02-10 09:31:12 +0000912void Sema::CheckLookupAccess(const LookupResult &R) {
913 assert(getLangOptions().AccessControl
914 && "performing access check without access control");
915 assert(R.getNamingClass() && "performing access check without naming class");
916
John McCall58e6f342010-03-16 05:22:47 +0000917 for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
918 if (I.getAccess() != AS_public) {
919 AccessedEntity Entity(AccessedEntity::Member,
John McCall9aa472c2010-03-19 07:35:19 +0000920 R.getNamingClass(),
921 I.getPair());
John McCall58e6f342010-03-16 05:22:47 +0000922 Entity.setDiag(diag::err_access);
923
924 CheckAccess(*this, R.getNameLoc(), Entity);
925 }
926 }
John McCall92f88312010-01-23 00:46:32 +0000927}