clang: lib/Sema/SemaAccess.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
24
25using namespace clang;
26using namespace sema;
27
28
34
38 if (!PrevMemberDecl) {
39
41 return false;
42 }
43
44
45
46 if (LexicalAS != AS_none && LexicalAS != PrevMemberDecl->getAccess()) {
48 diag::err_class_redeclared_with_different_access)
49 << MemberDecl << LexicalAS;
50 Diag(PrevMemberDecl->getLocation(), diag::note_previous_access_declaration)
51 << PrevMemberDecl << PrevMemberDecl->getAccess();
52
54 return true;
55 }
56
58 return false;
59}
60
63
64
65
68
72 return DeclaringClass;
73}
74
75namespace {
76struct EffectiveContext {
78
79 explicit EffectiveContext(DeclContext *DC)
80 : Inner(DC),
81 Dependent(DC->isDependentContext()) {
82
83
84
85
86 if (auto *DGD = dyn_cast(DC)) {
87 if (DGD->isImplicit()) {
88 DC = DGD->getCorrespondingConstructor();
89 if (!DC) {
90
91
92 DC = cast(DGD->getDeducedTemplate()->getTemplatedDecl());
93 }
94 }
95 }
96
97
98
99
100
101
102
103
104
105
106
107
108
109 while (true) {
110
111
112
113
114
115
119 DC = Record->getDeclContext();
122 Functions.push_back(Function->getCanonicalDecl());
123 if (Function->getFriendObjectKind())
124 DC = Function->getLexicalDeclContext();
125 else
126 DC = Function->getDeclContext();
128 break;
129 } else {
131 }
132 }
133 }
134
135 bool isDependent() const { return Dependent; }
136
137 bool includesClass(const CXXRecordDecl *R) const {
139 return llvm::is_contained(Records, R);
140 }
141
142
143
144 DeclContext *getInnerContext() const {
145 return Inner;
146 }
147
148 typedef SmallVectorImpl<CXXRecordDecl*>::const_iterator record_iterator;
149
150 DeclContext *Inner;
151 SmallVector<FunctionDecl*, 4> Functions;
152 SmallVector<CXXRecordDecl*, 4> Records;
154};
155
156
157
159 AccessTarget(const AccessedEntity &Entity)
160 : AccessedEntity(Entity) {
162 }
163
164 AccessTarget(ASTContext &Context,
165 MemberNonce _,
166 CXXRecordDecl *NamingClass,
167 DeclAccessPair FoundDecl,
168 QualType BaseObjectType)
169 : AccessedEntity(Context.getDiagAllocator(), Member, NamingClass,
170 FoundDecl, BaseObjectType) {
172 }
173
174 AccessTarget(ASTContext &Context,
175 BaseNonce _,
176 CXXRecordDecl *BaseClass,
177 CXXRecordDecl *DerivedClass,
179 : AccessedEntity(Context.getDiagAllocator(), Base, BaseClass, DerivedClass,
180 Access) {
182 }
183
184 bool isInstanceMember() const {
185 return (isMemberAccess() && getTargetDecl()->isCXXInstanceMember());
186 }
187
188 bool hasInstanceContext() const {
189 return HasInstanceContext;
190 }
191
192 class SavedInstanceContext {
193 public:
194 SavedInstanceContext(SavedInstanceContext &&S)
196 S.Target = nullptr;
197 }
198
199
200
201 SavedInstanceContext &operator=(SavedInstanceContext &&) = delete;
202
203
204
205 SavedInstanceContext(const SavedInstanceContext &) = delete;
206 SavedInstanceContext &operator=(const SavedInstanceContext &) = delete;
207
208 ~SavedInstanceContext() {
210 Target->HasInstanceContext = Has;
211 }
212
213 private:
214 friend struct AccessTarget;
215 explicit SavedInstanceContext(AccessTarget &Target)
217 AccessTarget *Target;
218 bool Has;
219 };
220
221 SavedInstanceContext saveInstanceContext() {
222 return SavedInstanceContext(*this);
223 }
224
225 void suppressInstanceContext() {
226 HasInstanceContext = false;
227 }
228
229 const CXXRecordDecl *resolveInstanceContext(Sema &S) const {
230 assert(HasInstanceContext);
231 if (CalculatedInstanceContext)
232 return InstanceContext;
233
234 CalculatedInstanceContext = true;
237 : nullptr);
238 return InstanceContext;
239 }
240
241 const CXXRecordDecl *getDeclaringClass() const {
242 return DeclaringClass;
243 }
244
245
246
247 const CXXRecordDecl *getEffectiveNamingClass() const {
248 const CXXRecordDecl *namingClass = getNamingClass();
252 }
253
254private:
256 HasInstanceContext = (isMemberAccess() &&
257 !getBaseObjectType().isNull() &&
258 getTargetDecl()->isCXXInstanceMember());
259 CalculatedInstanceContext = false;
260 InstanceContext = nullptr;
261
262 if (isMemberAccess())
264 else
265 DeclaringClass = getBaseClass();
266 DeclaringClass = DeclaringClass->getCanonicalDecl();
267 }
268
269 bool HasInstanceContext : 1;
270 mutable bool CalculatedInstanceContext : 1;
271 mutable const CXXRecordDecl *InstanceContext;
272 const CXXRecordDecl *DeclaringClass;
273};
274
275}
276
277
280
282 return false;
283
286 if (FromDC == ToDC) return true;
288
289
290 return true;
291}
292
293
294
295
296
297
301 assert(Target->getCanonicalDecl() == Target);
302
304
308
311
312 while (true) {
316
317 for (const auto &I : Derived->bases()) {
319
322 RD = Rec;
323 } else {
324 assert(T->isDependentType() && "non-dependent base wasn't a record?");
326 continue;
327 }
328
333
334 Queue.push_back(RD);
335 }
336
337 if (Queue.empty()) break;
338
339 Derived = Queue.pop_back_val();
340 }
341
342 return OnFailure;
343}
344
345
348 if (Friend == Context)
349 return true;
350
351 assert(->isDependentContext() &&
352 "can't handle friends with dependent contexts here");
353
354 if (!Context->isDependentContext())
355 return false;
356
357 if (Friend->isFileContext())
358 return false;
359
360
361 return true;
362}
363
364
365
367 if (Friend == Context)
368 return true;
369
370 if (->isDependentType() && !Context->isDependentType())
371 return false;
372
373
374 return true;
375}
376
380 if (Context->getDeclName() != Friend->getDeclName())
381 return false;
382
384 Context->getDeclContext(),
385 Friend->getDeclContext()))
386 return false;
387
394
395
396
397 if (FriendTy.getQualifiers() != ContextTy.getQualifiers())
398 return false;
399
400 if (FriendTy->getNumParams() != ContextTy->getNumParams())
401 return false;
402
404 FriendTy->getReturnType()))
405 return false;
406
407 for (unsigned I = 0, E = FriendTy->getNumParams(); I != E; ++I)
409 FriendTy->getParamType(I)))
410 return false;
411
412 return true;
413}
414
419 Context->getTemplatedDecl(),
420 Friend->getTemplatedDecl());
421}
422
424 const EffectiveContext &EC,
426 if (EC.includesClass(Friend))
428
429 if (EC.isDependent()) {
430 for (const CXXRecordDecl *Context : EC.Records) {
433 }
434 }
435
437}
438
440 const EffectiveContext &EC,
442 if (const auto *RD = Friend->getAsCXXRecordDecl())
444
445
446 if (Friend->isDependentType())
448
450}
451
452
453
455 const EffectiveContext &EC,
458
459
460
462 I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
464
465
467
468
471 ->getSpecializedTemplate();
472
473
474 } else {
475 CTD = Record->getDescribedClassTemplate();
476 if (!CTD) continue;
477 }
478
479
482
483
484 if (!EC.isDependent())
485 continue;
486
487
488
490 continue;
491
492
493
495 Friend->getDeclContext()))
496 continue;
497
498
500 }
501
502 return OnFailure;
503}
504
505
506
508 const EffectiveContext &EC,
511
513 I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) {
516
519 }
520
521 return OnFailure;
522}
523
524
525
527 const EffectiveContext &EC,
530
532
534 I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) {
535
537 if (!FTD)
538 FTD = (*I)->getDescribedFunctionTemplate();
539 if (!FTD)
540 continue;
541
543
546
549 }
550
551 return OnFailure;
552}
553
554
555
557 const EffectiveContext &EC,
559
560
563
565 return MatchesFriend(S, EC, T->getType()->getCanonicalTypeUnqualified());
566
569
570
571
574
577
580
583}
584
586 const EffectiveContext &EC,
589
590
591 for (auto *Friend : Class->friends()) {
595
597 continue;
598
601 break;
602 }
603 }
604
605
606 return OnFailure;
607}
608
609namespace {
610
611
612
613struct ProtectedFriendContext {
614 Sema &S;
615 const EffectiveContext &EC;
616 const CXXRecordDecl *NamingClass;
617 bool CheckDependent;
618 bool EverDependent;
619
620
621 SmallVector<const CXXRecordDecl*, 20> CurPath;
622
623 ProtectedFriendContext(Sema &S, const EffectiveContext &EC,
624 const CXXRecordDecl *InstanceContext,
625 const CXXRecordDecl *NamingClass)
626 : S(S), EC(EC), NamingClass(NamingClass),
627 CheckDependent(InstanceContext->isDependentContext() ||
628 NamingClass->isDependentContext()),
629 EverDependent(false) {}
630
631
632
633 bool checkFriendshipAlongPath(unsigned I) {
634 assert(I < CurPath.size());
635 for (unsigned E = CurPath.size(); I != E; ++I) {
639 case AR_dependent: EverDependent = true; continue;
640 }
641 }
642 return false;
643 }
644
645
646
647
648
649
650 bool findFriendship(const CXXRecordDecl *Cur, unsigned PrivateDepth) {
651
652
653
654 if (Cur == NamingClass)
655 return checkFriendshipAlongPath(PrivateDepth);
656
658 EverDependent = true;
659
660
661 for (const auto &I : Cur->bases()) {
662
663
664 unsigned BasePrivateDepth = PrivateDepth;
665 if (I.getAccessSpecifier() == AS_private)
666 BasePrivateDepth = CurPath.size() - 1;
667
668 const CXXRecordDecl *RD;
669
670 QualType T = I.getType();
672 RD = Rec;
673 } else {
674 assert(T->isDependentType() && "non-dependent base wasn't a record?");
675 EverDependent = true;
676 continue;
677 }
678
679
680 CurPath.push_back(RD);
681 if (findFriendship(RD->getCanonicalDecl(), BasePrivateDepth))
682 return true;
683 CurPath.pop_back();
684 }
685
686 return false;
687 }
688
689 bool findFriendship(const CXXRecordDecl *Cur) {
690 assert(CurPath.empty());
691 CurPath.push_back(Cur);
692 return findFriendship(Cur, 0);
693 }
694};
695}
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
726 assert(InstanceContext == nullptr ||
729
730
731
732
733 if (!InstanceContext) return GetFriendKind(S, EC, NamingClass);
734
735 ProtectedFriendContext PRC(S, EC, InstanceContext, NamingClass);
736 if (PRC.findFriendship(InstanceContext)) return AR_accessible;
739}
740
742 const EffectiveContext &EC,
745 const AccessTarget &Target) {
747 "declaration should be canonicalized before being passed here");
748
751
753
754 for (EffectiveContext::record_iterator
755 I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
756
757
759
760
762 if (ECRecord == NamingClass)
764
767
768
769 } else {
775 }
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794 if (.hasInstanceContext()) {
795
797
798
799
800
801
802
803
804
805 if (S.getLangOpts().MSVCCompat && !EC.Functions.empty())
806 if (CXXMethodDecl* MD = dyn_cast(EC.Functions.front()))
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825 if (NamingClass == ECRecord) return AR_accessible;
826
827
828 continue;
829 }
830
831 assert(Target.isInstanceMember());
832
834 if (!InstanceContext) {
836 continue;
837 }
838
843 }
844 }
845 }
846
847
848
849
850
851
852
853
854
855
856
858
860 if (Target.hasInstanceContext()) {
861 InstanceContext = Target.resolveInstanceContext(S);
863 }
864
869 }
870 llvm_unreachable("impossible friendship kind");
871 }
872
877 }
878
879
880 llvm_unreachable("impossible friendship kind");
881}
882
883
884
885
886
887
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
940 const EffectiveContext &EC,
941 AccessTarget &Target,
944
947
948
950 Paths);
951 assert(isDerived && "derived class not actually derived from base");
952 (void) isDerived;
953
955
956 assert(FinalAccess != AS_none && "forbidden access after declaring class");
957
958 bool AnyDependent = false;
959
960
962 PI != PE; ++PI) {
963 AccessTarget::SavedInstanceContext _ = Target.saveInstanceContext();
964
965
967 CXXBasePath::iterator I = PI->end(), E = PI->begin();
968 while (I != E) {
969 --I;
970
971 assert(PathAccess != AS_none);
972
973
974
975
978 break;
979 }
980
982
983 AccessSpecifier BaseAccess = I->Base->getAccessSpecifier();
984 PathAccess = std::max(PathAccess, BaseAccess);
985
990
991
992
993 Target.suppressInstanceContext();
994 break;
996 AnyDependent = true;
998 }
999 }
1000
1001
1002
1003 if (BestPath == nullptr || PathAccess < BestPath->Access) {
1004 BestPath = &*PI;
1005 BestPath->Access = PathAccess;
1006
1007
1009 return BestPath;
1010 }
1011
1013 }
1014
1016 "fell out of loop with public path");
1017
1018
1019
1020 if (AnyDependent)
1021 return nullptr;
1022
1023 return BestPath;
1024}
1025
1026
1027
1028
1029
1030
1032 AccessTarget &Target) {
1033
1034 if (.isInstanceMember())
1035 return false;
1036
1037 assert(Target.isMemberAccess());
1038
1040
1041 for (EffectiveContext::record_iterator
1042 I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
1048 }
1049
1050
1051
1052
1053
1054
1055
1056
1057
1059
1060
1061
1062 if (.hasInstanceContext()) {
1063
1064 if (NamingClass == ECRecord) continue;
1065
1066
1067
1068 S.Diag(D->getLocation(), diag::note_access_protected_restricted_noobject)
1070 return true;
1071 }
1072
1073 const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S);
1074 assert(InstanceContext && "diagnosing dependent access");
1075
1080 break;
1081 }
1082
1083
1084
1085
1091 diag::note_access_protected_restricted_ctordtor)
1093 }
1094
1095
1097 diag::note_access_protected_restricted_object)
1099 }
1100
1101 return false;
1102}
1103
1104
1105
1107 const EffectiveContext &EC,
1108 AccessTarget &entity) {
1109 assert(entity.isMemberAccess());
1110 NamedDecl *D = entity.getTargetDecl();
1111
1114 return;
1115
1116
1119 if (VarDecl *VD = dyn_cast(D))
1121 else if (FunctionDecl *FD = dyn_cast(D))
1123 else if (TypedefNameDecl *TND = dyn_cast(D))
1125 else if (TagDecl *TD = dyn_cast(D)) {
1126 if (const auto *RD = dyn_cast(TD);
1128 break;
1130 }
1131 if (!PrevDecl) break;
1132 D = PrevDecl;
1133 }
1134
1136 Decl *ImmediateChild;
1138 ImmediateChild = D;
1139 else {
1141 while (DC->getParent() != DeclaringClass)
1144 }
1145
1146
1147
1148 bool isImplicit = true;
1149 for (const auto *I : DeclaringClass->decls()) {
1150 if (I == ImmediateChild) break;
1152 isImplicit = false;
1153 break;
1154 }
1155 }
1156
1159 << isImplicit;
1160}
1161
1162
1163
1165 const EffectiveContext &EC,
1166 AccessTarget &entity) {
1167
1168 AccessTarget::SavedInstanceContext _ = entity.saveInstanceContext();
1169
1170
1171
1172
1173
1175
1176
1177 if (entity.isMemberAccess()) {
1178 NamedDecl *D = entity.getTargetDecl();
1180 const CXXRecordDecl *declaringClass = entity.getDeclaringClass();
1181
1182 switch (HasAccess(S, EC, declaringClass, accessSoFar, entity)) {
1183
1184
1187 entity.suppressInstanceContext();
1188 break;
1189
1192 declaringClass == entity.getEffectiveNamingClass())
1194 break;
1195
1197 llvm_unreachable("cannot diagnose dependent access");
1198 }
1199 }
1200
1204
1205 CXXBasePath::iterator i = path.end(), e = path.begin();
1206 CXXBasePath::iterator constrainingBase = i;
1207 while (i != e) {
1208 --i;
1209
1211
1212
1213
1216
1217
1218
1220 if (baseAccess > accessSoFar) {
1221 constrainingBase = i;
1222 accessSoFar = baseAccess;
1223 }
1224
1225 switch (HasAccess(S, EC, derivingClass, accessSoFar, entity)) {
1229 entity.suppressInstanceContext();
1230 constrainingBase = nullptr;
1231 break;
1233 llvm_unreachable("cannot diagnose dependent access");
1234 }
1235
1236
1237
1240 assert(constrainingBase == i);
1241 break;
1242 }
1243 }
1244
1245
1246
1247 if (constrainingBase == path.end())
1249
1250
1251
1252
1253 unsigned diagnostic;
1254 if (entity.isMemberAccess() ||
1255 constrainingBase + 1 != path.end()) {
1256 diagnostic = diag::note_access_constrained_by_path;
1257 } else {
1258 diagnostic = diag::note_access_natural;
1259 }
1260
1262
1267
1268 if (entity.isMemberAccess())
1269 S.Diag(entity.getTargetDecl()->getLocation(),
1270 diag::note_member_declared_at);
1271}
1272
1274 const EffectiveContext &EC,
1275 AccessTarget &Entity) {
1276 const CXXRecordDecl *NamingClass = Entity.getNamingClass();
1277 const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();
1278 NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : nullptr);
1279
1280 S.Diag(Loc, Entity.getDiag())
1286}
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1310 AccessTarget &Entity) {
1312 dyn_cast(Entity.getTargetDecl()))
1313 if (UsingDecl *UD = dyn_cast(Shadow->getIntroducer())) {
1314 const NamedDecl *OrigDecl = Entity.getTargetDecl()->getUnderlyingDecl();
1315 if (Entity.getTargetDecl()->getAccess() == AS_private &&
1318 S.Diag(AccessLoc, diag::ext_ms_using_declaration_inaccessible)
1319 << UD->getQualifiedNameAsString()
1321 return true;
1322 }
1323 }
1324 return false;
1325}
1326
1327
1328
1330 const EffectiveContext &EC,
1331 AccessTarget &Entity) {
1332
1333 const CXXRecordDecl *NamingClass = Entity.getEffectiveNamingClass();
1334
1335 AccessSpecifier UnprivilegedAccess = Entity.getAccess();
1336 assert(UnprivilegedAccess != AS_public && "public access not weeded out");
1337
1338
1339
1340
1341
1342 if (UnprivilegedAccess != AS_none) {
1343 switch (HasAccess(S, EC, NamingClass, UnprivilegedAccess, Entity)) {
1345
1346
1347
1348
1349
1350
1351
1353
1356 }
1357 }
1358
1359 AccessTarget::SavedInstanceContext _ = Entity.saveInstanceContext();
1360
1361
1362
1364
1365 if (Entity.isMemberAccess()) {
1366
1367
1369 const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();
1370
1371 FinalAccess = Target->getAccess();
1372 switch (HasAccess(S, EC, DeclaringClass, FinalAccess, Entity)) {
1374
1375
1376
1377
1378
1380 Entity.suppressInstanceContext();
1381 break;
1384 }
1385
1386 if (DeclaringClass == NamingClass)
1388 } else {
1390 }
1391
1392 assert(Entity.getDeclaringClass() != NamingClass);
1393
1394
1397 if (!Path)
1399
1400 assert(Path->Access <= UnprivilegedAccess &&
1401 "access along best path worse than direct?");
1405}
1406
1408 const EffectiveContext &EC,
1410 const AccessTarget &Entity) {
1411 assert(EC.isDependent() && "delaying non-dependent access");
1413 assert(DC->isDependentContext() && "delaying non-dependent access");
1415 Loc,
1416 Entity.isMemberAccess(),
1417 Entity.getAccess(),
1418 Entity.getTargetDecl(),
1419 Entity.getNamingClass(),
1420 Entity.getBaseObjectType(),
1421 Entity.getDiag());
1422}
1423
1424
1426 const EffectiveContext &EC,
1428 AccessTarget &Entity) {
1429 assert(Entity.getAccess() != AS_public && "called for public access!");
1430
1435
1440 if (!Entity.isQuiet())
1443
1446 }
1447
1448
1449 llvm_unreachable("invalid access result");
1450}
1451
1453 AccessTarget &Entity) {
1454
1455 if (Entity.getAccess() == AS_public)
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1476
1477
1478
1479
1480
1481
1483 bool IsFriendDeclaration = false;
1484 while (TS && !IsFriendDeclaration) {
1487 }
1488 if (!IsFriendDeclaration) {
1491 }
1492 }
1493
1499 }
1500 llvm_unreachable("invalid access result");
1501}
1502
1504
1505
1506
1507
1508
1512 } else if (FunctionDecl *FN = dyn_cast(D)) {
1513 DC = FN;
1514 } else if (TemplateDecl *TD = dyn_cast(D)) {
1515 if (auto *D = dyn_cast_if_present(TD->getTemplatedDecl()))
1516 DC = D;
1517 } else if (auto *RD = dyn_cast(D)) {
1518 DC = RD;
1519 }
1520
1521 EffectiveContext EC(DC);
1522
1524
1527}
1528
1533
1535 TemplateArgs);
1536 if (!NamingD) return;
1538 TemplateArgs);
1539 if (!TargetD) return;
1540
1545 if (!BaseObjectType.isNull()) {
1546 BaseObjectType = SubstType(BaseObjectType, TemplateArgs, Loc,
1548 if (BaseObjectType.isNull()) return;
1549 }
1550
1551 AccessTarget Entity(Context,
1552 AccessTarget::Member,
1553 NamingClass,
1555 BaseObjectType);
1558 } else {
1559 AccessTarget Entity(Context,
1560 AccessTarget::Base,
1563 Access);
1566 }
1567}
1568
1575
1578 Entity.setDiag(diag::err_access) << E->getSourceRange();
1579
1581}
1582
1588
1592
1594 Found, BaseType);
1595 Entity.setDiag(diag::err_access) << E->getSourceRange();
1596
1598}
1599
1605
1607 return true;
1608
1609 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
1610 ObjectType);
1611
1612
1613 Entity.setDiag(Diag);
1614
1615 switch (CheckAccess(*this, Loc, Entity)) {
1618 case AR_dependent: llvm_unreachable("dependent for =delete computation");
1619 case AR_delayed: llvm_unreachable("cannot delay =delete computation");
1620 }
1621 llvm_unreachable("bad access result");
1622}
1623
1630
1631
1635
1637 if (ObjectTy.isNull())
1638 ObjectTy = Context.getCanonicalTagType(NamingClass);
1639
1640 AccessTarget Entity(Context, AccessTarget::Member, NamingClass,
1642 ObjectTy);
1643 Entity.setDiag(PDiag);
1644
1646}
1647
1652 bool IsCopyBindingRefToTemp) {
1655
1657 switch (Entity.getKind()) {
1658 default:
1659 PD = PDiag(IsCopyBindingRefToTemp
1660 ? diag::ext_rvalue_to_reference_access_ctor
1661 : diag::err_access_ctor);
1662
1663 break;
1664
1666 PD = PDiag(diag::err_access_base_ctor);
1669 break;
1670
1674 PD = PDiag(diag::err_access_field_ctor);
1676 break;
1677 }
1678
1681 PD = PDiag(diag::err_access_lambda_capture);
1683 break;
1684 }
1685
1686 }
1687
1689}
1690
1699
1701
1702
1703
1704
1705
1706
1707
1708
1714 } else if (auto *Shadow =
1715 dyn_cast(Found.getDecl())) {
1716
1717
1718 ObjectClass = Shadow->getParent();
1719 } else {
1720 ObjectClass = NamingClass;
1721 }
1722
1723 AccessTarget AccessEntity(
1724 Context, AccessTarget::Member, NamingClass,
1726 Context.getCanonicalTagType(ObjectClass));
1727 AccessEntity.setDiag(PD);
1728
1729 return CheckAccess(*this, UseLoc, AccessEntity);
1730}
1731
1738 !NamingClass ||
1741
1742 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
1745 Entity.setDiag(diag::err_access)
1746 << PlacementRange;
1747
1748 return CheckAccess(*this, OpLoc, Entity);
1749}
1750
1755 !NamingClass ||
1758
1759 AccessTarget Entity(Context, AccessTarget::Member, NamingClass,
1761
1762 return CheckAccess(*this, UseLoc, Entity);
1763}
1764
1772
1773 AccessTarget Entity(Context, AccessTarget::Member, DecomposedClass, Field,
1774 Context.getCanonicalTagType(DecomposedClass));
1775 Entity.setDiag(diag::err_decomp_decl_inaccessible_field);
1776
1777 return CheckAccess(*this, UseLoc, Entity);
1778}
1779
1781 Expr *ObjectExpr,
1786
1788 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
1790 Entity.setDiag(diag::err_access) << ObjectExpr->getSourceRange() << Range;
1791
1792 return CheckAccess(*this, OpLoc, Entity);
1793}
1794
1796 Expr *ObjectExpr,
1797 Expr *ArgExpr,
1802}
1803
1805 Expr *ObjectExpr,
1809 if (!ArgExprs.empty()) {
1810 R = SourceRange(ArgExprs.front()->getBeginLoc(),
1811 ArgExprs.back()->getEndLoc());
1812 }
1813
1815}
1816
1819
1820
1821
1823
1826
1828
1829 AccessTarget entity(Context, AccessTarget::Member,
1832 QualType());
1833 entity.setDiag(diag::err_access_friend_function)
1836
1837
1838
1844 }
1845 llvm_unreachable("invalid access result");
1846}
1847
1854
1857
1858 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
1859 QualType());
1860 Entity.setDiag(diag::err_access)
1862
1864}
1865
1868 const CXXBasePath &Path, unsigned DiagID,
1869 llvm::function_ref<void(PartialDiagnostic &)> SetupPDiag, bool ForceCheck,
1870 bool ForceUnprivileged) {
1871 if (!ForceCheck && ().AccessControl)
1873
1876
1877 AccessTarget Entity(Context, AccessTarget::Base, Base, Derived, Path.Access);
1878 if (DiagID)
1879 SetupPDiag(Entity.setDiag(DiagID));
1880
1881 if (ForceUnprivileged) {
1882 switch (
1884 case ::AR_accessible:
1886 case ::AR_inaccessible:
1888 case ::AR_dependent:
1890 }
1891 llvm_unreachable("unexpected result from CheckEffectiveAccess");
1892 }
1893 return CheckAccess(*this, AccessLoc, Entity);
1894}
1895
1899 unsigned DiagID, bool ForceCheck,
1900 bool ForceUnprivileged) {
1903 Path, DiagID, [&](PartialDiagnostic &PD) { PD << Derived << Base; },
1904 ForceCheck, ForceUnprivileged);
1905}
1906
1909 && "performing access check without access control");
1910 assert(R.getNamingClass() && "performing access check without naming class");
1911
1913 if (I.getAccess() != AS_public) {
1917 Entity.setDiag(diag::err_access);
1919 }
1920 }
1921}
1922
1925
1926 if (Target->isCXXClassMember() && NamingClass) {
1928 return false;
1929
1930
1931
1932
1937 }
1938
1940
1943 return true;
1944
1945
1946
1949 ClassOfMethodDecl = MD->getClassInterface();
1952 = dyn_cast(FD->getLexicalDeclContext())) {
1954 = dyn_cast(Impl))
1955 ClassOfMethodDecl = IMPD->getClassInterface();
1957 = dyn_cast(Impl))
1958 ClassOfMethodDecl = CatImplClass->getClassInterface();
1959 }
1960 }
1961
1962
1963 if (!ClassOfMethodDecl)
1964 return false;
1965
1966
1967 if (declaresSameEntity(ClassOfMethodDecl, Ivar->getContainingInterface()))
1968 return true;
1969
1970
1972 return false;
1973
1974 return Ivar->getContainingInterface()->isSuperClassOf(ClassOfMethodDecl);
1975 }
1976
1977 return true;
1978}
Defines the clang::ASTContext interface.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the classes clang::DelayedDiagnostic and clang::AccessedEntity.
Defines the clang::Expr interface and subclasses for C++ expressions.
FormatToken * Next
The next token in the unwrapped line.
llvm::MachO::Target Target
llvm::MachO::Records Records
llvm::MachO::Record Record
static void DiagnoseBadAccess(Sema &S, SourceLocation Loc, const EffectiveContext &EC, AccessTarget &Entity)
Definition SemaAccess.cpp:1273
AccessResult
A copy of Sema's enum without AR_delayed.
Definition SemaAccess.cpp:29
@ AR_accessible
Definition SemaAccess.cpp:30
@ AR_dependent
Definition SemaAccess.cpp:32
@ AR_inaccessible
Definition SemaAccess.cpp:31
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...
Definition SemaAccess.cpp:1031
static AccessResult IsDerivedFromInclusive(const CXXRecordDecl *Derived, const CXXRecordDecl *Target)
Checks whether one class is derived from another, inclusively.
Definition SemaAccess.cpp:298
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.
Definition SemaAccess.cpp:1106
static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc, AccessTarget &Entity)
Definition SemaAccess.cpp:1452
static AccessResult GetFriendKind(Sema &S, const EffectiveContext &EC, const CXXRecordDecl *Class)
Definition SemaAccess.cpp:585
static AccessResult MatchesFriend(Sema &S, const EffectiveContext &EC, const CXXRecordDecl *Friend)
Definition SemaAccess.cpp:423
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...
Definition SemaAccess.cpp:723
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...
Definition SemaAccess.cpp:1308
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...
Definition SemaAccess.cpp:939
static AccessResult IsAccessible(Sema &S, const EffectiveContext &EC, AccessTarget &Entity)
Determines whether the accessed entity is accessible.
Definition SemaAccess.cpp:1329
static AccessResult HasAccess(Sema &S, const EffectiveContext &EC, const CXXRecordDecl *NamingClass, AccessSpecifier Access, const AccessTarget &Target)
Definition SemaAccess.cpp:741
static bool MightInstantiateTo(const CXXRecordDecl *From, const CXXRecordDecl *To)
Checks whether one class might instantiate to the other.
Definition SemaAccess.cpp:278
static void DiagnoseAccessPath(Sema &S, const EffectiveContext &EC, AccessTarget &entity)
Diagnose the path which caused the given declaration or base class to become inaccessible.
Definition SemaAccess.cpp:1164
static CXXRecordDecl * FindDeclaringClass(NamedDecl *D)
Definition SemaAccess.cpp:61
static AccessResult CheckEffectiveAccess(Sema &S, const EffectiveContext &EC, SourceLocation Loc, AccessTarget &Entity)
Checks access to an entity from the given effective context.
Definition SemaAccess.cpp:1425
static void DelayDependentAccess(Sema &S, const EffectiveContext &EC, SourceLocation Loc, const AccessTarget &Entity)
Definition SemaAccess.cpp:1407
Defines various enumerations that describe declaration and type specifiers.
static QualType getPointeeType(const MemRegion *R)
static CanQualType getCanonicalType(QualType T)
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
CanQualType getCanonicalTagType(const TagDecl *TD) const
Represents a path from a specific derived class (which is not represented as part of the path) to a p...
AccessSpecifier Access
The access along this inheritance path.
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
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
bool isInjectedClassName() const
Determines whether this declaration represents the injected class name.
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.
Represents a canonical, potentially-qualified type.
Qualifiers getQualifiers() const
Retrieve all qualifiers.
CanProxy< U > getAs() const
Retrieve a canonical type pointer with a different static type, upcasting or downcasting as needed.
Declaration of a class template.
ClassTemplateDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
A POD class for pairing a NamedDecl* with an access specifier.
static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS)
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
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.
NestedNameSpecifierLoc getQualifierLoc() const
Retrieve the nested-name-specifier (with source-location information) that qualifies the name of this...
NestedNameSpecifier getQualifier() const
Retrieve the nested-name-specifier that qualifies the name of this declaration, if it was present in ...
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 the given declaration.
Describes an entity that is being initialized.
EntityKind getKind() const
Determine the kind of initialization.
QualType getType() const
Retrieve type being initialized.
ValueDecl * getDecl() const
Retrieve the variable, parameter, or field being initialized.
const InitializedEntity * getParent() const
Retrieve the parent of the entity being initialized, when the initialization itself is occurring with...
bool isInheritedVirtualBase() const
Return whether the base is an inherited virtual base.
@ EK_Member
The entity being initialized is a non-static data member subobject.
@ EK_Base
The entity being initialized is a base member subobject.
@ EK_ParenAggInitMember
The entity being initialized is a non-static data member subobject of an object initialized via paren...
@ EK_Delegating
The initialization is being done by a delegating constructor.
@ EK_LambdaCapture
The entity being initialized is the field that captures a variable in a lambda.
StringRef getCapturedVarName() const
For a lambda capture, return the capture's name.
const CXXBaseSpecifier * getBaseSpecifier() const
Retrieve the base specifier.
Represents the results of name lookup.
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].
UnresolvedSetImpl::iterator iterator
Data structure that captures multiple levels of template argument lists for use in template instantia...
This represents a decl that may have a name.
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.
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.
PartialDiagnostic PDiag(unsigned DiagID=0)
Build a partial diagnostic.
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a 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.
Definition SemaAccess.cpp:35
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.
Definition SemaAccess.cpp:1817
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...
Definition SemaAccess.cpp:1600
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())
Definition SemaAccess.cpp:1624
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.
Definition SemaAccess.cpp:1732
AccessResult CheckMemberOperatorAccess(SourceLocation Loc, Expr *ObjectExpr, const SourceRange &, DeclAccessPair FoundDecl)
Definition SemaAccess.cpp:1780
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)
Definition SemaAccess.cpp:1529
const LangOptions & getLangOpts() const
AccessResult CheckStructuredBindingMemberAccess(SourceLocation UseLoc, CXXRecordDecl *DecomposedClass, DeclAccessPair Field)
Checks implicit access to a member in a structured binding.
Definition SemaAccess.cpp:1766
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.
Definition SemaAccess.cpp:1896
AccessResult CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E, DeclAccessPair FoundDecl)
Perform access-control checking on a previously-unresolved member access which has now been resolved ...
Definition SemaAccess.cpp:1583
bool IsSimplyAccessible(NamedDecl *Decl, CXXRecordDecl *NamingClass, QualType BaseType)
Checks access to Target from the given class.
Definition SemaAccess.cpp:1923
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.
Definition SemaAccess.cpp:1648
AccessResult CheckAddressOfMemberAccess(Expr *OvlExpr, DeclAccessPair FoundDecl)
Definition SemaAccess.cpp:1848
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.
Definition SemaAccess.cpp:1907
AccessResult CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E, DeclAccessPair FoundDecl)
Definition SemaAccess.cpp:1569
AccessResult CheckMemberAccess(SourceLocation UseLoc, CXXRecordDecl *NamingClass, DeclAccessPair Found)
Checks access to a member.
Definition SemaAccess.cpp:1751
void HandleDelayedAccessCheck(sema::DelayedDiagnostic &DD, Decl *Ctx)
Definition SemaAccess.cpp:1503
@ 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.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
CXXRecordDecl * castAsCXXRecordDecl() 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...
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...
CXXRecordDecl * getNamingClass()
Gets the 'naming class' (in the sense of C++0x [class.access.base]p5) of the lookup.
Represents a C++ member access expression for which lookup produced a set of overloaded functions.
QualType getBaseType() const
bool isArrow() const
Determine whether this member expression used the '->' operator; otherwise, it used the '.
CXXRecordDecl * getNamingClass()
Retrieve the naming class of this lookup.
SourceLocation getMemberLoc() const
Retrieve the location of the name of the member that this expression refers to.
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.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool isa(CodeGen::Address addr)
void initialize(TemplateInstantiationCallbackPtrs &Callbacks, const Sema &TheSema)
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
@ Dependent
Parse the block as a dependent block, which may be used in some template instantiations but not other...
const FunctionProtoType * T
bool declaresSameEntity(const Decl *D1, const Decl *D2)
Determine whether two declarations declare the same entity.
U cast(CodeGen::Address addr)
SourceRange getSourceRange() const LLVM_READONLY
getSourceRange - The range of the declaration name.
OverloadExpr * Expression