blob: 99a8f9f5bdd8e1a5da2491632c01eaa5c03a9bf2 [file] [log] [blame]
Anders Carlsson29f006b2009-03-27 05:05:05 +00001//===---- SemaAccess.cpp - C++ Access Control -------------------*- C++ -*-===//
Anders Carlsson60d6b0d2009-03-27 04:43:36 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file provides Sema routines for C++ access control semantics.
11//
12//===----------------------------------------------------------------------===//
Anders Carlssonc60e8882009-03-27 04:54:36 +000013
14#include "Sema.h"
John McCall92f88312010-01-23 00:46:32 +000015#include "Lookup.h"
Anders Carlssonc4f1e872009-03-27 06:03:27 +000016#include "clang/AST/ASTContext.h"
Douglas Gregora8f32e02009-10-06 17:59:45 +000017#include "clang/AST/CXXInheritance.h"
18#include "clang/AST/DeclCXX.h"
John McCalld60e22e2010-03-12 01:19:31 +000019#include "clang/AST/DeclFriend.h"
John McCall0c01d182010-03-24 05:22:00 +000020#include "clang/AST/DependentDiagnostic.h"
John McCallc373d482010-01-27 01:50:18 +000021#include "clang/AST/ExprCXX.h"
22
Anders Carlssonc60e8882009-03-27 04:54:36 +000023using namespace clang;
24
John McCall161755a2010-04-06 21:38:20 +000025/// A copy of Sema's enum without AR_delayed.
26enum AccessResult {
27 AR_accessible,
28 AR_inaccessible,
29 AR_dependent
30};
31
Anders Carlsson29f006b2009-03-27 05:05:05 +000032/// SetMemberAccessSpecifier - Set the access specifier of a member.
33/// Returns true on error (when the previous member decl access specifier
34/// is different from the new member decl access specifier).
Mike Stump1eb44332009-09-09 15:08:12 +000035bool Sema::SetMemberAccessSpecifier(NamedDecl *MemberDecl,
Anders Carlssonc60e8882009-03-27 04:54:36 +000036 NamedDecl *PrevMemberDecl,
37 AccessSpecifier LexicalAS) {
38 if (!PrevMemberDecl) {
39 // Use the lexical access specifier.
40 MemberDecl->setAccess(LexicalAS);
41 return false;
42 }
Mike Stump1eb44332009-09-09 15:08:12 +000043
Anders Carlssonc60e8882009-03-27 04:54:36 +000044 // C++ [class.access.spec]p3: When a member is redeclared its access
45 // specifier must be same as its initial declaration.
46 if (LexicalAS != AS_none && LexicalAS != PrevMemberDecl->getAccess()) {
Mike Stump1eb44332009-09-09 15:08:12 +000047 Diag(MemberDecl->getLocation(),
48 diag::err_class_redeclared_with_different_access)
Anders Carlssonc60e8882009-03-27 04:54:36 +000049 << MemberDecl << LexicalAS;
50 Diag(PrevMemberDecl->getLocation(), diag::note_previous_access_declaration)
51 << PrevMemberDecl << PrevMemberDecl->getAccess();
John McCall44e067b2009-12-23 00:37:40 +000052
53 MemberDecl->setAccess(LexicalAS);
Anders Carlssonc60e8882009-03-27 04:54:36 +000054 return true;
55 }
Mike Stump1eb44332009-09-09 15:08:12 +000056
Anders Carlssonc60e8882009-03-27 04:54:36 +000057 MemberDecl->setAccess(PrevMemberDecl->getAccess());
58 return false;
59}
Anders Carlsson29f006b2009-03-27 05:05:05 +000060
John McCall161755a2010-04-06 21:38:20 +000061static CXXRecordDecl *FindDeclaringClass(NamedDecl *D) {
62 DeclContext *DC = D->getDeclContext();
63
64 // This can only happen at top: enum decls only "publish" their
65 // immediate members.
66 if (isa<EnumDecl>(DC))
67 DC = cast<EnumDecl>(DC)->getDeclContext();
68
69 CXXRecordDecl *DeclaringClass = cast<CXXRecordDecl>(DC);
70 while (DeclaringClass->isAnonymousStructOrUnion())
71 DeclaringClass = cast<CXXRecordDecl>(DeclaringClass->getDeclContext());
72 return DeclaringClass;
73}
74
John McCall6b2accb2010-02-10 09:31:12 +000075namespace {
76struct EffectiveContext {
John McCall2cc26752010-03-27 06:55:49 +000077 EffectiveContext() : Inner(0), Dependent(false) {}
Anders Carlssonc4f1e872009-03-27 06:03:27 +000078
John McCall7ad650f2010-03-24 07:46:06 +000079 explicit EffectiveContext(DeclContext *DC)
80 : Inner(DC),
81 Dependent(DC->isDependentContext()) {
John McCall0c01d182010-03-24 05:22:00 +000082
John McCall88b6c712010-03-17 04:58:56 +000083 // C++ [class.access.nest]p1:
84 // A nested class is a member and as such has the same access
85 // rights as any other member.
86 // C++ [class.access]p2:
87 // A member of a class can also access all the names to which
John McCall2cc26752010-03-27 06:55:49 +000088 // the class has access. A local class of a member function
89 // may access the same names that the member function itself
90 // may access.
91 // This almost implies that the privileges of nesting are transitive.
92 // Technically it says nothing about the local classes of non-member
93 // functions (which can gain privileges through friendship), but we
94 // take that as an oversight.
95 while (true) {
96 if (isa<CXXRecordDecl>(DC)) {
97 CXXRecordDecl *Record = cast<CXXRecordDecl>(DC)->getCanonicalDecl();
98 Records.push_back(Record);
99 DC = Record->getDeclContext();
100 } else if (isa<FunctionDecl>(DC)) {
101 FunctionDecl *Function = cast<FunctionDecl>(DC)->getCanonicalDecl();
102 Functions.push_back(Function);
103 DC = Function->getDeclContext();
104 } else if (DC->isFileContext()) {
105 break;
106 } else {
107 DC = DC->getParent();
108 }
John McCall88b6c712010-03-17 04:58:56 +0000109 }
Anders Carlssonc4f1e872009-03-27 06:03:27 +0000110 }
Sebastian Redl726212f2009-07-18 14:32:15 +0000111
John McCall0c01d182010-03-24 05:22:00 +0000112 bool isDependent() const { return Dependent; }
113
John McCall88b6c712010-03-17 04:58:56 +0000114 bool includesClass(const CXXRecordDecl *R) const {
115 R = R->getCanonicalDecl();
116 return std::find(Records.begin(), Records.end(), R)
117 != Records.end();
John McCall6b2accb2010-02-10 09:31:12 +0000118 }
119
John McCall7ad650f2010-03-24 07:46:06 +0000120 /// Retrieves the innermost "useful" context. Can be null if we're
121 /// doing access-control without privileges.
122 DeclContext *getInnerContext() const {
123 return Inner;
John McCall0c01d182010-03-24 05:22:00 +0000124 }
125
126 typedef llvm::SmallVectorImpl<CXXRecordDecl*>::const_iterator record_iterator;
127
John McCall7ad650f2010-03-24 07:46:06 +0000128 DeclContext *Inner;
John McCall2cc26752010-03-27 06:55:49 +0000129 llvm::SmallVector<FunctionDecl*, 4> Functions;
John McCall88b6c712010-03-17 04:58:56 +0000130 llvm::SmallVector<CXXRecordDecl*, 4> Records;
John McCall0c01d182010-03-24 05:22:00 +0000131 bool Dependent;
John McCall6b2accb2010-02-10 09:31:12 +0000132};
John McCall161755a2010-04-06 21:38:20 +0000133
134/// Like Sema's AccessedEntity, but kindly lets us scribble all over
135/// it.
136struct AccessTarget : public Sema::AccessedEntity {
137 AccessTarget(const Sema::AccessedEntity &Entity)
138 : AccessedEntity(Entity) {
139 initialize();
140 }
141
142 AccessTarget(ASTContext &Context,
143 MemberNonce _,
144 CXXRecordDecl *NamingClass,
145 DeclAccessPair FoundDecl,
146 QualType BaseObjectType)
147 : AccessedEntity(Context, Member, NamingClass, FoundDecl, BaseObjectType) {
148 initialize();
149 }
150
151 AccessTarget(ASTContext &Context,
152 BaseNonce _,
153 CXXRecordDecl *BaseClass,
154 CXXRecordDecl *DerivedClass,
155 AccessSpecifier Access)
156 : AccessedEntity(Context, Base, BaseClass, DerivedClass, Access) {
157 initialize();
158 }
159
160 bool hasInstanceContext() const {
161 return HasInstanceContext;
162 }
163
164 class SavedInstanceContext {
165 public:
166 ~SavedInstanceContext() {
167 Target.HasInstanceContext = Has;
168 }
169
170 private:
171 friend class AccessTarget;
172 explicit SavedInstanceContext(AccessTarget &Target)
173 : Target(Target), Has(Target.HasInstanceContext) {}
174 AccessTarget &Target;
175 bool Has;
176 };
177
178 SavedInstanceContext saveInstanceContext() {
179 return SavedInstanceContext(*this);
180 }
181
182 void suppressInstanceContext() {
183 HasInstanceContext = false;
184 }
185
186 const CXXRecordDecl *resolveInstanceContext(Sema &S) const {
187 assert(HasInstanceContext);
188 if (CalculatedInstanceContext)
189 return InstanceContext;
190
191 CalculatedInstanceContext = true;
192 DeclContext *IC = S.computeDeclContext(getBaseObjectType());
193 InstanceContext = (IC ? cast<CXXRecordDecl>(IC)->getCanonicalDecl() : 0);
194 return InstanceContext;
195 }
196
197 const CXXRecordDecl *getDeclaringClass() const {
198 return DeclaringClass;
199 }
200
201private:
202 void initialize() {
203 HasInstanceContext = (isMemberAccess() &&
204 !getBaseObjectType().isNull() &&
205 getTargetDecl()->isCXXInstanceMember());
206 CalculatedInstanceContext = false;
207 InstanceContext = 0;
208
209 if (isMemberAccess())
210 DeclaringClass = FindDeclaringClass(getTargetDecl());
211 else
212 DeclaringClass = getBaseClass();
213 DeclaringClass = DeclaringClass->getCanonicalDecl();
214 }
215
216 bool HasInstanceContext : 1;
217 mutable bool CalculatedInstanceContext : 1;
218 mutable const CXXRecordDecl *InstanceContext;
219 const CXXRecordDecl *DeclaringClass;
220};
221
Anders Carlsson29f006b2009-03-27 05:05:05 +0000222}
John McCall92f88312010-01-23 00:46:32 +0000223
John McCall161755a2010-04-06 21:38:20 +0000224/// Checks whether one class is derived from another, inclusively.
225/// Properly indicates when it couldn't be determined due to
226/// dependence.
227///
228/// This should probably be donated to AST or at least Sema.
229static AccessResult IsDerivedFromInclusive(const CXXRecordDecl *Derived,
230 const CXXRecordDecl *Target) {
231 assert(Derived->getCanonicalDecl() == Derived);
232 assert(Target->getCanonicalDecl() == Target);
John McCallc1b621d2010-03-24 09:04:37 +0000233
John McCall161755a2010-04-06 21:38:20 +0000234 if (Derived == Target) return AR_accessible;
John McCallc1b621d2010-03-24 09:04:37 +0000235
John McCall161755a2010-04-06 21:38:20 +0000236 AccessResult OnFailure = AR_inaccessible;
237 llvm::SmallVector<const CXXRecordDecl*, 8> Queue; // actually a stack
238
239 while (true) {
240 for (CXXRecordDecl::base_class_const_iterator
241 I = Derived->bases_begin(), E = Derived->bases_end(); I != E; ++I) {
242
243 const CXXRecordDecl *RD;
244
245 QualType T = I->getType();
246 if (const RecordType *RT = T->getAs<RecordType>()) {
247 RD = cast<CXXRecordDecl>(RT->getDecl());
248 } else {
249 // It's possible for a base class to be the current
250 // instantiation of some enclosing template, but I'm guessing
251 // nobody will ever care that we just dependently delay here.
252 assert(T->isDependentType() && "non-dependent base wasn't a record?");
253 OnFailure = AR_dependent;
254 continue;
255 }
256
257 RD = RD->getCanonicalDecl();
258 if (RD == Target) return AR_accessible;
259 Queue.push_back(RD);
260 }
261
262 if (Queue.empty()) break;
263
264 Derived = Queue.back();
265 Queue.pop_back();
266 }
267
268 return OnFailure;
John McCall6b2accb2010-02-10 09:31:12 +0000269}
270
John McCall161755a2010-04-06 21:38:20 +0000271
John McCall0c01d182010-03-24 05:22:00 +0000272static bool MightInstantiateTo(Sema &S, DeclContext *Context,
273 DeclContext *Friend) {
274 if (Friend == Context)
275 return true;
276
277 assert(!Friend->isDependentContext() &&
278 "can't handle friends with dependent contexts here");
279
280 if (!Context->isDependentContext())
281 return false;
282
283 if (Friend->isFileContext())
284 return false;
285
286 // TODO: this is very conservative
287 return true;
288}
289
290// Asks whether the type in 'context' can ever instantiate to the type
291// in 'friend'.
292static bool MightInstantiateTo(Sema &S, CanQualType Context, CanQualType Friend) {
293 if (Friend == Context)
294 return true;
295
296 if (!Friend->isDependentType() && !Context->isDependentType())
297 return false;
298
299 // TODO: this is very conservative.
300 return true;
301}
302
303static bool MightInstantiateTo(Sema &S,
304 FunctionDecl *Context,
305 FunctionDecl *Friend) {
306 if (Context->getDeclName() != Friend->getDeclName())
307 return false;
308
309 if (!MightInstantiateTo(S,
310 Context->getDeclContext(),
311 Friend->getDeclContext()))
312 return false;
313
314 CanQual<FunctionProtoType> FriendTy
315 = S.Context.getCanonicalType(Friend->getType())
316 ->getAs<FunctionProtoType>();
317 CanQual<FunctionProtoType> ContextTy
318 = S.Context.getCanonicalType(Context->getType())
319 ->getAs<FunctionProtoType>();
320
321 // There isn't any way that I know of to add qualifiers
322 // during instantiation.
323 if (FriendTy.getQualifiers() != ContextTy.getQualifiers())
324 return false;
325
326 if (FriendTy->getNumArgs() != ContextTy->getNumArgs())
327 return false;
328
329 if (!MightInstantiateTo(S,
330 ContextTy->getResultType(),
331 FriendTy->getResultType()))
332 return false;
333
334 for (unsigned I = 0, E = FriendTy->getNumArgs(); I != E; ++I)
335 if (!MightInstantiateTo(S,
336 ContextTy->getArgType(I),
337 FriendTy->getArgType(I)))
338 return false;
339
340 return true;
341}
342
343static bool MightInstantiateTo(Sema &S,
344 FunctionTemplateDecl *Context,
345 FunctionTemplateDecl *Friend) {
346 return MightInstantiateTo(S,
347 Context->getTemplatedDecl(),
348 Friend->getTemplatedDecl());
349}
350
John McCall161755a2010-04-06 21:38:20 +0000351static AccessResult MatchesFriend(Sema &S,
352 const EffectiveContext &EC,
353 const CXXRecordDecl *Friend) {
John McCalla742db02010-03-17 20:01:29 +0000354 if (EC.includesClass(Friend))
John McCall161755a2010-04-06 21:38:20 +0000355 return AR_accessible;
John McCalla742db02010-03-17 20:01:29 +0000356
John McCall0c01d182010-03-24 05:22:00 +0000357 if (EC.isDependent()) {
358 CanQualType FriendTy
359 = S.Context.getCanonicalType(S.Context.getTypeDeclType(Friend));
360
361 for (EffectiveContext::record_iterator
362 I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
363 CanQualType ContextTy
364 = S.Context.getCanonicalType(S.Context.getTypeDeclType(*I));
365 if (MightInstantiateTo(S, ContextTy, FriendTy))
John McCall161755a2010-04-06 21:38:20 +0000366 return AR_dependent;
John McCall0c01d182010-03-24 05:22:00 +0000367 }
368 }
369
John McCall161755a2010-04-06 21:38:20 +0000370 return AR_inaccessible;
John McCalla742db02010-03-17 20:01:29 +0000371}
372
John McCall161755a2010-04-06 21:38:20 +0000373static AccessResult MatchesFriend(Sema &S,
374 const EffectiveContext &EC,
375 CanQualType Friend) {
John McCall0c01d182010-03-24 05:22:00 +0000376 if (const RecordType *RT = Friend->getAs<RecordType>())
377 return MatchesFriend(S, EC, cast<CXXRecordDecl>(RT->getDecl()));
John McCalla742db02010-03-17 20:01:29 +0000378
John McCall0c01d182010-03-24 05:22:00 +0000379 // TODO: we can do better than this
380 if (Friend->isDependentType())
John McCall161755a2010-04-06 21:38:20 +0000381 return AR_dependent;
John McCalla742db02010-03-17 20:01:29 +0000382
John McCall161755a2010-04-06 21:38:20 +0000383 return AR_inaccessible;
John McCall0c01d182010-03-24 05:22:00 +0000384}
385
386/// Determines whether the given friend class template matches
387/// anything in the effective context.
John McCall161755a2010-04-06 21:38:20 +0000388static AccessResult MatchesFriend(Sema &S,
389 const EffectiveContext &EC,
390 ClassTemplateDecl *Friend) {
391 AccessResult OnFailure = AR_inaccessible;
John McCall0c01d182010-03-24 05:22:00 +0000392
John McCall93ba8572010-03-25 06:39:04 +0000393 // Check whether the friend is the template of a class in the
394 // context chain.
John McCall0c01d182010-03-24 05:22:00 +0000395 for (llvm::SmallVectorImpl<CXXRecordDecl*>::const_iterator
396 I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
397 CXXRecordDecl *Record = *I;
398
John McCall93ba8572010-03-25 06:39:04 +0000399 // Figure out whether the current class has a template:
John McCall0c01d182010-03-24 05:22:00 +0000400 ClassTemplateDecl *CTD;
401
402 // A specialization of the template...
403 if (isa<ClassTemplateSpecializationDecl>(Record)) {
404 CTD = cast<ClassTemplateSpecializationDecl>(Record)
405 ->getSpecializedTemplate();
406
407 // ... or the template pattern itself.
408 } else {
409 CTD = Record->getDescribedClassTemplate();
410 if (!CTD) continue;
411 }
412
413 // It's a match.
414 if (Friend == CTD->getCanonicalDecl())
John McCall161755a2010-04-06 21:38:20 +0000415 return AR_accessible;
John McCall0c01d182010-03-24 05:22:00 +0000416
John McCall93ba8572010-03-25 06:39:04 +0000417 // If the context isn't dependent, it can't be a dependent match.
418 if (!EC.isDependent())
419 continue;
420
John McCall0c01d182010-03-24 05:22:00 +0000421 // If the template names don't match, it can't be a dependent
422 // match. This isn't true in C++0x because of template aliases.
423 if (!S.LangOpts.CPlusPlus0x && CTD->getDeclName() != Friend->getDeclName())
424 continue;
425
426 // If the class's context can't instantiate to the friend's
427 // context, it can't be a dependent match.
428 if (!MightInstantiateTo(S, CTD->getDeclContext(),
429 Friend->getDeclContext()))
430 continue;
431
432 // Otherwise, it's a dependent match.
John McCall161755a2010-04-06 21:38:20 +0000433 OnFailure = AR_dependent;
John McCalla742db02010-03-17 20:01:29 +0000434 }
435
John McCall0c01d182010-03-24 05:22:00 +0000436 return OnFailure;
437}
438
439/// Determines whether the given friend function matches anything in
440/// the effective context.
John McCall161755a2010-04-06 21:38:20 +0000441static AccessResult MatchesFriend(Sema &S,
442 const EffectiveContext &EC,
443 FunctionDecl *Friend) {
444 AccessResult OnFailure = AR_inaccessible;
John McCall0c01d182010-03-24 05:22:00 +0000445
John McCall2cc26752010-03-27 06:55:49 +0000446 for (llvm::SmallVectorImpl<FunctionDecl*>::const_iterator
447 I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) {
448 if (Friend == *I)
John McCall161755a2010-04-06 21:38:20 +0000449 return AR_accessible;
John McCall0c01d182010-03-24 05:22:00 +0000450
John McCall2cc26752010-03-27 06:55:49 +0000451 if (EC.isDependent() && MightInstantiateTo(S, *I, Friend))
John McCall161755a2010-04-06 21:38:20 +0000452 OnFailure = AR_dependent;
John McCall2cc26752010-03-27 06:55:49 +0000453 }
John McCall0c01d182010-03-24 05:22:00 +0000454
John McCall2cc26752010-03-27 06:55:49 +0000455 return OnFailure;
John McCall0c01d182010-03-24 05:22:00 +0000456}
457
458/// Determines whether the given friend function template matches
459/// anything in the effective context.
John McCall161755a2010-04-06 21:38:20 +0000460static AccessResult MatchesFriend(Sema &S,
461 const EffectiveContext &EC,
462 FunctionTemplateDecl *Friend) {
463 if (EC.Functions.empty()) return AR_inaccessible;
John McCall0c01d182010-03-24 05:22:00 +0000464
John McCall161755a2010-04-06 21:38:20 +0000465 AccessResult OnFailure = AR_inaccessible;
John McCall0c01d182010-03-24 05:22:00 +0000466
John McCall2cc26752010-03-27 06:55:49 +0000467 for (llvm::SmallVectorImpl<FunctionDecl*>::const_iterator
468 I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) {
John McCall0c01d182010-03-24 05:22:00 +0000469
John McCall2cc26752010-03-27 06:55:49 +0000470 FunctionTemplateDecl *FTD = (*I)->getPrimaryTemplate();
471 if (!FTD)
472 FTD = (*I)->getDescribedFunctionTemplate();
473 if (!FTD)
474 continue;
John McCall0c01d182010-03-24 05:22:00 +0000475
John McCall2cc26752010-03-27 06:55:49 +0000476 FTD = FTD->getCanonicalDecl();
477
478 if (Friend == FTD)
John McCall161755a2010-04-06 21:38:20 +0000479 return AR_accessible;
John McCall2cc26752010-03-27 06:55:49 +0000480
481 if (EC.isDependent() && MightInstantiateTo(S, FTD, Friend))
John McCall161755a2010-04-06 21:38:20 +0000482 OnFailure = AR_dependent;
John McCall2cc26752010-03-27 06:55:49 +0000483 }
484
485 return OnFailure;
John McCall0c01d182010-03-24 05:22:00 +0000486}
487
488/// Determines whether the given friend declaration matches anything
489/// in the effective context.
John McCall161755a2010-04-06 21:38:20 +0000490static AccessResult MatchesFriend(Sema &S,
491 const EffectiveContext &EC,
492 FriendDecl *FriendD) {
John McCall32f2fb52010-03-25 18:04:51 +0000493 if (TypeSourceInfo *T = FriendD->getFriendType())
494 return MatchesFriend(S, EC, T->getType()->getCanonicalTypeUnqualified());
John McCall0c01d182010-03-24 05:22:00 +0000495
496 NamedDecl *Friend
497 = cast<NamedDecl>(FriendD->getFriendDecl()->getCanonicalDecl());
John McCalla742db02010-03-17 20:01:29 +0000498
499 // FIXME: declarations with dependent or templated scope.
500
John McCall0c01d182010-03-24 05:22:00 +0000501 if (isa<ClassTemplateDecl>(Friend))
502 return MatchesFriend(S, EC, cast<ClassTemplateDecl>(Friend));
John McCalla742db02010-03-17 20:01:29 +0000503
John McCall0c01d182010-03-24 05:22:00 +0000504 if (isa<FunctionTemplateDecl>(Friend))
505 return MatchesFriend(S, EC, cast<FunctionTemplateDecl>(Friend));
John McCalla742db02010-03-17 20:01:29 +0000506
John McCall0c01d182010-03-24 05:22:00 +0000507 if (isa<CXXRecordDecl>(Friend))
508 return MatchesFriend(S, EC, cast<CXXRecordDecl>(Friend));
John McCalla742db02010-03-17 20:01:29 +0000509
John McCall0c01d182010-03-24 05:22:00 +0000510 assert(isa<FunctionDecl>(Friend) && "unknown friend decl kind");
511 return MatchesFriend(S, EC, cast<FunctionDecl>(Friend));
John McCalla742db02010-03-17 20:01:29 +0000512}
513
John McCall161755a2010-04-06 21:38:20 +0000514static AccessResult GetFriendKind(Sema &S,
515 const EffectiveContext &EC,
516 const CXXRecordDecl *Class) {
517 AccessResult OnFailure = AR_inaccessible;
John McCall88b6c712010-03-17 04:58:56 +0000518
John McCalld60e22e2010-03-12 01:19:31 +0000519 // Okay, check friends.
520 for (CXXRecordDecl::friend_iterator I = Class->friend_begin(),
521 E = Class->friend_end(); I != E; ++I) {
522 FriendDecl *Friend = *I;
523
John McCalla742db02010-03-17 20:01:29 +0000524 switch (MatchesFriend(S, EC, Friend)) {
John McCall161755a2010-04-06 21:38:20 +0000525 case AR_accessible:
526 return AR_accessible;
John McCalld60e22e2010-03-12 01:19:31 +0000527
John McCall161755a2010-04-06 21:38:20 +0000528 case AR_inaccessible:
529 continue;
530
531 case AR_dependent:
532 OnFailure = AR_dependent;
John McCalla742db02010-03-17 20:01:29 +0000533 break;
John McCalld60e22e2010-03-12 01:19:31 +0000534 }
John McCalld60e22e2010-03-12 01:19:31 +0000535 }
536
537 // That's it, give up.
John McCall88b6c712010-03-17 04:58:56 +0000538 return OnFailure;
John McCall6b2accb2010-02-10 09:31:12 +0000539}
540
John McCall161755a2010-04-06 21:38:20 +0000541static AccessResult HasAccess(Sema &S,
542 const EffectiveContext &EC,
543 const CXXRecordDecl *NamingClass,
544 AccessSpecifier Access,
545 const AccessTarget &Target) {
John McCalldb73c682010-04-02 00:03:43 +0000546 assert(NamingClass->getCanonicalDecl() == NamingClass &&
547 "declaration should be canonicalized before being passed here");
548
John McCall161755a2010-04-06 21:38:20 +0000549 if (Access == AS_public) return AR_accessible;
John McCalldb73c682010-04-02 00:03:43 +0000550 assert(Access == AS_private || Access == AS_protected);
551
John McCall161755a2010-04-06 21:38:20 +0000552 AccessResult OnFailure = AR_inaccessible;
553
John McCalldb73c682010-04-02 00:03:43 +0000554 for (EffectiveContext::record_iterator
555 I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
556 // All the declarations in EC have been canonicalized, so pointer
557 // equality from this point on will work fine.
558 const CXXRecordDecl *ECRecord = *I;
559
560 // [B2] and [M2]
John McCall161755a2010-04-06 21:38:20 +0000561 if (Access == AS_private) {
562 if (ECRecord == NamingClass)
563 return AR_accessible;
John McCalldb73c682010-04-02 00:03:43 +0000564
565 // [B3] and [M3]
John McCall161755a2010-04-06 21:38:20 +0000566 } else {
567 assert(Access == AS_protected);
568 switch (IsDerivedFromInclusive(ECRecord, NamingClass)) {
569 case AR_accessible: break;
570 case AR_inaccessible: continue;
571 case AR_dependent: OnFailure = AR_dependent; continue;
572 }
573
574 if (!Target.hasInstanceContext())
575 return AR_accessible;
576
577 const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S);
578 if (!InstanceContext) {
579 OnFailure = AR_dependent;
580 continue;
581 }
582
583 // C++ [class.protected]p1:
584 // An additional access check beyond those described earlier in
585 // [class.access] is applied when a non-static data member or
586 // non-static member function is a protected member of its naming
587 // class. As described earlier, access to a protected member is
588 // granted because the reference occurs in a friend or member of
589 // some class C. If the access is to form a pointer to member,
590 // the nested-name-specifier shall name C or a class derived from
591 // C. All other accesses involve a (possibly implicit) object
592 // expression. In this case, the class of the object expression
593 // shall be C or a class derived from C.
594 //
595 // We interpret this as a restriction on [M3]. Most of the
596 // conditions are encoded by not having any instance context.
597 switch (IsDerivedFromInclusive(InstanceContext, ECRecord)) {
598 case AR_accessible: return AR_accessible;
599 case AR_inaccessible: continue;
600 case AR_dependent: OnFailure = AR_dependent; continue;
601 }
602 }
John McCalldb73c682010-04-02 00:03:43 +0000603 }
604
John McCall161755a2010-04-06 21:38:20 +0000605 if (!NamingClass->hasFriends())
606 return OnFailure;
607
608 // Don't consider friends if we're under the [class.protected]
609 // restriction, above.
610 if (Access == AS_protected && Target.hasInstanceContext()) {
611 const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S);
612 if (!InstanceContext) return AR_dependent;
613
614 switch (IsDerivedFromInclusive(InstanceContext, NamingClass)) {
615 case AR_accessible: break;
616 case AR_inaccessible: return OnFailure;
617 case AR_dependent: return AR_dependent;
618 }
619 }
620
621 switch (GetFriendKind(S, EC, NamingClass)) {
622 case AR_accessible: return AR_accessible;
623 case AR_inaccessible: return OnFailure;
624 case AR_dependent: return AR_dependent;
625 }
626
627 // Silence bogus warnings
628 llvm_unreachable("impossible friendship kind");
629 return OnFailure;
John McCalldb73c682010-04-02 00:03:43 +0000630}
631
John McCall6b2accb2010-02-10 09:31:12 +0000632/// Finds the best path from the naming class to the declaring class,
633/// taking friend declarations into account.
634///
John McCalldb73c682010-04-02 00:03:43 +0000635/// C++0x [class.access.base]p5:
636/// A member m is accessible at the point R when named in class N if
637/// [M1] m as a member of N is public, or
638/// [M2] m as a member of N is private, and R occurs in a member or
639/// friend of class N, or
640/// [M3] m as a member of N is protected, and R occurs in a member or
641/// friend of class N, or in a member or friend of a class P
642/// derived from N, where m as a member of P is public, private,
643/// or protected, or
644/// [M4] there exists a base class B of N that is accessible at R, and
645/// m is accessible at R when named in class B.
646///
647/// C++0x [class.access.base]p4:
648/// A base class B of N is accessible at R, if
649/// [B1] an invented public member of B would be a public member of N, or
650/// [B2] R occurs in a member or friend of class N, and an invented public
651/// member of B would be a private or protected member of N, or
652/// [B3] R occurs in a member or friend of a class P derived from N, and an
653/// invented public member of B would be a private or protected member
654/// of P, or
655/// [B4] there exists a class S such that B is a base class of S accessible
656/// at R and S is a base class of N accessible at R.
657///
658/// Along a single inheritance path we can restate both of these
659/// iteratively:
660///
661/// First, we note that M1-4 are equivalent to B1-4 if the member is
662/// treated as a notional base of its declaring class with inheritance
663/// access equivalent to the member's access. Therefore we need only
664/// ask whether a class B is accessible from a class N in context R.
665///
666/// Let B_1 .. B_n be the inheritance path in question (i.e. where
667/// B_1 = N, B_n = B, and for all i, B_{i+1} is a direct base class of
668/// B_i). For i in 1..n, we will calculate ACAB(i), the access to the
669/// closest accessible base in the path:
670/// Access(a, b) = (* access on the base specifier from a to b *)
671/// Merge(a, forbidden) = forbidden
672/// Merge(a, private) = forbidden
673/// Merge(a, b) = min(a,b)
674/// Accessible(c, forbidden) = false
675/// Accessible(c, private) = (R is c) || IsFriend(c, R)
676/// Accessible(c, protected) = (R derived from c) || IsFriend(c, R)
677/// Accessible(c, public) = true
678/// ACAB(n) = public
679/// ACAB(i) =
680/// let AccessToBase = Merge(Access(B_i, B_{i+1}), ACAB(i+1)) in
681/// if Accessible(B_i, AccessToBase) then public else AccessToBase
682///
683/// B is an accessible base of N at R iff ACAB(1) = public.
684///
John McCall161755a2010-04-06 21:38:20 +0000685/// \param FinalAccess the access of the "final step", or AS_public if
John McCall7aceaf82010-03-18 23:49:19 +0000686/// there is no final step.
John McCall6b2accb2010-02-10 09:31:12 +0000687/// \return null if friendship is dependent
688static CXXBasePath *FindBestPath(Sema &S,
689 const EffectiveContext &EC,
John McCall161755a2010-04-06 21:38:20 +0000690 AccessTarget &Target,
John McCall7aceaf82010-03-18 23:49:19 +0000691 AccessSpecifier FinalAccess,
John McCall6b2accb2010-02-10 09:31:12 +0000692 CXXBasePaths &Paths) {
693 // Derive the paths to the desired base.
John McCall161755a2010-04-06 21:38:20 +0000694 const CXXRecordDecl *Derived = Target.getNamingClass();
695 const CXXRecordDecl *Base = Target.getDeclaringClass();
696
697 // FIXME: fail correctly when there are dependent paths.
698 bool isDerived = Derived->isDerivedFrom(const_cast<CXXRecordDecl*>(Base),
699 Paths);
John McCall6b2accb2010-02-10 09:31:12 +0000700 assert(isDerived && "derived class not actually derived from base");
701 (void) isDerived;
702
703 CXXBasePath *BestPath = 0;
704
John McCall7aceaf82010-03-18 23:49:19 +0000705 assert(FinalAccess != AS_none && "forbidden access after declaring class");
706
John McCall0c01d182010-03-24 05:22:00 +0000707 bool AnyDependent = false;
708
John McCall6b2accb2010-02-10 09:31:12 +0000709 // Derive the friend-modified access along each path.
710 for (CXXBasePaths::paths_iterator PI = Paths.begin(), PE = Paths.end();
711 PI != PE; ++PI) {
John McCall161755a2010-04-06 21:38:20 +0000712 AccessTarget::SavedInstanceContext _ = Target.saveInstanceContext();
John McCall6b2accb2010-02-10 09:31:12 +0000713
714 // Walk through the path backwards.
John McCall7aceaf82010-03-18 23:49:19 +0000715 AccessSpecifier PathAccess = FinalAccess;
John McCall6b2accb2010-02-10 09:31:12 +0000716 CXXBasePath::iterator I = PI->end(), E = PI->begin();
717 while (I != E) {
718 --I;
719
John McCall7aceaf82010-03-18 23:49:19 +0000720 assert(PathAccess != AS_none);
721
722 // If the declaration is a private member of a base class, there
723 // is no level of friendship in derived classes that can make it
724 // accessible.
725 if (PathAccess == AS_private) {
726 PathAccess = AS_none;
727 break;
728 }
729
John McCall161755a2010-04-06 21:38:20 +0000730 const CXXRecordDecl *NC = I->Class->getCanonicalDecl();
731
John McCall6b2accb2010-02-10 09:31:12 +0000732 AccessSpecifier BaseAccess = I->Base->getAccessSpecifier();
John McCalldb73c682010-04-02 00:03:43 +0000733 PathAccess = std::max(PathAccess, BaseAccess);
John McCall161755a2010-04-06 21:38:20 +0000734
735 switch (HasAccess(S, EC, NC, PathAccess, Target)) {
736 case AR_inaccessible: break;
737 case AR_accessible:
738 PathAccess = AS_public;
739
740 // Future tests are not against members and so do not have
741 // instance context.
742 Target.suppressInstanceContext();
743 break;
744 case AR_dependent:
John McCalldb73c682010-04-02 00:03:43 +0000745 AnyDependent = true;
746 goto Next;
John McCall6b2accb2010-02-10 09:31:12 +0000747 }
John McCall6b2accb2010-02-10 09:31:12 +0000748 }
749
750 // Note that we modify the path's Access field to the
751 // friend-modified access.
752 if (BestPath == 0 || PathAccess < BestPath->Access) {
753 BestPath = &*PI;
754 BestPath->Access = PathAccess;
John McCall0c01d182010-03-24 05:22:00 +0000755
756 // Short-circuit if we found a public path.
757 if (BestPath->Access == AS_public)
758 return BestPath;
John McCall6b2accb2010-02-10 09:31:12 +0000759 }
John McCall0c01d182010-03-24 05:22:00 +0000760
761 Next: ;
John McCall6b2accb2010-02-10 09:31:12 +0000762 }
763
John McCall0c01d182010-03-24 05:22:00 +0000764 assert((!BestPath || BestPath->Access != AS_public) &&
765 "fell out of loop with public path");
766
767 // We didn't find a public path, but at least one path was subject
768 // to dependent friendship, so delay the check.
769 if (AnyDependent)
770 return 0;
771
John McCall6b2accb2010-02-10 09:31:12 +0000772 return BestPath;
773}
774
775/// Diagnose the path which caused the given declaration or base class
776/// to become inaccessible.
777static void DiagnoseAccessPath(Sema &S,
778 const EffectiveContext &EC,
John McCall161755a2010-04-06 21:38:20 +0000779 AccessTarget &Entity) {
John McCalldb73c682010-04-02 00:03:43 +0000780 AccessSpecifier Access = Entity.getAccess();
John McCall161755a2010-04-06 21:38:20 +0000781 const CXXRecordDecl *NamingClass = Entity.getNamingClass();
John McCalldb73c682010-04-02 00:03:43 +0000782 NamingClass = NamingClass->getCanonicalDecl();
783
John McCall161755a2010-04-06 21:38:20 +0000784 NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : 0);
785 const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();
John McCalldb73c682010-04-02 00:03:43 +0000786
John McCall92f88312010-01-23 00:46:32 +0000787 // Easy case: the decl's natural access determined its path access.
John McCall6b2accb2010-02-10 09:31:12 +0000788 // We have to check against AS_private here in case Access is AS_none,
789 // indicating a non-public member of a private base class.
John McCall6b2accb2010-02-10 09:31:12 +0000790 if (D && (Access == D->getAccess() || D->getAccess() == AS_private)) {
John McCall161755a2010-04-06 21:38:20 +0000791 switch (HasAccess(S, EC, DeclaringClass, D->getAccess(), Entity)) {
792 case AR_inaccessible: {
John McCall6b2accb2010-02-10 09:31:12 +0000793 S.Diag(D->getLocation(), diag::note_access_natural)
794 << (unsigned) (Access == AS_protected)
795 << /*FIXME: not implicitly*/ 0;
796 return;
797 }
798
John McCall161755a2010-04-06 21:38:20 +0000799 case AR_accessible: break;
John McCall6b2accb2010-02-10 09:31:12 +0000800
John McCall161755a2010-04-06 21:38:20 +0000801 case AR_dependent:
802 llvm_unreachable("can't diagnose dependent access failures");
John McCall6b2accb2010-02-10 09:31:12 +0000803 return;
804 }
805 }
806
807 CXXBasePaths Paths;
John McCall161755a2010-04-06 21:38:20 +0000808 CXXBasePath &Path = *FindBestPath(S, EC, Entity, AS_public, Paths);
John McCall6b2accb2010-02-10 09:31:12 +0000809
810 CXXBasePath::iterator I = Path.end(), E = Path.begin();
811 while (I != E) {
812 --I;
813
814 const CXXBaseSpecifier *BS = I->Base;
815 AccessSpecifier BaseAccess = BS->getAccessSpecifier();
816
817 // If this is public inheritance, or the derived class is a friend,
818 // skip this step.
819 if (BaseAccess == AS_public)
820 continue;
821
822 switch (GetFriendKind(S, EC, I->Class)) {
John McCall161755a2010-04-06 21:38:20 +0000823 case AR_accessible: continue;
824 case AR_inaccessible: break;
825 case AR_dependent:
826 llvm_unreachable("can't diagnose dependent access failures");
John McCall6b2accb2010-02-10 09:31:12 +0000827 }
828
829 // Check whether this base specifier is the tighest point
830 // constraining access. We have to check against AS_private for
831 // the same reasons as above.
832 if (BaseAccess == AS_private || BaseAccess >= Access) {
833
834 // We're constrained by inheritance, but we want to say
835 // "declared private here" if we're diagnosing a hierarchy
836 // conversion and this is the final step.
837 unsigned diagnostic;
838 if (D) diagnostic = diag::note_access_constrained_by_path;
839 else if (I + 1 == Path.end()) diagnostic = diag::note_access_natural;
840 else diagnostic = diag::note_access_constrained_by_path;
841
842 S.Diag(BS->getSourceRange().getBegin(), diagnostic)
843 << BS->getSourceRange()
844 << (BaseAccess == AS_protected)
845 << (BS->getAccessSpecifierAsWritten() == AS_none);
846 return;
847 }
848 }
849
850 llvm_unreachable("access not apparently constrained by path");
851}
852
John McCall58e6f342010-03-16 05:22:47 +0000853static void DiagnoseBadAccess(Sema &S, SourceLocation Loc,
John McCall6b2accb2010-02-10 09:31:12 +0000854 const EffectiveContext &EC,
John McCall161755a2010-04-06 21:38:20 +0000855 AccessTarget &Entity) {
John McCalldb73c682010-04-02 00:03:43 +0000856 const CXXRecordDecl *NamingClass = Entity.getNamingClass();
John McCall161755a2010-04-06 21:38:20 +0000857 const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();
858 NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : 0);
John McCalldb73c682010-04-02 00:03:43 +0000859
860 S.Diag(Loc, Entity.getDiag())
861 << (Entity.getAccess() == AS_protected)
862 << (D ? D->getDeclName() : DeclarationName())
863 << S.Context.getTypeDeclType(NamingClass)
864 << S.Context.getTypeDeclType(DeclaringClass);
865 DiagnoseAccessPath(S, EC, Entity);
John McCall6b2accb2010-02-10 09:31:12 +0000866}
867
John McCalldb73c682010-04-02 00:03:43 +0000868/// Determines whether the accessed entity is accessible. Public members
869/// have been weeded out by this point.
John McCall161755a2010-04-06 21:38:20 +0000870static AccessResult IsAccessible(Sema &S,
871 const EffectiveContext &EC,
872 AccessTarget &Entity) {
John McCalldb73c682010-04-02 00:03:43 +0000873 // Determine the actual naming class.
874 CXXRecordDecl *NamingClass = Entity.getNamingClass();
875 while (NamingClass->isAnonymousStructOrUnion())
876 NamingClass = cast<CXXRecordDecl>(NamingClass->getParent());
877 NamingClass = NamingClass->getCanonicalDecl();
John McCall6b2accb2010-02-10 09:31:12 +0000878
John McCalldb73c682010-04-02 00:03:43 +0000879 AccessSpecifier UnprivilegedAccess = Entity.getAccess();
880 assert(UnprivilegedAccess != AS_public && "public access not weeded out");
881
882 // Before we try to recalculate access paths, try to white-list
883 // accesses which just trade in on the final step, i.e. accesses
884 // which don't require [M4] or [B4]. These are by far the most
John McCall161755a2010-04-06 21:38:20 +0000885 // common forms of privileged access.
John McCalldb73c682010-04-02 00:03:43 +0000886 if (UnprivilegedAccess != AS_none) {
John McCall161755a2010-04-06 21:38:20 +0000887 switch (HasAccess(S, EC, NamingClass, UnprivilegedAccess, Entity)) {
888 case AR_dependent:
John McCalldb73c682010-04-02 00:03:43 +0000889 // This is actually an interesting policy decision. We don't
890 // *have* to delay immediately here: we can do the full access
891 // calculation in the hope that friendship on some intermediate
892 // class will make the declaration accessible non-dependently.
893 // But that's not cheap, and odds are very good (note: assertion
894 // made without data) that the friend declaration will determine
895 // access.
John McCall161755a2010-04-06 21:38:20 +0000896 return AR_dependent;
John McCalldb73c682010-04-02 00:03:43 +0000897
John McCall161755a2010-04-06 21:38:20 +0000898 case AR_accessible: return AR_accessible;
899 case AR_inaccessible: break;
John McCalldb73c682010-04-02 00:03:43 +0000900 }
901 }
902
John McCall161755a2010-04-06 21:38:20 +0000903 AccessTarget::SavedInstanceContext _ = Entity.saveInstanceContext();
John McCall6b2accb2010-02-10 09:31:12 +0000904
John McCalldb73c682010-04-02 00:03:43 +0000905 // We lower member accesses to base accesses by pretending that the
906 // member is a base class of its declaring class.
907 AccessSpecifier FinalAccess;
908
John McCall6b2accb2010-02-10 09:31:12 +0000909 if (Entity.isMemberAccess()) {
John McCalldb73c682010-04-02 00:03:43 +0000910 // Determine if the declaration is accessible from EC when named
911 // in its declaring class.
John McCall6b2accb2010-02-10 09:31:12 +0000912 NamedDecl *Target = Entity.getTargetDecl();
John McCall161755a2010-04-06 21:38:20 +0000913 const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();
John McCall6b2accb2010-02-10 09:31:12 +0000914
John McCalldb73c682010-04-02 00:03:43 +0000915 FinalAccess = Target->getAccess();
John McCall161755a2010-04-06 21:38:20 +0000916 switch (HasAccess(S, EC, DeclaringClass, FinalAccess, Entity)) {
917 case AR_accessible:
918 FinalAccess = AS_public;
919 break;
920 case AR_inaccessible: break;
921 case AR_dependent: return AR_dependent; // see above
John McCall6b2accb2010-02-10 09:31:12 +0000922 }
923
John McCalldb73c682010-04-02 00:03:43 +0000924 if (DeclaringClass == NamingClass)
John McCall161755a2010-04-06 21:38:20 +0000925 return (FinalAccess == AS_public ? AR_accessible : AR_inaccessible);
926
927 Entity.suppressInstanceContext();
John McCalldb73c682010-04-02 00:03:43 +0000928 } else {
929 FinalAccess = AS_public;
John McCall6b2accb2010-02-10 09:31:12 +0000930 }
931
John McCall161755a2010-04-06 21:38:20 +0000932 assert(Entity.getDeclaringClass() != NamingClass);
John McCall6b2accb2010-02-10 09:31:12 +0000933
934 // Append the declaration's access if applicable.
935 CXXBasePaths Paths;
John McCall161755a2010-04-06 21:38:20 +0000936 CXXBasePath *Path = FindBestPath(S, EC, Entity, FinalAccess, Paths);
John McCall0c01d182010-03-24 05:22:00 +0000937 if (!Path)
John McCall161755a2010-04-06 21:38:20 +0000938 return AR_dependent;
John McCall92f88312010-01-23 00:46:32 +0000939
John McCalldb73c682010-04-02 00:03:43 +0000940 assert(Path->Access <= UnprivilegedAccess &&
941 "access along best path worse than direct?");
942 if (Path->Access == AS_public)
John McCall161755a2010-04-06 21:38:20 +0000943 return AR_accessible;
944 return AR_inaccessible;
John McCall0c01d182010-03-24 05:22:00 +0000945}
946
John McCall161755a2010-04-06 21:38:20 +0000947static void DelayDependentAccess(Sema &S,
948 const EffectiveContext &EC,
949 SourceLocation Loc,
950 const AccessTarget &Entity) {
John McCall0c01d182010-03-24 05:22:00 +0000951 assert(EC.isDependent() && "delaying non-dependent access");
John McCall7ad650f2010-03-24 07:46:06 +0000952 DeclContext *DC = EC.getInnerContext();
John McCall0c01d182010-03-24 05:22:00 +0000953 assert(DC->isDependentContext() && "delaying non-dependent access");
954 DependentDiagnostic::Create(S.Context, DC, DependentDiagnostic::Access,
955 Loc,
956 Entity.isMemberAccess(),
957 Entity.getAccess(),
958 Entity.getTargetDecl(),
959 Entity.getNamingClass(),
John McCall161755a2010-04-06 21:38:20 +0000960 Entity.getBaseObjectType(),
John McCall0c01d182010-03-24 05:22:00 +0000961 Entity.getDiag());
John McCall92f88312010-01-23 00:46:32 +0000962}
963
John McCall6b2accb2010-02-10 09:31:12 +0000964/// Checks access to an entity from the given effective context.
John McCall161755a2010-04-06 21:38:20 +0000965static AccessResult CheckEffectiveAccess(Sema &S,
966 const EffectiveContext &EC,
967 SourceLocation Loc,
968 AccessTarget &Entity) {
John McCalldb73c682010-04-02 00:03:43 +0000969 assert(Entity.getAccess() != AS_public && "called for public access!");
John McCall92f88312010-01-23 00:46:32 +0000970
John McCalldb73c682010-04-02 00:03:43 +0000971 switch (IsAccessible(S, EC, Entity)) {
John McCall161755a2010-04-06 21:38:20 +0000972 case AR_dependent:
973 DelayDependentAccess(S, EC, Loc, Entity);
974 return AR_dependent;
John McCalldb73c682010-04-02 00:03:43 +0000975
John McCall161755a2010-04-06 21:38:20 +0000976 case AR_inaccessible:
John McCalldb73c682010-04-02 00:03:43 +0000977 if (!Entity.isQuiet())
978 DiagnoseBadAccess(S, Loc, EC, Entity);
John McCall161755a2010-04-06 21:38:20 +0000979 return AR_inaccessible;
John McCalldb73c682010-04-02 00:03:43 +0000980
John McCall161755a2010-04-06 21:38:20 +0000981 case AR_accessible:
982 return AR_accessible;
John McCall0c01d182010-03-24 05:22:00 +0000983 }
984
John McCall161755a2010-04-06 21:38:20 +0000985 // silence unnecessary warning
986 llvm_unreachable("invalid access result");
987 return AR_accessible;
John McCall6b2accb2010-02-10 09:31:12 +0000988}
John McCall92f88312010-01-23 00:46:32 +0000989
John McCall6b2accb2010-02-10 09:31:12 +0000990static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc,
John McCall161755a2010-04-06 21:38:20 +0000991 AccessTarget &Entity) {
John McCall6b2accb2010-02-10 09:31:12 +0000992 // If the access path is public, it's accessible everywhere.
993 if (Entity.getAccess() == AS_public)
994 return Sema::AR_accessible;
John McCall92f88312010-01-23 00:46:32 +0000995
John McCall6b2accb2010-02-10 09:31:12 +0000996 // If we're currently parsing a top-level declaration, delay
997 // diagnostics. This is the only case where parsing a declaration
998 // can actually change our effective context for the purposes of
999 // access control.
1000 if (S.CurContext->isFileContext() && S.ParsingDeclDepth) {
John McCall6b2accb2010-02-10 09:31:12 +00001001 S.DelayedDiagnostics.push_back(
1002 Sema::DelayedDiagnostic::makeAccess(Loc, Entity));
1003 return Sema::AR_delayed;
John McCall92f88312010-01-23 00:46:32 +00001004 }
1005
John McCall161755a2010-04-06 21:38:20 +00001006 EffectiveContext EC(S.CurContext);
1007 switch (CheckEffectiveAccess(S, EC, Loc, Entity)) {
1008 case AR_accessible: return Sema::AR_accessible;
1009 case AR_inaccessible: return Sema::AR_inaccessible;
1010 case AR_dependent: return Sema::AR_dependent;
1011 }
1012 llvm_unreachable("falling off end");
1013 return Sema::AR_accessible;
John McCall92f88312010-01-23 00:46:32 +00001014}
1015
John McCall2f514482010-01-27 03:50:35 +00001016void Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *Ctx) {
John McCall2f514482010-01-27 03:50:35 +00001017 // Pretend we did this from the context of the newly-parsed
1018 // declaration.
John McCall6b2accb2010-02-10 09:31:12 +00001019 EffectiveContext EC(Ctx->getDeclContext());
John McCall2f514482010-01-27 03:50:35 +00001020
John McCall161755a2010-04-06 21:38:20 +00001021 AccessTarget Target(DD.getAccessData());
1022
1023 if (CheckEffectiveAccess(*this, EC, DD.Loc, Target) == ::AR_inaccessible)
John McCall2f514482010-01-27 03:50:35 +00001024 DD.Triggered = true;
1025}
1026
John McCall0c01d182010-03-24 05:22:00 +00001027void Sema::HandleDependentAccessCheck(const DependentDiagnostic &DD,
1028 const MultiLevelTemplateArgumentList &TemplateArgs) {
1029 SourceLocation Loc = DD.getAccessLoc();
1030 AccessSpecifier Access = DD.getAccess();
1031
1032 Decl *NamingD = FindInstantiatedDecl(Loc, DD.getAccessNamingClass(),
1033 TemplateArgs);
1034 if (!NamingD) return;
1035 Decl *TargetD = FindInstantiatedDecl(Loc, DD.getAccessTarget(),
1036 TemplateArgs);
1037 if (!TargetD) return;
1038
1039 if (DD.isAccessToMember()) {
John McCall161755a2010-04-06 21:38:20 +00001040 CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(NamingD);
1041 NamedDecl *TargetDecl = cast<NamedDecl>(TargetD);
1042 QualType BaseObjectType = DD.getAccessBaseObjectType();
1043 if (!BaseObjectType.isNull()) {
1044 BaseObjectType = SubstType(BaseObjectType, TemplateArgs, Loc,
1045 DeclarationName());
1046 if (BaseObjectType.isNull()) return;
1047 }
1048
1049 AccessTarget Entity(Context,
1050 AccessTarget::Member,
1051 NamingClass,
1052 DeclAccessPair::make(TargetDecl, Access),
1053 BaseObjectType);
John McCall0c01d182010-03-24 05:22:00 +00001054 Entity.setDiag(DD.getDiagnostic());
1055 CheckAccess(*this, Loc, Entity);
1056 } else {
John McCall161755a2010-04-06 21:38:20 +00001057 AccessTarget Entity(Context,
1058 AccessTarget::Base,
1059 cast<CXXRecordDecl>(TargetD),
1060 cast<CXXRecordDecl>(NamingD),
1061 Access);
John McCall0c01d182010-03-24 05:22:00 +00001062 Entity.setDiag(DD.getDiagnostic());
1063 CheckAccess(*this, Loc, Entity);
1064 }
1065}
1066
John McCall6b2accb2010-02-10 09:31:12 +00001067Sema::AccessResult Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E,
John McCall9aa472c2010-03-19 07:35:19 +00001068 DeclAccessPair Found) {
John McCall58e6f342010-03-16 05:22:47 +00001069 if (!getLangOptions().AccessControl ||
1070 !E->getNamingClass() ||
John McCall9aa472c2010-03-19 07:35:19 +00001071 Found.getAccess() == AS_public)
John McCall6b2accb2010-02-10 09:31:12 +00001072 return AR_accessible;
John McCallc373d482010-01-27 01:50:18 +00001073
John McCall161755a2010-04-06 21:38:20 +00001074 AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(),
1075 Found, QualType());
John McCall58e6f342010-03-16 05:22:47 +00001076 Entity.setDiag(diag::err_access) << E->getSourceRange();
1077
1078 return CheckAccess(*this, E->getNameLoc(), Entity);
John McCallc373d482010-01-27 01:50:18 +00001079}
1080
1081/// Perform access-control checking on a previously-unresolved member
1082/// access which has now been resolved to a member.
John McCall6b2accb2010-02-10 09:31:12 +00001083Sema::AccessResult Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E,
John McCall9aa472c2010-03-19 07:35:19 +00001084 DeclAccessPair Found) {
John McCall58e6f342010-03-16 05:22:47 +00001085 if (!getLangOptions().AccessControl ||
John McCall9aa472c2010-03-19 07:35:19 +00001086 Found.getAccess() == AS_public)
John McCall6b2accb2010-02-10 09:31:12 +00001087 return AR_accessible;
John McCallc373d482010-01-27 01:50:18 +00001088
John McCall161755a2010-04-06 21:38:20 +00001089 QualType BaseType = E->getBaseType();
1090 if (E->isArrow())
1091 BaseType = BaseType->getAs<PointerType>()->getPointeeType();
1092
1093 AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(),
1094 Found, BaseType);
John McCall58e6f342010-03-16 05:22:47 +00001095 Entity.setDiag(diag::err_access) << E->getSourceRange();
1096
1097 return CheckAccess(*this, E->getMemberLoc(), Entity);
John McCallc373d482010-01-27 01:50:18 +00001098}
1099
John McCall6b2accb2010-02-10 09:31:12 +00001100Sema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc,
John McCall58e6f342010-03-16 05:22:47 +00001101 CXXDestructorDecl *Dtor,
1102 const PartialDiagnostic &PDiag) {
John McCall4f9506a2010-02-02 08:45:54 +00001103 if (!getLangOptions().AccessControl)
John McCall6b2accb2010-02-10 09:31:12 +00001104 return AR_accessible;
John McCall4f9506a2010-02-02 08:45:54 +00001105
John McCall58e6f342010-03-16 05:22:47 +00001106 // There's never a path involved when checking implicit destructor access.
John McCall4f9506a2010-02-02 08:45:54 +00001107 AccessSpecifier Access = Dtor->getAccess();
1108 if (Access == AS_public)
John McCall6b2accb2010-02-10 09:31:12 +00001109 return AR_accessible;
John McCall4f9506a2010-02-02 08:45:54 +00001110
John McCall58e6f342010-03-16 05:22:47 +00001111 CXXRecordDecl *NamingClass = Dtor->getParent();
John McCall161755a2010-04-06 21:38:20 +00001112 AccessTarget Entity(Context, AccessTarget::Member, NamingClass,
1113 DeclAccessPair::make(Dtor, Access),
1114 QualType());
John McCall58e6f342010-03-16 05:22:47 +00001115 Entity.setDiag(PDiag); // TODO: avoid copy
1116
1117 return CheckAccess(*this, Loc, Entity);
John McCall4f9506a2010-02-02 08:45:54 +00001118}
1119
John McCallb13b7372010-02-01 03:16:54 +00001120/// Checks access to a constructor.
John McCall6b2accb2010-02-10 09:31:12 +00001121Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc,
John McCallb13b7372010-02-01 03:16:54 +00001122 CXXConstructorDecl *Constructor,
1123 AccessSpecifier Access) {
John McCall58e6f342010-03-16 05:22:47 +00001124 if (!getLangOptions().AccessControl ||
1125 Access == AS_public)
John McCall6b2accb2010-02-10 09:31:12 +00001126 return AR_accessible;
John McCallb13b7372010-02-01 03:16:54 +00001127
John McCall6b2accb2010-02-10 09:31:12 +00001128 CXXRecordDecl *NamingClass = Constructor->getParent();
John McCall161755a2010-04-06 21:38:20 +00001129 AccessTarget Entity(Context, AccessTarget::Member, NamingClass,
1130 DeclAccessPair::make(Constructor, Access),
1131 QualType());
John McCall58e6f342010-03-16 05:22:47 +00001132 Entity.setDiag(diag::err_access_ctor);
1133
1134 return CheckAccess(*this, UseLoc, Entity);
John McCallb13b7372010-02-01 03:16:54 +00001135}
1136
John McCallb0207482010-03-16 06:11:48 +00001137/// Checks direct (i.e. non-inherited) access to an arbitrary class
1138/// member.
1139Sema::AccessResult Sema::CheckDirectMemberAccess(SourceLocation UseLoc,
1140 NamedDecl *Target,
1141 const PartialDiagnostic &Diag) {
1142 AccessSpecifier Access = Target->getAccess();
1143 if (!getLangOptions().AccessControl ||
1144 Access == AS_public)
1145 return AR_accessible;
1146
1147 CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(Target->getDeclContext());
John McCall161755a2010-04-06 21:38:20 +00001148 AccessTarget Entity(Context, AccessTarget::Member, NamingClass,
1149 DeclAccessPair::make(Target, Access),
1150 QualType());
John McCallb0207482010-03-16 06:11:48 +00001151 Entity.setDiag(Diag);
1152 return CheckAccess(*this, UseLoc, Entity);
1153}
1154
1155
John McCall90c8c572010-03-18 08:19:33 +00001156/// Checks access to an overloaded operator new or delete.
1157Sema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc,
1158 SourceRange PlacementRange,
1159 CXXRecordDecl *NamingClass,
John McCall9aa472c2010-03-19 07:35:19 +00001160 DeclAccessPair Found) {
John McCall90c8c572010-03-18 08:19:33 +00001161 if (!getLangOptions().AccessControl ||
1162 !NamingClass ||
John McCall9aa472c2010-03-19 07:35:19 +00001163 Found.getAccess() == AS_public)
John McCall90c8c572010-03-18 08:19:33 +00001164 return AR_accessible;
1165
John McCall161755a2010-04-06 21:38:20 +00001166 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
1167 QualType());
John McCall90c8c572010-03-18 08:19:33 +00001168 Entity.setDiag(diag::err_access)
1169 << PlacementRange;
1170
1171 return CheckAccess(*this, OpLoc, Entity);
1172}
1173
John McCallb13b7372010-02-01 03:16:54 +00001174/// Checks access to an overloaded member operator, including
1175/// conversion operators.
John McCall6b2accb2010-02-10 09:31:12 +00001176Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc,
1177 Expr *ObjectExpr,
John McCall58e6f342010-03-16 05:22:47 +00001178 Expr *ArgExpr,
John McCall9aa472c2010-03-19 07:35:19 +00001179 DeclAccessPair Found) {
John McCall58e6f342010-03-16 05:22:47 +00001180 if (!getLangOptions().AccessControl ||
John McCall9aa472c2010-03-19 07:35:19 +00001181 Found.getAccess() == AS_public)
John McCall6b2accb2010-02-10 09:31:12 +00001182 return AR_accessible;
John McCall5357b612010-01-28 01:42:12 +00001183
1184 const RecordType *RT = ObjectExpr->getType()->getAs<RecordType>();
1185 assert(RT && "found member operator but object expr not of record type");
1186 CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(RT->getDecl());
1187
John McCall161755a2010-04-06 21:38:20 +00001188 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
1189 ObjectExpr->getType());
John McCall58e6f342010-03-16 05:22:47 +00001190 Entity.setDiag(diag::err_access)
1191 << ObjectExpr->getSourceRange()
1192 << (ArgExpr ? ArgExpr->getSourceRange() : SourceRange());
1193
1194 return CheckAccess(*this, OpLoc, Entity);
John McCall6b2accb2010-02-10 09:31:12 +00001195}
John McCall5357b612010-01-28 01:42:12 +00001196
John McCall6bb80172010-03-30 21:47:33 +00001197Sema::AccessResult Sema::CheckAddressOfMemberAccess(Expr *OvlExpr,
1198 DeclAccessPair Found) {
1199 if (!getLangOptions().AccessControl ||
John McCalle2f5ba92010-03-30 22:20:00 +00001200 Found.getAccess() == AS_none ||
John McCall6bb80172010-03-30 21:47:33 +00001201 Found.getAccess() == AS_public)
1202 return AR_accessible;
1203
1204 OverloadExpr *Ovl = OverloadExpr::find(OvlExpr).getPointer();
1205 NestedNameSpecifier *Qualifier = Ovl->getQualifier();
1206 assert(Qualifier && "address of overloaded member without qualifier");
1207
1208 CXXScopeSpec SS;
1209 SS.setScopeRep(Qualifier);
1210 SS.setRange(Ovl->getQualifierRange());
1211 DeclContext *DC = computeDeclContext(SS);
1212 assert(DC && DC->isRecord() && "scope did not resolve to record");
1213 CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(DC);
1214
John McCall161755a2010-04-06 21:38:20 +00001215 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
1216 Context.getTypeDeclType(NamingClass));
John McCall6bb80172010-03-30 21:47:33 +00001217 Entity.setDiag(diag::err_access)
1218 << Ovl->getSourceRange();
1219
1220 return CheckAccess(*this, Ovl->getNameLoc(), Entity);
1221}
1222
John McCall6b2accb2010-02-10 09:31:12 +00001223/// Checks access for a hierarchy conversion.
1224///
1225/// \param IsBaseToDerived whether this is a base-to-derived conversion (true)
1226/// or a derived-to-base conversion (false)
1227/// \param ForceCheck true if this check should be performed even if access
1228/// control is disabled; some things rely on this for semantics
1229/// \param ForceUnprivileged true if this check should proceed as if the
1230/// context had no special privileges
1231/// \param ADK controls the kind of diagnostics that are used
1232Sema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc,
John McCall6b2accb2010-02-10 09:31:12 +00001233 QualType Base,
1234 QualType Derived,
1235 const CXXBasePath &Path,
John McCall58e6f342010-03-16 05:22:47 +00001236 unsigned DiagID,
John McCall6b2accb2010-02-10 09:31:12 +00001237 bool ForceCheck,
John McCall58e6f342010-03-16 05:22:47 +00001238 bool ForceUnprivileged) {
John McCall6b2accb2010-02-10 09:31:12 +00001239 if (!ForceCheck && !getLangOptions().AccessControl)
1240 return AR_accessible;
John McCall5357b612010-01-28 01:42:12 +00001241
John McCall6b2accb2010-02-10 09:31:12 +00001242 if (Path.Access == AS_public)
1243 return AR_accessible;
John McCall5357b612010-01-28 01:42:12 +00001244
John McCall6b2accb2010-02-10 09:31:12 +00001245 CXXRecordDecl *BaseD, *DerivedD;
1246 BaseD = cast<CXXRecordDecl>(Base->getAs<RecordType>()->getDecl());
1247 DerivedD = cast<CXXRecordDecl>(Derived->getAs<RecordType>()->getDecl());
John McCall58e6f342010-03-16 05:22:47 +00001248
John McCall161755a2010-04-06 21:38:20 +00001249 AccessTarget Entity(Context, AccessTarget::Base, BaseD, DerivedD,
1250 Path.Access);
John McCall58e6f342010-03-16 05:22:47 +00001251 if (DiagID)
1252 Entity.setDiag(DiagID) << Derived << Base;
John McCall6b2accb2010-02-10 09:31:12 +00001253
John McCall161755a2010-04-06 21:38:20 +00001254 if (ForceUnprivileged) {
1255 switch (CheckEffectiveAccess(*this, EffectiveContext(),
1256 AccessLoc, Entity)) {
1257 case ::AR_accessible: return Sema::AR_accessible;
1258 case ::AR_inaccessible: return Sema::AR_inaccessible;
1259 case ::AR_dependent: return Sema::AR_dependent;
1260 }
1261 llvm_unreachable("unexpected result from CheckEffectiveAccess");
1262 }
John McCall58e6f342010-03-16 05:22:47 +00001263 return CheckAccess(*this, AccessLoc, Entity);
John McCall5357b612010-01-28 01:42:12 +00001264}
1265
John McCall92f88312010-01-23 00:46:32 +00001266/// Checks access to all the declarations in the given result set.
John McCall6b2accb2010-02-10 09:31:12 +00001267void Sema::CheckLookupAccess(const LookupResult &R) {
1268 assert(getLangOptions().AccessControl
1269 && "performing access check without access control");
1270 assert(R.getNamingClass() && "performing access check without naming class");
1271
John McCall58e6f342010-03-16 05:22:47 +00001272 for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
1273 if (I.getAccess() != AS_public) {
John McCall161755a2010-04-06 21:38:20 +00001274 AccessTarget Entity(Context, AccessedEntity::Member,
1275 R.getNamingClass(), I.getPair(),
1276 R.getBaseObjectType());
John McCall58e6f342010-03-16 05:22:47 +00001277 Entity.setDiag(diag::err_access);
1278
1279 CheckAccess(*this, R.getNameLoc(), Entity);
1280 }
1281 }
John McCall92f88312010-01-23 00:46:32 +00001282}