blob: 14a693f5b64138ec103eb12d36b504943d24bb98 [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"
Anders Carlsson9a68a672010-04-21 18:47:17 +000015#include "SemaInit.h"
John McCall92f88312010-01-23 00:46:32 +000016#include "Lookup.h"
Anders Carlssonc4f1e872009-03-27 06:03:27 +000017#include "clang/AST/ASTContext.h"
Douglas Gregora8f32e02009-10-06 17:59:45 +000018#include "clang/AST/CXXInheritance.h"
19#include "clang/AST/DeclCXX.h"
John McCalld60e22e2010-03-12 01:19:31 +000020#include "clang/AST/DeclFriend.h"
John McCall0c01d182010-03-24 05:22:00 +000021#include "clang/AST/DependentDiagnostic.h"
John McCallc373d482010-01-27 01:50:18 +000022#include "clang/AST/ExprCXX.h"
23
Anders Carlssonc60e8882009-03-27 04:54:36 +000024using namespace clang;
25
John McCall161755a2010-04-06 21:38:20 +000026/// A copy of Sema's enum without AR_delayed.
27enum AccessResult {
28 AR_accessible,
29 AR_inaccessible,
30 AR_dependent
31};
32
Anders Carlsson29f006b2009-03-27 05:05:05 +000033/// SetMemberAccessSpecifier - Set the access specifier of a member.
34/// Returns true on error (when the previous member decl access specifier
35/// is different from the new member decl access specifier).
Mike Stump1eb44332009-09-09 15:08:12 +000036bool Sema::SetMemberAccessSpecifier(NamedDecl *MemberDecl,
Anders Carlssonc60e8882009-03-27 04:54:36 +000037 NamedDecl *PrevMemberDecl,
38 AccessSpecifier LexicalAS) {
39 if (!PrevMemberDecl) {
40 // Use the lexical access specifier.
41 MemberDecl->setAccess(LexicalAS);
42 return false;
43 }
Mike Stump1eb44332009-09-09 15:08:12 +000044
Anders Carlssonc60e8882009-03-27 04:54:36 +000045 // C++ [class.access.spec]p3: When a member is redeclared its access
46 // specifier must be same as its initial declaration.
47 if (LexicalAS != AS_none && LexicalAS != PrevMemberDecl->getAccess()) {
Mike Stump1eb44332009-09-09 15:08:12 +000048 Diag(MemberDecl->getLocation(),
49 diag::err_class_redeclared_with_different_access)
Anders Carlssonc60e8882009-03-27 04:54:36 +000050 << MemberDecl << LexicalAS;
51 Diag(PrevMemberDecl->getLocation(), diag::note_previous_access_declaration)
52 << PrevMemberDecl << PrevMemberDecl->getAccess();
John McCall44e067b2009-12-23 00:37:40 +000053
54 MemberDecl->setAccess(LexicalAS);
Anders Carlssonc60e8882009-03-27 04:54:36 +000055 return true;
56 }
Mike Stump1eb44332009-09-09 15:08:12 +000057
Anders Carlssonc60e8882009-03-27 04:54:36 +000058 MemberDecl->setAccess(PrevMemberDecl->getAccess());
59 return false;
60}
Anders Carlsson29f006b2009-03-27 05:05:05 +000061
John McCall161755a2010-04-06 21:38:20 +000062static CXXRecordDecl *FindDeclaringClass(NamedDecl *D) {
63 DeclContext *DC = D->getDeclContext();
64
65 // This can only happen at top: enum decls only "publish" their
66 // immediate members.
67 if (isa<EnumDecl>(DC))
68 DC = cast<EnumDecl>(DC)->getDeclContext();
69
70 CXXRecordDecl *DeclaringClass = cast<CXXRecordDecl>(DC);
71 while (DeclaringClass->isAnonymousStructOrUnion())
72 DeclaringClass = cast<CXXRecordDecl>(DeclaringClass->getDeclContext());
73 return DeclaringClass;
74}
75
John McCall6b2accb2010-02-10 09:31:12 +000076namespace {
77struct EffectiveContext {
John McCall2cc26752010-03-27 06:55:49 +000078 EffectiveContext() : Inner(0), Dependent(false) {}
Anders Carlssonc4f1e872009-03-27 06:03:27 +000079
John McCall7ad650f2010-03-24 07:46:06 +000080 explicit EffectiveContext(DeclContext *DC)
81 : Inner(DC),
82 Dependent(DC->isDependentContext()) {
John McCall0c01d182010-03-24 05:22:00 +000083
John McCall88b6c712010-03-17 04:58:56 +000084 // C++ [class.access.nest]p1:
85 // A nested class is a member and as such has the same access
86 // rights as any other member.
87 // C++ [class.access]p2:
88 // A member of a class can also access all the names to which
John McCall2cc26752010-03-27 06:55:49 +000089 // the class has access. A local class of a member function
90 // may access the same names that the member function itself
91 // may access.
92 // This almost implies that the privileges of nesting are transitive.
93 // Technically it says nothing about the local classes of non-member
94 // functions (which can gain privileges through friendship), but we
95 // take that as an oversight.
96 while (true) {
97 if (isa<CXXRecordDecl>(DC)) {
98 CXXRecordDecl *Record = cast<CXXRecordDecl>(DC)->getCanonicalDecl();
99 Records.push_back(Record);
100 DC = Record->getDeclContext();
101 } else if (isa<FunctionDecl>(DC)) {
102 FunctionDecl *Function = cast<FunctionDecl>(DC)->getCanonicalDecl();
103 Functions.push_back(Function);
104 DC = Function->getDeclContext();
105 } else if (DC->isFileContext()) {
106 break;
107 } else {
108 DC = DC->getParent();
109 }
John McCall88b6c712010-03-17 04:58:56 +0000110 }
Anders Carlssonc4f1e872009-03-27 06:03:27 +0000111 }
Sebastian Redl726212f2009-07-18 14:32:15 +0000112
John McCall0c01d182010-03-24 05:22:00 +0000113 bool isDependent() const { return Dependent; }
114
John McCall88b6c712010-03-17 04:58:56 +0000115 bool includesClass(const CXXRecordDecl *R) const {
116 R = R->getCanonicalDecl();
117 return std::find(Records.begin(), Records.end(), R)
118 != Records.end();
John McCall6b2accb2010-02-10 09:31:12 +0000119 }
120
John McCall7ad650f2010-03-24 07:46:06 +0000121 /// Retrieves the innermost "useful" context. Can be null if we're
122 /// doing access-control without privileges.
123 DeclContext *getInnerContext() const {
124 return Inner;
John McCall0c01d182010-03-24 05:22:00 +0000125 }
126
127 typedef llvm::SmallVectorImpl<CXXRecordDecl*>::const_iterator record_iterator;
128
John McCall7ad650f2010-03-24 07:46:06 +0000129 DeclContext *Inner;
John McCall2cc26752010-03-27 06:55:49 +0000130 llvm::SmallVector<FunctionDecl*, 4> Functions;
John McCall88b6c712010-03-17 04:58:56 +0000131 llvm::SmallVector<CXXRecordDecl*, 4> Records;
John McCall0c01d182010-03-24 05:22:00 +0000132 bool Dependent;
John McCall6b2accb2010-02-10 09:31:12 +0000133};
John McCall161755a2010-04-06 21:38:20 +0000134
135/// Like Sema's AccessedEntity, but kindly lets us scribble all over
136/// it.
137struct AccessTarget : public Sema::AccessedEntity {
138 AccessTarget(const Sema::AccessedEntity &Entity)
139 : AccessedEntity(Entity) {
140 initialize();
141 }
142
143 AccessTarget(ASTContext &Context,
144 MemberNonce _,
145 CXXRecordDecl *NamingClass,
146 DeclAccessPair FoundDecl,
147 QualType BaseObjectType)
148 : AccessedEntity(Context, Member, NamingClass, FoundDecl, BaseObjectType) {
149 initialize();
150 }
151
152 AccessTarget(ASTContext &Context,
153 BaseNonce _,
154 CXXRecordDecl *BaseClass,
155 CXXRecordDecl *DerivedClass,
156 AccessSpecifier Access)
157 : AccessedEntity(Context, Base, BaseClass, DerivedClass, Access) {
158 initialize();
159 }
160
161 bool hasInstanceContext() const {
162 return HasInstanceContext;
163 }
164
165 class SavedInstanceContext {
166 public:
167 ~SavedInstanceContext() {
168 Target.HasInstanceContext = Has;
169 }
170
171 private:
John McCallc91cc662010-04-07 00:41:46 +0000172 friend struct AccessTarget;
John McCall161755a2010-04-06 21:38:20 +0000173 explicit SavedInstanceContext(AccessTarget &Target)
174 : Target(Target), Has(Target.HasInstanceContext) {}
175 AccessTarget &Target;
176 bool Has;
177 };
178
179 SavedInstanceContext saveInstanceContext() {
180 return SavedInstanceContext(*this);
181 }
182
183 void suppressInstanceContext() {
184 HasInstanceContext = false;
185 }
186
187 const CXXRecordDecl *resolveInstanceContext(Sema &S) const {
188 assert(HasInstanceContext);
189 if (CalculatedInstanceContext)
190 return InstanceContext;
191
192 CalculatedInstanceContext = true;
193 DeclContext *IC = S.computeDeclContext(getBaseObjectType());
194 InstanceContext = (IC ? cast<CXXRecordDecl>(IC)->getCanonicalDecl() : 0);
195 return InstanceContext;
196 }
197
198 const CXXRecordDecl *getDeclaringClass() const {
199 return DeclaringClass;
200 }
201
202private:
203 void initialize() {
204 HasInstanceContext = (isMemberAccess() &&
205 !getBaseObjectType().isNull() &&
206 getTargetDecl()->isCXXInstanceMember());
207 CalculatedInstanceContext = false;
208 InstanceContext = 0;
209
210 if (isMemberAccess())
211 DeclaringClass = FindDeclaringClass(getTargetDecl());
212 else
213 DeclaringClass = getBaseClass();
214 DeclaringClass = DeclaringClass->getCanonicalDecl();
215 }
216
217 bool HasInstanceContext : 1;
218 mutable bool CalculatedInstanceContext : 1;
219 mutable const CXXRecordDecl *InstanceContext;
220 const CXXRecordDecl *DeclaringClass;
221};
222
Anders Carlsson29f006b2009-03-27 05:05:05 +0000223}
John McCall92f88312010-01-23 00:46:32 +0000224
John McCall161755a2010-04-06 21:38:20 +0000225/// Checks whether one class is derived from another, inclusively.
226/// Properly indicates when it couldn't be determined due to
227/// dependence.
228///
229/// This should probably be donated to AST or at least Sema.
230static AccessResult IsDerivedFromInclusive(const CXXRecordDecl *Derived,
231 const CXXRecordDecl *Target) {
232 assert(Derived->getCanonicalDecl() == Derived);
233 assert(Target->getCanonicalDecl() == Target);
John McCallc1b621d2010-03-24 09:04:37 +0000234
John McCall161755a2010-04-06 21:38:20 +0000235 if (Derived == Target) return AR_accessible;
John McCallc1b621d2010-03-24 09:04:37 +0000236
John McCall161755a2010-04-06 21:38:20 +0000237 AccessResult OnFailure = AR_inaccessible;
238 llvm::SmallVector<const CXXRecordDecl*, 8> Queue; // actually a stack
239
240 while (true) {
241 for (CXXRecordDecl::base_class_const_iterator
242 I = Derived->bases_begin(), E = Derived->bases_end(); I != E; ++I) {
243
244 const CXXRecordDecl *RD;
245
246 QualType T = I->getType();
247 if (const RecordType *RT = T->getAs<RecordType>()) {
248 RD = cast<CXXRecordDecl>(RT->getDecl());
249 } else {
250 // It's possible for a base class to be the current
251 // instantiation of some enclosing template, but I'm guessing
252 // nobody will ever care that we just dependently delay here.
253 assert(T->isDependentType() && "non-dependent base wasn't a record?");
254 OnFailure = AR_dependent;
255 continue;
256 }
257
258 RD = RD->getCanonicalDecl();
259 if (RD == Target) return AR_accessible;
260 Queue.push_back(RD);
261 }
262
263 if (Queue.empty()) break;
264
265 Derived = Queue.back();
266 Queue.pop_back();
267 }
268
269 return OnFailure;
John McCall6b2accb2010-02-10 09:31:12 +0000270}
271
John McCall161755a2010-04-06 21:38:20 +0000272
John McCall0c01d182010-03-24 05:22:00 +0000273static bool MightInstantiateTo(Sema &S, DeclContext *Context,
274 DeclContext *Friend) {
275 if (Friend == Context)
276 return true;
277
278 assert(!Friend->isDependentContext() &&
279 "can't handle friends with dependent contexts here");
280
281 if (!Context->isDependentContext())
282 return false;
283
284 if (Friend->isFileContext())
285 return false;
286
287 // TODO: this is very conservative
288 return true;
289}
290
291// Asks whether the type in 'context' can ever instantiate to the type
292// in 'friend'.
293static bool MightInstantiateTo(Sema &S, CanQualType Context, CanQualType Friend) {
294 if (Friend == Context)
295 return true;
296
297 if (!Friend->isDependentType() && !Context->isDependentType())
298 return false;
299
300 // TODO: this is very conservative.
301 return true;
302}
303
304static bool MightInstantiateTo(Sema &S,
305 FunctionDecl *Context,
306 FunctionDecl *Friend) {
307 if (Context->getDeclName() != Friend->getDeclName())
308 return false;
309
310 if (!MightInstantiateTo(S,
311 Context->getDeclContext(),
312 Friend->getDeclContext()))
313 return false;
314
315 CanQual<FunctionProtoType> FriendTy
316 = S.Context.getCanonicalType(Friend->getType())
317 ->getAs<FunctionProtoType>();
318 CanQual<FunctionProtoType> ContextTy
319 = S.Context.getCanonicalType(Context->getType())
320 ->getAs<FunctionProtoType>();
321
322 // There isn't any way that I know of to add qualifiers
323 // during instantiation.
324 if (FriendTy.getQualifiers() != ContextTy.getQualifiers())
325 return false;
326
327 if (FriendTy->getNumArgs() != ContextTy->getNumArgs())
328 return false;
329
330 if (!MightInstantiateTo(S,
331 ContextTy->getResultType(),
332 FriendTy->getResultType()))
333 return false;
334
335 for (unsigned I = 0, E = FriendTy->getNumArgs(); I != E; ++I)
336 if (!MightInstantiateTo(S,
337 ContextTy->getArgType(I),
338 FriendTy->getArgType(I)))
339 return false;
340
341 return true;
342}
343
344static bool MightInstantiateTo(Sema &S,
345 FunctionTemplateDecl *Context,
346 FunctionTemplateDecl *Friend) {
347 return MightInstantiateTo(S,
348 Context->getTemplatedDecl(),
349 Friend->getTemplatedDecl());
350}
351
John McCall161755a2010-04-06 21:38:20 +0000352static AccessResult MatchesFriend(Sema &S,
353 const EffectiveContext &EC,
354 const CXXRecordDecl *Friend) {
John McCalla742db02010-03-17 20:01:29 +0000355 if (EC.includesClass(Friend))
John McCall161755a2010-04-06 21:38:20 +0000356 return AR_accessible;
John McCalla742db02010-03-17 20:01:29 +0000357
John McCall0c01d182010-03-24 05:22:00 +0000358 if (EC.isDependent()) {
359 CanQualType FriendTy
360 = S.Context.getCanonicalType(S.Context.getTypeDeclType(Friend));
361
362 for (EffectiveContext::record_iterator
363 I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
364 CanQualType ContextTy
365 = S.Context.getCanonicalType(S.Context.getTypeDeclType(*I));
366 if (MightInstantiateTo(S, ContextTy, FriendTy))
John McCall161755a2010-04-06 21:38:20 +0000367 return AR_dependent;
John McCall0c01d182010-03-24 05:22:00 +0000368 }
369 }
370
John McCall161755a2010-04-06 21:38:20 +0000371 return AR_inaccessible;
John McCalla742db02010-03-17 20:01:29 +0000372}
373
John McCall161755a2010-04-06 21:38:20 +0000374static AccessResult MatchesFriend(Sema &S,
375 const EffectiveContext &EC,
376 CanQualType Friend) {
John McCall0c01d182010-03-24 05:22:00 +0000377 if (const RecordType *RT = Friend->getAs<RecordType>())
378 return MatchesFriend(S, EC, cast<CXXRecordDecl>(RT->getDecl()));
John McCalla742db02010-03-17 20:01:29 +0000379
John McCall0c01d182010-03-24 05:22:00 +0000380 // TODO: we can do better than this
381 if (Friend->isDependentType())
John McCall161755a2010-04-06 21:38:20 +0000382 return AR_dependent;
John McCalla742db02010-03-17 20:01:29 +0000383
John McCall161755a2010-04-06 21:38:20 +0000384 return AR_inaccessible;
John McCall0c01d182010-03-24 05:22:00 +0000385}
386
387/// Determines whether the given friend class template matches
388/// anything in the effective context.
John McCall161755a2010-04-06 21:38:20 +0000389static AccessResult MatchesFriend(Sema &S,
390 const EffectiveContext &EC,
391 ClassTemplateDecl *Friend) {
392 AccessResult OnFailure = AR_inaccessible;
John McCall0c01d182010-03-24 05:22:00 +0000393
John McCall93ba8572010-03-25 06:39:04 +0000394 // Check whether the friend is the template of a class in the
395 // context chain.
John McCall0c01d182010-03-24 05:22:00 +0000396 for (llvm::SmallVectorImpl<CXXRecordDecl*>::const_iterator
397 I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
398 CXXRecordDecl *Record = *I;
399
John McCall93ba8572010-03-25 06:39:04 +0000400 // Figure out whether the current class has a template:
John McCall0c01d182010-03-24 05:22:00 +0000401 ClassTemplateDecl *CTD;
402
403 // A specialization of the template...
404 if (isa<ClassTemplateSpecializationDecl>(Record)) {
405 CTD = cast<ClassTemplateSpecializationDecl>(Record)
406 ->getSpecializedTemplate();
407
408 // ... or the template pattern itself.
409 } else {
410 CTD = Record->getDescribedClassTemplate();
411 if (!CTD) continue;
412 }
413
414 // It's a match.
415 if (Friend == CTD->getCanonicalDecl())
John McCall161755a2010-04-06 21:38:20 +0000416 return AR_accessible;
John McCall0c01d182010-03-24 05:22:00 +0000417
John McCall93ba8572010-03-25 06:39:04 +0000418 // If the context isn't dependent, it can't be a dependent match.
419 if (!EC.isDependent())
420 continue;
421
John McCall0c01d182010-03-24 05:22:00 +0000422 // If the template names don't match, it can't be a dependent
423 // match. This isn't true in C++0x because of template aliases.
424 if (!S.LangOpts.CPlusPlus0x && CTD->getDeclName() != Friend->getDeclName())
425 continue;
426
427 // If the class's context can't instantiate to the friend's
428 // context, it can't be a dependent match.
429 if (!MightInstantiateTo(S, CTD->getDeclContext(),
430 Friend->getDeclContext()))
431 continue;
432
433 // Otherwise, it's a dependent match.
John McCall161755a2010-04-06 21:38:20 +0000434 OnFailure = AR_dependent;
John McCalla742db02010-03-17 20:01:29 +0000435 }
436
John McCall0c01d182010-03-24 05:22:00 +0000437 return OnFailure;
438}
439
440/// Determines whether the given friend function matches anything in
441/// the effective context.
John McCall161755a2010-04-06 21:38:20 +0000442static AccessResult MatchesFriend(Sema &S,
443 const EffectiveContext &EC,
444 FunctionDecl *Friend) {
445 AccessResult OnFailure = AR_inaccessible;
John McCall0c01d182010-03-24 05:22:00 +0000446
John McCall2cc26752010-03-27 06:55:49 +0000447 for (llvm::SmallVectorImpl<FunctionDecl*>::const_iterator
448 I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) {
449 if (Friend == *I)
John McCall161755a2010-04-06 21:38:20 +0000450 return AR_accessible;
John McCall0c01d182010-03-24 05:22:00 +0000451
John McCall2cc26752010-03-27 06:55:49 +0000452 if (EC.isDependent() && MightInstantiateTo(S, *I, Friend))
John McCall161755a2010-04-06 21:38:20 +0000453 OnFailure = AR_dependent;
John McCall2cc26752010-03-27 06:55:49 +0000454 }
John McCall0c01d182010-03-24 05:22:00 +0000455
John McCall2cc26752010-03-27 06:55:49 +0000456 return OnFailure;
John McCall0c01d182010-03-24 05:22:00 +0000457}
458
459/// Determines whether the given friend function template matches
460/// anything in the effective context.
John McCall161755a2010-04-06 21:38:20 +0000461static AccessResult MatchesFriend(Sema &S,
462 const EffectiveContext &EC,
463 FunctionTemplateDecl *Friend) {
464 if (EC.Functions.empty()) return AR_inaccessible;
John McCall0c01d182010-03-24 05:22:00 +0000465
John McCall161755a2010-04-06 21:38:20 +0000466 AccessResult OnFailure = AR_inaccessible;
John McCall0c01d182010-03-24 05:22:00 +0000467
John McCall2cc26752010-03-27 06:55:49 +0000468 for (llvm::SmallVectorImpl<FunctionDecl*>::const_iterator
469 I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) {
John McCall0c01d182010-03-24 05:22:00 +0000470
John McCall2cc26752010-03-27 06:55:49 +0000471 FunctionTemplateDecl *FTD = (*I)->getPrimaryTemplate();
472 if (!FTD)
473 FTD = (*I)->getDescribedFunctionTemplate();
474 if (!FTD)
475 continue;
John McCall0c01d182010-03-24 05:22:00 +0000476
John McCall2cc26752010-03-27 06:55:49 +0000477 FTD = FTD->getCanonicalDecl();
478
479 if (Friend == FTD)
John McCall161755a2010-04-06 21:38:20 +0000480 return AR_accessible;
John McCall2cc26752010-03-27 06:55:49 +0000481
482 if (EC.isDependent() && MightInstantiateTo(S, FTD, Friend))
John McCall161755a2010-04-06 21:38:20 +0000483 OnFailure = AR_dependent;
John McCall2cc26752010-03-27 06:55:49 +0000484 }
485
486 return OnFailure;
John McCall0c01d182010-03-24 05:22:00 +0000487}
488
489/// Determines whether the given friend declaration matches anything
490/// in the effective context.
John McCall161755a2010-04-06 21:38:20 +0000491static AccessResult MatchesFriend(Sema &S,
492 const EffectiveContext &EC,
493 FriendDecl *FriendD) {
John McCall32f2fb52010-03-25 18:04:51 +0000494 if (TypeSourceInfo *T = FriendD->getFriendType())
495 return MatchesFriend(S, EC, T->getType()->getCanonicalTypeUnqualified());
John McCall0c01d182010-03-24 05:22:00 +0000496
497 NamedDecl *Friend
498 = cast<NamedDecl>(FriendD->getFriendDecl()->getCanonicalDecl());
John McCalla742db02010-03-17 20:01:29 +0000499
500 // FIXME: declarations with dependent or templated scope.
501
John McCall0c01d182010-03-24 05:22:00 +0000502 if (isa<ClassTemplateDecl>(Friend))
503 return MatchesFriend(S, EC, cast<ClassTemplateDecl>(Friend));
John McCalla742db02010-03-17 20:01:29 +0000504
John McCall0c01d182010-03-24 05:22:00 +0000505 if (isa<FunctionTemplateDecl>(Friend))
506 return MatchesFriend(S, EC, cast<FunctionTemplateDecl>(Friend));
John McCalla742db02010-03-17 20:01:29 +0000507
John McCall0c01d182010-03-24 05:22:00 +0000508 if (isa<CXXRecordDecl>(Friend))
509 return MatchesFriend(S, EC, cast<CXXRecordDecl>(Friend));
John McCalla742db02010-03-17 20:01:29 +0000510
John McCall0c01d182010-03-24 05:22:00 +0000511 assert(isa<FunctionDecl>(Friend) && "unknown friend decl kind");
512 return MatchesFriend(S, EC, cast<FunctionDecl>(Friend));
John McCalla742db02010-03-17 20:01:29 +0000513}
514
John McCall161755a2010-04-06 21:38:20 +0000515static AccessResult GetFriendKind(Sema &S,
516 const EffectiveContext &EC,
517 const CXXRecordDecl *Class) {
518 AccessResult OnFailure = AR_inaccessible;
John McCall88b6c712010-03-17 04:58:56 +0000519
John McCalld60e22e2010-03-12 01:19:31 +0000520 // Okay, check friends.
521 for (CXXRecordDecl::friend_iterator I = Class->friend_begin(),
522 E = Class->friend_end(); I != E; ++I) {
523 FriendDecl *Friend = *I;
524
John McCalla742db02010-03-17 20:01:29 +0000525 switch (MatchesFriend(S, EC, Friend)) {
John McCall161755a2010-04-06 21:38:20 +0000526 case AR_accessible:
527 return AR_accessible;
John McCalld60e22e2010-03-12 01:19:31 +0000528
John McCall161755a2010-04-06 21:38:20 +0000529 case AR_inaccessible:
530 continue;
531
532 case AR_dependent:
533 OnFailure = AR_dependent;
John McCalla742db02010-03-17 20:01:29 +0000534 break;
John McCalld60e22e2010-03-12 01:19:31 +0000535 }
John McCalld60e22e2010-03-12 01:19:31 +0000536 }
537
538 // That's it, give up.
John McCall88b6c712010-03-17 04:58:56 +0000539 return OnFailure;
John McCall6b2accb2010-02-10 09:31:12 +0000540}
541
John McCall161755a2010-04-06 21:38:20 +0000542static AccessResult HasAccess(Sema &S,
543 const EffectiveContext &EC,
544 const CXXRecordDecl *NamingClass,
545 AccessSpecifier Access,
546 const AccessTarget &Target) {
John McCalldb73c682010-04-02 00:03:43 +0000547 assert(NamingClass->getCanonicalDecl() == NamingClass &&
548 "declaration should be canonicalized before being passed here");
549
John McCall161755a2010-04-06 21:38:20 +0000550 if (Access == AS_public) return AR_accessible;
John McCalldb73c682010-04-02 00:03:43 +0000551 assert(Access == AS_private || Access == AS_protected);
552
John McCall161755a2010-04-06 21:38:20 +0000553 AccessResult OnFailure = AR_inaccessible;
554
John McCalldb73c682010-04-02 00:03:43 +0000555 for (EffectiveContext::record_iterator
556 I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
557 // All the declarations in EC have been canonicalized, so pointer
558 // equality from this point on will work fine.
559 const CXXRecordDecl *ECRecord = *I;
560
561 // [B2] and [M2]
John McCall161755a2010-04-06 21:38:20 +0000562 if (Access == AS_private) {
563 if (ECRecord == NamingClass)
564 return AR_accessible;
John McCalldb73c682010-04-02 00:03:43 +0000565
566 // [B3] and [M3]
John McCall161755a2010-04-06 21:38:20 +0000567 } else {
568 assert(Access == AS_protected);
569 switch (IsDerivedFromInclusive(ECRecord, NamingClass)) {
570 case AR_accessible: break;
571 case AR_inaccessible: continue;
572 case AR_dependent: OnFailure = AR_dependent; continue;
573 }
574
575 if (!Target.hasInstanceContext())
576 return AR_accessible;
577
578 const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S);
579 if (!InstanceContext) {
580 OnFailure = AR_dependent;
581 continue;
582 }
583
584 // C++ [class.protected]p1:
585 // An additional access check beyond those described earlier in
586 // [class.access] is applied when a non-static data member or
587 // non-static member function is a protected member of its naming
588 // class. As described earlier, access to a protected member is
589 // granted because the reference occurs in a friend or member of
590 // some class C. If the access is to form a pointer to member,
591 // the nested-name-specifier shall name C or a class derived from
592 // C. All other accesses involve a (possibly implicit) object
593 // expression. In this case, the class of the object expression
594 // shall be C or a class derived from C.
595 //
596 // We interpret this as a restriction on [M3]. Most of the
597 // conditions are encoded by not having any instance context.
598 switch (IsDerivedFromInclusive(InstanceContext, ECRecord)) {
599 case AR_accessible: return AR_accessible;
600 case AR_inaccessible: continue;
601 case AR_dependent: OnFailure = AR_dependent; continue;
602 }
603 }
John McCalldb73c682010-04-02 00:03:43 +0000604 }
605
John McCall161755a2010-04-06 21:38:20 +0000606 if (!NamingClass->hasFriends())
607 return OnFailure;
608
609 // Don't consider friends if we're under the [class.protected]
610 // restriction, above.
611 if (Access == AS_protected && Target.hasInstanceContext()) {
612 const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S);
613 if (!InstanceContext) return AR_dependent;
614
615 switch (IsDerivedFromInclusive(InstanceContext, NamingClass)) {
616 case AR_accessible: break;
617 case AR_inaccessible: return OnFailure;
618 case AR_dependent: return AR_dependent;
619 }
620 }
621
622 switch (GetFriendKind(S, EC, NamingClass)) {
623 case AR_accessible: return AR_accessible;
624 case AR_inaccessible: return OnFailure;
625 case AR_dependent: return AR_dependent;
626 }
627
628 // Silence bogus warnings
629 llvm_unreachable("impossible friendship kind");
630 return OnFailure;
John McCalldb73c682010-04-02 00:03:43 +0000631}
632
John McCall6b2accb2010-02-10 09:31:12 +0000633/// Finds the best path from the naming class to the declaring class,
634/// taking friend declarations into account.
635///
John McCalldb73c682010-04-02 00:03:43 +0000636/// C++0x [class.access.base]p5:
637/// A member m is accessible at the point R when named in class N if
638/// [M1] m as a member of N is public, or
639/// [M2] m as a member of N is private, and R occurs in a member or
640/// friend of class N, or
641/// [M3] m as a member of N is protected, and R occurs in a member or
642/// friend of class N, or in a member or friend of a class P
643/// derived from N, where m as a member of P is public, private,
644/// or protected, or
645/// [M4] there exists a base class B of N that is accessible at R, and
646/// m is accessible at R when named in class B.
647///
648/// C++0x [class.access.base]p4:
649/// A base class B of N is accessible at R, if
650/// [B1] an invented public member of B would be a public member of N, or
651/// [B2] R occurs in a member or friend of class N, and an invented public
652/// member of B would be a private or protected member of N, or
653/// [B3] R occurs in a member or friend of a class P derived from N, and an
654/// invented public member of B would be a private or protected member
655/// of P, or
656/// [B4] there exists a class S such that B is a base class of S accessible
657/// at R and S is a base class of N accessible at R.
658///
659/// Along a single inheritance path we can restate both of these
660/// iteratively:
661///
662/// First, we note that M1-4 are equivalent to B1-4 if the member is
663/// treated as a notional base of its declaring class with inheritance
664/// access equivalent to the member's access. Therefore we need only
665/// ask whether a class B is accessible from a class N in context R.
666///
667/// Let B_1 .. B_n be the inheritance path in question (i.e. where
668/// B_1 = N, B_n = B, and for all i, B_{i+1} is a direct base class of
669/// B_i). For i in 1..n, we will calculate ACAB(i), the access to the
670/// closest accessible base in the path:
671/// Access(a, b) = (* access on the base specifier from a to b *)
672/// Merge(a, forbidden) = forbidden
673/// Merge(a, private) = forbidden
674/// Merge(a, b) = min(a,b)
675/// Accessible(c, forbidden) = false
676/// Accessible(c, private) = (R is c) || IsFriend(c, R)
677/// Accessible(c, protected) = (R derived from c) || IsFriend(c, R)
678/// Accessible(c, public) = true
679/// ACAB(n) = public
680/// ACAB(i) =
681/// let AccessToBase = Merge(Access(B_i, B_{i+1}), ACAB(i+1)) in
682/// if Accessible(B_i, AccessToBase) then public else AccessToBase
683///
684/// B is an accessible base of N at R iff ACAB(1) = public.
685///
John McCall161755a2010-04-06 21:38:20 +0000686/// \param FinalAccess the access of the "final step", or AS_public if
John McCall7aceaf82010-03-18 23:49:19 +0000687/// there is no final step.
John McCall6b2accb2010-02-10 09:31:12 +0000688/// \return null if friendship is dependent
689static CXXBasePath *FindBestPath(Sema &S,
690 const EffectiveContext &EC,
John McCall161755a2010-04-06 21:38:20 +0000691 AccessTarget &Target,
John McCall7aceaf82010-03-18 23:49:19 +0000692 AccessSpecifier FinalAccess,
John McCall6b2accb2010-02-10 09:31:12 +0000693 CXXBasePaths &Paths) {
694 // Derive the paths to the desired base.
John McCall161755a2010-04-06 21:38:20 +0000695 const CXXRecordDecl *Derived = Target.getNamingClass();
696 const CXXRecordDecl *Base = Target.getDeclaringClass();
697
698 // FIXME: fail correctly when there are dependent paths.
699 bool isDerived = Derived->isDerivedFrom(const_cast<CXXRecordDecl*>(Base),
700 Paths);
John McCall6b2accb2010-02-10 09:31:12 +0000701 assert(isDerived && "derived class not actually derived from base");
702 (void) isDerived;
703
704 CXXBasePath *BestPath = 0;
705
John McCall7aceaf82010-03-18 23:49:19 +0000706 assert(FinalAccess != AS_none && "forbidden access after declaring class");
707
John McCall0c01d182010-03-24 05:22:00 +0000708 bool AnyDependent = false;
709
John McCall6b2accb2010-02-10 09:31:12 +0000710 // Derive the friend-modified access along each path.
711 for (CXXBasePaths::paths_iterator PI = Paths.begin(), PE = Paths.end();
712 PI != PE; ++PI) {
John McCall161755a2010-04-06 21:38:20 +0000713 AccessTarget::SavedInstanceContext _ = Target.saveInstanceContext();
John McCall6b2accb2010-02-10 09:31:12 +0000714
715 // Walk through the path backwards.
John McCall7aceaf82010-03-18 23:49:19 +0000716 AccessSpecifier PathAccess = FinalAccess;
John McCall6b2accb2010-02-10 09:31:12 +0000717 CXXBasePath::iterator I = PI->end(), E = PI->begin();
718 while (I != E) {
719 --I;
720
John McCall7aceaf82010-03-18 23:49:19 +0000721 assert(PathAccess != AS_none);
722
723 // If the declaration is a private member of a base class, there
724 // is no level of friendship in derived classes that can make it
725 // accessible.
726 if (PathAccess == AS_private) {
727 PathAccess = AS_none;
728 break;
729 }
730
John McCall161755a2010-04-06 21:38:20 +0000731 const CXXRecordDecl *NC = I->Class->getCanonicalDecl();
732
John McCall6b2accb2010-02-10 09:31:12 +0000733 AccessSpecifier BaseAccess = I->Base->getAccessSpecifier();
John McCalldb73c682010-04-02 00:03:43 +0000734 PathAccess = std::max(PathAccess, BaseAccess);
John McCall161755a2010-04-06 21:38:20 +0000735
736 switch (HasAccess(S, EC, NC, PathAccess, Target)) {
737 case AR_inaccessible: break;
738 case AR_accessible:
739 PathAccess = AS_public;
740
741 // Future tests are not against members and so do not have
742 // instance context.
743 Target.suppressInstanceContext();
744 break;
745 case AR_dependent:
John McCalldb73c682010-04-02 00:03:43 +0000746 AnyDependent = true;
747 goto Next;
John McCall6b2accb2010-02-10 09:31:12 +0000748 }
John McCall6b2accb2010-02-10 09:31:12 +0000749 }
750
751 // Note that we modify the path's Access field to the
752 // friend-modified access.
753 if (BestPath == 0 || PathAccess < BestPath->Access) {
754 BestPath = &*PI;
755 BestPath->Access = PathAccess;
John McCall0c01d182010-03-24 05:22:00 +0000756
757 // Short-circuit if we found a public path.
758 if (BestPath->Access == AS_public)
759 return BestPath;
John McCall6b2accb2010-02-10 09:31:12 +0000760 }
John McCall0c01d182010-03-24 05:22:00 +0000761
762 Next: ;
John McCall6b2accb2010-02-10 09:31:12 +0000763 }
764
John McCall0c01d182010-03-24 05:22:00 +0000765 assert((!BestPath || BestPath->Access != AS_public) &&
766 "fell out of loop with public path");
767
768 // We didn't find a public path, but at least one path was subject
769 // to dependent friendship, so delay the check.
770 if (AnyDependent)
771 return 0;
772
John McCall6b2accb2010-02-10 09:31:12 +0000773 return BestPath;
774}
775
776/// Diagnose the path which caused the given declaration or base class
777/// to become inaccessible.
778static void DiagnoseAccessPath(Sema &S,
779 const EffectiveContext &EC,
John McCall161755a2010-04-06 21:38:20 +0000780 AccessTarget &Entity) {
John McCalldb73c682010-04-02 00:03:43 +0000781 AccessSpecifier Access = Entity.getAccess();
John McCall161755a2010-04-06 21:38:20 +0000782 const CXXRecordDecl *NamingClass = Entity.getNamingClass();
John McCalldb73c682010-04-02 00:03:43 +0000783 NamingClass = NamingClass->getCanonicalDecl();
784
John McCall161755a2010-04-06 21:38:20 +0000785 NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : 0);
786 const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();
John McCalldb73c682010-04-02 00:03:43 +0000787
John McCall92f88312010-01-23 00:46:32 +0000788 // Easy case: the decl's natural access determined its path access.
John McCall6b2accb2010-02-10 09:31:12 +0000789 // We have to check against AS_private here in case Access is AS_none,
790 // indicating a non-public member of a private base class.
John McCall6b2accb2010-02-10 09:31:12 +0000791 if (D && (Access == D->getAccess() || D->getAccess() == AS_private)) {
John McCall161755a2010-04-06 21:38:20 +0000792 switch (HasAccess(S, EC, DeclaringClass, D->getAccess(), Entity)) {
793 case AR_inaccessible: {
John McCall6b2accb2010-02-10 09:31:12 +0000794 S.Diag(D->getLocation(), diag::note_access_natural)
795 << (unsigned) (Access == AS_protected)
796 << /*FIXME: not implicitly*/ 0;
797 return;
798 }
799
John McCall161755a2010-04-06 21:38:20 +0000800 case AR_accessible: break;
John McCall6b2accb2010-02-10 09:31:12 +0000801
John McCall161755a2010-04-06 21:38:20 +0000802 case AR_dependent:
803 llvm_unreachable("can't diagnose dependent access failures");
John McCall6b2accb2010-02-10 09:31:12 +0000804 return;
805 }
806 }
807
808 CXXBasePaths Paths;
John McCall161755a2010-04-06 21:38:20 +0000809 CXXBasePath &Path = *FindBestPath(S, EC, Entity, AS_public, Paths);
John McCall6b2accb2010-02-10 09:31:12 +0000810
811 CXXBasePath::iterator I = Path.end(), E = Path.begin();
812 while (I != E) {
813 --I;
814
815 const CXXBaseSpecifier *BS = I->Base;
816 AccessSpecifier BaseAccess = BS->getAccessSpecifier();
817
818 // If this is public inheritance, or the derived class is a friend,
819 // skip this step.
820 if (BaseAccess == AS_public)
821 continue;
822
823 switch (GetFriendKind(S, EC, I->Class)) {
John McCall161755a2010-04-06 21:38:20 +0000824 case AR_accessible: continue;
825 case AR_inaccessible: break;
826 case AR_dependent:
827 llvm_unreachable("can't diagnose dependent access failures");
John McCall6b2accb2010-02-10 09:31:12 +0000828 }
829
830 // Check whether this base specifier is the tighest point
831 // constraining access. We have to check against AS_private for
832 // the same reasons as above.
833 if (BaseAccess == AS_private || BaseAccess >= Access) {
834
835 // We're constrained by inheritance, but we want to say
836 // "declared private here" if we're diagnosing a hierarchy
837 // conversion and this is the final step.
838 unsigned diagnostic;
839 if (D) diagnostic = diag::note_access_constrained_by_path;
840 else if (I + 1 == Path.end()) diagnostic = diag::note_access_natural;
841 else diagnostic = diag::note_access_constrained_by_path;
842
843 S.Diag(BS->getSourceRange().getBegin(), diagnostic)
844 << BS->getSourceRange()
845 << (BaseAccess == AS_protected)
846 << (BS->getAccessSpecifierAsWritten() == AS_none);
847 return;
848 }
849 }
850
851 llvm_unreachable("access not apparently constrained by path");
852}
853
John McCall58e6f342010-03-16 05:22:47 +0000854static void DiagnoseBadAccess(Sema &S, SourceLocation Loc,
John McCall6b2accb2010-02-10 09:31:12 +0000855 const EffectiveContext &EC,
John McCall161755a2010-04-06 21:38:20 +0000856 AccessTarget &Entity) {
John McCalldb73c682010-04-02 00:03:43 +0000857 const CXXRecordDecl *NamingClass = Entity.getNamingClass();
John McCall161755a2010-04-06 21:38:20 +0000858 const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();
859 NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : 0);
John McCalldb73c682010-04-02 00:03:43 +0000860
861 S.Diag(Loc, Entity.getDiag())
862 << (Entity.getAccess() == AS_protected)
863 << (D ? D->getDeclName() : DeclarationName())
864 << S.Context.getTypeDeclType(NamingClass)
865 << S.Context.getTypeDeclType(DeclaringClass);
866 DiagnoseAccessPath(S, EC, Entity);
John McCall6b2accb2010-02-10 09:31:12 +0000867}
868
John McCalldb73c682010-04-02 00:03:43 +0000869/// Determines whether the accessed entity is accessible. Public members
870/// have been weeded out by this point.
John McCall161755a2010-04-06 21:38:20 +0000871static AccessResult IsAccessible(Sema &S,
872 const EffectiveContext &EC,
873 AccessTarget &Entity) {
John McCalldb73c682010-04-02 00:03:43 +0000874 // Determine the actual naming class.
875 CXXRecordDecl *NamingClass = Entity.getNamingClass();
876 while (NamingClass->isAnonymousStructOrUnion())
877 NamingClass = cast<CXXRecordDecl>(NamingClass->getParent());
878 NamingClass = NamingClass->getCanonicalDecl();
John McCall6b2accb2010-02-10 09:31:12 +0000879
John McCalldb73c682010-04-02 00:03:43 +0000880 AccessSpecifier UnprivilegedAccess = Entity.getAccess();
881 assert(UnprivilegedAccess != AS_public && "public access not weeded out");
882
883 // Before we try to recalculate access paths, try to white-list
884 // accesses which just trade in on the final step, i.e. accesses
885 // which don't require [M4] or [B4]. These are by far the most
John McCall161755a2010-04-06 21:38:20 +0000886 // common forms of privileged access.
John McCalldb73c682010-04-02 00:03:43 +0000887 if (UnprivilegedAccess != AS_none) {
John McCall161755a2010-04-06 21:38:20 +0000888 switch (HasAccess(S, EC, NamingClass, UnprivilegedAccess, Entity)) {
889 case AR_dependent:
John McCalldb73c682010-04-02 00:03:43 +0000890 // This is actually an interesting policy decision. We don't
891 // *have* to delay immediately here: we can do the full access
892 // calculation in the hope that friendship on some intermediate
893 // class will make the declaration accessible non-dependently.
894 // But that's not cheap, and odds are very good (note: assertion
895 // made without data) that the friend declaration will determine
896 // access.
John McCall161755a2010-04-06 21:38:20 +0000897 return AR_dependent;
John McCalldb73c682010-04-02 00:03:43 +0000898
John McCall161755a2010-04-06 21:38:20 +0000899 case AR_accessible: return AR_accessible;
900 case AR_inaccessible: break;
John McCalldb73c682010-04-02 00:03:43 +0000901 }
902 }
903
John McCall161755a2010-04-06 21:38:20 +0000904 AccessTarget::SavedInstanceContext _ = Entity.saveInstanceContext();
John McCall6b2accb2010-02-10 09:31:12 +0000905
John McCalldb73c682010-04-02 00:03:43 +0000906 // We lower member accesses to base accesses by pretending that the
907 // member is a base class of its declaring class.
908 AccessSpecifier FinalAccess;
909
John McCall6b2accb2010-02-10 09:31:12 +0000910 if (Entity.isMemberAccess()) {
John McCalldb73c682010-04-02 00:03:43 +0000911 // Determine if the declaration is accessible from EC when named
912 // in its declaring class.
John McCall6b2accb2010-02-10 09:31:12 +0000913 NamedDecl *Target = Entity.getTargetDecl();
John McCall161755a2010-04-06 21:38:20 +0000914 const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();
John McCall6b2accb2010-02-10 09:31:12 +0000915
John McCalldb73c682010-04-02 00:03:43 +0000916 FinalAccess = Target->getAccess();
John McCall161755a2010-04-06 21:38:20 +0000917 switch (HasAccess(S, EC, DeclaringClass, FinalAccess, Entity)) {
918 case AR_accessible:
919 FinalAccess = AS_public;
920 break;
921 case AR_inaccessible: break;
922 case AR_dependent: return AR_dependent; // see above
John McCall6b2accb2010-02-10 09:31:12 +0000923 }
924
John McCalldb73c682010-04-02 00:03:43 +0000925 if (DeclaringClass == NamingClass)
John McCall161755a2010-04-06 21:38:20 +0000926 return (FinalAccess == AS_public ? AR_accessible : AR_inaccessible);
927
928 Entity.suppressInstanceContext();
John McCalldb73c682010-04-02 00:03:43 +0000929 } else {
930 FinalAccess = AS_public;
John McCall6b2accb2010-02-10 09:31:12 +0000931 }
932
John McCall161755a2010-04-06 21:38:20 +0000933 assert(Entity.getDeclaringClass() != NamingClass);
John McCall6b2accb2010-02-10 09:31:12 +0000934
935 // Append the declaration's access if applicable.
936 CXXBasePaths Paths;
John McCall161755a2010-04-06 21:38:20 +0000937 CXXBasePath *Path = FindBestPath(S, EC, Entity, FinalAccess, Paths);
John McCall0c01d182010-03-24 05:22:00 +0000938 if (!Path)
John McCall161755a2010-04-06 21:38:20 +0000939 return AR_dependent;
John McCall92f88312010-01-23 00:46:32 +0000940
John McCalldb73c682010-04-02 00:03:43 +0000941 assert(Path->Access <= UnprivilegedAccess &&
942 "access along best path worse than direct?");
943 if (Path->Access == AS_public)
John McCall161755a2010-04-06 21:38:20 +0000944 return AR_accessible;
945 return AR_inaccessible;
John McCall0c01d182010-03-24 05:22:00 +0000946}
947
John McCall161755a2010-04-06 21:38:20 +0000948static void DelayDependentAccess(Sema &S,
949 const EffectiveContext &EC,
950 SourceLocation Loc,
951 const AccessTarget &Entity) {
John McCall0c01d182010-03-24 05:22:00 +0000952 assert(EC.isDependent() && "delaying non-dependent access");
John McCall7ad650f2010-03-24 07:46:06 +0000953 DeclContext *DC = EC.getInnerContext();
John McCall0c01d182010-03-24 05:22:00 +0000954 assert(DC->isDependentContext() && "delaying non-dependent access");
955 DependentDiagnostic::Create(S.Context, DC, DependentDiagnostic::Access,
956 Loc,
957 Entity.isMemberAccess(),
958 Entity.getAccess(),
959 Entity.getTargetDecl(),
960 Entity.getNamingClass(),
John McCall161755a2010-04-06 21:38:20 +0000961 Entity.getBaseObjectType(),
John McCall0c01d182010-03-24 05:22:00 +0000962 Entity.getDiag());
John McCall92f88312010-01-23 00:46:32 +0000963}
964
John McCall6b2accb2010-02-10 09:31:12 +0000965/// Checks access to an entity from the given effective context.
John McCall161755a2010-04-06 21:38:20 +0000966static AccessResult CheckEffectiveAccess(Sema &S,
967 const EffectiveContext &EC,
968 SourceLocation Loc,
969 AccessTarget &Entity) {
John McCalldb73c682010-04-02 00:03:43 +0000970 assert(Entity.getAccess() != AS_public && "called for public access!");
John McCall92f88312010-01-23 00:46:32 +0000971
John McCalldb73c682010-04-02 00:03:43 +0000972 switch (IsAccessible(S, EC, Entity)) {
John McCall161755a2010-04-06 21:38:20 +0000973 case AR_dependent:
974 DelayDependentAccess(S, EC, Loc, Entity);
975 return AR_dependent;
John McCalldb73c682010-04-02 00:03:43 +0000976
John McCall161755a2010-04-06 21:38:20 +0000977 case AR_inaccessible:
John McCalldb73c682010-04-02 00:03:43 +0000978 if (!Entity.isQuiet())
979 DiagnoseBadAccess(S, Loc, EC, Entity);
John McCall161755a2010-04-06 21:38:20 +0000980 return AR_inaccessible;
John McCalldb73c682010-04-02 00:03:43 +0000981
John McCall161755a2010-04-06 21:38:20 +0000982 case AR_accessible:
983 return AR_accessible;
John McCall0c01d182010-03-24 05:22:00 +0000984 }
985
John McCall161755a2010-04-06 21:38:20 +0000986 // silence unnecessary warning
987 llvm_unreachable("invalid access result");
988 return AR_accessible;
John McCall6b2accb2010-02-10 09:31:12 +0000989}
John McCall92f88312010-01-23 00:46:32 +0000990
John McCall6b2accb2010-02-10 09:31:12 +0000991static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc,
John McCall161755a2010-04-06 21:38:20 +0000992 AccessTarget &Entity) {
John McCall6b2accb2010-02-10 09:31:12 +0000993 // If the access path is public, it's accessible everywhere.
994 if (Entity.getAccess() == AS_public)
995 return Sema::AR_accessible;
John McCall92f88312010-01-23 00:46:32 +0000996
John McCall6b2accb2010-02-10 09:31:12 +0000997 // If we're currently parsing a top-level declaration, delay
998 // diagnostics. This is the only case where parsing a declaration
999 // can actually change our effective context for the purposes of
1000 // access control.
1001 if (S.CurContext->isFileContext() && S.ParsingDeclDepth) {
John McCall6b2accb2010-02-10 09:31:12 +00001002 S.DelayedDiagnostics.push_back(
1003 Sema::DelayedDiagnostic::makeAccess(Loc, Entity));
1004 return Sema::AR_delayed;
John McCall92f88312010-01-23 00:46:32 +00001005 }
1006
John McCall161755a2010-04-06 21:38:20 +00001007 EffectiveContext EC(S.CurContext);
1008 switch (CheckEffectiveAccess(S, EC, Loc, Entity)) {
1009 case AR_accessible: return Sema::AR_accessible;
1010 case AR_inaccessible: return Sema::AR_inaccessible;
1011 case AR_dependent: return Sema::AR_dependent;
1012 }
1013 llvm_unreachable("falling off end");
1014 return Sema::AR_accessible;
John McCall92f88312010-01-23 00:46:32 +00001015}
1016
John McCall2f514482010-01-27 03:50:35 +00001017void Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *Ctx) {
John McCall2f514482010-01-27 03:50:35 +00001018 // Pretend we did this from the context of the newly-parsed
Chandler Carruth630eb012010-04-18 08:23:21 +00001019 // declaration. If that declaration itself forms a declaration context,
1020 // include it in the effective context so that parameters and return types of
1021 // befriended functions have that function's access priveledges.
1022 DeclContext *DC = Ctx->getDeclContext();
1023 if (isa<FunctionDecl>(Ctx))
1024 DC = cast<DeclContext>(Ctx);
1025 else if (FunctionTemplateDecl *FnTpl = dyn_cast<FunctionTemplateDecl>(Ctx))
1026 DC = cast<DeclContext>(FnTpl->getTemplatedDecl());
1027 EffectiveContext EC(DC);
John McCall2f514482010-01-27 03:50:35 +00001028
John McCall161755a2010-04-06 21:38:20 +00001029 AccessTarget Target(DD.getAccessData());
1030
1031 if (CheckEffectiveAccess(*this, EC, DD.Loc, Target) == ::AR_inaccessible)
John McCall2f514482010-01-27 03:50:35 +00001032 DD.Triggered = true;
1033}
1034
John McCall0c01d182010-03-24 05:22:00 +00001035void Sema::HandleDependentAccessCheck(const DependentDiagnostic &DD,
1036 const MultiLevelTemplateArgumentList &TemplateArgs) {
1037 SourceLocation Loc = DD.getAccessLoc();
1038 AccessSpecifier Access = DD.getAccess();
1039
1040 Decl *NamingD = FindInstantiatedDecl(Loc, DD.getAccessNamingClass(),
1041 TemplateArgs);
1042 if (!NamingD) return;
1043 Decl *TargetD = FindInstantiatedDecl(Loc, DD.getAccessTarget(),
1044 TemplateArgs);
1045 if (!TargetD) return;
1046
1047 if (DD.isAccessToMember()) {
John McCall161755a2010-04-06 21:38:20 +00001048 CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(NamingD);
1049 NamedDecl *TargetDecl = cast<NamedDecl>(TargetD);
1050 QualType BaseObjectType = DD.getAccessBaseObjectType();
1051 if (!BaseObjectType.isNull()) {
1052 BaseObjectType = SubstType(BaseObjectType, TemplateArgs, Loc,
1053 DeclarationName());
1054 if (BaseObjectType.isNull()) return;
1055 }
1056
1057 AccessTarget Entity(Context,
1058 AccessTarget::Member,
1059 NamingClass,
1060 DeclAccessPair::make(TargetDecl, Access),
1061 BaseObjectType);
John McCall0c01d182010-03-24 05:22:00 +00001062 Entity.setDiag(DD.getDiagnostic());
1063 CheckAccess(*this, Loc, Entity);
1064 } else {
John McCall161755a2010-04-06 21:38:20 +00001065 AccessTarget Entity(Context,
1066 AccessTarget::Base,
1067 cast<CXXRecordDecl>(TargetD),
1068 cast<CXXRecordDecl>(NamingD),
1069 Access);
John McCall0c01d182010-03-24 05:22:00 +00001070 Entity.setDiag(DD.getDiagnostic());
1071 CheckAccess(*this, Loc, Entity);
1072 }
1073}
1074
John McCall6b2accb2010-02-10 09:31:12 +00001075Sema::AccessResult Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E,
John McCall9aa472c2010-03-19 07:35:19 +00001076 DeclAccessPair Found) {
John McCall58e6f342010-03-16 05:22:47 +00001077 if (!getLangOptions().AccessControl ||
1078 !E->getNamingClass() ||
John McCall9aa472c2010-03-19 07:35:19 +00001079 Found.getAccess() == AS_public)
John McCall6b2accb2010-02-10 09:31:12 +00001080 return AR_accessible;
John McCallc373d482010-01-27 01:50:18 +00001081
John McCall161755a2010-04-06 21:38:20 +00001082 AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(),
1083 Found, QualType());
John McCall58e6f342010-03-16 05:22:47 +00001084 Entity.setDiag(diag::err_access) << E->getSourceRange();
1085
1086 return CheckAccess(*this, E->getNameLoc(), Entity);
John McCallc373d482010-01-27 01:50:18 +00001087}
1088
1089/// Perform access-control checking on a previously-unresolved member
1090/// access which has now been resolved to a member.
John McCall6b2accb2010-02-10 09:31:12 +00001091Sema::AccessResult Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E,
John McCall9aa472c2010-03-19 07:35:19 +00001092 DeclAccessPair Found) {
John McCall58e6f342010-03-16 05:22:47 +00001093 if (!getLangOptions().AccessControl ||
John McCall9aa472c2010-03-19 07:35:19 +00001094 Found.getAccess() == AS_public)
John McCall6b2accb2010-02-10 09:31:12 +00001095 return AR_accessible;
John McCallc373d482010-01-27 01:50:18 +00001096
John McCall161755a2010-04-06 21:38:20 +00001097 QualType BaseType = E->getBaseType();
1098 if (E->isArrow())
1099 BaseType = BaseType->getAs<PointerType>()->getPointeeType();
1100
1101 AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(),
1102 Found, BaseType);
John McCall58e6f342010-03-16 05:22:47 +00001103 Entity.setDiag(diag::err_access) << E->getSourceRange();
1104
1105 return CheckAccess(*this, E->getMemberLoc(), Entity);
John McCallc373d482010-01-27 01:50:18 +00001106}
1107
John McCall6b2accb2010-02-10 09:31:12 +00001108Sema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc,
John McCall58e6f342010-03-16 05:22:47 +00001109 CXXDestructorDecl *Dtor,
1110 const PartialDiagnostic &PDiag) {
John McCall4f9506a2010-02-02 08:45:54 +00001111 if (!getLangOptions().AccessControl)
John McCall6b2accb2010-02-10 09:31:12 +00001112 return AR_accessible;
John McCall4f9506a2010-02-02 08:45:54 +00001113
John McCall58e6f342010-03-16 05:22:47 +00001114 // There's never a path involved when checking implicit destructor access.
John McCall4f9506a2010-02-02 08:45:54 +00001115 AccessSpecifier Access = Dtor->getAccess();
1116 if (Access == AS_public)
John McCall6b2accb2010-02-10 09:31:12 +00001117 return AR_accessible;
John McCall4f9506a2010-02-02 08:45:54 +00001118
John McCall58e6f342010-03-16 05:22:47 +00001119 CXXRecordDecl *NamingClass = Dtor->getParent();
John McCall161755a2010-04-06 21:38:20 +00001120 AccessTarget Entity(Context, AccessTarget::Member, NamingClass,
1121 DeclAccessPair::make(Dtor, Access),
1122 QualType());
John McCall58e6f342010-03-16 05:22:47 +00001123 Entity.setDiag(PDiag); // TODO: avoid copy
1124
1125 return CheckAccess(*this, Loc, Entity);
John McCall4f9506a2010-02-02 08:45:54 +00001126}
1127
John McCallb13b7372010-02-01 03:16:54 +00001128/// Checks access to a constructor.
John McCall6b2accb2010-02-10 09:31:12 +00001129Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc,
John McCallb13b7372010-02-01 03:16:54 +00001130 CXXConstructorDecl *Constructor,
Anders Carlsson9a68a672010-04-21 18:47:17 +00001131 const InitializedEntity &Entity,
John McCallb13b7372010-02-01 03:16:54 +00001132 AccessSpecifier Access) {
John McCall58e6f342010-03-16 05:22:47 +00001133 if (!getLangOptions().AccessControl ||
1134 Access == AS_public)
John McCall6b2accb2010-02-10 09:31:12 +00001135 return AR_accessible;
John McCallb13b7372010-02-01 03:16:54 +00001136
John McCall6b2accb2010-02-10 09:31:12 +00001137 CXXRecordDecl *NamingClass = Constructor->getParent();
Anders Carlsson9a68a672010-04-21 18:47:17 +00001138 AccessTarget AccessEntity(Context, AccessTarget::Member, NamingClass,
1139 DeclAccessPair::make(Constructor, Access),
1140 QualType());
1141 switch (Entity.getKind()) {
1142 default:
1143 AccessEntity.setDiag(diag::err_access_ctor);
1144 break;
John McCall58e6f342010-03-16 05:22:47 +00001145
Anders Carlsson3b8c53b2010-04-22 05:40:53 +00001146 case InitializedEntity::EK_Base:
1147 AccessEntity.setDiag(PDiag(diag::err_access_base)
1148 << Entity.isInheritedVirtualBase()
1149 << Entity.getBaseSpecifier()->getType()
1150 << getSpecialMember(Constructor));
Anders Carlsson9a68a672010-04-21 18:47:17 +00001151 break;
Anders Carlsson3b8c53b2010-04-22 05:40:53 +00001152
Anders Carlssonb99c6662010-04-21 20:28:29 +00001153 case InitializedEntity::EK_Member: {
1154 const FieldDecl *Field = cast<FieldDecl>(Entity.getDecl());
1155 AccessEntity.setDiag(PDiag(diag::err_access_ctor_field)
1156 << Field->getDeclName() << Field->getType());
1157 break;
1158 }
Anders Carlsson9a68a672010-04-21 18:47:17 +00001159
Anders Carlsson711f34a2010-04-21 19:52:01 +00001160 }
1161
Anders Carlsson9a68a672010-04-21 18:47:17 +00001162 return CheckAccess(*this, UseLoc, AccessEntity);
John McCallb13b7372010-02-01 03:16:54 +00001163}
1164
John McCallb0207482010-03-16 06:11:48 +00001165/// Checks direct (i.e. non-inherited) access to an arbitrary class
1166/// member.
1167Sema::AccessResult Sema::CheckDirectMemberAccess(SourceLocation UseLoc,
1168 NamedDecl *Target,
1169 const PartialDiagnostic &Diag) {
1170 AccessSpecifier Access = Target->getAccess();
1171 if (!getLangOptions().AccessControl ||
1172 Access == AS_public)
1173 return AR_accessible;
1174
1175 CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(Target->getDeclContext());
John McCall161755a2010-04-06 21:38:20 +00001176 AccessTarget Entity(Context, AccessTarget::Member, NamingClass,
1177 DeclAccessPair::make(Target, Access),
1178 QualType());
John McCallb0207482010-03-16 06:11:48 +00001179 Entity.setDiag(Diag);
1180 return CheckAccess(*this, UseLoc, Entity);
1181}
1182
1183
John McCall90c8c572010-03-18 08:19:33 +00001184/// Checks access to an overloaded operator new or delete.
1185Sema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc,
1186 SourceRange PlacementRange,
1187 CXXRecordDecl *NamingClass,
John McCall9aa472c2010-03-19 07:35:19 +00001188 DeclAccessPair Found) {
John McCall90c8c572010-03-18 08:19:33 +00001189 if (!getLangOptions().AccessControl ||
1190 !NamingClass ||
John McCall9aa472c2010-03-19 07:35:19 +00001191 Found.getAccess() == AS_public)
John McCall90c8c572010-03-18 08:19:33 +00001192 return AR_accessible;
1193
John McCall161755a2010-04-06 21:38:20 +00001194 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
1195 QualType());
John McCall90c8c572010-03-18 08:19:33 +00001196 Entity.setDiag(diag::err_access)
1197 << PlacementRange;
1198
1199 return CheckAccess(*this, OpLoc, Entity);
1200}
1201
John McCallb13b7372010-02-01 03:16:54 +00001202/// Checks access to an overloaded member operator, including
1203/// conversion operators.
John McCall6b2accb2010-02-10 09:31:12 +00001204Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc,
1205 Expr *ObjectExpr,
John McCall58e6f342010-03-16 05:22:47 +00001206 Expr *ArgExpr,
John McCall9aa472c2010-03-19 07:35:19 +00001207 DeclAccessPair Found) {
John McCall58e6f342010-03-16 05:22:47 +00001208 if (!getLangOptions().AccessControl ||
John McCall9aa472c2010-03-19 07:35:19 +00001209 Found.getAccess() == AS_public)
John McCall6b2accb2010-02-10 09:31:12 +00001210 return AR_accessible;
John McCall5357b612010-01-28 01:42:12 +00001211
1212 const RecordType *RT = ObjectExpr->getType()->getAs<RecordType>();
1213 assert(RT && "found member operator but object expr not of record type");
1214 CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(RT->getDecl());
1215
John McCall161755a2010-04-06 21:38:20 +00001216 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
1217 ObjectExpr->getType());
John McCall58e6f342010-03-16 05:22:47 +00001218 Entity.setDiag(diag::err_access)
1219 << ObjectExpr->getSourceRange()
1220 << (ArgExpr ? ArgExpr->getSourceRange() : SourceRange());
1221
1222 return CheckAccess(*this, OpLoc, Entity);
John McCall6b2accb2010-02-10 09:31:12 +00001223}
John McCall5357b612010-01-28 01:42:12 +00001224
John McCall6bb80172010-03-30 21:47:33 +00001225Sema::AccessResult Sema::CheckAddressOfMemberAccess(Expr *OvlExpr,
1226 DeclAccessPair Found) {
1227 if (!getLangOptions().AccessControl ||
John McCalle2f5ba92010-03-30 22:20:00 +00001228 Found.getAccess() == AS_none ||
John McCall6bb80172010-03-30 21:47:33 +00001229 Found.getAccess() == AS_public)
1230 return AR_accessible;
1231
1232 OverloadExpr *Ovl = OverloadExpr::find(OvlExpr).getPointer();
John McCalle9ee23e2010-04-22 18:44:12 +00001233 CXXRecordDecl *NamingClass = Ovl->getNamingClass();
John McCall6bb80172010-03-30 21:47:33 +00001234
John McCall161755a2010-04-06 21:38:20 +00001235 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
1236 Context.getTypeDeclType(NamingClass));
John McCall6bb80172010-03-30 21:47:33 +00001237 Entity.setDiag(diag::err_access)
1238 << Ovl->getSourceRange();
1239
1240 return CheckAccess(*this, Ovl->getNameLoc(), Entity);
1241}
1242
John McCall6b2accb2010-02-10 09:31:12 +00001243/// Checks access for a hierarchy conversion.
1244///
1245/// \param IsBaseToDerived whether this is a base-to-derived conversion (true)
1246/// or a derived-to-base conversion (false)
1247/// \param ForceCheck true if this check should be performed even if access
1248/// control is disabled; some things rely on this for semantics
1249/// \param ForceUnprivileged true if this check should proceed as if the
1250/// context had no special privileges
1251/// \param ADK controls the kind of diagnostics that are used
1252Sema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc,
John McCall6b2accb2010-02-10 09:31:12 +00001253 QualType Base,
1254 QualType Derived,
1255 const CXXBasePath &Path,
John McCall58e6f342010-03-16 05:22:47 +00001256 unsigned DiagID,
John McCall6b2accb2010-02-10 09:31:12 +00001257 bool ForceCheck,
John McCall58e6f342010-03-16 05:22:47 +00001258 bool ForceUnprivileged) {
John McCall6b2accb2010-02-10 09:31:12 +00001259 if (!ForceCheck && !getLangOptions().AccessControl)
1260 return AR_accessible;
John McCall5357b612010-01-28 01:42:12 +00001261
John McCall6b2accb2010-02-10 09:31:12 +00001262 if (Path.Access == AS_public)
1263 return AR_accessible;
John McCall5357b612010-01-28 01:42:12 +00001264
John McCall6b2accb2010-02-10 09:31:12 +00001265 CXXRecordDecl *BaseD, *DerivedD;
1266 BaseD = cast<CXXRecordDecl>(Base->getAs<RecordType>()->getDecl());
1267 DerivedD = cast<CXXRecordDecl>(Derived->getAs<RecordType>()->getDecl());
John McCall58e6f342010-03-16 05:22:47 +00001268
John McCall161755a2010-04-06 21:38:20 +00001269 AccessTarget Entity(Context, AccessTarget::Base, BaseD, DerivedD,
1270 Path.Access);
John McCall58e6f342010-03-16 05:22:47 +00001271 if (DiagID)
1272 Entity.setDiag(DiagID) << Derived << Base;
John McCall6b2accb2010-02-10 09:31:12 +00001273
John McCall161755a2010-04-06 21:38:20 +00001274 if (ForceUnprivileged) {
1275 switch (CheckEffectiveAccess(*this, EffectiveContext(),
1276 AccessLoc, Entity)) {
1277 case ::AR_accessible: return Sema::AR_accessible;
1278 case ::AR_inaccessible: return Sema::AR_inaccessible;
1279 case ::AR_dependent: return Sema::AR_dependent;
1280 }
1281 llvm_unreachable("unexpected result from CheckEffectiveAccess");
1282 }
John McCall58e6f342010-03-16 05:22:47 +00001283 return CheckAccess(*this, AccessLoc, Entity);
John McCall5357b612010-01-28 01:42:12 +00001284}
1285
John McCall92f88312010-01-23 00:46:32 +00001286/// Checks access to all the declarations in the given result set.
John McCall6b2accb2010-02-10 09:31:12 +00001287void Sema::CheckLookupAccess(const LookupResult &R) {
1288 assert(getLangOptions().AccessControl
1289 && "performing access check without access control");
1290 assert(R.getNamingClass() && "performing access check without naming class");
1291
John McCall58e6f342010-03-16 05:22:47 +00001292 for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
1293 if (I.getAccess() != AS_public) {
John McCall161755a2010-04-06 21:38:20 +00001294 AccessTarget Entity(Context, AccessedEntity::Member,
1295 R.getNamingClass(), I.getPair(),
1296 R.getBaseObjectType());
John McCall58e6f342010-03-16 05:22:47 +00001297 Entity.setDiag(diag::err_access);
1298
1299 CheckAccess(*this, R.getNameLoc(), Entity);
1300 }
1301 }
John McCall92f88312010-01-23 00:46:32 +00001302}