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