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