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