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

source code of clang/lib/Sema/SemaAccess.cpp