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