blob: 7845f6d0a94a8c254194dcd62a09c41d83293c34 [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 McCall01ebd9d2010-05-04 05:11:27 +0000225/// Checks whether one class might instantiate to the other.
226static bool MightInstantiateTo(const CXXRecordDecl *From,
227 const CXXRecordDecl *To) {
228 // Declaration names are always preserved by instantiation.
229 if (From->getDeclName() != To->getDeclName())
230 return false;
231
232 const DeclContext *FromDC = From->getDeclContext()->getPrimaryContext();
233 const DeclContext *ToDC = To->getDeclContext()->getPrimaryContext();
234 if (FromDC == ToDC) return true;
235 if (FromDC->isFileContext() || ToDC->isFileContext()) return false;
236
237 // Be conservative.
238 return true;
239}
240
John McCall161755a2010-04-06 21:38:20 +0000241/// Checks whether one class is derived from another, inclusively.
242/// Properly indicates when it couldn't be determined due to
243/// dependence.
244///
245/// This should probably be donated to AST or at least Sema.
246static AccessResult IsDerivedFromInclusive(const CXXRecordDecl *Derived,
247 const CXXRecordDecl *Target) {
248 assert(Derived->getCanonicalDecl() == Derived);
249 assert(Target->getCanonicalDecl() == Target);
John McCallc1b621d2010-03-24 09:04:37 +0000250
John McCall161755a2010-04-06 21:38:20 +0000251 if (Derived == Target) return AR_accessible;
John McCallc1b621d2010-03-24 09:04:37 +0000252
John McCall01ebd9d2010-05-04 05:11:27 +0000253 bool CheckDependent = Derived->isDependentContext();
254 if (CheckDependent && MightInstantiateTo(Derived, Target))
255 return AR_dependent;
256
John McCall161755a2010-04-06 21:38:20 +0000257 AccessResult OnFailure = AR_inaccessible;
258 llvm::SmallVector<const CXXRecordDecl*, 8> Queue; // actually a stack
259
260 while (true) {
261 for (CXXRecordDecl::base_class_const_iterator
262 I = Derived->bases_begin(), E = Derived->bases_end(); I != E; ++I) {
263
264 const CXXRecordDecl *RD;
265
266 QualType T = I->getType();
267 if (const RecordType *RT = T->getAs<RecordType>()) {
268 RD = cast<CXXRecordDecl>(RT->getDecl());
John McCall01ebd9d2010-05-04 05:11:27 +0000269 } else if (const InjectedClassNameType *IT
270 = T->getAs<InjectedClassNameType>()) {
271 RD = IT->getDecl();
John McCall161755a2010-04-06 21:38:20 +0000272 } else {
John McCall161755a2010-04-06 21:38:20 +0000273 assert(T->isDependentType() && "non-dependent base wasn't a record?");
274 OnFailure = AR_dependent;
275 continue;
276 }
277
278 RD = RD->getCanonicalDecl();
279 if (RD == Target) return AR_accessible;
John McCall01ebd9d2010-05-04 05:11:27 +0000280 if (CheckDependent && MightInstantiateTo(RD, Target))
281 OnFailure = AR_dependent;
282
John McCall161755a2010-04-06 21:38:20 +0000283 Queue.push_back(RD);
284 }
285
286 if (Queue.empty()) break;
287
288 Derived = Queue.back();
289 Queue.pop_back();
290 }
291
292 return OnFailure;
John McCall6b2accb2010-02-10 09:31:12 +0000293}
294
John McCall161755a2010-04-06 21:38:20 +0000295
John McCall0c01d182010-03-24 05:22:00 +0000296static bool MightInstantiateTo(Sema &S, DeclContext *Context,
297 DeclContext *Friend) {
298 if (Friend == Context)
299 return true;
300
301 assert(!Friend->isDependentContext() &&
302 "can't handle friends with dependent contexts here");
303
304 if (!Context->isDependentContext())
305 return false;
306
307 if (Friend->isFileContext())
308 return false;
309
310 // TODO: this is very conservative
311 return true;
312}
313
314// Asks whether the type in 'context' can ever instantiate to the type
315// in 'friend'.
316static bool MightInstantiateTo(Sema &S, CanQualType Context, CanQualType Friend) {
317 if (Friend == Context)
318 return true;
319
320 if (!Friend->isDependentType() && !Context->isDependentType())
321 return false;
322
323 // TODO: this is very conservative.
324 return true;
325}
326
327static bool MightInstantiateTo(Sema &S,
328 FunctionDecl *Context,
329 FunctionDecl *Friend) {
330 if (Context->getDeclName() != Friend->getDeclName())
331 return false;
332
333 if (!MightInstantiateTo(S,
334 Context->getDeclContext(),
335 Friend->getDeclContext()))
336 return false;
337
338 CanQual<FunctionProtoType> FriendTy
339 = S.Context.getCanonicalType(Friend->getType())
340 ->getAs<FunctionProtoType>();
341 CanQual<FunctionProtoType> ContextTy
342 = S.Context.getCanonicalType(Context->getType())
343 ->getAs<FunctionProtoType>();
344
345 // There isn't any way that I know of to add qualifiers
346 // during instantiation.
347 if (FriendTy.getQualifiers() != ContextTy.getQualifiers())
348 return false;
349
350 if (FriendTy->getNumArgs() != ContextTy->getNumArgs())
351 return false;
352
353 if (!MightInstantiateTo(S,
354 ContextTy->getResultType(),
355 FriendTy->getResultType()))
356 return false;
357
358 for (unsigned I = 0, E = FriendTy->getNumArgs(); I != E; ++I)
359 if (!MightInstantiateTo(S,
360 ContextTy->getArgType(I),
361 FriendTy->getArgType(I)))
362 return false;
363
364 return true;
365}
366
367static bool MightInstantiateTo(Sema &S,
368 FunctionTemplateDecl *Context,
369 FunctionTemplateDecl *Friend) {
370 return MightInstantiateTo(S,
371 Context->getTemplatedDecl(),
372 Friend->getTemplatedDecl());
373}
374
John McCall161755a2010-04-06 21:38:20 +0000375static AccessResult MatchesFriend(Sema &S,
376 const EffectiveContext &EC,
377 const CXXRecordDecl *Friend) {
John McCalla742db02010-03-17 20:01:29 +0000378 if (EC.includesClass(Friend))
John McCall161755a2010-04-06 21:38:20 +0000379 return AR_accessible;
John McCalla742db02010-03-17 20:01:29 +0000380
John McCall0c01d182010-03-24 05:22:00 +0000381 if (EC.isDependent()) {
382 CanQualType FriendTy
383 = S.Context.getCanonicalType(S.Context.getTypeDeclType(Friend));
384
385 for (EffectiveContext::record_iterator
386 I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
387 CanQualType ContextTy
388 = S.Context.getCanonicalType(S.Context.getTypeDeclType(*I));
389 if (MightInstantiateTo(S, ContextTy, FriendTy))
John McCall161755a2010-04-06 21:38:20 +0000390 return AR_dependent;
John McCall0c01d182010-03-24 05:22:00 +0000391 }
392 }
393
John McCall161755a2010-04-06 21:38:20 +0000394 return AR_inaccessible;
John McCalla742db02010-03-17 20:01:29 +0000395}
396
John McCall161755a2010-04-06 21:38:20 +0000397static AccessResult MatchesFriend(Sema &S,
398 const EffectiveContext &EC,
399 CanQualType Friend) {
John McCall0c01d182010-03-24 05:22:00 +0000400 if (const RecordType *RT = Friend->getAs<RecordType>())
401 return MatchesFriend(S, EC, cast<CXXRecordDecl>(RT->getDecl()));
John McCalla742db02010-03-17 20:01:29 +0000402
John McCall0c01d182010-03-24 05:22:00 +0000403 // TODO: we can do better than this
404 if (Friend->isDependentType())
John McCall161755a2010-04-06 21:38:20 +0000405 return AR_dependent;
John McCalla742db02010-03-17 20:01:29 +0000406
John McCall161755a2010-04-06 21:38:20 +0000407 return AR_inaccessible;
John McCall0c01d182010-03-24 05:22:00 +0000408}
409
410/// Determines whether the given friend class template matches
411/// anything in the effective context.
John McCall161755a2010-04-06 21:38:20 +0000412static AccessResult MatchesFriend(Sema &S,
413 const EffectiveContext &EC,
414 ClassTemplateDecl *Friend) {
415 AccessResult OnFailure = AR_inaccessible;
John McCall0c01d182010-03-24 05:22:00 +0000416
John McCall93ba8572010-03-25 06:39:04 +0000417 // Check whether the friend is the template of a class in the
418 // context chain.
John McCall0c01d182010-03-24 05:22:00 +0000419 for (llvm::SmallVectorImpl<CXXRecordDecl*>::const_iterator
420 I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
421 CXXRecordDecl *Record = *I;
422
John McCall93ba8572010-03-25 06:39:04 +0000423 // Figure out whether the current class has a template:
John McCall0c01d182010-03-24 05:22:00 +0000424 ClassTemplateDecl *CTD;
425
426 // A specialization of the template...
427 if (isa<ClassTemplateSpecializationDecl>(Record)) {
428 CTD = cast<ClassTemplateSpecializationDecl>(Record)
429 ->getSpecializedTemplate();
430
431 // ... or the template pattern itself.
432 } else {
433 CTD = Record->getDescribedClassTemplate();
434 if (!CTD) continue;
435 }
436
437 // It's a match.
438 if (Friend == CTD->getCanonicalDecl())
John McCall161755a2010-04-06 21:38:20 +0000439 return AR_accessible;
John McCall0c01d182010-03-24 05:22:00 +0000440
John McCall93ba8572010-03-25 06:39:04 +0000441 // If the context isn't dependent, it can't be a dependent match.
442 if (!EC.isDependent())
443 continue;
444
John McCall0c01d182010-03-24 05:22:00 +0000445 // If the template names don't match, it can't be a dependent
446 // match. This isn't true in C++0x because of template aliases.
447 if (!S.LangOpts.CPlusPlus0x && CTD->getDeclName() != Friend->getDeclName())
448 continue;
449
450 // If the class's context can't instantiate to the friend's
451 // context, it can't be a dependent match.
452 if (!MightInstantiateTo(S, CTD->getDeclContext(),
453 Friend->getDeclContext()))
454 continue;
455
456 // Otherwise, it's a dependent match.
John McCall161755a2010-04-06 21:38:20 +0000457 OnFailure = AR_dependent;
John McCalla742db02010-03-17 20:01:29 +0000458 }
459
John McCall0c01d182010-03-24 05:22:00 +0000460 return OnFailure;
461}
462
463/// Determines whether the given friend function matches anything in
464/// the effective context.
John McCall161755a2010-04-06 21:38:20 +0000465static AccessResult MatchesFriend(Sema &S,
466 const EffectiveContext &EC,
467 FunctionDecl *Friend) {
468 AccessResult OnFailure = AR_inaccessible;
John McCall0c01d182010-03-24 05:22:00 +0000469
John McCall2cc26752010-03-27 06:55:49 +0000470 for (llvm::SmallVectorImpl<FunctionDecl*>::const_iterator
471 I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) {
472 if (Friend == *I)
John McCall161755a2010-04-06 21:38:20 +0000473 return AR_accessible;
John McCall0c01d182010-03-24 05:22:00 +0000474
John McCall2cc26752010-03-27 06:55:49 +0000475 if (EC.isDependent() && MightInstantiateTo(S, *I, Friend))
John McCall161755a2010-04-06 21:38:20 +0000476 OnFailure = AR_dependent;
John McCall2cc26752010-03-27 06:55:49 +0000477 }
John McCall0c01d182010-03-24 05:22:00 +0000478
John McCall2cc26752010-03-27 06:55:49 +0000479 return OnFailure;
John McCall0c01d182010-03-24 05:22:00 +0000480}
481
482/// Determines whether the given friend function template matches
483/// anything in the effective context.
John McCall161755a2010-04-06 21:38:20 +0000484static AccessResult MatchesFriend(Sema &S,
485 const EffectiveContext &EC,
486 FunctionTemplateDecl *Friend) {
487 if (EC.Functions.empty()) return AR_inaccessible;
John McCall0c01d182010-03-24 05:22:00 +0000488
John McCall161755a2010-04-06 21:38:20 +0000489 AccessResult OnFailure = AR_inaccessible;
John McCall0c01d182010-03-24 05:22:00 +0000490
John McCall2cc26752010-03-27 06:55:49 +0000491 for (llvm::SmallVectorImpl<FunctionDecl*>::const_iterator
492 I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) {
John McCall0c01d182010-03-24 05:22:00 +0000493
John McCall2cc26752010-03-27 06:55:49 +0000494 FunctionTemplateDecl *FTD = (*I)->getPrimaryTemplate();
495 if (!FTD)
496 FTD = (*I)->getDescribedFunctionTemplate();
497 if (!FTD)
498 continue;
John McCall0c01d182010-03-24 05:22:00 +0000499
John McCall2cc26752010-03-27 06:55:49 +0000500 FTD = FTD->getCanonicalDecl();
501
502 if (Friend == FTD)
John McCall161755a2010-04-06 21:38:20 +0000503 return AR_accessible;
John McCall2cc26752010-03-27 06:55:49 +0000504
505 if (EC.isDependent() && MightInstantiateTo(S, FTD, Friend))
John McCall161755a2010-04-06 21:38:20 +0000506 OnFailure = AR_dependent;
John McCall2cc26752010-03-27 06:55:49 +0000507 }
508
509 return OnFailure;
John McCall0c01d182010-03-24 05:22:00 +0000510}
511
512/// Determines whether the given friend declaration matches anything
513/// in the effective context.
John McCall161755a2010-04-06 21:38:20 +0000514static AccessResult MatchesFriend(Sema &S,
515 const EffectiveContext &EC,
516 FriendDecl *FriendD) {
John McCall32f2fb52010-03-25 18:04:51 +0000517 if (TypeSourceInfo *T = FriendD->getFriendType())
518 return MatchesFriend(S, EC, T->getType()->getCanonicalTypeUnqualified());
John McCall0c01d182010-03-24 05:22:00 +0000519
520 NamedDecl *Friend
521 = cast<NamedDecl>(FriendD->getFriendDecl()->getCanonicalDecl());
John McCalla742db02010-03-17 20:01:29 +0000522
523 // FIXME: declarations with dependent or templated scope.
524
John McCall0c01d182010-03-24 05:22:00 +0000525 if (isa<ClassTemplateDecl>(Friend))
526 return MatchesFriend(S, EC, cast<ClassTemplateDecl>(Friend));
John McCalla742db02010-03-17 20:01:29 +0000527
John McCall0c01d182010-03-24 05:22:00 +0000528 if (isa<FunctionTemplateDecl>(Friend))
529 return MatchesFriend(S, EC, cast<FunctionTemplateDecl>(Friend));
John McCalla742db02010-03-17 20:01:29 +0000530
John McCall0c01d182010-03-24 05:22:00 +0000531 if (isa<CXXRecordDecl>(Friend))
532 return MatchesFriend(S, EC, cast<CXXRecordDecl>(Friend));
John McCalla742db02010-03-17 20:01:29 +0000533
John McCall0c01d182010-03-24 05:22:00 +0000534 assert(isa<FunctionDecl>(Friend) && "unknown friend decl kind");
535 return MatchesFriend(S, EC, cast<FunctionDecl>(Friend));
John McCalla742db02010-03-17 20:01:29 +0000536}
537
John McCall161755a2010-04-06 21:38:20 +0000538static AccessResult GetFriendKind(Sema &S,
539 const EffectiveContext &EC,
540 const CXXRecordDecl *Class) {
541 AccessResult OnFailure = AR_inaccessible;
John McCall88b6c712010-03-17 04:58:56 +0000542
John McCalld60e22e2010-03-12 01:19:31 +0000543 // Okay, check friends.
544 for (CXXRecordDecl::friend_iterator I = Class->friend_begin(),
545 E = Class->friend_end(); I != E; ++I) {
546 FriendDecl *Friend = *I;
547
John McCalla742db02010-03-17 20:01:29 +0000548 switch (MatchesFriend(S, EC, Friend)) {
John McCall161755a2010-04-06 21:38:20 +0000549 case AR_accessible:
550 return AR_accessible;
John McCalld60e22e2010-03-12 01:19:31 +0000551
John McCall161755a2010-04-06 21:38:20 +0000552 case AR_inaccessible:
553 continue;
554
555 case AR_dependent:
556 OnFailure = AR_dependent;
John McCalla742db02010-03-17 20:01:29 +0000557 break;
John McCalld60e22e2010-03-12 01:19:31 +0000558 }
John McCalld60e22e2010-03-12 01:19:31 +0000559 }
560
561 // That's it, give up.
John McCall88b6c712010-03-17 04:58:56 +0000562 return OnFailure;
John McCall6b2accb2010-02-10 09:31:12 +0000563}
564
John McCall161755a2010-04-06 21:38:20 +0000565static AccessResult HasAccess(Sema &S,
566 const EffectiveContext &EC,
567 const CXXRecordDecl *NamingClass,
568 AccessSpecifier Access,
569 const AccessTarget &Target) {
John McCalldb73c682010-04-02 00:03:43 +0000570 assert(NamingClass->getCanonicalDecl() == NamingClass &&
571 "declaration should be canonicalized before being passed here");
572
John McCall161755a2010-04-06 21:38:20 +0000573 if (Access == AS_public) return AR_accessible;
John McCalldb73c682010-04-02 00:03:43 +0000574 assert(Access == AS_private || Access == AS_protected);
575
John McCall161755a2010-04-06 21:38:20 +0000576 AccessResult OnFailure = AR_inaccessible;
577
John McCalldb73c682010-04-02 00:03:43 +0000578 for (EffectiveContext::record_iterator
579 I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
580 // All the declarations in EC have been canonicalized, so pointer
581 // equality from this point on will work fine.
582 const CXXRecordDecl *ECRecord = *I;
583
584 // [B2] and [M2]
John McCall161755a2010-04-06 21:38:20 +0000585 if (Access == AS_private) {
586 if (ECRecord == NamingClass)
587 return AR_accessible;
John McCalldb73c682010-04-02 00:03:43 +0000588
John McCall01ebd9d2010-05-04 05:11:27 +0000589 if (EC.isDependent() && MightInstantiateTo(ECRecord, NamingClass))
590 OnFailure = AR_dependent;
591
John McCalldb73c682010-04-02 00:03:43 +0000592 // [B3] and [M3]
John McCall161755a2010-04-06 21:38:20 +0000593 } else {
594 assert(Access == AS_protected);
595 switch (IsDerivedFromInclusive(ECRecord, NamingClass)) {
596 case AR_accessible: break;
597 case AR_inaccessible: continue;
598 case AR_dependent: OnFailure = AR_dependent; continue;
599 }
600
601 if (!Target.hasInstanceContext())
602 return AR_accessible;
603
604 const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S);
605 if (!InstanceContext) {
606 OnFailure = AR_dependent;
607 continue;
608 }
609
610 // C++ [class.protected]p1:
611 // An additional access check beyond those described earlier in
612 // [class.access] is applied when a non-static data member or
613 // non-static member function is a protected member of its naming
614 // class. As described earlier, access to a protected member is
615 // granted because the reference occurs in a friend or member of
616 // some class C. If the access is to form a pointer to member,
617 // the nested-name-specifier shall name C or a class derived from
618 // C. All other accesses involve a (possibly implicit) object
619 // expression. In this case, the class of the object expression
620 // shall be C or a class derived from C.
621 //
622 // We interpret this as a restriction on [M3]. Most of the
623 // conditions are encoded by not having any instance context.
624 switch (IsDerivedFromInclusive(InstanceContext, ECRecord)) {
625 case AR_accessible: return AR_accessible;
626 case AR_inaccessible: continue;
627 case AR_dependent: OnFailure = AR_dependent; continue;
628 }
629 }
John McCalldb73c682010-04-02 00:03:43 +0000630 }
631
John McCall161755a2010-04-06 21:38:20 +0000632 if (!NamingClass->hasFriends())
633 return OnFailure;
634
635 // Don't consider friends if we're under the [class.protected]
636 // restriction, above.
637 if (Access == AS_protected && Target.hasInstanceContext()) {
638 const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S);
639 if (!InstanceContext) return AR_dependent;
640
641 switch (IsDerivedFromInclusive(InstanceContext, NamingClass)) {
642 case AR_accessible: break;
643 case AR_inaccessible: return OnFailure;
644 case AR_dependent: return AR_dependent;
645 }
646 }
647
648 switch (GetFriendKind(S, EC, NamingClass)) {
649 case AR_accessible: return AR_accessible;
650 case AR_inaccessible: return OnFailure;
651 case AR_dependent: return AR_dependent;
652 }
653
654 // Silence bogus warnings
655 llvm_unreachable("impossible friendship kind");
656 return OnFailure;
John McCalldb73c682010-04-02 00:03:43 +0000657}
658
John McCall6b2accb2010-02-10 09:31:12 +0000659/// Finds the best path from the naming class to the declaring class,
660/// taking friend declarations into account.
661///
John McCalldb73c682010-04-02 00:03:43 +0000662/// C++0x [class.access.base]p5:
663/// A member m is accessible at the point R when named in class N if
664/// [M1] m as a member of N is public, or
665/// [M2] m as a member of N is private, and R occurs in a member or
666/// friend of class N, or
667/// [M3] m as a member of N is protected, and R occurs in a member or
668/// friend of class N, or in a member or friend of a class P
669/// derived from N, where m as a member of P is public, private,
670/// or protected, or
671/// [M4] there exists a base class B of N that is accessible at R, and
672/// m is accessible at R when named in class B.
673///
674/// C++0x [class.access.base]p4:
675/// A base class B of N is accessible at R, if
676/// [B1] an invented public member of B would be a public member of N, or
677/// [B2] R occurs in a member or friend of class N, and an invented public
678/// member of B would be a private or protected member of N, or
679/// [B3] R occurs in a member or friend of a class P derived from N, and an
680/// invented public member of B would be a private or protected member
681/// of P, or
682/// [B4] there exists a class S such that B is a base class of S accessible
683/// at R and S is a base class of N accessible at R.
684///
685/// Along a single inheritance path we can restate both of these
686/// iteratively:
687///
688/// First, we note that M1-4 are equivalent to B1-4 if the member is
689/// treated as a notional base of its declaring class with inheritance
690/// access equivalent to the member's access. Therefore we need only
691/// ask whether a class B is accessible from a class N in context R.
692///
693/// Let B_1 .. B_n be the inheritance path in question (i.e. where
694/// B_1 = N, B_n = B, and for all i, B_{i+1} is a direct base class of
695/// B_i). For i in 1..n, we will calculate ACAB(i), the access to the
696/// closest accessible base in the path:
697/// Access(a, b) = (* access on the base specifier from a to b *)
698/// Merge(a, forbidden) = forbidden
699/// Merge(a, private) = forbidden
700/// Merge(a, b) = min(a,b)
701/// Accessible(c, forbidden) = false
702/// Accessible(c, private) = (R is c) || IsFriend(c, R)
703/// Accessible(c, protected) = (R derived from c) || IsFriend(c, R)
704/// Accessible(c, public) = true
705/// ACAB(n) = public
706/// ACAB(i) =
707/// let AccessToBase = Merge(Access(B_i, B_{i+1}), ACAB(i+1)) in
708/// if Accessible(B_i, AccessToBase) then public else AccessToBase
709///
710/// B is an accessible base of N at R iff ACAB(1) = public.
711///
John McCall161755a2010-04-06 21:38:20 +0000712/// \param FinalAccess the access of the "final step", or AS_public if
John McCall7aceaf82010-03-18 23:49:19 +0000713/// there is no final step.
John McCall6b2accb2010-02-10 09:31:12 +0000714/// \return null if friendship is dependent
715static CXXBasePath *FindBestPath(Sema &S,
716 const EffectiveContext &EC,
John McCall161755a2010-04-06 21:38:20 +0000717 AccessTarget &Target,
John McCall7aceaf82010-03-18 23:49:19 +0000718 AccessSpecifier FinalAccess,
John McCall6b2accb2010-02-10 09:31:12 +0000719 CXXBasePaths &Paths) {
720 // Derive the paths to the desired base.
John McCall161755a2010-04-06 21:38:20 +0000721 const CXXRecordDecl *Derived = Target.getNamingClass();
722 const CXXRecordDecl *Base = Target.getDeclaringClass();
723
724 // FIXME: fail correctly when there are dependent paths.
725 bool isDerived = Derived->isDerivedFrom(const_cast<CXXRecordDecl*>(Base),
726 Paths);
John McCall6b2accb2010-02-10 09:31:12 +0000727 assert(isDerived && "derived class not actually derived from base");
728 (void) isDerived;
729
730 CXXBasePath *BestPath = 0;
731
John McCall7aceaf82010-03-18 23:49:19 +0000732 assert(FinalAccess != AS_none && "forbidden access after declaring class");
733
John McCall0c01d182010-03-24 05:22:00 +0000734 bool AnyDependent = false;
735
John McCall6b2accb2010-02-10 09:31:12 +0000736 // Derive the friend-modified access along each path.
737 for (CXXBasePaths::paths_iterator PI = Paths.begin(), PE = Paths.end();
738 PI != PE; ++PI) {
John McCall161755a2010-04-06 21:38:20 +0000739 AccessTarget::SavedInstanceContext _ = Target.saveInstanceContext();
John McCall6b2accb2010-02-10 09:31:12 +0000740
741 // Walk through the path backwards.
John McCall7aceaf82010-03-18 23:49:19 +0000742 AccessSpecifier PathAccess = FinalAccess;
John McCall6b2accb2010-02-10 09:31:12 +0000743 CXXBasePath::iterator I = PI->end(), E = PI->begin();
744 while (I != E) {
745 --I;
746
John McCall7aceaf82010-03-18 23:49:19 +0000747 assert(PathAccess != AS_none);
748
749 // If the declaration is a private member of a base class, there
750 // is no level of friendship in derived classes that can make it
751 // accessible.
752 if (PathAccess == AS_private) {
753 PathAccess = AS_none;
754 break;
755 }
756
John McCall161755a2010-04-06 21:38:20 +0000757 const CXXRecordDecl *NC = I->Class->getCanonicalDecl();
758
John McCall6b2accb2010-02-10 09:31:12 +0000759 AccessSpecifier BaseAccess = I->Base->getAccessSpecifier();
John McCalldb73c682010-04-02 00:03:43 +0000760 PathAccess = std::max(PathAccess, BaseAccess);
John McCall161755a2010-04-06 21:38:20 +0000761
762 switch (HasAccess(S, EC, NC, PathAccess, Target)) {
763 case AR_inaccessible: break;
764 case AR_accessible:
765 PathAccess = AS_public;
766
767 // Future tests are not against members and so do not have
768 // instance context.
769 Target.suppressInstanceContext();
770 break;
771 case AR_dependent:
John McCalldb73c682010-04-02 00:03:43 +0000772 AnyDependent = true;
773 goto Next;
John McCall6b2accb2010-02-10 09:31:12 +0000774 }
John McCall6b2accb2010-02-10 09:31:12 +0000775 }
776
777 // Note that we modify the path's Access field to the
778 // friend-modified access.
779 if (BestPath == 0 || PathAccess < BestPath->Access) {
780 BestPath = &*PI;
781 BestPath->Access = PathAccess;
John McCall0c01d182010-03-24 05:22:00 +0000782
783 // Short-circuit if we found a public path.
784 if (BestPath->Access == AS_public)
785 return BestPath;
John McCall6b2accb2010-02-10 09:31:12 +0000786 }
John McCall0c01d182010-03-24 05:22:00 +0000787
788 Next: ;
John McCall6b2accb2010-02-10 09:31:12 +0000789 }
790
John McCall0c01d182010-03-24 05:22:00 +0000791 assert((!BestPath || BestPath->Access != AS_public) &&
792 "fell out of loop with public path");
793
794 // We didn't find a public path, but at least one path was subject
795 // to dependent friendship, so delay the check.
796 if (AnyDependent)
797 return 0;
798
John McCall6b2accb2010-02-10 09:31:12 +0000799 return BestPath;
800}
801
802/// Diagnose the path which caused the given declaration or base class
803/// to become inaccessible.
804static void DiagnoseAccessPath(Sema &S,
805 const EffectiveContext &EC,
John McCall161755a2010-04-06 21:38:20 +0000806 AccessTarget &Entity) {
John McCalldb73c682010-04-02 00:03:43 +0000807 AccessSpecifier Access = Entity.getAccess();
John McCall161755a2010-04-06 21:38:20 +0000808 const CXXRecordDecl *NamingClass = Entity.getNamingClass();
John McCalldb73c682010-04-02 00:03:43 +0000809 NamingClass = NamingClass->getCanonicalDecl();
810
John McCall161755a2010-04-06 21:38:20 +0000811 NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : 0);
812 const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();
John McCalldb73c682010-04-02 00:03:43 +0000813
John McCall92f88312010-01-23 00:46:32 +0000814 // Easy case: the decl's natural access determined its path access.
John McCall6b2accb2010-02-10 09:31:12 +0000815 // We have to check against AS_private here in case Access is AS_none,
816 // indicating a non-public member of a private base class.
John McCall6b2accb2010-02-10 09:31:12 +0000817 if (D && (Access == D->getAccess() || D->getAccess() == AS_private)) {
John McCall161755a2010-04-06 21:38:20 +0000818 switch (HasAccess(S, EC, DeclaringClass, D->getAccess(), Entity)) {
819 case AR_inaccessible: {
John McCall6b2accb2010-02-10 09:31:12 +0000820 S.Diag(D->getLocation(), diag::note_access_natural)
821 << (unsigned) (Access == AS_protected)
822 << /*FIXME: not implicitly*/ 0;
823 return;
824 }
825
John McCall161755a2010-04-06 21:38:20 +0000826 case AR_accessible: break;
John McCall6b2accb2010-02-10 09:31:12 +0000827
John McCall161755a2010-04-06 21:38:20 +0000828 case AR_dependent:
829 llvm_unreachable("can't diagnose dependent access failures");
John McCall6b2accb2010-02-10 09:31:12 +0000830 return;
831 }
832 }
833
834 CXXBasePaths Paths;
John McCall161755a2010-04-06 21:38:20 +0000835 CXXBasePath &Path = *FindBestPath(S, EC, Entity, AS_public, Paths);
John McCall6b2accb2010-02-10 09:31:12 +0000836
837 CXXBasePath::iterator I = Path.end(), E = Path.begin();
838 while (I != E) {
839 --I;
840
841 const CXXBaseSpecifier *BS = I->Base;
842 AccessSpecifier BaseAccess = BS->getAccessSpecifier();
843
844 // If this is public inheritance, or the derived class is a friend,
845 // skip this step.
846 if (BaseAccess == AS_public)
847 continue;
848
849 switch (GetFriendKind(S, EC, I->Class)) {
John McCall161755a2010-04-06 21:38:20 +0000850 case AR_accessible: continue;
851 case AR_inaccessible: break;
852 case AR_dependent:
853 llvm_unreachable("can't diagnose dependent access failures");
John McCall6b2accb2010-02-10 09:31:12 +0000854 }
855
856 // Check whether this base specifier is the tighest point
857 // constraining access. We have to check against AS_private for
858 // the same reasons as above.
859 if (BaseAccess == AS_private || BaseAccess >= Access) {
860
861 // We're constrained by inheritance, but we want to say
862 // "declared private here" if we're diagnosing a hierarchy
863 // conversion and this is the final step.
864 unsigned diagnostic;
865 if (D) diagnostic = diag::note_access_constrained_by_path;
866 else if (I + 1 == Path.end()) diagnostic = diag::note_access_natural;
867 else diagnostic = diag::note_access_constrained_by_path;
868
869 S.Diag(BS->getSourceRange().getBegin(), diagnostic)
870 << BS->getSourceRange()
871 << (BaseAccess == AS_protected)
872 << (BS->getAccessSpecifierAsWritten() == AS_none);
Douglas Gregor76ef6582010-05-28 04:34:55 +0000873
874 if (D)
875 S.Diag(D->getLocation(), diag::note_field_decl);
876
John McCall6b2accb2010-02-10 09:31:12 +0000877 return;
878 }
879 }
880
881 llvm_unreachable("access not apparently constrained by path");
882}
883
John McCall58e6f342010-03-16 05:22:47 +0000884static void DiagnoseBadAccess(Sema &S, SourceLocation Loc,
John McCall6b2accb2010-02-10 09:31:12 +0000885 const EffectiveContext &EC,
John McCall161755a2010-04-06 21:38:20 +0000886 AccessTarget &Entity) {
John McCalldb73c682010-04-02 00:03:43 +0000887 const CXXRecordDecl *NamingClass = Entity.getNamingClass();
John McCall161755a2010-04-06 21:38:20 +0000888 const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();
889 NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : 0);
John McCalldb73c682010-04-02 00:03:43 +0000890
891 S.Diag(Loc, Entity.getDiag())
892 << (Entity.getAccess() == AS_protected)
893 << (D ? D->getDeclName() : DeclarationName())
894 << S.Context.getTypeDeclType(NamingClass)
895 << S.Context.getTypeDeclType(DeclaringClass);
896 DiagnoseAccessPath(S, EC, Entity);
John McCall6b2accb2010-02-10 09:31:12 +0000897}
898
John McCalldb73c682010-04-02 00:03:43 +0000899/// Determines whether the accessed entity is accessible. Public members
900/// have been weeded out by this point.
John McCall161755a2010-04-06 21:38:20 +0000901static AccessResult IsAccessible(Sema &S,
902 const EffectiveContext &EC,
903 AccessTarget &Entity) {
John McCalldb73c682010-04-02 00:03:43 +0000904 // Determine the actual naming class.
905 CXXRecordDecl *NamingClass = Entity.getNamingClass();
906 while (NamingClass->isAnonymousStructOrUnion())
907 NamingClass = cast<CXXRecordDecl>(NamingClass->getParent());
908 NamingClass = NamingClass->getCanonicalDecl();
John McCall6b2accb2010-02-10 09:31:12 +0000909
John McCalldb73c682010-04-02 00:03:43 +0000910 AccessSpecifier UnprivilegedAccess = Entity.getAccess();
911 assert(UnprivilegedAccess != AS_public && "public access not weeded out");
912
913 // Before we try to recalculate access paths, try to white-list
914 // accesses which just trade in on the final step, i.e. accesses
915 // which don't require [M4] or [B4]. These are by far the most
John McCall161755a2010-04-06 21:38:20 +0000916 // common forms of privileged access.
John McCalldb73c682010-04-02 00:03:43 +0000917 if (UnprivilegedAccess != AS_none) {
John McCall161755a2010-04-06 21:38:20 +0000918 switch (HasAccess(S, EC, NamingClass, UnprivilegedAccess, Entity)) {
919 case AR_dependent:
John McCalldb73c682010-04-02 00:03:43 +0000920 // This is actually an interesting policy decision. We don't
921 // *have* to delay immediately here: we can do the full access
922 // calculation in the hope that friendship on some intermediate
923 // class will make the declaration accessible non-dependently.
924 // But that's not cheap, and odds are very good (note: assertion
925 // made without data) that the friend declaration will determine
926 // access.
John McCall161755a2010-04-06 21:38:20 +0000927 return AR_dependent;
John McCalldb73c682010-04-02 00:03:43 +0000928
John McCall161755a2010-04-06 21:38:20 +0000929 case AR_accessible: return AR_accessible;
930 case AR_inaccessible: break;
John McCalldb73c682010-04-02 00:03:43 +0000931 }
932 }
933
John McCall161755a2010-04-06 21:38:20 +0000934 AccessTarget::SavedInstanceContext _ = Entity.saveInstanceContext();
John McCall6b2accb2010-02-10 09:31:12 +0000935
John McCalldb73c682010-04-02 00:03:43 +0000936 // We lower member accesses to base accesses by pretending that the
937 // member is a base class of its declaring class.
938 AccessSpecifier FinalAccess;
939
John McCall6b2accb2010-02-10 09:31:12 +0000940 if (Entity.isMemberAccess()) {
John McCalldb73c682010-04-02 00:03:43 +0000941 // Determine if the declaration is accessible from EC when named
942 // in its declaring class.
John McCall6b2accb2010-02-10 09:31:12 +0000943 NamedDecl *Target = Entity.getTargetDecl();
John McCall161755a2010-04-06 21:38:20 +0000944 const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();
John McCall6b2accb2010-02-10 09:31:12 +0000945
John McCalldb73c682010-04-02 00:03:43 +0000946 FinalAccess = Target->getAccess();
John McCall161755a2010-04-06 21:38:20 +0000947 switch (HasAccess(S, EC, DeclaringClass, FinalAccess, Entity)) {
948 case AR_accessible:
949 FinalAccess = AS_public;
950 break;
951 case AR_inaccessible: break;
952 case AR_dependent: return AR_dependent; // see above
John McCall6b2accb2010-02-10 09:31:12 +0000953 }
954
John McCalldb73c682010-04-02 00:03:43 +0000955 if (DeclaringClass == NamingClass)
John McCall161755a2010-04-06 21:38:20 +0000956 return (FinalAccess == AS_public ? AR_accessible : AR_inaccessible);
957
958 Entity.suppressInstanceContext();
John McCalldb73c682010-04-02 00:03:43 +0000959 } else {
960 FinalAccess = AS_public;
John McCall6b2accb2010-02-10 09:31:12 +0000961 }
962
John McCall161755a2010-04-06 21:38:20 +0000963 assert(Entity.getDeclaringClass() != NamingClass);
John McCall6b2accb2010-02-10 09:31:12 +0000964
965 // Append the declaration's access if applicable.
966 CXXBasePaths Paths;
John McCall161755a2010-04-06 21:38:20 +0000967 CXXBasePath *Path = FindBestPath(S, EC, Entity, FinalAccess, Paths);
John McCall0c01d182010-03-24 05:22:00 +0000968 if (!Path)
John McCall161755a2010-04-06 21:38:20 +0000969 return AR_dependent;
John McCall92f88312010-01-23 00:46:32 +0000970
John McCalldb73c682010-04-02 00:03:43 +0000971 assert(Path->Access <= UnprivilegedAccess &&
972 "access along best path worse than direct?");
973 if (Path->Access == AS_public)
John McCall161755a2010-04-06 21:38:20 +0000974 return AR_accessible;
975 return AR_inaccessible;
John McCall0c01d182010-03-24 05:22:00 +0000976}
977
John McCall161755a2010-04-06 21:38:20 +0000978static void DelayDependentAccess(Sema &S,
979 const EffectiveContext &EC,
980 SourceLocation Loc,
981 const AccessTarget &Entity) {
John McCall0c01d182010-03-24 05:22:00 +0000982 assert(EC.isDependent() && "delaying non-dependent access");
John McCall7ad650f2010-03-24 07:46:06 +0000983 DeclContext *DC = EC.getInnerContext();
John McCall0c01d182010-03-24 05:22:00 +0000984 assert(DC->isDependentContext() && "delaying non-dependent access");
985 DependentDiagnostic::Create(S.Context, DC, DependentDiagnostic::Access,
986 Loc,
987 Entity.isMemberAccess(),
988 Entity.getAccess(),
989 Entity.getTargetDecl(),
990 Entity.getNamingClass(),
John McCall161755a2010-04-06 21:38:20 +0000991 Entity.getBaseObjectType(),
John McCall0c01d182010-03-24 05:22:00 +0000992 Entity.getDiag());
John McCall92f88312010-01-23 00:46:32 +0000993}
994
John McCall6b2accb2010-02-10 09:31:12 +0000995/// Checks access to an entity from the given effective context.
John McCall161755a2010-04-06 21:38:20 +0000996static AccessResult CheckEffectiveAccess(Sema &S,
997 const EffectiveContext &EC,
998 SourceLocation Loc,
999 AccessTarget &Entity) {
John McCalldb73c682010-04-02 00:03:43 +00001000 assert(Entity.getAccess() != AS_public && "called for public access!");
John McCall92f88312010-01-23 00:46:32 +00001001
John McCalldb73c682010-04-02 00:03:43 +00001002 switch (IsAccessible(S, EC, Entity)) {
John McCall161755a2010-04-06 21:38:20 +00001003 case AR_dependent:
1004 DelayDependentAccess(S, EC, Loc, Entity);
1005 return AR_dependent;
John McCalldb73c682010-04-02 00:03:43 +00001006
John McCall161755a2010-04-06 21:38:20 +00001007 case AR_inaccessible:
John McCalldb73c682010-04-02 00:03:43 +00001008 if (!Entity.isQuiet())
1009 DiagnoseBadAccess(S, Loc, EC, Entity);
John McCall161755a2010-04-06 21:38:20 +00001010 return AR_inaccessible;
John McCalldb73c682010-04-02 00:03:43 +00001011
John McCall161755a2010-04-06 21:38:20 +00001012 case AR_accessible:
1013 return AR_accessible;
John McCall0c01d182010-03-24 05:22:00 +00001014 }
1015
John McCall161755a2010-04-06 21:38:20 +00001016 // silence unnecessary warning
1017 llvm_unreachable("invalid access result");
1018 return AR_accessible;
John McCall6b2accb2010-02-10 09:31:12 +00001019}
John McCall92f88312010-01-23 00:46:32 +00001020
John McCall6b2accb2010-02-10 09:31:12 +00001021static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc,
John McCall161755a2010-04-06 21:38:20 +00001022 AccessTarget &Entity) {
John McCall6b2accb2010-02-10 09:31:12 +00001023 // If the access path is public, it's accessible everywhere.
1024 if (Entity.getAccess() == AS_public)
1025 return Sema::AR_accessible;
John McCall92f88312010-01-23 00:46:32 +00001026
John McCall6b2accb2010-02-10 09:31:12 +00001027 // If we're currently parsing a top-level declaration, delay
1028 // diagnostics. This is the only case where parsing a declaration
1029 // can actually change our effective context for the purposes of
1030 // access control.
1031 if (S.CurContext->isFileContext() && S.ParsingDeclDepth) {
John McCall6b2accb2010-02-10 09:31:12 +00001032 S.DelayedDiagnostics.push_back(
1033 Sema::DelayedDiagnostic::makeAccess(Loc, Entity));
1034 return Sema::AR_delayed;
John McCall92f88312010-01-23 00:46:32 +00001035 }
1036
John McCall161755a2010-04-06 21:38:20 +00001037 EffectiveContext EC(S.CurContext);
1038 switch (CheckEffectiveAccess(S, EC, Loc, Entity)) {
1039 case AR_accessible: return Sema::AR_accessible;
1040 case AR_inaccessible: return Sema::AR_inaccessible;
1041 case AR_dependent: return Sema::AR_dependent;
1042 }
1043 llvm_unreachable("falling off end");
1044 return Sema::AR_accessible;
John McCall92f88312010-01-23 00:46:32 +00001045}
1046
John McCall2f514482010-01-27 03:50:35 +00001047void Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *Ctx) {
John McCall2f514482010-01-27 03:50:35 +00001048 // Pretend we did this from the context of the newly-parsed
Chandler Carruth630eb012010-04-18 08:23:21 +00001049 // declaration. If that declaration itself forms a declaration context,
1050 // include it in the effective context so that parameters and return types of
1051 // befriended functions have that function's access priveledges.
1052 DeclContext *DC = Ctx->getDeclContext();
1053 if (isa<FunctionDecl>(Ctx))
1054 DC = cast<DeclContext>(Ctx);
1055 else if (FunctionTemplateDecl *FnTpl = dyn_cast<FunctionTemplateDecl>(Ctx))
1056 DC = cast<DeclContext>(FnTpl->getTemplatedDecl());
1057 EffectiveContext EC(DC);
John McCall2f514482010-01-27 03:50:35 +00001058
John McCall161755a2010-04-06 21:38:20 +00001059 AccessTarget Target(DD.getAccessData());
1060
1061 if (CheckEffectiveAccess(*this, EC, DD.Loc, Target) == ::AR_inaccessible)
John McCall2f514482010-01-27 03:50:35 +00001062 DD.Triggered = true;
1063}
1064
John McCall0c01d182010-03-24 05:22:00 +00001065void Sema::HandleDependentAccessCheck(const DependentDiagnostic &DD,
1066 const MultiLevelTemplateArgumentList &TemplateArgs) {
1067 SourceLocation Loc = DD.getAccessLoc();
1068 AccessSpecifier Access = DD.getAccess();
1069
1070 Decl *NamingD = FindInstantiatedDecl(Loc, DD.getAccessNamingClass(),
1071 TemplateArgs);
1072 if (!NamingD) return;
1073 Decl *TargetD = FindInstantiatedDecl(Loc, DD.getAccessTarget(),
1074 TemplateArgs);
1075 if (!TargetD) return;
1076
1077 if (DD.isAccessToMember()) {
John McCall161755a2010-04-06 21:38:20 +00001078 CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(NamingD);
1079 NamedDecl *TargetDecl = cast<NamedDecl>(TargetD);
1080 QualType BaseObjectType = DD.getAccessBaseObjectType();
1081 if (!BaseObjectType.isNull()) {
1082 BaseObjectType = SubstType(BaseObjectType, TemplateArgs, Loc,
1083 DeclarationName());
1084 if (BaseObjectType.isNull()) return;
1085 }
1086
1087 AccessTarget Entity(Context,
1088 AccessTarget::Member,
1089 NamingClass,
1090 DeclAccessPair::make(TargetDecl, Access),
1091 BaseObjectType);
John McCall0c01d182010-03-24 05:22:00 +00001092 Entity.setDiag(DD.getDiagnostic());
1093 CheckAccess(*this, Loc, Entity);
1094 } else {
John McCall161755a2010-04-06 21:38:20 +00001095 AccessTarget Entity(Context,
1096 AccessTarget::Base,
1097 cast<CXXRecordDecl>(TargetD),
1098 cast<CXXRecordDecl>(NamingD),
1099 Access);
John McCall0c01d182010-03-24 05:22:00 +00001100 Entity.setDiag(DD.getDiagnostic());
1101 CheckAccess(*this, Loc, Entity);
1102 }
1103}
1104
John McCall6b2accb2010-02-10 09:31:12 +00001105Sema::AccessResult Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E,
John McCall9aa472c2010-03-19 07:35:19 +00001106 DeclAccessPair Found) {
John McCall58e6f342010-03-16 05:22:47 +00001107 if (!getLangOptions().AccessControl ||
1108 !E->getNamingClass() ||
John McCall9aa472c2010-03-19 07:35:19 +00001109 Found.getAccess() == AS_public)
John McCall6b2accb2010-02-10 09:31:12 +00001110 return AR_accessible;
John McCallc373d482010-01-27 01:50:18 +00001111
John McCall161755a2010-04-06 21:38:20 +00001112 AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(),
1113 Found, QualType());
John McCall58e6f342010-03-16 05:22:47 +00001114 Entity.setDiag(diag::err_access) << E->getSourceRange();
1115
1116 return CheckAccess(*this, E->getNameLoc(), Entity);
John McCallc373d482010-01-27 01:50:18 +00001117}
1118
1119/// Perform access-control checking on a previously-unresolved member
1120/// access which has now been resolved to a member.
John McCall6b2accb2010-02-10 09:31:12 +00001121Sema::AccessResult Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E,
John McCall9aa472c2010-03-19 07:35:19 +00001122 DeclAccessPair Found) {
John McCall58e6f342010-03-16 05:22:47 +00001123 if (!getLangOptions().AccessControl ||
John McCall9aa472c2010-03-19 07:35:19 +00001124 Found.getAccess() == AS_public)
John McCall6b2accb2010-02-10 09:31:12 +00001125 return AR_accessible;
John McCallc373d482010-01-27 01:50:18 +00001126
John McCall161755a2010-04-06 21:38:20 +00001127 QualType BaseType = E->getBaseType();
1128 if (E->isArrow())
1129 BaseType = BaseType->getAs<PointerType>()->getPointeeType();
1130
1131 AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(),
1132 Found, BaseType);
John McCall58e6f342010-03-16 05:22:47 +00001133 Entity.setDiag(diag::err_access) << E->getSourceRange();
1134
1135 return CheckAccess(*this, E->getMemberLoc(), Entity);
John McCallc373d482010-01-27 01:50:18 +00001136}
1137
John McCall6b2accb2010-02-10 09:31:12 +00001138Sema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc,
John McCall58e6f342010-03-16 05:22:47 +00001139 CXXDestructorDecl *Dtor,
1140 const PartialDiagnostic &PDiag) {
John McCall4f9506a2010-02-02 08:45:54 +00001141 if (!getLangOptions().AccessControl)
John McCall6b2accb2010-02-10 09:31:12 +00001142 return AR_accessible;
John McCall4f9506a2010-02-02 08:45:54 +00001143
John McCall58e6f342010-03-16 05:22:47 +00001144 // There's never a path involved when checking implicit destructor access.
John McCall4f9506a2010-02-02 08:45:54 +00001145 AccessSpecifier Access = Dtor->getAccess();
1146 if (Access == AS_public)
John McCall6b2accb2010-02-10 09:31:12 +00001147 return AR_accessible;
John McCall4f9506a2010-02-02 08:45:54 +00001148
John McCall58e6f342010-03-16 05:22:47 +00001149 CXXRecordDecl *NamingClass = Dtor->getParent();
John McCall161755a2010-04-06 21:38:20 +00001150 AccessTarget Entity(Context, AccessTarget::Member, NamingClass,
1151 DeclAccessPair::make(Dtor, Access),
1152 QualType());
John McCall58e6f342010-03-16 05:22:47 +00001153 Entity.setDiag(PDiag); // TODO: avoid copy
1154
1155 return CheckAccess(*this, Loc, Entity);
John McCall4f9506a2010-02-02 08:45:54 +00001156}
1157
John McCallb13b7372010-02-01 03:16:54 +00001158/// Checks access to a constructor.
John McCall6b2accb2010-02-10 09:31:12 +00001159Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc,
Jeffrey Yasskin57d12fd2010-06-07 15:58:05 +00001160 CXXConstructorDecl *Constructor,
1161 const InitializedEntity &Entity,
1162 AccessSpecifier Access,
1163 bool IsCopyBindingRefToTemp) {
John McCall58e6f342010-03-16 05:22:47 +00001164 if (!getLangOptions().AccessControl ||
1165 Access == AS_public)
John McCall6b2accb2010-02-10 09:31:12 +00001166 return AR_accessible;
John McCallb13b7372010-02-01 03:16:54 +00001167
John McCall6b2accb2010-02-10 09:31:12 +00001168 CXXRecordDecl *NamingClass = Constructor->getParent();
Anders Carlsson9a68a672010-04-21 18:47:17 +00001169 AccessTarget AccessEntity(Context, AccessTarget::Member, NamingClass,
1170 DeclAccessPair::make(Constructor, Access),
1171 QualType());
1172 switch (Entity.getKind()) {
1173 default:
Jeffrey Yasskin57d12fd2010-06-07 15:58:05 +00001174 AccessEntity.setDiag(IsCopyBindingRefToTemp
1175 ? diag::ext_rvalue_to_reference_access_ctor
1176 : diag::err_access_ctor);
Anders Carlsson9a68a672010-04-21 18:47:17 +00001177 break;
John McCall58e6f342010-03-16 05:22:47 +00001178
Anders Carlsson3b8c53b2010-04-22 05:40:53 +00001179 case InitializedEntity::EK_Base:
1180 AccessEntity.setDiag(PDiag(diag::err_access_base)
1181 << Entity.isInheritedVirtualBase()
1182 << Entity.getBaseSpecifier()->getType()
1183 << getSpecialMember(Constructor));
Anders Carlsson9a68a672010-04-21 18:47:17 +00001184 break;
Anders Carlsson3b8c53b2010-04-22 05:40:53 +00001185
Anders Carlssonb99c6662010-04-21 20:28:29 +00001186 case InitializedEntity::EK_Member: {
1187 const FieldDecl *Field = cast<FieldDecl>(Entity.getDecl());
Anders Carlsson0e313bd2010-04-23 03:41:35 +00001188 AccessEntity.setDiag(PDiag(diag::err_access_field)
1189 << Field->getType()
1190 << getSpecialMember(Constructor));
Anders Carlssonb99c6662010-04-21 20:28:29 +00001191 break;
1192 }
Anders Carlsson9a68a672010-04-21 18:47:17 +00001193
Anders Carlsson711f34a2010-04-21 19:52:01 +00001194 }
1195
Anders Carlsson9a68a672010-04-21 18:47:17 +00001196 return CheckAccess(*this, UseLoc, AccessEntity);
John McCallb13b7372010-02-01 03:16:54 +00001197}
1198
John McCallb0207482010-03-16 06:11:48 +00001199/// Checks direct (i.e. non-inherited) access to an arbitrary class
1200/// member.
1201Sema::AccessResult Sema::CheckDirectMemberAccess(SourceLocation UseLoc,
1202 NamedDecl *Target,
1203 const PartialDiagnostic &Diag) {
1204 AccessSpecifier Access = Target->getAccess();
1205 if (!getLangOptions().AccessControl ||
1206 Access == AS_public)
1207 return AR_accessible;
1208
1209 CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(Target->getDeclContext());
John McCall161755a2010-04-06 21:38:20 +00001210 AccessTarget Entity(Context, AccessTarget::Member, NamingClass,
1211 DeclAccessPair::make(Target, Access),
1212 QualType());
John McCallb0207482010-03-16 06:11:48 +00001213 Entity.setDiag(Diag);
1214 return CheckAccess(*this, UseLoc, Entity);
1215}
1216
1217
John McCall90c8c572010-03-18 08:19:33 +00001218/// Checks access to an overloaded operator new or delete.
1219Sema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc,
1220 SourceRange PlacementRange,
1221 CXXRecordDecl *NamingClass,
John McCall9aa472c2010-03-19 07:35:19 +00001222 DeclAccessPair Found) {
John McCall90c8c572010-03-18 08:19:33 +00001223 if (!getLangOptions().AccessControl ||
1224 !NamingClass ||
John McCall9aa472c2010-03-19 07:35:19 +00001225 Found.getAccess() == AS_public)
John McCall90c8c572010-03-18 08:19:33 +00001226 return AR_accessible;
1227
John McCall161755a2010-04-06 21:38:20 +00001228 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
1229 QualType());
John McCall90c8c572010-03-18 08:19:33 +00001230 Entity.setDiag(diag::err_access)
1231 << PlacementRange;
1232
1233 return CheckAccess(*this, OpLoc, Entity);
1234}
1235
John McCallb13b7372010-02-01 03:16:54 +00001236/// Checks access to an overloaded member operator, including
1237/// conversion operators.
John McCall6b2accb2010-02-10 09:31:12 +00001238Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc,
1239 Expr *ObjectExpr,
John McCall58e6f342010-03-16 05:22:47 +00001240 Expr *ArgExpr,
John McCall9aa472c2010-03-19 07:35:19 +00001241 DeclAccessPair Found) {
John McCall58e6f342010-03-16 05:22:47 +00001242 if (!getLangOptions().AccessControl ||
John McCall9aa472c2010-03-19 07:35:19 +00001243 Found.getAccess() == AS_public)
John McCall6b2accb2010-02-10 09:31:12 +00001244 return AR_accessible;
John McCall5357b612010-01-28 01:42:12 +00001245
1246 const RecordType *RT = ObjectExpr->getType()->getAs<RecordType>();
1247 assert(RT && "found member operator but object expr not of record type");
1248 CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(RT->getDecl());
1249
John McCall161755a2010-04-06 21:38:20 +00001250 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
1251 ObjectExpr->getType());
John McCall58e6f342010-03-16 05:22:47 +00001252 Entity.setDiag(diag::err_access)
1253 << ObjectExpr->getSourceRange()
1254 << (ArgExpr ? ArgExpr->getSourceRange() : SourceRange());
1255
1256 return CheckAccess(*this, OpLoc, Entity);
John McCall6b2accb2010-02-10 09:31:12 +00001257}
John McCall5357b612010-01-28 01:42:12 +00001258
John McCall6bb80172010-03-30 21:47:33 +00001259Sema::AccessResult Sema::CheckAddressOfMemberAccess(Expr *OvlExpr,
1260 DeclAccessPair Found) {
1261 if (!getLangOptions().AccessControl ||
John McCalle2f5ba92010-03-30 22:20:00 +00001262 Found.getAccess() == AS_none ||
John McCall6bb80172010-03-30 21:47:33 +00001263 Found.getAccess() == AS_public)
1264 return AR_accessible;
1265
1266 OverloadExpr *Ovl = OverloadExpr::find(OvlExpr).getPointer();
John McCalle9ee23e2010-04-22 18:44:12 +00001267 CXXRecordDecl *NamingClass = Ovl->getNamingClass();
John McCall6bb80172010-03-30 21:47:33 +00001268
John McCall161755a2010-04-06 21:38:20 +00001269 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
1270 Context.getTypeDeclType(NamingClass));
John McCall6bb80172010-03-30 21:47:33 +00001271 Entity.setDiag(diag::err_access)
1272 << Ovl->getSourceRange();
1273
1274 return CheckAccess(*this, Ovl->getNameLoc(), Entity);
1275}
1276
John McCall6b2accb2010-02-10 09:31:12 +00001277/// Checks access for a hierarchy conversion.
1278///
1279/// \param IsBaseToDerived whether this is a base-to-derived conversion (true)
1280/// or a derived-to-base conversion (false)
1281/// \param ForceCheck true if this check should be performed even if access
1282/// control is disabled; some things rely on this for semantics
1283/// \param ForceUnprivileged true if this check should proceed as if the
1284/// context had no special privileges
1285/// \param ADK controls the kind of diagnostics that are used
1286Sema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc,
John McCall6b2accb2010-02-10 09:31:12 +00001287 QualType Base,
1288 QualType Derived,
1289 const CXXBasePath &Path,
John McCall58e6f342010-03-16 05:22:47 +00001290 unsigned DiagID,
John McCall6b2accb2010-02-10 09:31:12 +00001291 bool ForceCheck,
John McCall58e6f342010-03-16 05:22:47 +00001292 bool ForceUnprivileged) {
John McCall6b2accb2010-02-10 09:31:12 +00001293 if (!ForceCheck && !getLangOptions().AccessControl)
1294 return AR_accessible;
John McCall5357b612010-01-28 01:42:12 +00001295
John McCall6b2accb2010-02-10 09:31:12 +00001296 if (Path.Access == AS_public)
1297 return AR_accessible;
John McCall5357b612010-01-28 01:42:12 +00001298
John McCall6b2accb2010-02-10 09:31:12 +00001299 CXXRecordDecl *BaseD, *DerivedD;
1300 BaseD = cast<CXXRecordDecl>(Base->getAs<RecordType>()->getDecl());
1301 DerivedD = cast<CXXRecordDecl>(Derived->getAs<RecordType>()->getDecl());
John McCall58e6f342010-03-16 05:22:47 +00001302
John McCall161755a2010-04-06 21:38:20 +00001303 AccessTarget Entity(Context, AccessTarget::Base, BaseD, DerivedD,
1304 Path.Access);
John McCall58e6f342010-03-16 05:22:47 +00001305 if (DiagID)
1306 Entity.setDiag(DiagID) << Derived << Base;
John McCall6b2accb2010-02-10 09:31:12 +00001307
John McCall161755a2010-04-06 21:38:20 +00001308 if (ForceUnprivileged) {
1309 switch (CheckEffectiveAccess(*this, EffectiveContext(),
1310 AccessLoc, Entity)) {
1311 case ::AR_accessible: return Sema::AR_accessible;
1312 case ::AR_inaccessible: return Sema::AR_inaccessible;
1313 case ::AR_dependent: return Sema::AR_dependent;
1314 }
1315 llvm_unreachable("unexpected result from CheckEffectiveAccess");
1316 }
John McCall58e6f342010-03-16 05:22:47 +00001317 return CheckAccess(*this, AccessLoc, Entity);
John McCall5357b612010-01-28 01:42:12 +00001318}
1319
John McCall92f88312010-01-23 00:46:32 +00001320/// Checks access to all the declarations in the given result set.
John McCall6b2accb2010-02-10 09:31:12 +00001321void Sema::CheckLookupAccess(const LookupResult &R) {
1322 assert(getLangOptions().AccessControl
1323 && "performing access check without access control");
1324 assert(R.getNamingClass() && "performing access check without naming class");
1325
John McCall58e6f342010-03-16 05:22:47 +00001326 for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
1327 if (I.getAccess() != AS_public) {
John McCall161755a2010-04-06 21:38:20 +00001328 AccessTarget Entity(Context, AccessedEntity::Member,
1329 R.getNamingClass(), I.getPair(),
1330 R.getBaseObjectType());
John McCall58e6f342010-03-16 05:22:47 +00001331 Entity.setDiag(diag::err_access);
1332
1333 CheckAccess(*this, R.getNameLoc(), Entity);
1334 }
1335 }
John McCall92f88312010-01-23 00:46:32 +00001336}