1 //===---- SemaAccess.cpp - C++ Access Control -------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // This file provides Sema routines for C++ access control semantics.
11 //===----------------------------------------------------------------------===//
13 #include "clang/Basic/Specifiers.h"
14 #include "clang/Sema/SemaInternal.h"
15 #include "clang/AST/ASTContext.h"
16 #include "clang/AST/CXXInheritance.h"
17 #include "clang/AST/DeclCXX.h"
18 #include "clang/AST/DeclFriend.h"
19 #include "clang/AST/DeclObjC.h"
20 #include "clang/AST/DependentDiagnostic.h"
21 #include "clang/AST/ExprCXX.h"
22 #include "clang/Sema/DelayedDiagnostic.h"
23 #include "clang/Sema/Initialization.h"
24 #include "clang/Sema/Lookup.h"
26 using namespace clang
;
29 /// A copy of Sema's enum without AR_delayed.
36 /// SetMemberAccessSpecifier - Set the access specifier of a member.
37 /// Returns true on error (when the previous member decl access specifier
38 /// is different from the new member decl access specifier).
39 bool Sema::SetMemberAccessSpecifier(NamedDecl
*MemberDecl
,
40 NamedDecl
*PrevMemberDecl
,
41 AccessSpecifier LexicalAS
) {
42 if (!PrevMemberDecl
) {
43 // Use the lexical access specifier.
44 MemberDecl
->setAccess(LexicalAS
);
48 // C++ [class.access.spec]p3: When a member is redeclared its access
49 // specifier must be same as its initial declaration.
50 if (LexicalAS
!= AS_none
&& LexicalAS
!= PrevMemberDecl
->getAccess()) {
51 Diag(MemberDecl
->getLocation(),
52 diag::err_class_redeclared_with_different_access
)
53 << MemberDecl
<< LexicalAS
;
54 Diag(PrevMemberDecl
->getLocation(), diag::note_previous_access_declaration
)
55 << PrevMemberDecl
<< PrevMemberDecl
->getAccess();
57 MemberDecl
->setAccess(LexicalAS
);
61 MemberDecl
->setAccess(PrevMemberDecl
->getAccess());
65 static CXXRecordDecl
*FindDeclaringClass(NamedDecl
*D
) {
66 DeclContext
*DC
= D
->getDeclContext();
68 // This can only happen at top: enum decls only "publish" their
70 if (isa
<EnumDecl
>(DC
))
71 DC
= cast
<EnumDecl
>(DC
)->getDeclContext();
73 CXXRecordDecl
*DeclaringClass
= cast
<CXXRecordDecl
>(DC
);
74 while (DeclaringClass
->isAnonymousStructOrUnion())
75 DeclaringClass
= cast
<CXXRecordDecl
>(DeclaringClass
->getDeclContext());
76 return DeclaringClass
;
80 struct EffectiveContext
{
81 EffectiveContext() : Inner(nullptr), Dependent(false) {}
83 explicit EffectiveContext(DeclContext
*DC
)
85 Dependent(DC
->isDependentContext()) {
87 // An implicit deduction guide is semantically in the context enclosing the
88 // class template, but for access purposes behaves like the constructor
89 // from which it was produced.
90 if (auto *DGD
= dyn_cast
<CXXDeductionGuideDecl
>(DC
)) {
91 if (DGD
->isImplicit()) {
92 DC
= DGD
->getCorrespondingConstructor();
94 // The copy deduction candidate doesn't have a corresponding
96 DC
= cast
<DeclContext
>(DGD
->getDeducedTemplate()->getTemplatedDecl());
101 // C++11 [class.access.nest]p1:
102 // A nested class is a member and as such has the same access
103 // rights as any other member.
104 // C++11 [class.access]p2:
105 // A member of a class can also access all the names to which
106 // the class has access. A local class of a member function
107 // may access the same names that the member function itself
109 // This almost implies that the privileges of nesting are transitive.
110 // Technically it says nothing about the local classes of non-member
111 // functions (which can gain privileges through friendship), but we
112 // take that as an oversight.
114 // We want to add canonical declarations to the EC lists for
115 // simplicity of checking, but we need to walk up through the
116 // actual current DC chain. Otherwise, something like a local
117 // extern or friend which happens to be the canonical
118 // declaration will really mess us up.
120 if (isa
<CXXRecordDecl
>(DC
)) {
121 CXXRecordDecl
*Record
= cast
<CXXRecordDecl
>(DC
);
122 Records
.push_back(Record
->getCanonicalDecl());
123 DC
= Record
->getDeclContext();
124 } else if (isa
<FunctionDecl
>(DC
)) {
125 FunctionDecl
*Function
= cast
<FunctionDecl
>(DC
);
126 Functions
.push_back(Function
->getCanonicalDecl());
127 if (Function
->getFriendObjectKind())
128 DC
= Function
->getLexicalDeclContext();
130 DC
= Function
->getDeclContext();
131 } else if (DC
->isFileContext()) {
134 DC
= DC
->getParent();
139 bool isDependent() const { return Dependent
; }
141 bool includesClass(const CXXRecordDecl
*R
) const {
142 R
= R
->getCanonicalDecl();
143 return llvm::is_contained(Records
, R
);
146 /// Retrieves the innermost "useful" context. Can be null if we're
147 /// doing access-control without privileges.
148 DeclContext
*getInnerContext() const {
152 typedef SmallVectorImpl
<CXXRecordDecl
*>::const_iterator record_iterator
;
155 SmallVector
<FunctionDecl
*, 4> Functions
;
156 SmallVector
<CXXRecordDecl
*, 4> Records
;
160 /// Like sema::AccessedEntity, but kindly lets us scribble all over
162 struct AccessTarget
: public AccessedEntity
{
163 AccessTarget(const AccessedEntity
&Entity
)
164 : AccessedEntity(Entity
) {
168 AccessTarget(ASTContext
&Context
,
170 CXXRecordDecl
*NamingClass
,
171 DeclAccessPair FoundDecl
,
172 QualType BaseObjectType
)
173 : AccessedEntity(Context
.getDiagAllocator(), Member
, NamingClass
,
174 FoundDecl
, BaseObjectType
) {
178 AccessTarget(ASTContext
&Context
,
180 CXXRecordDecl
*BaseClass
,
181 CXXRecordDecl
*DerivedClass
,
182 AccessSpecifier Access
)
183 : AccessedEntity(Context
.getDiagAllocator(), Base
, BaseClass
, DerivedClass
,
188 bool isInstanceMember() const {
189 return (isMemberAccess() && getTargetDecl()->isCXXInstanceMember());
192 bool hasInstanceContext() const {
193 return HasInstanceContext
;
196 class SavedInstanceContext
{
198 SavedInstanceContext(SavedInstanceContext
&&S
)
199 : Target(S
.Target
), Has(S
.Has
) {
202 ~SavedInstanceContext() {
204 Target
->HasInstanceContext
= Has
;
208 friend struct AccessTarget
;
209 explicit SavedInstanceContext(AccessTarget
&Target
)
210 : Target(&Target
), Has(Target
.HasInstanceContext
) {}
211 AccessTarget
*Target
;
215 SavedInstanceContext
saveInstanceContext() {
216 return SavedInstanceContext(*this);
219 void suppressInstanceContext() {
220 HasInstanceContext
= false;
223 const CXXRecordDecl
*resolveInstanceContext(Sema
&S
) const {
224 assert(HasInstanceContext
);
225 if (CalculatedInstanceContext
)
226 return InstanceContext
;
228 CalculatedInstanceContext
= true;
229 DeclContext
*IC
= S
.computeDeclContext(getBaseObjectType());
230 InstanceContext
= (IC
? cast
<CXXRecordDecl
>(IC
)->getCanonicalDecl()
232 return InstanceContext
;
235 const CXXRecordDecl
*getDeclaringClass() const {
236 return DeclaringClass
;
239 /// The "effective" naming class is the canonical non-anonymous
240 /// class containing the actual naming class.
241 const CXXRecordDecl
*getEffectiveNamingClass() const {
242 const CXXRecordDecl
*namingClass
= getNamingClass();
243 while (namingClass
->isAnonymousStructOrUnion())
244 namingClass
= cast
<CXXRecordDecl
>(namingClass
->getParent());
245 return namingClass
->getCanonicalDecl();
250 HasInstanceContext
= (isMemberAccess() &&
251 !getBaseObjectType().isNull() &&
252 getTargetDecl()->isCXXInstanceMember());
253 CalculatedInstanceContext
= false;
254 InstanceContext
= nullptr;
256 if (isMemberAccess())
257 DeclaringClass
= FindDeclaringClass(getTargetDecl());
259 DeclaringClass
= getBaseClass();
260 DeclaringClass
= DeclaringClass
->getCanonicalDecl();
263 bool HasInstanceContext
: 1;
264 mutable bool CalculatedInstanceContext
: 1;
265 mutable const CXXRecordDecl
*InstanceContext
;
266 const CXXRecordDecl
*DeclaringClass
;
271 /// Checks whether one class might instantiate to the other.
272 static bool MightInstantiateTo(const CXXRecordDecl
*From
,
273 const CXXRecordDecl
*To
) {
274 // Declaration names are always preserved by instantiation.
275 if (From
->getDeclName() != To
->getDeclName())
278 const DeclContext
*FromDC
= From
->getDeclContext()->getPrimaryContext();
279 const DeclContext
*ToDC
= To
->getDeclContext()->getPrimaryContext();
280 if (FromDC
== ToDC
) return true;
281 if (FromDC
->isFileContext() || ToDC
->isFileContext()) return false;
287 /// Checks whether one class is derived from another, inclusively.
288 /// Properly indicates when it couldn't be determined due to
291 /// This should probably be donated to AST or at least Sema.
292 static AccessResult
IsDerivedFromInclusive(const CXXRecordDecl
*Derived
,
293 const CXXRecordDecl
*Target
) {
294 assert(Derived
->getCanonicalDecl() == Derived
);
295 assert(Target
->getCanonicalDecl() == Target
);
297 if (Derived
== Target
) return AR_accessible
;
299 bool CheckDependent
= Derived
->isDependentContext();
300 if (CheckDependent
&& MightInstantiateTo(Derived
, Target
))
303 AccessResult OnFailure
= AR_inaccessible
;
304 SmallVector
<const CXXRecordDecl
*, 8> Queue
; // actually a stack
307 if (Derived
->isDependentContext() && !Derived
->hasDefinition() &&
308 !Derived
->isLambda())
311 for (const auto &I
: Derived
->bases()) {
312 const CXXRecordDecl
*RD
;
314 QualType T
= I
.getType();
315 if (const RecordType
*RT
= T
->getAs
<RecordType
>()) {
316 RD
= cast
<CXXRecordDecl
>(RT
->getDecl());
317 } else if (const InjectedClassNameType
*IT
318 = T
->getAs
<InjectedClassNameType
>()) {
321 assert(T
->isDependentType() && "non-dependent base wasn't a record?");
322 OnFailure
= AR_dependent
;
326 RD
= RD
->getCanonicalDecl();
327 if (RD
== Target
) return AR_accessible
;
328 if (CheckDependent
&& MightInstantiateTo(RD
, Target
))
329 OnFailure
= AR_dependent
;
334 if (Queue
.empty()) break;
336 Derived
= Queue
.pop_back_val();
343 static bool MightInstantiateTo(Sema
&S
, DeclContext
*Context
,
344 DeclContext
*Friend
) {
345 if (Friend
== Context
)
348 assert(!Friend
->isDependentContext() &&
349 "can't handle friends with dependent contexts here");
351 if (!Context
->isDependentContext())
354 if (Friend
->isFileContext())
357 // TODO: this is very conservative
361 // Asks whether the type in 'context' can ever instantiate to the type
363 static bool MightInstantiateTo(Sema
&S
, CanQualType Context
, CanQualType Friend
) {
364 if (Friend
== Context
)
367 if (!Friend
->isDependentType() && !Context
->isDependentType())
370 // TODO: this is very conservative.
374 static bool MightInstantiateTo(Sema
&S
,
375 FunctionDecl
*Context
,
376 FunctionDecl
*Friend
) {
377 if (Context
->getDeclName() != Friend
->getDeclName())
380 if (!MightInstantiateTo(S
,
381 Context
->getDeclContext(),
382 Friend
->getDeclContext()))
385 CanQual
<FunctionProtoType
> FriendTy
386 = S
.Context
.getCanonicalType(Friend
->getType())
387 ->getAs
<FunctionProtoType
>();
388 CanQual
<FunctionProtoType
> ContextTy
389 = S
.Context
.getCanonicalType(Context
->getType())
390 ->getAs
<FunctionProtoType
>();
392 // There isn't any way that I know of to add qualifiers
393 // during instantiation.
394 if (FriendTy
.getQualifiers() != ContextTy
.getQualifiers())
397 if (FriendTy
->getNumParams() != ContextTy
->getNumParams())
400 if (!MightInstantiateTo(S
, ContextTy
->getReturnType(),
401 FriendTy
->getReturnType()))
404 for (unsigned I
= 0, E
= FriendTy
->getNumParams(); I
!= E
; ++I
)
405 if (!MightInstantiateTo(S
, ContextTy
->getParamType(I
),
406 FriendTy
->getParamType(I
)))
412 static bool MightInstantiateTo(Sema
&S
,
413 FunctionTemplateDecl
*Context
,
414 FunctionTemplateDecl
*Friend
) {
415 return MightInstantiateTo(S
,
416 Context
->getTemplatedDecl(),
417 Friend
->getTemplatedDecl());
420 static AccessResult
MatchesFriend(Sema
&S
,
421 const EffectiveContext
&EC
,
422 const CXXRecordDecl
*Friend
) {
423 if (EC
.includesClass(Friend
))
424 return AR_accessible
;
426 if (EC
.isDependent()) {
427 for (const CXXRecordDecl
*Context
: EC
.Records
) {
428 if (MightInstantiateTo(Context
, Friend
))
433 return AR_inaccessible
;
436 static AccessResult
MatchesFriend(Sema
&S
,
437 const EffectiveContext
&EC
,
438 CanQualType Friend
) {
439 if (const RecordType
*RT
= Friend
->getAs
<RecordType
>())
440 return MatchesFriend(S
, EC
, cast
<CXXRecordDecl
>(RT
->getDecl()));
442 // TODO: we can do better than this
443 if (Friend
->isDependentType())
446 return AR_inaccessible
;
449 /// Determines whether the given friend class template matches
450 /// anything in the effective context.
451 static AccessResult
MatchesFriend(Sema
&S
,
452 const EffectiveContext
&EC
,
453 ClassTemplateDecl
*Friend
) {
454 AccessResult OnFailure
= AR_inaccessible
;
456 // Check whether the friend is the template of a class in the
458 for (SmallVectorImpl
<CXXRecordDecl
*>::const_iterator
459 I
= EC
.Records
.begin(), E
= EC
.Records
.end(); I
!= E
; ++I
) {
460 CXXRecordDecl
*Record
= *I
;
462 // Figure out whether the current class has a template:
463 ClassTemplateDecl
*CTD
;
465 // A specialization of the template...
466 if (isa
<ClassTemplateSpecializationDecl
>(Record
)) {
467 CTD
= cast
<ClassTemplateSpecializationDecl
>(Record
)
468 ->getSpecializedTemplate();
470 // ... or the template pattern itself.
472 CTD
= Record
->getDescribedClassTemplate();
477 if (Friend
== CTD
->getCanonicalDecl())
478 return AR_accessible
;
480 // If the context isn't dependent, it can't be a dependent match.
481 if (!EC
.isDependent())
484 // If the template names don't match, it can't be a dependent
486 if (CTD
->getDeclName() != Friend
->getDeclName())
489 // If the class's context can't instantiate to the friend's
490 // context, it can't be a dependent match.
491 if (!MightInstantiateTo(S
, CTD
->getDeclContext(),
492 Friend
->getDeclContext()))
495 // Otherwise, it's a dependent match.
496 OnFailure
= AR_dependent
;
502 /// Determines whether the given friend function matches anything in
503 /// the effective context.
504 static AccessResult
MatchesFriend(Sema
&S
,
505 const EffectiveContext
&EC
,
506 FunctionDecl
*Friend
) {
507 AccessResult OnFailure
= AR_inaccessible
;
509 for (SmallVectorImpl
<FunctionDecl
*>::const_iterator
510 I
= EC
.Functions
.begin(), E
= EC
.Functions
.end(); I
!= E
; ++I
) {
512 return AR_accessible
;
514 if (EC
.isDependent() && MightInstantiateTo(S
, *I
, Friend
))
515 OnFailure
= AR_dependent
;
521 /// Determines whether the given friend function template matches
522 /// anything in the effective context.
523 static AccessResult
MatchesFriend(Sema
&S
,
524 const EffectiveContext
&EC
,
525 FunctionTemplateDecl
*Friend
) {
526 if (EC
.Functions
.empty()) return AR_inaccessible
;
528 AccessResult OnFailure
= AR_inaccessible
;
530 for (SmallVectorImpl
<FunctionDecl
*>::const_iterator
531 I
= EC
.Functions
.begin(), E
= EC
.Functions
.end(); I
!= E
; ++I
) {
533 FunctionTemplateDecl
*FTD
= (*I
)->getPrimaryTemplate();
535 FTD
= (*I
)->getDescribedFunctionTemplate();
539 FTD
= FTD
->getCanonicalDecl();
542 return AR_accessible
;
544 if (EC
.isDependent() && MightInstantiateTo(S
, FTD
, Friend
))
545 OnFailure
= AR_dependent
;
551 /// Determines whether the given friend declaration matches anything
552 /// in the effective context.
553 static AccessResult
MatchesFriend(Sema
&S
,
554 const EffectiveContext
&EC
,
555 FriendDecl
*FriendD
) {
556 // Whitelist accesses if there's an invalid or unsupported friend
558 if (FriendD
->isInvalidDecl() || FriendD
->isUnsupportedFriend())
559 return AR_accessible
;
561 if (TypeSourceInfo
*T
= FriendD
->getFriendType())
562 return MatchesFriend(S
, EC
, T
->getType()->getCanonicalTypeUnqualified());
565 = cast
<NamedDecl
>(FriendD
->getFriendDecl()->getCanonicalDecl());
567 // FIXME: declarations with dependent or templated scope.
569 if (isa
<ClassTemplateDecl
>(Friend
))
570 return MatchesFriend(S
, EC
, cast
<ClassTemplateDecl
>(Friend
));
572 if (isa
<FunctionTemplateDecl
>(Friend
))
573 return MatchesFriend(S
, EC
, cast
<FunctionTemplateDecl
>(Friend
));
575 if (isa
<CXXRecordDecl
>(Friend
))
576 return MatchesFriend(S
, EC
, cast
<CXXRecordDecl
>(Friend
));
578 assert(isa
<FunctionDecl
>(Friend
) && "unknown friend decl kind");
579 return MatchesFriend(S
, EC
, cast
<FunctionDecl
>(Friend
));
582 static AccessResult
GetFriendKind(Sema
&S
,
583 const EffectiveContext
&EC
,
584 const CXXRecordDecl
*Class
) {
585 AccessResult OnFailure
= AR_inaccessible
;
587 // Okay, check friends.
588 for (auto *Friend
: Class
->friends()) {
589 switch (MatchesFriend(S
, EC
, Friend
)) {
591 return AR_accessible
;
593 case AR_inaccessible
:
597 OnFailure
= AR_dependent
;
602 // That's it, give up.
608 /// A helper class for checking for a friend which will grant access
609 /// to a protected instance member.
610 struct ProtectedFriendContext
{
612 const EffectiveContext
&EC
;
613 const CXXRecordDecl
*NamingClass
;
617 /// The path down to the current base class.
618 SmallVector
<const CXXRecordDecl
*, 20> CurPath
;
620 ProtectedFriendContext(Sema
&S
, const EffectiveContext
&EC
,
621 const CXXRecordDecl
*InstanceContext
,
622 const CXXRecordDecl
*NamingClass
)
623 : S(S
), EC(EC
), NamingClass(NamingClass
),
624 CheckDependent(InstanceContext
->isDependentContext() ||
625 NamingClass
->isDependentContext()),
626 EverDependent(false) {}
628 /// Check classes in the current path for friendship, starting at
630 bool checkFriendshipAlongPath(unsigned I
) {
631 assert(I
< CurPath
.size());
632 for (unsigned E
= CurPath
.size(); I
!= E
; ++I
) {
633 switch (GetFriendKind(S
, EC
, CurPath
[I
])) {
634 case AR_accessible
: return true;
635 case AR_inaccessible
: continue;
636 case AR_dependent
: EverDependent
= true; continue;
642 /// Perform a search starting at the given class.
644 /// PrivateDepth is the index of the last (least derived) class
645 /// along the current path such that a notional public member of
646 /// the final class in the path would have access in that class.
647 bool findFriendship(const CXXRecordDecl
*Cur
, unsigned PrivateDepth
) {
648 // If we ever reach the naming class, check the current path for
649 // friendship. We can also stop recursing because we obviously
650 // won't find the naming class there again.
651 if (Cur
== NamingClass
)
652 return checkFriendshipAlongPath(PrivateDepth
);
654 if (CheckDependent
&& MightInstantiateTo(Cur
, NamingClass
))
655 EverDependent
= true;
657 // Recurse into the base classes.
658 for (const auto &I
: Cur
->bases()) {
659 // If this is private inheritance, then a public member of the
660 // base will not have any access in classes derived from Cur.
661 unsigned BasePrivateDepth
= PrivateDepth
;
662 if (I
.getAccessSpecifier() == AS_private
)
663 BasePrivateDepth
= CurPath
.size() - 1;
665 const CXXRecordDecl
*RD
;
667 QualType T
= I
.getType();
668 if (const RecordType
*RT
= T
->getAs
<RecordType
>()) {
669 RD
= cast
<CXXRecordDecl
>(RT
->getDecl());
670 } else if (const InjectedClassNameType
*IT
671 = T
->getAs
<InjectedClassNameType
>()) {
674 assert(T
->isDependentType() && "non-dependent base wasn't a record?");
675 EverDependent
= true;
679 // Recurse. We don't need to clean up if this returns true.
680 CurPath
.push_back(RD
);
681 if (findFriendship(RD
->getCanonicalDecl(), BasePrivateDepth
))
689 bool findFriendship(const CXXRecordDecl
*Cur
) {
690 assert(CurPath
.empty());
691 CurPath
.push_back(Cur
);
692 return findFriendship(Cur
, 0);
697 /// Search for a class P that EC is a friend of, under the constraint
698 /// InstanceContext <= P
699 /// if InstanceContext exists, or else
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.
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
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.
723 static 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
);
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
, NamingClass
);
735 ProtectedFriendContext
PRC(S
, EC
, InstanceContext
, NamingClass
);
736 if (PRC
.findFriendship(InstanceContext
)) return AR_accessible
;
737 if (PRC
.EverDependent
) return AR_dependent
;
738 return AR_inaccessible
;
741 static 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");
749 if (Access
== AS_public
) return AR_accessible
;
750 assert(Access
== AS_private
|| Access
== AS_protected
);
752 AccessResult OnFailure
= AR_inaccessible
;
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
;
761 if (Access
== AS_private
) {
762 if (ECRecord
== NamingClass
)
763 return AR_accessible
;
765 if (EC
.isDependent() && MightInstantiateTo(ECRecord
, NamingClass
))
766 OnFailure
= AR_dependent
;
770 assert(Access
== AS_protected
);
771 switch (IsDerivedFromInclusive(ECRecord
, NamingClass
)) {
772 case AR_accessible
: break;
773 case AR_inaccessible
: continue;
774 case AR_dependent
: OnFailure
= AR_dependent
; continue;
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.
789 // We interpret this as a restriction on [M3].
791 // In this part of the code, 'C' is just our context class ECRecord.
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
;
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
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
>(EC
.Functions
.front()))
807 if (MD
->isStatic()) return AR_accessible
;
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.
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
825 if (NamingClass
== ECRecord
) return AR_accessible
;
827 // Otherwise, this context class tells us nothing; on to the next.
831 assert(Target
.isInstanceMember());
833 const CXXRecordDecl
*InstanceContext
= Target
.resolveInstanceContext(S
);
834 if (!InstanceContext
) {
835 OnFailure
= AR_dependent
;
839 switch (IsDerivedFromInclusive(InstanceContext
, ECRecord
)) {
840 case AR_accessible
: return AR_accessible
;
841 case AR_inaccessible
: continue;
842 case AR_dependent
: OnFailure
= AR_dependent
; continue;
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
;
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
;
870 llvm_unreachable("impossible friendship kind");
873 switch (GetFriendKind(S
, EC
, NamingClass
)) {
874 case AR_accessible
: return AR_accessible
;
875 case AR_inaccessible
: return OnFailure
;
876 case AR_dependent
: return AR_dependent
;
879 // Silence bogus warnings
880 llvm_unreachable("impossible friendship kind");
883 /// Finds the best path from the naming class to the declaring class,
884 /// taking friend declarations into account.
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,
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.
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
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.
909 /// Along a single inheritance path we can restate both of these
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.
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
931 /// let AccessToBase = Merge(Access(B_i, B_{i+1}), ACAB(i+1)) in
932 /// if Accessible(B_i, AccessToBase) then public else AccessToBase
934 /// B is an accessible base of N at R iff ACAB(1) = public.
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
939 static 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();
948 // FIXME: fail correctly when there are dependent paths.
949 bool isDerived
= Derived
->isDerivedFrom(const_cast<CXXRecordDecl
*>(Base
),
951 assert(isDerived
&& "derived class not actually derived from base");
954 CXXBasePath
*BestPath
= nullptr;
956 assert(FinalAccess
!= AS_none
&& "forbidden access after declaring class");
958 bool AnyDependent
= false;
960 // Derive the friend-modified access along each path.
961 for (CXXBasePaths::paths_iterator PI
= Paths
.begin(), PE
= Paths
.end();
963 AccessTarget::SavedInstanceContext _
= Target
.saveInstanceContext();
965 // Walk through the path backwards.
966 AccessSpecifier PathAccess
= FinalAccess
;
967 CXXBasePath::iterator I
= PI
->end(), E
= PI
->begin();
971 assert(PathAccess
!= AS_none
);
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
976 if (PathAccess
== AS_private
) {
977 PathAccess
= AS_none
;
981 const CXXRecordDecl
*NC
= I
->Class
->getCanonicalDecl();
983 AccessSpecifier BaseAccess
= I
->Base
->getAccessSpecifier();
984 PathAccess
= std::max(PathAccess
, BaseAccess
);
986 switch (HasAccess(S
, EC
, NC
, PathAccess
, Target
)) {
987 case AR_inaccessible
: break;
989 PathAccess
= AS_public
;
991 // Future tests are not against members and so do not have
993 Target
.suppressInstanceContext();
1001 // Note that we modify the path's Access field to the
1002 // friend-modified access.
1003 if (BestPath
== nullptr || PathAccess
< BestPath
->Access
) {
1005 BestPath
->Access
= PathAccess
;
1007 // Short-circuit if we found a public path.
1008 if (BestPath
->Access
== AS_public
)
1015 assert((!BestPath
|| BestPath
->Access
!= AS_public
) &&
1016 "fell out of loop with public path");
1018 // We didn't find a public path, but at least one path was subject
1019 // to dependent friendship, so delay the check.
1026 /// Given that an entity has protected natural access, check whether
1027 /// access might be denied because of the protected member access
1030 /// \return true if a note was emitted
1031 static bool TryDiagnoseProtectedAccess(Sema
&S
, const EffectiveContext
&EC
,
1032 AccessTarget
&Target
) {
1033 // Only applies to instance accesses.
1034 if (!Target
.isInstanceMember())
1037 assert(Target
.isMemberAccess());
1039 const CXXRecordDecl
*NamingClass
= Target
.getEffectiveNamingClass();
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(ECRecord
, NamingClass
)) {
1045 case AR_accessible
: break;
1046 case AR_inaccessible
: continue;
1047 case AR_dependent
: continue;
1050 // The effective context is a subclass of the declaring class.
1051 // Check whether the [class.protected] restriction is limiting
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.
1058 NamedDecl
*D
= Target
.getTargetDecl();
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;
1066 // TODO: it would be great to have a fixit here, since this is
1067 // such an obvious error.
1068 S
.Diag(D
->getLocation(), diag::note_access_protected_restricted_noobject
)
1069 << S
.Context
.getTypeDeclType(ECRecord
);
1073 const CXXRecordDecl
*InstanceContext
= Target
.resolveInstanceContext(S
);
1074 assert(InstanceContext
&& "diagnosing dependent access");
1076 switch (IsDerivedFromInclusive(InstanceContext
, ECRecord
)) {
1077 case AR_accessible
: continue;
1078 case AR_dependent
: continue;
1079 case AR_inaccessible
:
1083 // Okay, the restriction seems to be what's limiting us.
1085 // Use a special diagnostic for constructors and destructors.
1086 if (isa
<CXXConstructorDecl
>(D
) || isa
<CXXDestructorDecl
>(D
) ||
1087 (isa
<FunctionTemplateDecl
>(D
) &&
1088 isa
<CXXConstructorDecl
>(
1089 cast
<FunctionTemplateDecl
>(D
)->getTemplatedDecl()))) {
1090 return S
.Diag(D
->getLocation(),
1091 diag::note_access_protected_restricted_ctordtor
)
1092 << isa
<CXXDestructorDecl
>(D
->getAsFunction());
1095 // Otherwise, use the generic diagnostic.
1096 return S
.Diag(D
->getLocation(),
1097 diag::note_access_protected_restricted_object
)
1098 << S
.Context
.getTypeDeclType(ECRecord
);
1104 /// We are unable to access a given declaration due to its direct
1105 /// access control; diagnose that.
1106 static void diagnoseBadDirectAccess(Sema
&S
,
1107 const EffectiveContext
&EC
,
1108 AccessTarget
&entity
) {
1109 assert(entity
.isMemberAccess());
1110 NamedDecl
*D
= entity
.getTargetDecl();
1112 if (D
->getAccess() == AS_protected
&&
1113 TryDiagnoseProtectedAccess(S
, EC
, entity
))
1116 // Find an original declaration.
1117 while (D
->isOutOfLine()) {
1118 NamedDecl
*PrevDecl
= nullptr;
1119 if (VarDecl
*VD
= dyn_cast
<VarDecl
>(D
))
1120 PrevDecl
= VD
->getPreviousDecl();
1121 else if (FunctionDecl
*FD
= dyn_cast
<FunctionDecl
>(D
))
1122 PrevDecl
= FD
->getPreviousDecl();
1123 else if (TypedefNameDecl
*TND
= dyn_cast
<TypedefNameDecl
>(D
))
1124 PrevDecl
= TND
->getPreviousDecl();
1125 else if (TagDecl
*TD
= dyn_cast
<TagDecl
>(D
)) {
1126 if (isa
<RecordDecl
>(D
) && cast
<RecordDecl
>(D
)->isInjectedClassName())
1128 PrevDecl
= TD
->getPreviousDecl();
1130 if (!PrevDecl
) break;
1134 CXXRecordDecl
*DeclaringClass
= FindDeclaringClass(D
);
1135 Decl
*ImmediateChild
;
1136 if (D
->getDeclContext() == DeclaringClass
)
1139 DeclContext
*DC
= D
->getDeclContext();
1140 while (DC
->getParent() != DeclaringClass
)
1141 DC
= DC
->getParent();
1142 ImmediateChild
= cast
<Decl
>(DC
);
1145 // Check whether there's an AccessSpecDecl preceding this in the
1146 // chain of the DeclContext.
1147 bool isImplicit
= true;
1148 for (const auto *I
: DeclaringClass
->decls()) {
1149 if (I
== ImmediateChild
) break;
1150 if (isa
<AccessSpecDecl
>(I
)) {
1156 S
.Diag(D
->getLocation(), diag::note_access_natural
)
1157 << (unsigned) (D
->getAccess() == AS_protected
)
1161 /// Diagnose the path which caused the given declaration or base class
1162 /// to become inaccessible.
1163 static void DiagnoseAccessPath(Sema
&S
,
1164 const EffectiveContext
&EC
,
1165 AccessTarget
&entity
) {
1166 // Save the instance context to preserve invariants.
1167 AccessTarget::SavedInstanceContext _
= entity
.saveInstanceContext();
1169 // This basically repeats the main algorithm but keeps some more
1172 // The natural access so far.
1173 AccessSpecifier accessSoFar
= AS_public
;
1175 // Check whether we have special rights to the declaring class.
1176 if (entity
.isMemberAccess()) {
1177 NamedDecl
*D
= entity
.getTargetDecl();
1178 accessSoFar
= D
->getAccess();
1179 const CXXRecordDecl
*declaringClass
= entity
.getDeclaringClass();
1181 switch (HasAccess(S
, EC
, declaringClass
, accessSoFar
, entity
)) {
1182 // If the declaration is accessible when named in its declaring
1183 // class, then we must be constrained by the path.
1185 accessSoFar
= AS_public
;
1186 entity
.suppressInstanceContext();
1189 case AR_inaccessible
:
1190 if (accessSoFar
== AS_private
||
1191 declaringClass
== entity
.getEffectiveNamingClass())
1192 return diagnoseBadDirectAccess(S
, EC
, entity
);
1196 llvm_unreachable("cannot diagnose dependent access");
1201 CXXBasePath
&path
= *FindBestPath(S
, EC
, entity
, accessSoFar
, paths
);
1202 assert(path
.Access
!= AS_public
);
1204 CXXBasePath::iterator i
= path
.end(), e
= path
.begin();
1205 CXXBasePath::iterator constrainingBase
= i
;
1209 assert(accessSoFar
!= AS_none
&& accessSoFar
!= AS_private
);
1211 // Is the entity accessible when named in the deriving class, as
1212 // modified by the base specifier?
1213 const CXXRecordDecl
*derivingClass
= i
->Class
->getCanonicalDecl();
1214 const CXXBaseSpecifier
*base
= i
->Base
;
1216 // If the access to this base is worse than the access we have to
1217 // the declaration, remember it.
1218 AccessSpecifier baseAccess
= base
->getAccessSpecifier();
1219 if (baseAccess
> accessSoFar
) {
1220 constrainingBase
= i
;
1221 accessSoFar
= baseAccess
;
1224 switch (HasAccess(S
, EC
, derivingClass
, accessSoFar
, entity
)) {
1225 case AR_inaccessible
: break;
1227 accessSoFar
= AS_public
;
1228 entity
.suppressInstanceContext();
1229 constrainingBase
= nullptr;
1232 llvm_unreachable("cannot diagnose dependent access");
1235 // If this was private inheritance, but we don't have access to
1236 // the deriving class, we're done.
1237 if (accessSoFar
== AS_private
) {
1238 assert(baseAccess
== AS_private
);
1239 assert(constrainingBase
== i
);
1244 // If we don't have a constraining base, the access failure must be
1245 // due to the original declaration.
1246 if (constrainingBase
== path
.end())
1247 return diagnoseBadDirectAccess(S
, EC
, entity
);
1249 // We're constrained by inheritance, but we want to say
1250 // "declared private here" if we're diagnosing a hierarchy
1251 // conversion and this is the final step.
1252 unsigned diagnostic
;
1253 if (entity
.isMemberAccess() ||
1254 constrainingBase
+ 1 != path
.end()) {
1255 diagnostic
= diag::note_access_constrained_by_path
;
1257 diagnostic
= diag::note_access_natural
;
1260 const CXXBaseSpecifier
*base
= constrainingBase
->Base
;
1262 S
.Diag(base
->getSourceRange().getBegin(), diagnostic
)
1263 << base
->getSourceRange()
1264 << (base
->getAccessSpecifier() == AS_protected
)
1265 << (base
->getAccessSpecifierAsWritten() == AS_none
);
1267 if (entity
.isMemberAccess())
1268 S
.Diag(entity
.getTargetDecl()->getLocation(),
1269 diag::note_member_declared_at
);
1272 static void DiagnoseBadAccess(Sema
&S
, SourceLocation Loc
,
1273 const EffectiveContext
&EC
,
1274 AccessTarget
&Entity
) {
1275 const CXXRecordDecl
*NamingClass
= Entity
.getNamingClass();
1276 const CXXRecordDecl
*DeclaringClass
= Entity
.getDeclaringClass();
1277 NamedDecl
*D
= (Entity
.isMemberAccess() ? Entity
.getTargetDecl() : nullptr);
1279 S
.Diag(Loc
, Entity
.getDiag())
1280 << (Entity
.getAccess() == AS_protected
)
1281 << (D
? D
->getDeclName() : DeclarationName())
1282 << S
.Context
.getTypeDeclType(NamingClass
)
1283 << S
.Context
.getTypeDeclType(DeclaringClass
);
1284 DiagnoseAccessPath(S
, EC
, Entity
);
1287 /// MSVC has a bug where if during an using declaration name lookup,
1288 /// the declaration found is unaccessible (private) and that declaration
1289 /// was bring into scope via another using declaration whose target
1290 /// declaration is accessible (public) then no error is generated.
1296 /// class B : public A {
1300 /// class C : public B {
1305 /// Here, B::f is private so this should fail in Standard C++, but
1306 /// because B::f refers to A::f which is public MSVC accepts it.
1307 static bool IsMicrosoftUsingDeclarationAccessBug(Sema
& S
,
1308 SourceLocation AccessLoc
,
1309 AccessTarget
&Entity
) {
1310 if (UsingShadowDecl
*Shadow
=
1311 dyn_cast
<UsingShadowDecl
>(Entity
.getTargetDecl()))
1312 if (UsingDecl
*UD
= dyn_cast
<UsingDecl
>(Shadow
->getIntroducer())) {
1313 const NamedDecl
*OrigDecl
= Entity
.getTargetDecl()->getUnderlyingDecl();
1314 if (Entity
.getTargetDecl()->getAccess() == AS_private
&&
1315 (OrigDecl
->getAccess() == AS_public
||
1316 OrigDecl
->getAccess() == AS_protected
)) {
1317 S
.Diag(AccessLoc
, diag::ext_ms_using_declaration_inaccessible
)
1318 << UD
->getQualifiedNameAsString()
1319 << OrigDecl
->getQualifiedNameAsString();
1326 /// Determines whether the accessed entity is accessible. Public members
1327 /// have been weeded out by this point.
1328 static AccessResult
IsAccessible(Sema
&S
,
1329 const EffectiveContext
&EC
,
1330 AccessTarget
&Entity
) {
1331 // Determine the actual naming class.
1332 const CXXRecordDecl
*NamingClass
= Entity
.getEffectiveNamingClass();
1334 AccessSpecifier UnprivilegedAccess
= Entity
.getAccess();
1335 assert(UnprivilegedAccess
!= AS_public
&& "public access not weeded out");
1337 // Before we try to recalculate access paths, try to white-list
1338 // accesses which just trade in on the final step, i.e. accesses
1339 // which don't require [M4] or [B4]. These are by far the most
1340 // common forms of privileged access.
1341 if (UnprivilegedAccess
!= AS_none
) {
1342 switch (HasAccess(S
, EC
, NamingClass
, UnprivilegedAccess
, Entity
)) {
1344 // This is actually an interesting policy decision. We don't
1345 // *have* to delay immediately here: we can do the full access
1346 // calculation in the hope that friendship on some intermediate
1347 // class will make the declaration accessible non-dependently.
1348 // But that's not cheap, and odds are very good (note: assertion
1349 // made without data) that the friend declaration will determine
1351 return AR_dependent
;
1353 case AR_accessible
: return AR_accessible
;
1354 case AR_inaccessible
: break;
1358 AccessTarget::SavedInstanceContext _
= Entity
.saveInstanceContext();
1360 // We lower member accesses to base accesses by pretending that the
1361 // member is a base class of its declaring class.
1362 AccessSpecifier FinalAccess
;
1364 if (Entity
.isMemberAccess()) {
1365 // Determine if the declaration is accessible from EC when named
1366 // in its declaring class.
1367 NamedDecl
*Target
= Entity
.getTargetDecl();
1368 const CXXRecordDecl
*DeclaringClass
= Entity
.getDeclaringClass();
1370 FinalAccess
= Target
->getAccess();
1371 switch (HasAccess(S
, EC
, DeclaringClass
, FinalAccess
, Entity
)) {
1373 // Target is accessible at EC when named in its declaring class.
1374 // We can now hill-climb and simply check whether the declaring
1375 // class is accessible as a base of the naming class. This is
1376 // equivalent to checking the access of a notional public
1377 // member with no instance context.
1378 FinalAccess
= AS_public
;
1379 Entity
.suppressInstanceContext();
1381 case AR_inaccessible
: break;
1382 case AR_dependent
: return AR_dependent
; // see above
1385 if (DeclaringClass
== NamingClass
)
1386 return (FinalAccess
== AS_public
? AR_accessible
: AR_inaccessible
);
1388 FinalAccess
= AS_public
;
1391 assert(Entity
.getDeclaringClass() != NamingClass
);
1393 // Append the declaration's access if applicable.
1395 CXXBasePath
*Path
= FindBestPath(S
, EC
, Entity
, FinalAccess
, Paths
);
1397 return AR_dependent
;
1399 assert(Path
->Access
<= UnprivilegedAccess
&&
1400 "access along best path worse than direct?");
1401 if (Path
->Access
== AS_public
)
1402 return AR_accessible
;
1403 return AR_inaccessible
;
1406 static void DelayDependentAccess(Sema
&S
,
1407 const EffectiveContext
&EC
,
1409 const AccessTarget
&Entity
) {
1410 assert(EC
.isDependent() && "delaying non-dependent access");
1411 DeclContext
*DC
= EC
.getInnerContext();
1412 assert(DC
->isDependentContext() && "delaying non-dependent access");
1413 DependentDiagnostic::Create(S
.Context
, DC
, DependentDiagnostic::Access
,
1415 Entity
.isMemberAccess(),
1417 Entity
.getTargetDecl(),
1418 Entity
.getNamingClass(),
1419 Entity
.getBaseObjectType(),
1423 /// Checks access to an entity from the given effective context.
1424 static AccessResult
CheckEffectiveAccess(Sema
&S
,
1425 const EffectiveContext
&EC
,
1427 AccessTarget
&Entity
) {
1428 assert(Entity
.getAccess() != AS_public
&& "called for public access!");
1430 switch (IsAccessible(S
, EC
, Entity
)) {
1432 DelayDependentAccess(S
, EC
, Loc
, Entity
);
1433 return AR_dependent
;
1435 case AR_inaccessible
:
1436 if (S
.getLangOpts().MSVCCompat
&&
1437 IsMicrosoftUsingDeclarationAccessBug(S
, Loc
, Entity
))
1438 return AR_accessible
;
1439 if (!Entity
.isQuiet())
1440 DiagnoseBadAccess(S
, Loc
, EC
, Entity
);
1441 return AR_inaccessible
;
1444 return AR_accessible
;
1447 // silence unnecessary warning
1448 llvm_unreachable("invalid access result");
1451 static Sema::AccessResult
CheckAccess(Sema
&S
, SourceLocation Loc
,
1452 AccessTarget
&Entity
) {
1453 // If the access path is public, it's accessible everywhere.
1454 if (Entity
.getAccess() == AS_public
)
1455 return Sema::AR_accessible
;
1457 // If we're currently parsing a declaration, we may need to delay
1458 // access control checking, because our effective context might be
1459 // different based on what the declaration comes out as.
1461 // For example, we might be parsing a declaration with a scope
1462 // specifier, like this:
1463 // A::private_type A::foo() { ... }
1465 // Or we might be parsing something that will turn out to be a friend:
1466 // void foo(A::private_type);
1467 // void B::foo(A::private_type);
1468 if (S
.DelayedDiagnostics
.shouldDelayDiagnostics()) {
1469 S
.DelayedDiagnostics
.add(DelayedDiagnostic::makeAccess(Loc
, Entity
));
1470 return Sema::AR_delayed
;
1473 EffectiveContext
EC(S
.CurContext
);
1474 switch (CheckEffectiveAccess(S
, EC
, Loc
, Entity
)) {
1475 case AR_accessible
: return Sema::AR_accessible
;
1476 case AR_inaccessible
: return Sema::AR_inaccessible
;
1477 case AR_dependent
: return Sema::AR_dependent
;
1479 llvm_unreachable("invalid access result");
1482 void Sema::HandleDelayedAccessCheck(DelayedDiagnostic
&DD
, Decl
*D
) {
1483 // Access control for names used in the declarations of functions
1484 // and function templates should normally be evaluated in the context
1485 // of the declaration, just in case it's a friend of something.
1486 // However, this does not apply to local extern declarations.
1488 DeclContext
*DC
= D
->getDeclContext();
1489 if (D
->isLocalExternDecl()) {
1490 DC
= D
->getLexicalDeclContext();
1491 } else if (FunctionDecl
*FN
= dyn_cast
<FunctionDecl
>(D
)) {
1493 } else if (TemplateDecl
*TD
= dyn_cast
<TemplateDecl
>(D
)) {
1494 if (isa
<DeclContext
>(TD
->getTemplatedDecl()))
1495 DC
= cast
<DeclContext
>(TD
->getTemplatedDecl());
1498 EffectiveContext
EC(DC
);
1500 AccessTarget
Target(DD
.getAccessData());
1502 if (CheckEffectiveAccess(*this, EC
, DD
.Loc
, Target
) == ::AR_inaccessible
)
1503 DD
.Triggered
= true;
1506 void Sema::HandleDependentAccessCheck(const DependentDiagnostic
&DD
,
1507 const MultiLevelTemplateArgumentList
&TemplateArgs
) {
1508 SourceLocation Loc
= DD
.getAccessLoc();
1509 AccessSpecifier Access
= DD
.getAccess();
1511 Decl
*NamingD
= FindInstantiatedDecl(Loc
, DD
.getAccessNamingClass(),
1513 if (!NamingD
) return;
1514 Decl
*TargetD
= FindInstantiatedDecl(Loc
, DD
.getAccessTarget(),
1516 if (!TargetD
) return;
1518 if (DD
.isAccessToMember()) {
1519 CXXRecordDecl
*NamingClass
= cast
<CXXRecordDecl
>(NamingD
);
1520 NamedDecl
*TargetDecl
= cast
<NamedDecl
>(TargetD
);
1521 QualType BaseObjectType
= DD
.getAccessBaseObjectType();
1522 if (!BaseObjectType
.isNull()) {
1523 BaseObjectType
= SubstType(BaseObjectType
, TemplateArgs
, Loc
,
1525 if (BaseObjectType
.isNull()) return;
1528 AccessTarget
Entity(Context
,
1529 AccessTarget::Member
,
1531 DeclAccessPair::make(TargetDecl
, Access
),
1533 Entity
.setDiag(DD
.getDiagnostic());
1534 CheckAccess(*this, Loc
, Entity
);
1536 AccessTarget
Entity(Context
,
1538 cast
<CXXRecordDecl
>(TargetD
),
1539 cast
<CXXRecordDecl
>(NamingD
),
1541 Entity
.setDiag(DD
.getDiagnostic());
1542 CheckAccess(*this, Loc
, Entity
);
1546 Sema::AccessResult
Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr
*E
,
1547 DeclAccessPair Found
) {
1548 if (!getLangOpts().AccessControl
||
1549 !E
->getNamingClass() ||
1550 Found
.getAccess() == AS_public
)
1551 return AR_accessible
;
1553 AccessTarget
Entity(Context
, AccessTarget::Member
, E
->getNamingClass(),
1555 Entity
.setDiag(diag::err_access
) << E
->getSourceRange();
1557 return CheckAccess(*this, E
->getNameLoc(), Entity
);
1560 /// Perform access-control checking on a previously-unresolved member
1561 /// access which has now been resolved to a member.
1562 Sema::AccessResult
Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr
*E
,
1563 DeclAccessPair Found
) {
1564 if (!getLangOpts().AccessControl
||
1565 Found
.getAccess() == AS_public
)
1566 return AR_accessible
;
1568 QualType BaseType
= E
->getBaseType();
1570 BaseType
= BaseType
->castAs
<PointerType
>()->getPointeeType();
1572 AccessTarget
Entity(Context
, AccessTarget::Member
, E
->getNamingClass(),
1574 Entity
.setDiag(diag::err_access
) << E
->getSourceRange();
1576 return CheckAccess(*this, E
->getMemberLoc(), Entity
);
1579 /// Is the given member accessible for the purposes of deciding whether to
1580 /// define a special member function as deleted?
1581 bool Sema::isMemberAccessibleForDeletion(CXXRecordDecl
*NamingClass
,
1582 DeclAccessPair Found
,
1583 QualType ObjectType
,
1585 const PartialDiagnostic
&Diag
) {
1587 if (Found
.getAccess() == AS_public
|| !getLangOpts().AccessControl
)
1590 AccessTarget
Entity(Context
, AccessTarget::Member
, NamingClass
, Found
,
1593 // Suppress diagnostics.
1594 Entity
.setDiag(Diag
);
1596 switch (CheckAccess(*this, Loc
, Entity
)) {
1597 case AR_accessible
: return true;
1598 case AR_inaccessible
: return false;
1599 case AR_dependent
: llvm_unreachable("dependent for =delete computation");
1600 case AR_delayed
: llvm_unreachable("cannot delay =delete computation");
1602 llvm_unreachable("bad access result");
1605 Sema::AccessResult
Sema::CheckDestructorAccess(SourceLocation Loc
,
1606 CXXDestructorDecl
*Dtor
,
1607 const PartialDiagnostic
&PDiag
,
1608 QualType ObjectTy
) {
1609 if (!getLangOpts().AccessControl
)
1610 return AR_accessible
;
1612 // There's never a path involved when checking implicit destructor access.
1613 AccessSpecifier Access
= Dtor
->getAccess();
1614 if (Access
== AS_public
)
1615 return AR_accessible
;
1617 CXXRecordDecl
*NamingClass
= Dtor
->getParent();
1618 if (ObjectTy
.isNull()) ObjectTy
= Context
.getTypeDeclType(NamingClass
);
1620 AccessTarget
Entity(Context
, AccessTarget::Member
, NamingClass
,
1621 DeclAccessPair::make(Dtor
, Access
),
1623 Entity
.setDiag(PDiag
); // TODO: avoid copy
1625 return CheckAccess(*this, Loc
, Entity
);
1628 /// Checks access to a constructor.
1629 Sema::AccessResult
Sema::CheckConstructorAccess(SourceLocation UseLoc
,
1630 CXXConstructorDecl
*Constructor
,
1631 DeclAccessPair Found
,
1632 const InitializedEntity
&Entity
,
1633 bool IsCopyBindingRefToTemp
) {
1634 if (!getLangOpts().AccessControl
|| Found
.getAccess() == AS_public
)
1635 return AR_accessible
;
1637 PartialDiagnostic
PD(PDiag());
1638 switch (Entity
.getKind()) {
1640 PD
= PDiag(IsCopyBindingRefToTemp
1641 ? diag::ext_rvalue_to_reference_access_ctor
1642 : diag::err_access_ctor
);
1646 case InitializedEntity::EK_Base
:
1647 PD
= PDiag(diag::err_access_base_ctor
);
1648 PD
<< Entity
.isInheritedVirtualBase()
1649 << Entity
.getBaseSpecifier()->getType() << getSpecialMember(Constructor
);
1652 case InitializedEntity::EK_Member
: {
1653 const FieldDecl
*Field
= cast
<FieldDecl
>(Entity
.getDecl());
1654 PD
= PDiag(diag::err_access_field_ctor
);
1655 PD
<< Field
->getType() << getSpecialMember(Constructor
);
1659 case InitializedEntity::EK_LambdaCapture
: {
1660 StringRef VarName
= Entity
.getCapturedVarName();
1661 PD
= PDiag(diag::err_access_lambda_capture
);
1662 PD
<< VarName
<< Entity
.getType() << getSpecialMember(Constructor
);
1668 return CheckConstructorAccess(UseLoc
, Constructor
, Found
, Entity
, PD
);
1671 /// Checks access to a constructor.
1672 Sema::AccessResult
Sema::CheckConstructorAccess(SourceLocation UseLoc
,
1673 CXXConstructorDecl
*Constructor
,
1674 DeclAccessPair Found
,
1675 const InitializedEntity
&Entity
,
1676 const PartialDiagnostic
&PD
) {
1677 if (!getLangOpts().AccessControl
||
1678 Found
.getAccess() == AS_public
)
1679 return AR_accessible
;
1681 CXXRecordDecl
*NamingClass
= Constructor
->getParent();
1683 // Initializing a base sub-object is an instance method call on an
1684 // object of the derived class. Otherwise, we have an instance method
1685 // call on an object of the constructed type.
1687 // FIXME: If we have a parent, we're initializing the base class subobject
1688 // in aggregate initialization. It's not clear whether the object class
1689 // should be the base class or the derived class in that case.
1690 CXXRecordDecl
*ObjectClass
;
1691 if ((Entity
.getKind() == InitializedEntity::EK_Base
||
1692 Entity
.getKind() == InitializedEntity::EK_Delegating
) &&
1693 !Entity
.getParent()) {
1694 ObjectClass
= cast
<CXXConstructorDecl
>(CurContext
)->getParent();
1695 } else if (auto *Shadow
=
1696 dyn_cast
<ConstructorUsingShadowDecl
>(Found
.getDecl())) {
1697 // If we're using an inheriting constructor to construct an object,
1698 // the object class is the derived class, not the base class.
1699 ObjectClass
= Shadow
->getParent();
1701 ObjectClass
= NamingClass
;
1704 AccessTarget
AccessEntity(
1705 Context
, AccessTarget::Member
, NamingClass
,
1706 DeclAccessPair::make(Constructor
, Found
.getAccess()),
1707 Context
.getTypeDeclType(ObjectClass
));
1708 AccessEntity
.setDiag(PD
);
1710 return CheckAccess(*this, UseLoc
, AccessEntity
);
1713 /// Checks access to an overloaded operator new or delete.
1714 Sema::AccessResult
Sema::CheckAllocationAccess(SourceLocation OpLoc
,
1715 SourceRange PlacementRange
,
1716 CXXRecordDecl
*NamingClass
,
1717 DeclAccessPair Found
,
1719 if (!getLangOpts().AccessControl
||
1721 Found
.getAccess() == AS_public
)
1722 return AR_accessible
;
1724 AccessTarget
Entity(Context
, AccessTarget::Member
, NamingClass
, Found
,
1727 Entity
.setDiag(diag::err_access
)
1730 return CheckAccess(*this, OpLoc
, Entity
);
1733 /// Checks access to a member.
1734 Sema::AccessResult
Sema::CheckMemberAccess(SourceLocation UseLoc
,
1735 CXXRecordDecl
*NamingClass
,
1736 DeclAccessPair Found
) {
1737 if (!getLangOpts().AccessControl
||
1739 Found
.getAccess() == AS_public
)
1740 return AR_accessible
;
1742 AccessTarget
Entity(Context
, AccessTarget::Member
, NamingClass
,
1745 return CheckAccess(*this, UseLoc
, Entity
);
1748 /// Checks implicit access to a member in a structured binding.
1750 Sema::CheckStructuredBindingMemberAccess(SourceLocation UseLoc
,
1751 CXXRecordDecl
*DecomposedClass
,
1752 DeclAccessPair Field
) {
1753 if (!getLangOpts().AccessControl
||
1754 Field
.getAccess() == AS_public
)
1755 return AR_accessible
;
1757 AccessTarget
Entity(Context
, AccessTarget::Member
, DecomposedClass
, Field
,
1758 Context
.getRecordType(DecomposedClass
));
1759 Entity
.setDiag(diag::err_decomp_decl_inaccessible_field
);
1761 return CheckAccess(*this, UseLoc
, Entity
);
1764 Sema::AccessResult
Sema::CheckMemberOperatorAccess(SourceLocation OpLoc
,
1766 const SourceRange
&Range
,
1767 DeclAccessPair Found
) {
1768 if (!getLangOpts().AccessControl
|| Found
.getAccess() == AS_public
)
1769 return AR_accessible
;
1771 const RecordType
*RT
= ObjectExpr
->getType()->castAs
<RecordType
>();
1772 CXXRecordDecl
*NamingClass
= cast
<CXXRecordDecl
>(RT
->getDecl());
1774 AccessTarget
Entity(Context
, AccessTarget::Member
, NamingClass
, Found
,
1775 ObjectExpr
->getType());
1776 Entity
.setDiag(diag::err_access
) << ObjectExpr
->getSourceRange() << Range
;
1778 return CheckAccess(*this, OpLoc
, Entity
);
1781 /// Checks access to an overloaded member operator, including
1782 /// conversion operators.
1783 Sema::AccessResult
Sema::CheckMemberOperatorAccess(SourceLocation OpLoc
,
1786 DeclAccessPair Found
) {
1787 return CheckMemberOperatorAccess(
1788 OpLoc
, ObjectExpr
, ArgExpr
? ArgExpr
->getSourceRange() : SourceRange(),
1792 Sema::AccessResult
Sema::CheckMemberOperatorAccess(SourceLocation OpLoc
,
1794 ArrayRef
<Expr
*> ArgExprs
,
1795 DeclAccessPair FoundDecl
) {
1797 if (!ArgExprs
.empty()) {
1798 R
= SourceRange(ArgExprs
.front()->getBeginLoc(),
1799 ArgExprs
.back()->getEndLoc());
1802 return CheckMemberOperatorAccess(OpLoc
, ObjectExpr
, R
, FoundDecl
);
1805 /// Checks access to the target of a friend declaration.
1806 Sema::AccessResult
Sema::CheckFriendAccess(NamedDecl
*target
) {
1807 assert(isa
<CXXMethodDecl
>(target
->getAsFunction()));
1809 // Friendship lookup is a redeclaration lookup, so there's never an
1810 // inheritance path modifying access.
1811 AccessSpecifier access
= target
->getAccess();
1813 if (!getLangOpts().AccessControl
|| access
== AS_public
)
1814 return AR_accessible
;
1816 CXXMethodDecl
*method
= cast
<CXXMethodDecl
>(target
->getAsFunction());
1818 AccessTarget
entity(Context
, AccessTarget::Member
,
1819 cast
<CXXRecordDecl
>(target
->getDeclContext()),
1820 DeclAccessPair::make(target
, access
),
1821 /*no instance context*/ QualType());
1822 entity
.setDiag(diag::err_access_friend_function
)
1823 << (method
->getQualifier() ? method
->getQualifierLoc().getSourceRange()
1824 : method
->getNameInfo().getSourceRange());
1826 // We need to bypass delayed-diagnostics because we might be called
1827 // while the ParsingDeclarator is active.
1828 EffectiveContext
EC(CurContext
);
1829 switch (CheckEffectiveAccess(*this, EC
, target
->getLocation(), entity
)) {
1830 case ::AR_accessible
: return Sema::AR_accessible
;
1831 case ::AR_inaccessible
: return Sema::AR_inaccessible
;
1832 case ::AR_dependent
: return Sema::AR_dependent
;
1834 llvm_unreachable("invalid access result");
1837 Sema::AccessResult
Sema::CheckAddressOfMemberAccess(Expr
*OvlExpr
,
1838 DeclAccessPair Found
) {
1839 if (!getLangOpts().AccessControl
||
1840 Found
.getAccess() == AS_none
||
1841 Found
.getAccess() == AS_public
)
1842 return AR_accessible
;
1844 OverloadExpr
*Ovl
= OverloadExpr::find(OvlExpr
).Expression
;
1845 CXXRecordDecl
*NamingClass
= Ovl
->getNamingClass();
1847 AccessTarget
Entity(Context
, AccessTarget::Member
, NamingClass
, Found
,
1848 /*no instance context*/ QualType());
1849 Entity
.setDiag(diag::err_access
)
1850 << Ovl
->getSourceRange();
1852 return CheckAccess(*this, Ovl
->getNameLoc(), Entity
);
1855 /// Checks access for a hierarchy conversion.
1857 /// \param ForceCheck true if this check should be performed even if access
1858 /// control is disabled; some things rely on this for semantics
1859 /// \param ForceUnprivileged true if this check should proceed as if the
1860 /// context had no special privileges
1861 Sema::AccessResult
Sema::CheckBaseClassAccess(SourceLocation AccessLoc
,
1864 const CXXBasePath
&Path
,
1867 bool ForceUnprivileged
) {
1868 if (!ForceCheck
&& !getLangOpts().AccessControl
)
1869 return AR_accessible
;
1871 if (Path
.Access
== AS_public
)
1872 return AR_accessible
;
1874 CXXRecordDecl
*BaseD
, *DerivedD
;
1875 BaseD
= cast
<CXXRecordDecl
>(Base
->castAs
<RecordType
>()->getDecl());
1876 DerivedD
= cast
<CXXRecordDecl
>(Derived
->castAs
<RecordType
>()->getDecl());
1878 AccessTarget
Entity(Context
, AccessTarget::Base
, BaseD
, DerivedD
,
1881 Entity
.setDiag(DiagID
) << Derived
<< Base
;
1883 if (ForceUnprivileged
) {
1884 switch (CheckEffectiveAccess(*this, EffectiveContext(),
1885 AccessLoc
, Entity
)) {
1886 case ::AR_accessible
: return Sema::AR_accessible
;
1887 case ::AR_inaccessible
: return Sema::AR_inaccessible
;
1888 case ::AR_dependent
: return Sema::AR_dependent
;
1890 llvm_unreachable("unexpected result from CheckEffectiveAccess");
1892 return CheckAccess(*this, AccessLoc
, Entity
);
1895 /// Checks access to all the declarations in the given result set.
1896 void Sema::CheckLookupAccess(const LookupResult
&R
) {
1897 assert(getLangOpts().AccessControl
1898 && "performing access check without access control");
1899 assert(R
.getNamingClass() && "performing access check without naming class");
1901 for (LookupResult::iterator I
= R
.begin(), E
= R
.end(); I
!= E
; ++I
) {
1902 if (I
.getAccess() != AS_public
) {
1903 AccessTarget
Entity(Context
, AccessedEntity::Member
,
1904 R
.getNamingClass(), I
.getPair(),
1905 R
.getBaseObjectType());
1906 Entity
.setDiag(diag::err_access
);
1907 CheckAccess(*this, R
.getNameLoc(), Entity
);
1912 /// Checks access to Target from the given class. The check will take access
1913 /// specifiers into account, but no member access expressions and such.
1915 /// \param Target the declaration to check if it can be accessed
1916 /// \param NamingClass the class in which the lookup was started.
1917 /// \param BaseType type of the left side of member access expression.
1918 /// \p BaseType and \p NamingClass are used for C++ access control.
1919 /// Depending on the lookup case, they should be set to the following:
1920 /// - lhs.target (member access without a qualifier):
1921 /// \p BaseType and \p NamingClass are both the type of 'lhs'.
1922 /// - lhs.X::target (member access with a qualifier):
1923 /// BaseType is the type of 'lhs', NamingClass is 'X'
1924 /// - X::target (qualified lookup without member access):
1925 /// BaseType is null, NamingClass is 'X'.
1926 /// - target (unqualified lookup).
1927 /// BaseType is null, NamingClass is the parent class of 'target'.
1928 /// \return true if the Target is accessible from the Class, false otherwise.
1929 bool Sema::IsSimplyAccessible(NamedDecl
*Target
, CXXRecordDecl
*NamingClass
,
1930 QualType BaseType
) {
1931 // Perform the C++ accessibility checks first.
1932 if (Target
->isCXXClassMember() && NamingClass
) {
1933 if (!getLangOpts().CPlusPlus
)
1935 // The unprivileged access is AS_none as we don't know how the member was
1936 // accessed, which is described by the access in DeclAccessPair.
1937 // `IsAccessible` will examine the actual access of Target (i.e.
1938 // Decl->getAccess()) when calculating the access.
1939 AccessTarget
Entity(Context
, AccessedEntity::Member
, NamingClass
,
1940 DeclAccessPair::make(Target
, AS_none
), BaseType
);
1941 EffectiveContext
EC(CurContext
);
1942 return ::IsAccessible(*this, EC
, Entity
) != ::AR_inaccessible
;
1945 if (ObjCIvarDecl
*Ivar
= dyn_cast
<ObjCIvarDecl
>(Target
)) {
1946 // @public and @package ivars are always accessible.
1947 if (Ivar
->getCanonicalAccessControl() == ObjCIvarDecl::Public
||
1948 Ivar
->getCanonicalAccessControl() == ObjCIvarDecl::Package
)
1951 // If we are inside a class or category implementation, determine the
1952 // interface we're in.
1953 ObjCInterfaceDecl
*ClassOfMethodDecl
= nullptr;
1954 if (ObjCMethodDecl
*MD
= getCurMethodDecl())
1955 ClassOfMethodDecl
= MD
->getClassInterface();
1956 else if (FunctionDecl
*FD
= getCurFunctionDecl()) {
1957 if (ObjCImplDecl
*Impl
1958 = dyn_cast
<ObjCImplDecl
>(FD
->getLexicalDeclContext())) {
1959 if (ObjCImplementationDecl
*IMPD
1960 = dyn_cast
<ObjCImplementationDecl
>(Impl
))
1961 ClassOfMethodDecl
= IMPD
->getClassInterface();
1962 else if (ObjCCategoryImplDecl
* CatImplClass
1963 = dyn_cast
<ObjCCategoryImplDecl
>(Impl
))
1964 ClassOfMethodDecl
= CatImplClass
->getClassInterface();
1968 // If we're not in an interface, this ivar is inaccessible.
1969 if (!ClassOfMethodDecl
)
1972 // If we're inside the same interface that owns the ivar, we're fine.
1973 if (declaresSameEntity(ClassOfMethodDecl
, Ivar
->getContainingInterface()))
1976 // If the ivar is private, it's inaccessible.
1977 if (Ivar
->getCanonicalAccessControl() == ObjCIvarDecl::Private
)
1980 return Ivar
->getContainingInterface()->isSuperClassOf(ClassOfMethodDecl
);