clang: lib/Sema/SemaAccess.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
24#include "llvm/ADT/STLForwardCompat.h"
25
26using namespace clang;
27using namespace sema;
28
29
35
39 if (!PrevMemberDecl) {
40
42 return false;
43 }
44
45
46
47 if (LexicalAS != AS_none && LexicalAS != PrevMemberDecl->getAccess()) {
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
55 return true;
56 }
57
59 return false;
60}
61
64
65
66
67 if (isa(DC))
68 DC = cast(DC)->getDeclContext();
69
70 CXXRecordDecl *DeclaringClass = cast(DC);
72 DeclaringClass = cast(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
85
86
87 if (auto *DGD = dyn_cast(DC)) {
88 if (DGD->isImplicit()) {
89 DC = DGD->getCorrespondingConstructor();
90 if (!DC) {
91
92
93 DC = cast(DGD->getDeducedTemplate()->getTemplatedDecl());
94 }
95 }
96 }
97
98
99
100
101
102
103
104
105
106
107
108
109
110 while (true) {
111
112
113
114
115
116
117 if (isa(DC)) {
120 DC = Record->getDeclContext();
121 } else if (isa(DC)) {
123 Functions.push_back(Function->getCanonicalDecl());
124 if (Function->getFriendObjectKind())
125 DC = Function->getLexicalDeclContext();
126 else
127 DC = Function->getDeclContext();
129 break;
130 } else {
132 }
133 }
134 }
135
136 bool isDependent() const { return Dependent; }
137
138 bool includesClass(const CXXRecordDecl *R) const {
140 return llvm::is_contained(Records, R);
141 }
142
143
144
146 return Inner;
147 }
148
150
155};
156
157
158
163 }
164
166 MemberNonce _,
171 FoundDecl, BaseObjectType) {
173 }
174
176 BaseNonce _,
180 : AccessedEntity(Context.getDiagAllocator(), Base, BaseClass, DerivedClass,
181 Access) {
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)
197 S.Target = nullptr;
198 }
199
200
201
202 SavedInstanceContext &operator=(SavedInstanceContext &&) = delete;
203
204
205
206 SavedInstanceContext(const SavedInstanceContext &) = delete;
207 SavedInstanceContext &operator=(const SavedInstanceContext &) = delete;
208
209 ~SavedInstanceContext() {
211 Target->HasInstanceContext = Has;
212 }
213
214 private:
215 friend struct AccessTarget;
216 explicit SavedInstanceContext(AccessTarget &Target)
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
231 assert(HasInstanceContext);
232 if (CalculatedInstanceContext)
233 return InstanceContext;
234
235 CalculatedInstanceContext = true;
237 InstanceContext = (IC ? cast(IC)->getCanonicalDecl()
238 : nullptr);
239 return InstanceContext;
240 }
241
243 return DeclaringClass;
244 }
245
246
247
248 const CXXRecordDecl *getEffectiveNamingClass() const {
249 const CXXRecordDecl *namingClass = getNamingClass();
251 namingClass = cast(namingClass->getParent());
253 }
254
255private:
257 HasInstanceContext = (isMemberAccess() &&
258 !getBaseObjectType().isNull() &&
259 getTargetDecl()->isCXXInstanceMember());
260 CalculatedInstanceContext = false;
261 InstanceContext = nullptr;
262
263 if (isMemberAccess())
265 else
266 DeclaringClass = getBaseClass();
267 DeclaringClass = DeclaringClass->getCanonicalDecl();
268 }
269
270 bool HasInstanceContext : 1;
271 mutable bool CalculatedInstanceContext : 1;
274};
275
276}
277
278
281
283 return false;
284
287 if (FromDC == ToDC) return true;
289
290
291 return true;
292}
293
294
295
296
297
298
302 assert(Target->getCanonicalDecl() == Target);
303
305
309
312
313 while (true) {
317
318 for (const auto &I : Derived->bases()) {
320
323 RD = cast(RT->getDecl());
326 RD = IT->getDecl();
327 } else {
328 assert(T->isDependentType() && "non-dependent base wasn't a record?");
330 continue;
331 }
332
337
338 Queue.push_back(RD);
339 }
340
341 if (Queue.empty()) break;
342
343 Derived = Queue.pop_back_val();
344 }
345
346 return OnFailure;
347}
348
349
352 if (Friend == Context)
353 return true;
354
355 assert(->isDependentContext() &&
356 "can't handle friends with dependent contexts here");
357
358 if (!Context->isDependentContext())
359 return false;
360
361 if (Friend->isFileContext())
362 return false;
363
364
365 return true;
366}
367
368
369
371 if (Friend == Context)
372 return true;
373
374 if (->isDependentType() && !Context->isDependentType())
375 return false;
376
377
378 return true;
379}
380
384 if (Context->getDeclName() != Friend->getDeclName())
385 return false;
386
388 Context->getDeclContext(),
389 Friend->getDeclContext()))
390 return false;
391
397 ->getAs();
398
399
400
401 if (FriendTy.getQualifiers() != ContextTy.getQualifiers())
402 return false;
403
404 if (FriendTy->getNumParams() != ContextTy->getNumParams())
405 return false;
406
408 FriendTy->getReturnType()))
409 return false;
410
411 for (unsigned I = 0, E = FriendTy->getNumParams(); I != E; ++I)
413 FriendTy->getParamType(I)))
414 return false;
415
416 return true;
417}
418
423 Context->getTemplatedDecl(),
424 Friend->getTemplatedDecl());
425}
426
428 const EffectiveContext &EC,
430 if (EC.includesClass(Friend))
432
433 if (EC.isDependent()) {
434 for (const CXXRecordDecl *Context : EC.Records) {
437 }
438 }
439
441}
442
444 const EffectiveContext &EC,
447 return MatchesFriend(S, EC, cast(RT->getDecl()));
448
449
450 if (Friend->isDependentType())
452
454}
455
456
457
459 const EffectiveContext &EC,
462
463
464
466 I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
468
469
471
472
473 if (isa(Record)) {
474 CTD = cast(Record)
475 ->getSpecializedTemplate();
476
477
478 } else {
479 CTD = Record->getDescribedClassTemplate();
480 if (!CTD) continue;
481 }
482
483
486
487
488 if (!EC.isDependent())
489 continue;
490
491
492
494 continue;
495
496
497
499 Friend->getDeclContext()))
500 continue;
501
502
504 }
505
506 return OnFailure;
507}
508
509
510
512 const EffectiveContext &EC,
515
517 I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) {
520
523 }
524
525 return OnFailure;
526}
527
528
529
531 const EffectiveContext &EC,
534
536
538 I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) {
539
541 if (!FTD)
542 FTD = (*I)->getDescribedFunctionTemplate();
543 if (!FTD)
544 continue;
545
547
550
553 }
554
555 return OnFailure;
556}
557
558
559
561 const EffectiveContext &EC,
563
564
567
570
573
574
575
576 if (isa(Friend))
578
579 if (isa(Friend))
581
582 if (isa(Friend))
584
585 assert(isa(Friend) && "unknown friend decl kind");
587}
588
590 const EffectiveContext &EC,
593
594
599
601 continue;
602
605 break;
606 }
607 }
608
609
610 return OnFailure;
611}
612
613namespace {
614
615
616
617struct ProtectedFriendContext {
619 const EffectiveContext &EC;
621 bool CheckDependent;
622 bool EverDependent;
623
624
626
627 ProtectedFriendContext(Sema &S, const EffectiveContext &EC,
630 : S(S), EC(EC), NamingClass(NamingClass),
631 CheckDependent(InstanceContext->isDependentContext() ||
632 NamingClass->isDependentContext()),
633 EverDependent(false) {}
634
635
636
637 bool checkFriendshipAlongPath(unsigned I) {
638 assert(I < CurPath.size());
639 for (unsigned E = CurPath.size(); I != E; ++I) {
643 case AR_dependent: EverDependent = true; continue;
644 }
645 }
646 return false;
647 }
648
649
650
651
652
653
654 bool findFriendship(const CXXRecordDecl *Cur, unsigned PrivateDepth) {
655
656
657
658 if (Cur == NamingClass)
659 return checkFriendshipAlongPath(PrivateDepth);
660
662 EverDependent = true;
663
664
665 for (const auto &I : Cur->bases()) {
666
667
668 unsigned BasePrivateDepth = PrivateDepth;
669 if (I.getAccessSpecifier() == AS_private)
670 BasePrivateDepth = CurPath.size() - 1;
671
673
676 RD = cast(RT->getDecl());
679 RD = IT->getDecl();
680 } else {
681 assert(T->isDependentType() && "non-dependent base wasn't a record?");
682 EverDependent = true;
683 continue;
684 }
685
686
687 CurPath.push_back(RD);
688 if (findFriendship(RD->getCanonicalDecl(), BasePrivateDepth))
689 return true;
690 CurPath.pop_back();
691 }
692
693 return false;
694 }
695
697 assert(CurPath.empty());
698 CurPath.push_back(Cur);
699 return findFriendship(Cur, 0);
700 }
701};
702}
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
733 assert(InstanceContext == nullptr ||
736
737
738
739
740 if (!InstanceContext) return GetFriendKind(S, EC, NamingClass);
741
742 ProtectedFriendContext PRC(S, EC, InstanceContext, NamingClass);
743 if (PRC.findFriendship(InstanceContext)) return AR_accessible;
746}
747
749 const EffectiveContext &EC,
752 const AccessTarget &Target) {
754 "declaration should be canonicalized before being passed here");
755
758
760
761 for (EffectiveContext::record_iterator
762 I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
763
764
766
767
769 if (ECRecord == NamingClass)
771
774
775
776 } else {
782 }
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801 if (.hasInstanceContext()) {
802
804
805
806
807
808
809
810
811
812 if (S.getLangOpts().MSVCCompat && !EC.Functions.empty())
813 if (CXXMethodDecl* MD = dyn_cast(EC.Functions.front()))
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832 if (NamingClass == ECRecord) return AR_accessible;
833
834
835 continue;
836 }
837
838 assert(Target.isInstanceMember());
839
841 if (!InstanceContext) {
843 continue;
844 }
845
850 }
851 }
852 }
853
854
855
856
857
858
859
860
861
862
863
865
867 if (Target.hasInstanceContext()) {
868 InstanceContext = Target.resolveInstanceContext(S);
870 }
871
876 }
877 llvm_unreachable("impossible friendship kind");
878 }
879
884 }
885
886
887 llvm_unreachable("impossible friendship kind");
888}
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
947 const EffectiveContext &EC,
948 AccessTarget &Target,
951
954
955
957 Paths);
958 assert(isDerived && "derived class not actually derived from base");
959 (void) isDerived;
960
962
963 assert(FinalAccess != AS_none && "forbidden access after declaring class");
964
965 bool AnyDependent = false;
966
967
969 PI != PE; ++PI) {
970 AccessTarget::SavedInstanceContext _ = Target.saveInstanceContext();
971
972
974 CXXBasePath::iterator I = PI->end(), E = PI->begin();
975 while (I != E) {
976 --I;
977
978 assert(PathAccess != AS_none);
979
980
981
982
985 break;
986 }
987
989
990 AccessSpecifier BaseAccess = I->Base->getAccessSpecifier();
991 PathAccess = std::max(PathAccess, BaseAccess);
992
997
998
999
1000 Target.suppressInstanceContext();
1001 break;
1003 AnyDependent = true;
1004 goto Next;
1005 }
1006 }
1007
1008
1009
1010 if (BestPath == nullptr || PathAccess < BestPath->Access) {
1011 BestPath = &*PI;
1012 BestPath->Access = PathAccess;
1013
1014
1016 return BestPath;
1017 }
1018
1019 Next: ;
1020 }
1021
1023 "fell out of loop with public path");
1024
1025
1026
1027 if (AnyDependent)
1028 return nullptr;
1029
1030 return BestPath;
1031}
1032
1033
1034
1035
1036
1037
1039 AccessTarget &Target) {
1040
1041 if (.isInstanceMember())
1042 return false;
1043
1044 assert(Target.isMemberAccess());
1045
1047
1048 for (EffectiveContext::record_iterator
1049 I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
1055 }
1056
1057
1058
1059
1060
1061
1062
1063
1064
1066
1067
1068
1069 if (.hasInstanceContext()) {
1070
1071 if (NamingClass == ECRecord) continue;
1072
1073
1074
1075 S.Diag(D->getLocation(), diag::note_access_protected_restricted_noobject)
1077 return true;
1078 }
1079
1080 const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S);
1081 assert(InstanceContext && "diagnosing dependent access");
1082
1087 break;
1088 }
1089
1090
1091
1092
1094 (isa(D) &&
1095 isa(
1096 cast(D)->getTemplatedDecl()))) {
1098 diag::note_access_protected_restricted_ctordtor)
1100 }
1101
1102
1104 diag::note_access_protected_restricted_object)
1106 }
1107
1108 return false;
1109}
1110
1111
1112
1114 const EffectiveContext &EC,
1115 AccessTarget &entity) {
1116 assert(entity.isMemberAccess());
1117 NamedDecl *D = entity.getTargetDecl();
1118
1121 return;
1122
1123
1126 if (VarDecl *VD = dyn_cast(D))
1128 else if (FunctionDecl *FD = dyn_cast(D))
1130 else if (TypedefNameDecl *TND = dyn_cast(D))
1132 else if (TagDecl *TD = dyn_cast(D)) {
1133 if (isa(D) && cast(D)->isInjectedClassName())
1134 break;
1136 }
1137 if (!PrevDecl) break;
1138 D = PrevDecl;
1139 }
1140
1142 Decl *ImmediateChild;
1144 ImmediateChild = D;
1145 else {
1147 while (DC->getParent() != DeclaringClass)
1149 ImmediateChild = cast(DC);
1150 }
1151
1152
1153
1154 bool isImplicit = true;
1155 for (const auto *I : DeclaringClass->decls()) {
1156 if (I == ImmediateChild) break;
1157 if (isa(I)) {
1158 isImplicit = false;
1159 break;
1160 }
1161 }
1162
1165 << isImplicit;
1166}
1167
1168
1169
1171 const EffectiveContext &EC,
1172 AccessTarget &entity) {
1173
1174 AccessTarget::SavedInstanceContext _ = entity.saveInstanceContext();
1175
1176
1177
1178
1179
1181
1182
1183 if (entity.isMemberAccess()) {
1184 NamedDecl *D = entity.getTargetDecl();
1186 const CXXRecordDecl *declaringClass = entity.getDeclaringClass();
1187
1188 switch (HasAccess(S, EC, declaringClass, accessSoFar, entity)) {
1189
1190
1193 entity.suppressInstanceContext();
1194 break;
1195
1198 declaringClass == entity.getEffectiveNamingClass())
1200 break;
1201
1203 llvm_unreachable("cannot diagnose dependent access");
1204 }
1205 }
1206
1210
1211 CXXBasePath::iterator i = path.end(), e = path.begin();
1212 CXXBasePath::iterator constrainingBase = i;
1213 while (i != e) {
1214 --i;
1215
1217
1218
1219
1222
1223
1224
1226 if (baseAccess > accessSoFar) {
1227 constrainingBase = i;
1228 accessSoFar = baseAccess;
1229 }
1230
1231 switch (HasAccess(S, EC, derivingClass, accessSoFar, entity)) {
1235 entity.suppressInstanceContext();
1236 constrainingBase = nullptr;
1237 break;
1239 llvm_unreachable("cannot diagnose dependent access");
1240 }
1241
1242
1243
1246 assert(constrainingBase == i);
1247 break;
1248 }
1249 }
1250
1251
1252
1253 if (constrainingBase == path.end())
1255
1256
1257
1258
1259 unsigned diagnostic;
1260 if (entity.isMemberAccess() ||
1261 constrainingBase + 1 != path.end()) {
1262 diagnostic = diag::note_access_constrained_by_path;
1263 } else {
1264 diagnostic = diag::note_access_natural;
1265 }
1266
1268
1273
1274 if (entity.isMemberAccess())
1275 S.Diag(entity.getTargetDecl()->getLocation(),
1276 diag::note_member_declared_at);
1277}
1278
1280 const EffectiveContext &EC,
1281 AccessTarget &Entity) {
1282 const CXXRecordDecl *NamingClass = Entity.getNamingClass();
1283 const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();
1284 NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : nullptr);
1285
1286 S.Diag(Loc, Entity.getDiag())
1292}
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1316 AccessTarget &Entity) {
1318 dyn_cast(Entity.getTargetDecl()))
1319 if (UsingDecl *UD = dyn_cast(Shadow->getIntroducer())) {
1321 if (Entity.getTargetDecl()->getAccess() == AS_private &&
1324 S.Diag(AccessLoc, diag::ext_ms_using_declaration_inaccessible)
1325 << UD->getQualifiedNameAsString()
1327 return true;
1328 }
1329 }
1330 return false;
1331}
1332
1333
1334
1336 const EffectiveContext &EC,
1337 AccessTarget &Entity) {
1338
1339 const CXXRecordDecl *NamingClass = Entity.getEffectiveNamingClass();
1340
1342 assert(UnprivilegedAccess != AS_public && "public access not weeded out");
1343
1344
1345
1346
1347
1348 if (UnprivilegedAccess != AS_none) {
1349 switch (HasAccess(S, EC, NamingClass, UnprivilegedAccess, Entity)) {
1351
1352
1353
1354
1355
1356
1357
1359
1362 }
1363 }
1364
1365 AccessTarget::SavedInstanceContext _ = Entity.saveInstanceContext();
1366
1367
1368
1370
1371 if (Entity.isMemberAccess()) {
1372
1373
1375 const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();
1376
1378 switch (HasAccess(S, EC, DeclaringClass, FinalAccess, Entity)) {
1380
1381
1382
1383
1384
1386 Entity.suppressInstanceContext();
1387 break;
1390 }
1391
1392 if (DeclaringClass == NamingClass)
1394 } else {
1396 }
1397
1398 assert(Entity.getDeclaringClass() != NamingClass);
1399
1400
1405
1406 assert(Path->Access <= UnprivilegedAccess &&
1407 "access along best path worse than direct?");
1411}
1412
1414 const EffectiveContext &EC,
1416 const AccessTarget &Entity) {
1417 assert(EC.isDependent() && "delaying non-dependent access");
1419 assert(DC->isDependentContext() && "delaying non-dependent access");
1422 Entity.isMemberAccess(),
1423 Entity.getAccess(),
1424 Entity.getTargetDecl(),
1425 Entity.getNamingClass(),
1426 Entity.getBaseObjectType(),
1427 Entity.getDiag());
1428}
1429
1430
1432 const EffectiveContext &EC,
1434 AccessTarget &Entity) {
1435 assert(Entity.getAccess() != AS_public && "called for public access!");
1436
1441
1446 if (!Entity.isQuiet())
1449
1452 }
1453
1454
1455 llvm_unreachable("invalid access result");
1456}
1457
1459 AccessTarget &Entity) {
1460
1461 if (Entity.getAccess() == AS_public)
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1482
1483
1484
1485
1486
1487
1489 bool IsFriendDeclaration = false;
1490 while (TS && !IsFriendDeclaration) {
1493 }
1494 if (!IsFriendDeclaration) {
1497 }
1498 }
1499
1505 }
1506 llvm_unreachable("invalid access result");
1507}
1508
1510
1511
1512
1513
1514
1518 } else if (FunctionDecl *FN = dyn_cast(D)) {
1519 DC = FN;
1520 } else if (TemplateDecl *TD = dyn_cast(D)) {
1521 if (isa(TD->getTemplatedDecl()))
1522 DC = cast(TD->getTemplatedDecl());
1523 } else if (auto *RD = dyn_cast(D)) {
1524 DC = RD;
1525 }
1526
1527 EffectiveContext EC(DC);
1528
1530
1533}
1534
1539
1541 TemplateArgs);
1542 if (!NamingD) return;
1544 TemplateArgs);
1545 if (!TargetD) return;
1546
1548 CXXRecordDecl *NamingClass = cast(NamingD);
1549 NamedDecl *TargetDecl = cast(TargetD);
1551 if (!BaseObjectType.isNull()) {
1552 BaseObjectType = SubstType(BaseObjectType, TemplateArgs, Loc,
1554 if (BaseObjectType.isNull()) return;
1555 }
1556
1557 AccessTarget Entity(Context,
1558 AccessTarget::Member,
1559 NamingClass,
1561 BaseObjectType);
1564 } else {
1565 AccessTarget Entity(Context,
1566 AccessTarget::Base,
1567 cast(TargetD),
1568 cast(NamingD),
1569 Access);
1572 }
1573}
1574
1578 ->getNamingClass() ||
1581
1582 AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(),
1584 Entity.setDiag(diag::err_access) << E->getSourceRange();
1585
1586 return CheckAccess(*this, E->getNameLoc(), Entity);
1587}
1588
1594
1595 QualType BaseType = E->getBaseType();
1596 if (E->isArrow())
1598
1599 AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(),
1600 Found, BaseType);
1601 Entity.setDiag(diag::err_access) << E->getSourceRange();
1602
1603 return CheckAccess(*this, E->getMemberLoc(), Entity);
1604}
1605
1611
1613 return true;
1614
1615 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
1616 ObjectType);
1617
1618
1619 Entity.setDiag(Diag);
1620
1624 case AR_dependent: llvm_unreachable("dependent for =delete computation");
1625 case AR_delayed: llvm_unreachable("cannot delay =delete computation");
1626 }
1627 llvm_unreachable("bad access result");
1628}
1629
1636
1637
1641
1644
1645 AccessTarget Entity(Context, AccessTarget::Member, NamingClass,
1647 ObjectTy);
1648 Entity.setDiag(PDiag);
1649
1651}
1652
1657 bool IsCopyBindingRefToTemp) {
1660
1662 switch (Entity.getKind()) {
1663 default:
1664 PD = PDiag(IsCopyBindingRefToTemp
1665 ? diag::ext_rvalue_to_reference_access_ctor
1666 : diag::err_access_ctor);
1667
1668 break;
1669
1671 PD = PDiag(diag::err_access_base_ctor);
1675 break;
1676
1680 PD = PDiag(diag::err_access_field_ctor);
1681 PD << Field->getType()
1683 break;
1684 }
1685
1688 PD = PDiag(diag::err_access_lambda_capture);
1689 PD << VarName << Entity.getType()
1691 break;
1692 }
1693
1694 }
1695
1697}
1698
1707
1708 CXXRecordDecl *NamingClass = Constructor->getParent();
1709
1710
1711
1712
1713
1714
1715
1716
1722 } else if (auto *Shadow =
1723 dyn_cast(Found.getDecl())) {
1724
1725
1726 ObjectClass = Shadow->getParent();
1727 } else {
1728 ObjectClass = NamingClass;
1729 }
1730
1731 AccessTarget AccessEntity(
1732 Context, AccessTarget::Member, NamingClass,
1735 AccessEntity.setDiag(PD);
1736
1737 return CheckAccess(*this, UseLoc, AccessEntity);
1738}
1739
1744 bool Diagnose) {
1746 !NamingClass ||
1749
1750 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
1753 Entity.setDiag(diag::err_access)
1754 << PlacementRange;
1755
1756 return CheckAccess(*this, OpLoc, Entity);
1757}
1758
1763 !NamingClass ||
1766
1767 AccessTarget Entity(Context, AccessTarget::Member, NamingClass,
1769
1770 return CheckAccess(*this, UseLoc, Entity);
1771}
1772
1780
1781 AccessTarget Entity(Context, AccessTarget::Member, DecomposedClass, Field,
1783 Entity.setDiag(diag::err_decomp_decl_inaccessible_field);
1784
1785 return CheckAccess(*this, UseLoc, Entity);
1786}
1787
1789 Expr *ObjectExpr,
1794
1797
1798 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
1800 Entity.setDiag(diag::err_access) << ObjectExpr->getSourceRange() << Range;
1801
1802 return CheckAccess(*this, OpLoc, Entity);
1803}
1804
1806 Expr *ObjectExpr,
1807 Expr *ArgExpr,
1812}
1813
1815 Expr *ObjectExpr,
1819 if (!ArgExprs.empty()) {
1820 R = SourceRange(ArgExprs.front()->getBeginLoc(),
1821 ArgExprs.back()->getEndLoc());
1822 }
1823
1825}
1826
1828 assert(isa(target->getAsFunction()));
1829
1830
1831
1833
1836
1838
1839 AccessTarget entity(Context, AccessTarget::Member,
1842 QualType());
1843 entity.setDiag(diag::err_access_friend_function)
1846
1847
1848
1854 }
1855 llvm_unreachable("invalid access result");
1856}
1857
1864
1867
1868 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
1869 QualType());
1870 Entity.setDiag(diag::err_access)
1872
1874}
1875
1880 unsigned DiagID,
1881 bool ForceCheck,
1882 bool ForceUnprivileged) {
1883 if (!ForceCheck && ().AccessControl)
1885
1888
1892
1893 AccessTarget Entity(Context, AccessTarget::Base, BaseD, DerivedD,
1894 Path.Access);
1895 if (DiagID)
1896 Entity.setDiag(DiagID) << Derived << Base;
1897
1898 if (ForceUnprivileged) {
1900 AccessLoc, Entity)) {
1904 }
1905 llvm_unreachable("unexpected result from CheckEffectiveAccess");
1906 }
1907 return CheckAccess(*this, AccessLoc, Entity);
1908}
1909
1912 && "performing access check without access control");
1913 assert(R.getNamingClass() && "performing access check without naming class");
1914
1916 if (I.getAccess() != AS_public) {
1920 Entity.setDiag(diag::err_access);
1922 }
1923 }
1924}
1925
1928
1929 if (Target->isCXXClassMember() && NamingClass) {
1931 return false;
1932
1933
1934
1935
1940 }
1941
1943
1946 return true;
1947
1948
1949
1952 ClassOfMethodDecl = MD->getClassInterface();
1955 = dyn_cast(FD->getLexicalDeclContext())) {
1957 = dyn_cast(Impl))
1958 ClassOfMethodDecl = IMPD->getClassInterface();
1960 = dyn_cast(Impl))
1961 ClassOfMethodDecl = CatImplClass->getClassInterface();
1962 }
1963 }
1964
1965
1966 if (!ClassOfMethodDecl)
1967 return false;
1968
1969
1970 if (declaresSameEntity(ClassOfMethodDecl, Ivar->getContainingInterface()))
1971 return true;
1972
1973
1975 return false;
1976
1977 return Ivar->getContainingInterface()->isSuperClassOf(ClassOfMethodDecl);
1978 }
1979
1980 return true;
1981}
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.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
llvm::MachO::Target Target
llvm::MachO::Records Records
llvm::MachO::Record Record
static void DiagnoseBadAccess(Sema &S, SourceLocation Loc, const EffectiveContext &EC, AccessTarget &Entity)
AccessResult
A copy of Sema's enum without AR_delayed.
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)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
QualType getRecordType(const RecordDecl *Decl) const
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
QualType getTypeDeclType(const TypeDecl *Decl, const TypeDecl *PrevDecl=nullptr) const
Return the unique reference to the type for the specified type declaration.
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...
std::list< CXXBasePath >::iterator paths_iterator
Represents a base class of a C++ class.
AccessSpecifier getAccessSpecifierAsWritten() const
Retrieves the access specifier as written in the source code (which may mean that no access specifier...
QualType getType() const
Retrieves the type of the base class.
SourceRange getSourceRange() const LLVM_READONLY
Retrieves the source range that contains the entire base specifier.
AccessSpecifier getAccessSpecifier() const
Returns the access specifier for this base specifier.
Represents a C++ constructor within a class.
Represents a C++ destructor within a class.
Represents a static or instance method of a struct/union/class.
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Represents a C++ struct/union/class.
bool isLambda() const
Determine whether this class describes a lambda function object.
bool hasDefinition() const
CXXRecordDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
bool isDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is derived from the class Base.
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 this template.
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...
DeclContext * getParent()
getParent - Returns the containing DeclContext.
bool isFileContext() const
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.
Decl - This represents one declaration (or definition), e.g.
Decl * getPreviousDecl()
Retrieve the previous declaration that declares the same entity as this declaration,...
virtual bool isOutOfLine() const
Determine whether this declaration is declared out of line (outside its semantic context).
FunctionDecl * getAsFunction() LLVM_READONLY
Returns the function itself, or the templated function if this is a function template.
bool isInvalidDecl() const
bool isLocalExternDecl() const
Determine whether this is a block-scope declaration with linkage.
void setAccess(AccessSpecifier AS)
SourceLocation getLocation() const
DeclContext * getDeclContext()
AccessSpecifier getAccess() const
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC).
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
The name of a declaration.
NestedNameSpecifier * getQualifier() const
Retrieve the nested-name-specifier that qualifies the name of this declaration, if it was present in ...
NestedNameSpecifierLoc getQualifierLoc() const
Retrieve the nested-name-specifier (with source-location information) that qualifies the name of this...
A dependently-generated diagnostic.
NamedDecl * getAccessNamingClass() const
QualType getAccessBaseObjectType() const
bool isAccessToMember() 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.
Represents a member of a struct/union/class.
FriendDecl - Represents the declaration of a friend entity, which can be a function,...
bool isUnsupportedFriend() const
Determines if this friend kind is unsupported.
NamedDecl * getFriendDecl() const
If this friend declaration doesn't name a type, return the inner declaration.
TypeSourceInfo * getFriendType() const
If this friend declaration names an (untemplated but possibly dependent) type, return the type; other...
Represents a function declaration or definition.
DeclarationNameInfo getNameInfo() const
Represents a prototype with parameter type info, e.g.
Declaration of a template function.
FunctionTemplateDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this template.
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.
The injected class name of a C++ class template or class template partial specialization.
Represents the results of name lookup.
SourceLocation getNameLoc() const
Gets the location of the identifier.
CXXRecordDecl * getNamingClass() const
Returns the 'naming class' for this lookup, i.e.
QualType getBaseObjectType() const
Returns the base object type associated with this lookup; important for [class.protected].
Data structure that captures multiple levels of template argument lists for use in template instantia...
This represents a decl that may have a name.
NamedDecl * getUnderlyingDecl()
Looks through UsingDecls and ObjCCompatibleAliasDecls for the underlying named decl.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
std::string getQualifiedNameAsString() const
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.
ObjCImplementationDecl - Represents a class definition - this is where method definitions are specifi...
Represents an ObjC class declaration.
bool isSuperClassOf(const ObjCInterfaceDecl *I) const
isSuperClassOf - Return true if this class is the specified class or is a super class of the specifie...
ObjCIvarDecl - Represents an ObjC instance variable.
ObjCMethodDecl - Represents an instance or class method declaration.
A reference to an overloaded function set, either an UnresolvedLookupExpr or an UnresolvedMemberExpr.
static FindResult find(Expr *E)
Finds the overloaded expression in the given expression E of OverloadTy.
SourceLocation getNameLoc() const
Gets the location of the name.
CXXRecordDecl * getNamingClass()
Gets the naming class of this lookup, if any.
PointerType - C99 6.7.5.1 - Pointer Declarators.
A (possibly-)qualified type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
bool isAnonymousStructOrUnion() const
Whether this is an anonymous struct or union.
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
RecordDecl * getDecl() const
Scope - A scope is a transient data structure that is used while parsing the program.
bool isFriendScope() const
Determine whether this scope is a friend scope.
const Scope * getParent() const
getParent - Return the scope that this is nested in.
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
PartialDiagnostic PDiag(unsigned DiagID=0)
Build a partial diagnostic.
bool shouldDelayDiagnostics()
Determines whether diagnostics should be delayed.
void add(const sema::DelayedDiagnostic &diag)
Adds a delayed diagnostic.
Sema - This implements semantic analysis and AST building for C.
Scope * getCurScope() const
Retrieve the parser's current scope.
CXXSpecialMemberKind getSpecialMember(const CXXMethodDecl *MD)
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.
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...
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...
void HandleDependentAccessCheck(const DependentDiagnostic &DD, const MultiLevelTemplateArgumentList &TemplateArgs)
const LangOptions & getLangOpts() const
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.
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.
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...
Represents the declaration of a struct/union/class/enum.
The base class of all kinds of template declarations (e.g., class, function, etc.).
A container of type source information.
CanQualType getCanonicalTypeUnqualified() const
const T * castAs() const
Member-template castAs.
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
const T * getAs() const
Member-template getAs'.
Base class for declarations which introduce a typedef-name.
A reference to a name which we were able to look up during parsing but could not resolve to a specifi...
Represents a C++ member access expression for which lookup produced a set of overloaded functions.
The iterator over UnresolvedSets.
Represents a C++ using-declaration.
Represents a shadow declaration implicitly introduced into a scope by a (resolved) using-declaration ...
Represents a variable declaration or definition.
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...
AccessedEntity & getAccessData()
static DelayedDiagnostic makeAccess(SourceLocation Loc, const AccessedEntity &Entity)
The JSON file list parser is used to communicate input to InstallAPI.
void initialize(TemplateInstantiationCallbackPtrs &Callbacks, const Sema &TheSema)
const FunctionProtoType * T
bool declaresSameEntity(const Decl *D1, const Decl *D2)
Determine whether two declarations declare the same entity.
@ Class
The "class" keyword introduces the elaborated-type-specifier.
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
SourceRange getSourceRange() const LLVM_READONLY
getSourceRange - The range of the declaration name.
OverloadExpr * Expression