clang: lib/AST/ASTStructuralEquivalence.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
87#include "llvm/ADT/APInt.h"
88#include "llvm/ADT/APSInt.h"
89#include "llvm/ADT/StringExtras.h"
90#include "llvm/Support/Compiler.h"
91#include "llvm/Support/ErrorHandling.h"
92#include
93#include
94#include
95
96using namespace clang;
97
103 const Stmt *S1, const Stmt *S2);
115
120 return false;
121
123
127
133
138 return false;
142 }
143
146
150
152 return true;
153
157 return true;
158 }
159
160 llvm_unreachable("Unhandled kind of DeclarationName");
161 return true;
162}
163
164namespace {
165
166class StmtComparer {
168
169
170
171
172
175 }
176
179 }
180
183 }
184
185 bool IsStmtEquivalent(const CallExpr *E1, const CallExpr *E2) {
186
189
190
191 if (static_cast<bool>(Callee1) != static_cast<bool>(Callee2))
192 return false;
193
194
195 if (!static_cast<bool>(Callee1))
196 return true;
197
198 assert(Callee2);
200 }
201
205 }
206
208 return true;
209 }
210
212
213
214
215
216
217 return E1->size() == E2->size();
218 }
219
223 if (!Decl1 || !Decl2)
224 return false;
227 }
228
233 return false;
236 }
237
238 bool IsStmtEquivalent(const Expr *E1, const Expr *E2) {
240 }
241
245 }
246
249 }
250
255 std::optional<TypeSourceInfo *> Child1 = std::get<0>(Pair);
256 std::optional<TypeSourceInfo *> Child2 = std::get<1>(Pair);
257
258 if (!Child1 || !Child2)
259 return false;
260
262 (*Child2)->getType()))
263 return false;
264 }
265
266 return true;
267 }
268
273 }
274
277 }
278
282 }
283
286
287 return true;
288 }
289
290 bool IsStmtEquivalent(const Stmt *S1, const Stmt *S2) { return true; }
291
292 bool IsStmtEquivalent(const GotoStmt *S1, const GotoStmt *S2) {
295 if (!L1 || !L2)
296 return L1 == L2;
297
300 return ::IsStructurallyEquivalent(Name1, Name2);
301 }
302
305 }
306
307 bool IsStmtEquivalent(const StmtExpr *E1, const StmtExpr *E2) {
309 }
310
313 }
314
319 return false;
321 return false;
323 return false;
324 return true;
325 }
326
331 }
332
335 return false;
336
337 for (auto Pair : zip_longest(E1->getArgs(), E2->getArgs())) {
338 std::optional<TypeSourceInfo *> Child1 = std::get<0>(Pair);
339 std::optional<TypeSourceInfo *> Child2 = std::get<1>(Pair);
340
341 if (!Child1 || !Child2)
342 return false;
343
345 (*Child2)->getType()))
346 return false;
347 }
348 return true;
349 }
350
354 return false;
355 }
358 }
359
363 return false;
366 }
367
370 }
371
373
374 return true;
375 }
376
379 return false;
380
383 return false;
387 return false;
388
390 return false;
393 for (unsigned int ArgI = 0, ArgN = E1->getNumTemplateArgs(); ArgI < ArgN;
394 ++ArgI)
396 return false;
397
398 return true;
399 }
400
403 }
404
405
406 bool TraverseStmt(const Stmt *S1, const Stmt *S2) { return true; }
407
408
409
410
411
412
413#define STMT(CLASS, PARENT) \
414 bool TraverseStmt(const CLASS *S1, const CLASS *S2) { \
415 if (!TraverseStmt(static_cast<const PARENT *>(S1), \
416 static_cast<const PARENT *>(S2))) \
417 return false; \
418 return IsStmtEquivalent(S1, S2); \
419 }
420#include "clang/AST/StmtNodes.inc"
421
422public:
424
425
426
427
428 bool IsEquivalent(const Stmt *S1, const Stmt *S2) {
430 return false;
431
432
433
434
435
436
439 llvm_unreachable("Can't traverse NoStmtClass");
440#define STMT(CLASS, PARENT) \
441 case Stmt::StmtClass::CLASS##Class: \
442 return TraverseStmt(static_cast<const CLASS *>(S1), \
443 static_cast<const CLASS *>(S2));
444#define ABSTRACT_STMT(S)
445#include "clang/AST/StmtNodes.inc"
446 }
447 llvm_unreachable("Invalid statement kind");
448 }
449};
450}
451
458}
459
466}
467
475}
476
484}
485
486
488 const Stmt *S1, const Stmt *S2) {
489 if (!S1 || !S2)
490 return S1 == S2;
491
492
493
494
495
496
497
498
499
500 if (const auto *E2CXXOperatorCall = dyn_cast(S2)) {
501 if (const auto *E1Unary = dyn_cast(S1))
503 if (const auto *E1Binary = dyn_cast(S1))
505 }
506 if (const auto *E1CXXOperatorCall = dyn_cast(S1)) {
507 if (const auto *E2Unary = dyn_cast(S2))
509 if (const auto *E2Binary = dyn_cast(S2))
511 }
512
513
514 StmtComparer Comparer(Context);
515 if (!Comparer.IsEquivalent(S1, S2))
516 return false;
517
518
519 for (auto Pair : zip_longest(S1->children(), S2->children())) {
520 std::optional<const Stmt *> Child1 = std::get<0>(Pair);
521 std::optional<const Stmt *> Child2 = std::get<1>(Pair);
522
523
524 if (!Child1 || !Child2)
525 return false;
527 return false;
528 }
529 return true;
530}
531
532
535 if (!Name1 || !Name2)
536 return Name1 == Name2;
537
539}
540
541
546 return false;
547
550 if ((bool)Prefix1 != (bool)Prefix2)
551 return false;
552
553 if (Prefix1)
555 return false;
556
557 switch (NNS1->getKind()) {
572 return true;
576 }
577 return false;
578}
579
585 if (TemplateDeclN1 && TemplateDeclN2) {
587 return false;
588
590 return true;
591 } else if (TemplateDeclN1 || TemplateDeclN2)
592 return false;
594 return false;
595
596
598
603 E1 = OS1->end(), E2 = OS2->end();
604 for (; I1 != E1 && I2 != E2; ++I1, ++I2)
606 return false;
607 return I1 == E1 && I2 == E2;
608 }
609
613 return TN1->getDeclName() == TN2->getDeclName();
614 }
615
620 DN2->getQualifier()))
621 return false;
622 if (DN1->isIdentifier() && DN2->isIdentifier())
624 DN2->getIdentifier());
626 return DN1->getOperator() == DN2->getOperator();
627 return false;
628 }
629
635 P2->getArgumentPack()) &&
637 P2->getAssociatedDecl()) &&
638 P1->getIndex() == P2->getIndex();
639 }
640
645
646 break;
647
649
650 llvm_unreachable("unimplemented");
651 }
652
653 return true;
654}
655
659
660
665 return false;
666
667 switch (Arg1.getKind()) {
669 return true;
670
673
677 return false;
678
679 return llvm::APSInt::isSameValue(Arg1.getAsIntegral(),
681
684
686 return true;
687
691
696
700
703
707 }
708
709 llvm_unreachable("Invalid template argument kind");
710}
711
712
716 if (Args1.size() != Args2.size())
717 return false;
718 for (unsigned I = 0, N = Args1.size(); I != N; ++I) {
720 return false;
721 }
722 return true;
723}
724
725
731}
732
733
734
740 return false;
742 return false;
744 return false;
745
746 return true;
747}
748
749
750
751
755
757 return false;
758
759
761 return false;
763 return false;
764
766 return false;
768 return false;
770 return false;
771
772 return true;
773}
774
775
779
782
784 return true;
785
786 if (Spec1 != Spec2)
787 return false;
790 return false;
791 for (unsigned I = 0, N = Proto1->getNumExceptions(); I != N; ++I) {
794 return false;
795 }
799 return false;
800 }
801
802 return true;
803}
804
805
810
813
814 if (!Context.StrictTypeSpelling) {
815
816
819 }
820
822 return false;
823
825
827
828
829 if (T1->getTypeClass() == Type::FunctionProto &&
831 TC = Type::FunctionNoProto;
832 else if (T1->getTypeClass() == Type::FunctionNoProto &&
834 TC = Type::FunctionNoProto;
835 else
836 return false;
837 }
838
839 switch (TC) {
840 case Type::Builtin:
841
842 if (cast(T1)->getKind() != cast(T2)->getKind())
843 return false;
844 break;
845
846 case Type::Complex:
848 cast(T1)->getElementType(),
849 cast(T2)->getElementType()))
850 return false;
851 break;
852
853 case Type::Adjusted:
854 case Type::Decayed:
855 case Type::ArrayParameter:
857 cast(T1)->getOriginalType(),
858 cast(T2)->getOriginalType()))
859 return false;
860 break;
861
862 case Type::Pointer:
866 return false;
867 break;
868
869 case Type::BlockPointer:
873 return false;
874 break;
875
876 case Type::LValueReference:
877 case Type::RValueReference: {
878 const auto *Ref1 = cast(T1);
879 const auto *Ref2 = cast(T2);
880 if (Ref1->isSpelledAsLValue() != Ref2->isSpelledAsLValue())
881 return false;
882 if (Ref1->isInnerRef() != Ref2->isInnerRef())
883 return false;
885 Ref2->getPointeeTypeAsWritten()))
886 return false;
887 break;
888 }
889
890 case Type::MemberPointer: {
891 const auto *MemPtr1 = cast(T1);
892 const auto *MemPtr2 = cast(T2);
894 MemPtr2->getPointeeType()))
895 return false;
897 QualType(MemPtr2->getClass(), 0)))
898 return false;
899 break;
900 }
901
902 case Type::ConstantArray: {
903 const auto *Array1 = cast(T1);
904 const auto *Array2 = cast(T2);
905 if (!llvm::APInt::isSameValue(Array1->getSize(), Array2->getSize()))
906 return false;
907
909 return false;
910 break;
911 }
912
913 case Type::IncompleteArray:
915 cast(T2)))
916 return false;
917 break;
918
919 case Type::VariableArray: {
920 const auto *Array1 = cast(T1);
921 const auto *Array2 = cast(T2);
923 Array2->getSizeExpr()))
924 return false;
925
927 return false;
928
929 break;
930 }
931
932 case Type::DependentSizedArray: {
933 const auto *Array1 = cast(T1);
934 const auto *Array2 = cast(T2);
936 Array2->getSizeExpr()))
937 return false;
938
940 return false;
941
942 break;
943 }
944
945 case Type::DependentAddressSpace: {
946 const auto *DepAddressSpace1 = cast(T1);
947 const auto *DepAddressSpace2 = cast(T2);
949 DepAddressSpace2->getAddrSpaceExpr()))
950 return false;
952 DepAddressSpace2->getPointeeType()))
953 return false;
954
955 break;
956 }
957
958 case Type::DependentSizedExtVector: {
959 const auto *Vec1 = cast(T1);
960 const auto *Vec2 = cast(T2);
962 Vec2->getSizeExpr()))
963 return false;
965 Vec2->getElementType()))
966 return false;
967 break;
968 }
969
970 case Type::DependentVector: {
971 const auto *Vec1 = cast(T1);
972 const auto *Vec2 = cast(T2);
973 if (Vec1->getVectorKind() != Vec2->getVectorKind())
974 return false;
976 Vec2->getSizeExpr()))
977 return false;
979 Vec2->getElementType()))
980 return false;
981 break;
982 }
983
984 case Type::Vector:
985 case Type::ExtVector: {
986 const auto *Vec1 = cast(T1);
987 const auto *Vec2 = cast(T2);
989 Vec2->getElementType()))
990 return false;
991 if (Vec1->getNumElements() != Vec2->getNumElements())
992 return false;
993 if (Vec1->getVectorKind() != Vec2->getVectorKind())
994 return false;
995 break;
996 }
997
998 case Type::DependentSizedMatrix: {
1001
1002
1009 return false;
1010 break;
1011 }
1012
1013 case Type::ConstantMatrix: {
1016
1017
1022 return false;
1023 break;
1024 }
1025
1026 case Type::FunctionProto: {
1027 const auto *Proto1 = cast(T1);
1028 const auto *Proto2 = cast(T2);
1029
1030 if (Proto1->getNumParams() != Proto2->getNumParams())
1031 return false;
1032 for (unsigned I = 0, N = Proto1->getNumParams(); I != N; ++I) {
1034 Proto2->getParamType(I)))
1035 return false;
1036 }
1037 if (Proto1->isVariadic() != Proto2->isVariadic())
1038 return false;
1039
1040 if (Proto1->getMethodQuals() != Proto2->getMethodQuals())
1041 return false;
1042
1043
1044 const auto *OrigProto1 =
1045 cast(OrigT1.getDesugaredType(Context.FromCtx));
1046 const auto *OrigProto2 =
1047 cast(OrigT2.getDesugaredType(Context.ToCtx));
1049 return false;
1050
1051
1052 [[fallthrough]];
1053 }
1054
1055 case Type::FunctionNoProto: {
1056 const auto *Function1 = cast(T1);
1057 const auto *Function2 = cast(T2);
1059 Function2->getReturnType()))
1060 return false;
1062 Function2->getExtInfo()))
1063 return false;
1064 break;
1065 }
1066
1067 case Type::UnresolvedUsing:
1069 cast(T1)->getDecl(),
1070 cast(T2)->getDecl()))
1071 return false;
1072 break;
1073
1074 case Type::Attributed:
1076 cast(T1)->getModifiedType(),
1077 cast(T2)->getModifiedType()))
1078 return false;
1080 Context, cast(T1)->getEquivalentType(),
1081 cast(T2)->getEquivalentType()))
1082 return false;
1083 break;
1084
1085 case Type::CountAttributed:
1087 cast(T1)->desugar(),
1088 cast(T2)->desugar()))
1089 return false;
1090 break;
1091
1092 case Type::BTFTagAttributed:
1094 Context, cast(T1)->getWrappedType(),
1095 cast(T2)->getWrappedType()))
1096 return false;
1097 break;
1098
1099 case Type::HLSLAttributedResource:
1101 Context, cast(T1)->getWrappedType(),
1102 cast(T2)->getWrappedType()))
1103 return false;
1105 Context, cast(T1)->getContainedType(),
1106 cast(T2)->getContainedType()))
1107 return false;
1108 if (cast(T1)->getAttrs() !=
1109 cast(T2)->getAttrs())
1110 return false;
1111 break;
1112
1113 case Type::Paren:
1115 cast(T2)->getInnerType()))
1116 return false;
1117 break;
1118
1119 case Type::MacroQualified:
1123 return false;
1124 break;
1125
1126 case Type::Using:
1128 cast(T2)->getFoundDecl()))
1129 return false;
1133 return false;
1134 break;
1135
1136 case Type::Typedef:
1138 cast(T2)->getDecl()) ||
1140 cast(T2)->desugar()))
1141 return false;
1142 break;
1143
1144 case Type::TypeOfExpr:
1146 Context, cast(T1)->getUnderlyingExpr(),
1147 cast(T2)->getUnderlyingExpr()))
1148 return false;
1149 break;
1150
1151 case Type::TypeOf:
1153 cast(T1)->getUnmodifiedType(),
1154 cast(T2)->getUnmodifiedType()))
1155 return false;
1156 break;
1157
1158 case Type::UnaryTransform:
1162 return false;
1163 break;
1164
1165 case Type::Decltype:
1167 cast(T1)->getUnderlyingExpr(),
1168 cast(T2)->getUnderlyingExpr()))
1169 return false;
1170 break;
1171
1172 case Type::Auto: {
1173 auto *Auto1 = cast(T1);
1174 auto *Auto2 = cast(T2);
1176 Auto2->getDeducedType()))
1177 return false;
1178 if (Auto1->isConstrained() != Auto2->isConstrained())
1179 return false;
1180 if (Auto1->isConstrained()) {
1181 if (Auto1->getTypeConstraintConcept() !=
1182 Auto2->getTypeConstraintConcept())
1183 return false;
1185 Auto1->getTypeConstraintArguments(),
1186 Auto2->getTypeConstraintArguments()))
1187 return false;
1188 }
1189 break;
1190 }
1191
1192 case Type::DeducedTemplateSpecialization: {
1193 const auto *DT1 = cast(T1);
1194 const auto *DT2 = cast(T2);
1196 DT2->getTemplateName()))
1197 return false;
1199 DT2->getDeducedType()))
1200 return false;
1201 break;
1202 }
1203
1204 case Type::Record:
1205 case Type::Enum:
1207 cast(T2)->getDecl()))
1208 return false;
1209 break;
1210
1211 case Type::TemplateTypeParm: {
1212 const auto *Parm1 = cast(T1);
1213 const auto *Parm2 = cast(T2);
1214 if (!Context.IgnoreTemplateParmDepth &&
1215 Parm1->getDepth() != Parm2->getDepth())
1216 return false;
1217 if (Parm1->getIndex() != Parm2->getIndex())
1218 return false;
1219 if (Parm1->isParameterPack() != Parm2->isParameterPack())
1220 return false;
1221
1222
1223 break;
1224 }
1225
1226 case Type::SubstTemplateTypeParm: {
1227 const auto *Subst1 = cast(T1);
1228 const auto *Subst2 = cast(T2);
1230 Subst2->getReplacementType()))
1231 return false;
1233 Subst2->getAssociatedDecl()))
1234 return false;
1235 if (Subst1->getIndex() != Subst2->getIndex())
1236 return false;
1237 if (Subst1->getPackIndex() != Subst2->getPackIndex())
1238 return false;
1239 break;
1240 }
1241
1242 case Type::SubstTemplateTypeParmPack: {
1243 const auto *Subst1 = cast(T1);
1244 const auto *Subst2 = cast(T2);
1246 Subst2->getAssociatedDecl()))
1247 return false;
1248 if (Subst1->getIndex() != Subst2->getIndex())
1249 return false;
1251 Subst2->getArgumentPack()))
1252 return false;
1253 break;
1254 }
1255
1256 case Type::TemplateSpecialization: {
1257 const auto *Spec1 = cast(T1);
1258 const auto *Spec2 = cast(T2);
1260 Spec2->getTemplateName()))
1261 return false;
1263 Spec2->template_arguments()))
1264 return false;
1265 break;
1266 }
1267
1268 case Type::Elaborated: {
1269 const auto *Elab1 = cast(T1);
1270 const auto *Elab2 = cast(T2);
1271
1272
1273
1274 if (Elab1->getKeyword() != Elab2->getKeyword())
1275 return false;
1277 Elab2->getQualifier()))
1278 return false;
1280 Elab2->getNamedType()))
1281 return false;
1282 break;
1283 }
1284
1285 case Type::InjectedClassName: {
1286 const auto *Inj1 = cast(T1);
1287 const auto *Inj2 = cast(T2);
1289 Inj1->getInjectedSpecializationType(),
1290 Inj2->getInjectedSpecializationType()))
1291 return false;
1292 break;
1293 }
1294
1295 case Type::DependentName: {
1296 const auto *Typename1 = cast(T1);
1297 const auto *Typename2 = cast(T2);
1299 Typename2->getQualifier()))
1300 return false;
1302 Typename2->getIdentifier()))
1303 return false;
1304
1305 break;
1306 }
1307
1308 case Type::DependentTemplateSpecialization: {
1309 const auto *Spec1 = cast(T1);
1310 const auto *Spec2 = cast(T2);
1312 Spec2->getQualifier()))
1313 return false;
1315 Spec2->getIdentifier()))
1316 return false;
1318 Spec2->template_arguments()))
1319 return false;
1320 break;
1321 }
1322
1323 case Type::PackExpansion:
1325 cast(T1)->getPattern(),
1326 cast(T2)->getPattern()))
1327 return false;
1328 break;
1329
1330 case Type::PackIndexing:
1332 cast(T1)->getPattern(),
1333 cast(T2)->getPattern()))
1335 cast(T1)->getIndexExpr(),
1336 cast(T2)->getIndexExpr()))
1337 return false;
1338 break;
1339
1340 case Type::ObjCInterface: {
1341 const auto *Iface1 = cast(T1);
1342 const auto *Iface2 = cast(T2);
1344 Iface2->getDecl()))
1345 return false;
1346 break;
1347 }
1348
1349 case Type::ObjCTypeParam: {
1350 const auto *Obj1 = cast(T1);
1351 const auto *Obj2 = cast(T2);
1353 return false;
1354
1355 if (Obj1->getNumProtocols() != Obj2->getNumProtocols())
1356 return false;
1357 for (unsigned I = 0, N = Obj1->getNumProtocols(); I != N; ++I) {
1359 Obj2->getProtocol(I)))
1360 return false;
1361 }
1362 break;
1363 }
1364
1365 case Type::ObjCObject: {
1366 const auto *Obj1 = cast(T1);
1367 const auto *Obj2 = cast(T2);
1369 Obj2->getBaseType()))
1370 return false;
1371 if (Obj1->getNumProtocols() != Obj2->getNumProtocols())
1372 return false;
1373 for (unsigned I = 0, N = Obj1->getNumProtocols(); I != N; ++I) {
1375 Obj2->getProtocol(I)))
1376 return false;
1377 }
1378 break;
1379 }
1380
1381 case Type::ObjCObjectPointer: {
1382 const auto *Ptr1 = cast(T1);
1383 const auto *Ptr2 = cast(T2);
1385 Ptr2->getPointeeType()))
1386 return false;
1387 break;
1388 }
1389
1390 case Type::Atomic:
1392 cast(T2)->getValueType()))
1393 return false;
1394 break;
1395
1396 case Type::Pipe:
1398 cast(T2)->getElementType()))
1399 return false;
1400 break;
1401 case Type::BitInt: {
1402 const auto *Int1 = cast(T1);
1403 const auto *Int2 = cast(T2);
1404
1405 if (Int1->isUnsigned() != Int2->isUnsigned() ||
1406 Int1->getNumBits() != Int2->getNumBits())
1407 return false;
1408 break;
1409 }
1410 case Type::DependentBitInt: {
1411 const auto *Int1 = cast(T1);
1412 const auto *Int2 = cast(T2);
1413
1414 if (Int1->isUnsigned() != Int2->isUnsigned() ||
1416 Int2->getNumBitsExpr()))
1417 return false;
1418 break;
1419 }
1420 }
1421
1422 return true;
1423}
1424
1430 return false;
1431
1433 return false;
1434
1435
1436
1437
1439 return true;
1440
1442 return false;
1443
1445}
1446
1450 const auto *Owner2 = cast(Field2->getDeclContext());
1451
1452
1453
1454
1460 }
1461
1462
1466 if (Context.Complain) {
1467 Context.Diag2(
1468 Owner2->getLocation(),
1469 Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent))
1470 << Owner2Type;
1471 Context.Diag2(Field2->getLocation(), diag::note_odr_field_name)
1473 Context.Diag1(Field1->getLocation(), diag::note_odr_field_name)
1475 }
1476 return false;
1477 }
1478
1481 if (Context.Complain) {
1482 Context.Diag2(
1483 Owner2->getLocation(),
1484 Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent))
1485 << Owner2Type;
1486 Context.Diag2(Field2->getLocation(), diag::note_odr_field)
1488 Context.Diag1(Field1->getLocation(), diag::note_odr_field)
1490 }
1491 return false;
1492 }
1493
1497
1498 return true;
1499}
1500
1501
1504 const auto *Owner2 = cast(Field2->getDeclContext());
1507}
1508
1509
1513 bool PropertiesEqual =
1527 if (!PropertiesEqual)
1528 return false;
1529
1530
1531 if (auto *Constructor1 = dyn_cast(Method1)) {
1532 auto *Constructor2 = cast(Method2);
1533 if (!Constructor1->getExplicitSpecifier().isEquivalent(
1534 Constructor2->getExplicitSpecifier()))
1535 return false;
1536 }
1537
1538 if (auto *Conversion1 = dyn_cast(Method1)) {
1539 auto *Conversion2 = cast(Method2);
1540 if (!Conversion1->getExplicitSpecifier().isEquivalent(
1541 Conversion2->getExplicitSpecifier()))
1542 return false;
1544 Conversion2->getConversionType()))
1545 return false;
1546 }
1547
1551 return false;
1552
1553 }
1554
1555
1558 return false;
1559
1560 return true;
1561}
1562
1563
1564static bool
1568 "Must be called on lambda classes");
1571 return false;
1572
1573 return true;
1574}
1575
1576
1577static bool
1580
1581
1582
1583
1586 while (true) {
1587
1588
1591 return true;
1592
1594 return false;
1596 break;
1598 return false;
1599 if (const auto *ND1 = dyn_cast(DC1)) {
1600 const auto *ND2 = cast(DC2);
1603 return false;
1604 }
1605
1606 if (auto *D1Spec = dyn_cast(DC1)) {
1607 auto *D2Spec = dyn_cast(DC2);
1609 return false;
1610 }
1611
1614 }
1615
1616 return true;
1617}
1618
1622 return Name;
1623 if (const TypedefNameDecl *TypedefName = D.getTypedefNameForAnonDecl())
1624 return TypedefName->getIdentifier();
1625 return nullptr;
1626 };
1628}
1629
1630
1634 return false;
1635 }
1636
1638 if (Context.Complain) {
1639 Context.Diag2(D2->getLocation(), Context.getApplicableDiagnostic(
1640 diag::err_odr_tag_type_inconsistent))
1642 Context.Diag1(D1->getLocation(), diag::note_odr_tag_kind_here)
1644 }
1645 return false;
1646 }
1647
1649
1650
1651 if (std::optional Index1 =
1653 if (std::optional Index2 =
1655 D2)) {
1656 if (*Index1 != *Index2)
1657 return false;
1658 }
1659 }
1660 }
1661
1662
1663
1664
1666 return false;
1667
1668
1669
1670 const auto *Spec1 = dyn_cast(D1);
1671 const auto *Spec2 = dyn_cast(D2);
1672 if (Spec1 && Spec2) {
1673
1675 Spec2->getSpecializedTemplate()))
1676 return false;
1677
1678
1679 if (Spec1->getTemplateArgs().size() != Spec2->getTemplateArgs().size())
1680 return false;
1681
1682 for (unsigned I = 0, N = Spec1->getTemplateArgs().size(); I != N; ++I)
1684 Spec2->getTemplateArgs().get(I)))
1685 return false;
1686 }
1687
1688
1689 else if (Spec1 || Spec2)
1690 return false;
1691
1692
1693
1694
1697 if (!D1 || !D2)
1698 return true;
1699
1700
1701
1702
1703
1704
1705 if (Context.EqKind == StructuralEquivalenceKind::Minimal)
1707 return true;
1708
1709
1710
1712 return true;
1713
1714 if (auto *D1CXX = dyn_cast(D1)) {
1715 if (auto *D2CXX = dyn_cast(D2)) {
1716 if (D1CXX->hasExternalLexicalStorage() &&
1717 !D1CXX->isCompleteDefinition()) {
1719 }
1720
1721 if (D1CXX->isLambda() != D2CXX->isLambda())
1722 return false;
1723 if (D1CXX->isLambda()) {
1725 return false;
1726 }
1727
1728 if (D1CXX->getNumBases() != D2CXX->getNumBases()) {
1729 if (Context.Complain) {
1731 Context.getApplicableDiagnostic(
1732 diag::err_odr_tag_type_inconsistent))
1734 Context.Diag2(D2->getLocation(), diag::note_odr_number_of_bases)
1735 << D2CXX->getNumBases();
1736 Context.Diag1(D1->getLocation(), diag::note_odr_number_of_bases)
1737 << D1CXX->getNumBases();
1738 }
1739 return false;
1740 }
1741
1742
1744 BaseEnd1 = D1CXX->bases_end(),
1745 Base2 = D2CXX->bases_begin();
1746 Base1 != BaseEnd1; ++Base1, ++Base2) {
1748 Base2->getType())) {
1749 if (Context.Complain) {
1751 Context.getApplicableDiagnostic(
1752 diag::err_odr_tag_type_inconsistent))
1754 Context.Diag2(Base2->getBeginLoc(), diag::note_odr_base)
1755 << Base2->getType() << Base2->getSourceRange();
1756 Context.Diag1(Base1->getBeginLoc(), diag::note_odr_base)
1757 << Base1->getType() << Base1->getSourceRange();
1758 }
1759 return false;
1760 }
1761
1762
1763 if (Base1->isVirtual() != Base2->isVirtual()) {
1764 if (Context.Complain) {
1766 Context.getApplicableDiagnostic(
1767 diag::err_odr_tag_type_inconsistent))
1769 Context.Diag2(Base2->getBeginLoc(), diag::note_odr_virtual_base)
1770 << Base2->isVirtual() << Base2->getSourceRange();
1771 Context.Diag1(Base1->getBeginLoc(), diag::note_odr_base)
1772 << Base1->isVirtual() << Base1->getSourceRange();
1773 }
1774 return false;
1775 }
1776 }
1777
1778
1780 Friend2End = D2CXX->friend_end();
1782 Friend1End = D1CXX->friend_end();
1783 Friend1 != Friend1End; ++Friend1, ++Friend2) {
1784 if (Friend2 == Friend2End) {
1785 if (Context.Complain) {
1787 Context.getApplicableDiagnostic(
1788 diag::err_odr_tag_type_inconsistent))
1790 Context.Diag1((*Friend1)->getFriendLoc(), diag::note_odr_friend);
1791 Context.Diag2(D2->getLocation(), diag::note_odr_missing_friend);
1792 }
1793 return false;
1794 }
1795
1797 if (Context.Complain) {
1799 Context.getApplicableDiagnostic(
1800 diag::err_odr_tag_type_inconsistent))
1802 Context.Diag1((*Friend1)->getFriendLoc(), diag::note_odr_friend);
1803 Context.Diag2((*Friend2)->getFriendLoc(), diag::note_odr_friend);
1804 }
1805 return false;
1806 }
1807 }
1808
1809 if (Friend2 != Friend2End) {
1810 if (Context.Complain) {
1812 Context.getApplicableDiagnostic(
1813 diag::err_odr_tag_type_inconsistent))
1815 Context.Diag2((*Friend2)->getFriendLoc(), diag::note_odr_friend);
1816 Context.Diag1(D1->getLocation(), diag::note_odr_missing_friend);
1817 }
1818 return false;
1819 }
1820 } else if (D1CXX->getNumBases() > 0) {
1821 if (Context.Complain) {
1823 Context.getApplicableDiagnostic(
1824 diag::err_odr_tag_type_inconsistent))
1827 Context.Diag1(Base1->getBeginLoc(), diag::note_odr_base)
1829 Context.Diag2(D2->getLocation(), diag::note_odr_missing_base);
1830 }
1831 return false;
1832 }
1833 }
1834
1835
1841 Field1 != Field1End; ++Field1, ++Field2) {
1842 if (Field2 == Field2End) {
1843 if (Context.Complain) {
1845 Context.getApplicableDiagnostic(
1846 diag::err_odr_tag_type_inconsistent))
1848 Context.Diag1(Field1->getLocation(), diag::note_odr_field)
1849 << Field1->getDeclName() << Field1->getType();
1850 Context.Diag2(D2->getLocation(), diag::note_odr_missing_field);
1851 }
1852 return false;
1853 }
1854
1856 return false;
1857 }
1858
1859 if (Field2 != Field2End) {
1860 if (Context.Complain) {
1861 Context.Diag2(D2->getLocation(), Context.getApplicableDiagnostic(
1862 diag::err_odr_tag_type_inconsistent))
1864 Context.Diag2(Field2->getLocation(), diag::note_odr_field)
1865 << Field2->getDeclName() << Field2->getType();
1866 Context.Diag1(D1->getLocation(), diag::note_odr_missing_field);
1867 }
1868 return false;
1869 }
1870
1871 return true;
1872}
1873
1877 const llvm::APSInt &FromVal = D1->getInitVal();
1878 const llvm::APSInt &ToVal = D2->getInitVal();
1879 if (FromVal.isSigned() != ToVal.isSigned())
1880 return false;
1881 if (FromVal.getBitWidth() != ToVal.getBitWidth())
1882 return false;
1883 if (FromVal != ToVal)
1884 return false;
1885
1887 return false;
1888
1889
1892}
1893
1894
1898 return false;
1899 }
1900
1901
1902
1905 if (!D1 || !D2)
1906 return true;
1907
1912 EC1 != EC1End; ++EC1, ++EC2) {
1913 if (EC2 == EC2End) {
1914 if (Context.Complain) {
1916 Context.getApplicableDiagnostic(
1917 diag::err_odr_tag_type_inconsistent))
1919 Context.Diag1(EC1->getLocation(), diag::note_odr_enumerator)
1920 << EC1->getDeclName() << toString(EC1->getInitVal(), 10);
1921 Context.Diag2(D2->getLocation(), diag::note_odr_missing_enumerator);
1922 }
1923 return false;
1924 }
1925
1926 llvm::APSInt Val1 = EC1->getInitVal();
1927 llvm::APSInt Val2 = EC2->getInitVal();
1928 if (!llvm::APSInt::isSameValue(Val1, Val2) ||
1930 if (Context.Complain) {
1932 Context.getApplicableDiagnostic(
1933 diag::err_odr_tag_type_inconsistent))
1935 Context.Diag2(EC2->getLocation(), diag::note_odr_enumerator)
1936 << EC2->getDeclName() << toString(EC2->getInitVal(), 10);
1937 Context.Diag1(EC1->getLocation(), diag::note_odr_enumerator)
1938 << EC1->getDeclName() << toString(EC1->getInitVal(), 10);
1939 }
1940 return false;
1941 }
1942 }
1943
1944 if (EC2 != EC2End) {
1945 if (Context.Complain) {
1946 Context.Diag2(D2->getLocation(), Context.getApplicableDiagnostic(
1947 diag::err_odr_tag_type_inconsistent))
1949 Context.Diag2(EC2->getLocation(), diag::note_odr_enumerator)
1950 << EC2->getDeclName() << toString(EC2->getInitVal(), 10);
1951 Context.Diag1(D1->getLocation(), diag::note_odr_missing_enumerator);
1952 }
1953 return false;
1954 }
1955
1956 return true;
1957}
1958
1962 if (Params1->size() != Params2->size()) {
1963 if (Context.Complain) {
1965 Context.getApplicableDiagnostic(
1966 diag::err_odr_different_num_template_parameters))
1967 << Params1->size() << Params2->size();
1969 diag::note_odr_template_parameter_list);
1970 }
1971 return false;
1972 }
1973
1974 for (unsigned I = 0, N = Params1->size(); I != N; ++I) {
1976 if (Context.Complain) {
1978 Context.getApplicableDiagnostic(
1979 diag::err_odr_different_template_parameter_kind));
1981 diag::note_odr_template_parameter_here);
1982 }
1983 return false;
1984 }
1985
1988 return false;
1989 }
1990
1991 return true;
1992}
1993
1998 if (Context.Complain) {
2000 Context.getApplicableDiagnostic(
2001 diag::err_odr_parameter_pack_non_pack))
2003 Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack)
2005 }
2006 return false;
2007 }
2008
2009 return true;
2010}
2011
2016 if (Context.Complain) {
2018 Context.getApplicableDiagnostic(
2019 diag::err_odr_parameter_pack_non_pack))
2021 Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack)
2023 }
2024 return false;
2025 }
2026 if (!Context.IgnoreTemplateParmDepth && D1->getDepth() != D2->getDepth())
2027 return false;
2029 return false;
2030
2032 if (Context.Complain) {
2034 Context.getApplicableDiagnostic(
2035 diag::err_odr_non_type_parameter_type_inconsistent))
2037 Context.Diag1(D1->getLocation(), diag::note_odr_value_here)
2039 }
2040 return false;
2041 }
2042
2043 return true;
2044}
2045
2050 if (Context.Complain) {
2052 Context.getApplicableDiagnostic(
2053 diag::err_odr_parameter_pack_non_pack))
2055 Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack)
2057 }
2058 return false;
2059 }
2060
2061
2064}
2065
2069 return false;
2072 return false;
2075}
2076
2080
2082 return false;
2083
2084
2087}
2088
2092
2094 return false;
2095
2096
2099}
2100
2104
2106 return false;
2107
2108
2111}
2112
2116
2118 return false;
2119
2120
2123}
2124
2129 return false;
2130 }
2138 return false;
2139}
2140
2144 return false;
2145
2148}
2149
2153 return false;
2154
2157 return false;
2159 return false;
2160 }
2161
2162
2164 return false;
2165
2166 return true;
2167}
2168
2173 return false;
2174
2176 cast(D2), Owner2Type);
2177}
2178
2184}
2185
2189 bool PropertiesEqual =
2193 if (!PropertiesEqual)
2194 return false;
2195
2196
2199 unsigned NumArgs = Selector1.getNumArgs();
2200 if (NumArgs != Selector2.getNumArgs())
2201 return false;
2202
2203
2204 unsigned SlotsToCheck = NumArgs > 0 ? NumArgs : 1;
2205 for (unsigned I = 0; I < SlotsToCheck; ++I) {
2207 Selector2.getIdentifierInfoForSlot(I)))
2208 return false;
2209 }
2210
2211
2214 return false;
2215 assert(
2217 "Same number of arguments should be already enforced in Selector checks");
2223 (ParamT1 != ParamT1End) && (ParamT2 != ParamT2End);
2224 ++ParamT1, ++ParamT2) {
2226 return false;
2227 }
2228
2229 return true;
2230}
2231
2236 return false;
2237
2240 if ((!Intf1 || !Intf2) && (Intf1 != Intf2))
2241 return false;
2242
2243 if (Intf1 &&
2245 return false;
2246
2247
2252 Protocol1 != Protocol1End; ++Protocol1, ++Protocol2) {
2253 if (Protocol2 == Protocol2End)
2254 return false;
2256 (*Protocol2)->getIdentifier()))
2257 return false;
2258 }
2259 if (Protocol2 != Protocol2End)
2260 return false;
2261
2262
2269 Ivar1 != Ivar1End; ++Ivar1, ++Ivar2) {
2270 if (Ivar2 == Ivar2End)
2271 return false;
2273 return false;
2274 }
2275 if (Ivar2 != Ivar2End)
2276 return false;
2277
2278
2280 Method2End = D2->meth_end();
2282 Method1End = D1->meth_end();
2283 Method1 != Method1End; ++Method1, ++Method2) {
2284 if (Method2 == Method2End)
2285 return false;
2287 return false;
2288 }
2289 if (Method2 != Method2End)
2290 return false;
2291
2292 return true;
2293}
2294
2295
2298
2299
2302 std::pair<Decl *, Decl *> P{D1, D2};
2303
2304
2305
2306 if (Context.NonEquivalentDecls.count(
2307 std::make_tuple(D1, D2, Context.IgnoreTemplateParmDepth)))
2308 return false;
2309
2310
2311
2312
2313 bool Inserted = Context.VisitedDecls.insert(P).second;
2314 if (!Inserted)
2315 return true;
2316
2317 Context.DeclsToCheck.push(P);
2318
2319 return true;
2320}
2321
2323 unsigned DiagID) {
2324 assert(Complain && "Not allowed to complain");
2329}
2330
2332 unsigned DiagID) {
2333 assert(Complain && "Not allowed to complain");
2338}
2339
2340std::optional
2344
2345 const auto *Owner = dyn_cast(Anon->getDeclContext());
2346 if (!Owner)
2347 return std::nullopt;
2348
2349 unsigned Index = 0;
2350 for (const auto *D : Owner->noload_decls()) {
2351 const auto *F = dyn_cast(D);
2352 if (!F)
2353 continue;
2354
2355 if (F->isAnonymousStructOrUnion()) {
2356 if (Context.hasSameType(F->getType(), AnonTy))
2357 break;
2358 ++Index;
2359 continue;
2360 }
2361
2362
2363
2364 QualType FieldType = F->getType();
2365
2366 while (const auto *ElabType = dyn_cast(FieldType))
2367 FieldType = ElabType->getNamedType();
2368
2369 if (const auto *RecType = dyn_cast(FieldType)) {
2370 const RecordDecl *RecDecl = RecType->getDecl();
2372 if (Context.hasSameType(FieldType, AnonTy))
2373 break;
2374 ++Index;
2375 continue;
2376 }
2377 }
2378 }
2379
2380 return Index;
2381}
2382
2384 unsigned ErrorDiagnostic) {
2386 return ErrorDiagnostic;
2387
2388 switch (ErrorDiagnostic) {
2389 case diag::err_odr_variable_type_inconsistent:
2390 return diag::warn_odr_variable_type_inconsistent;
2391 case diag::err_odr_variable_multiple_def:
2392 return diag::warn_odr_variable_multiple_def;
2393 case diag::err_odr_function_type_inconsistent:
2394 return diag::warn_odr_function_type_inconsistent;
2395 case diag::err_odr_tag_type_inconsistent:
2396 return diag::warn_odr_tag_type_inconsistent;
2397 case diag::err_odr_field_type_inconsistent:
2398 return diag::warn_odr_field_type_inconsistent;
2399 case diag::err_odr_ivar_type_inconsistent:
2400 return diag::warn_odr_ivar_type_inconsistent;
2401 case diag::err_odr_objc_superclass_inconsistent:
2402 return diag::warn_odr_objc_superclass_inconsistent;
2403 case diag::err_odr_objc_method_result_type_inconsistent:
2404 return diag::warn_odr_objc_method_result_type_inconsistent;
2405 case diag::err_odr_objc_method_num_params_inconsistent:
2406 return diag::warn_odr_objc_method_num_params_inconsistent;
2407 case diag::err_odr_objc_method_param_type_inconsistent:
2408 return diag::warn_odr_objc_method_param_type_inconsistent;
2409 case diag::err_odr_objc_method_variadic_inconsistent:
2410 return diag::warn_odr_objc_method_variadic_inconsistent;
2411 case diag::err_odr_objc_property_type_inconsistent:
2412 return diag::warn_odr_objc_property_type_inconsistent;
2413 case diag::err_odr_objc_property_impl_kind_inconsistent:
2414 return diag::warn_odr_objc_property_impl_kind_inconsistent;
2415 case diag::err_odr_objc_synthesize_ivar_inconsistent:
2416 return diag::warn_odr_objc_synthesize_ivar_inconsistent;
2417 case diag::err_odr_different_num_template_parameters:
2418 return diag::warn_odr_different_num_template_parameters;
2419 case diag::err_odr_different_template_parameter_kind:
2420 return diag::warn_odr_different_template_parameter_kind;
2421 case diag::err_odr_parameter_pack_non_pack:
2422 return diag::warn_odr_parameter_pack_non_pack;
2423 case diag::err_odr_non_type_parameter_type_inconsistent:
2424 return diag::warn_odr_non_type_parameter_type_inconsistent;
2425 }
2426 llvm_unreachable("Diagnostic kind not handled in preceding switch");
2427}
2428
2430
2431
2432
2433
2434
2435
2436
2437
2438
2441
2443 return false;
2444
2445 return !Finish();
2446}
2447
2452 return false;
2453
2454 return !Finish();
2455}
2456
2461 return false;
2462
2463 return !Finish();
2464}
2465
2466bool StructuralEquivalenceContext::CheckCommonEquivalence(Decl *D1, Decl *D2) {
2467
2470 if ((Template1 != nullptr) != (Template2 != nullptr))
2471 return false;
2473 return false;
2474
2475
2476
2477 return true;
2478}
2479
2480bool StructuralEquivalenceContext::CheckKindSpecificEquivalence(
2482
2483
2485 return false;
2486
2487
2488
2489 switch (D1->getKind()) {
2490#define ABSTRACT_DECL(DECL)
2491#define DECL(DERIVED, BASE) \
2492 case Decl::Kind::DERIVED: \
2493 return ::IsStructurallyEquivalent(*this, static_cast<DERIVED##Decl *>(D1), \
2494 static_cast<DERIVED##Decl *>(D2));
2495#include "clang/AST/DeclNodes.inc"
2496 }
2497 return true;
2498}
2499
2500bool StructuralEquivalenceContext::Finish() {
2502
2503 std::pair<Decl *, Decl *> P = DeclsToCheck.front();
2505
2508
2510 CheckCommonEquivalence(D1, D2) && CheckKindSpecificEquivalence(D1, D2);
2511
2513
2514
2517
2518 return true;
2519 }
2520 }
2521
2522 return false;
2523}
Defines the clang::ASTContext interface.
static bool IsTemplateDeclCommonStructurallyEquivalent(StructuralEquivalenceContext &Ctx, TemplateDecl *D1, TemplateDecl *D2)
static bool IsStructurallyEquivalentLambdas(StructuralEquivalenceContext &Context, CXXRecordDecl *D1, CXXRecordDecl *D2)
Determine structural equivalence of two lambda classes.
static bool NameIsStructurallyEquivalent(const TagDecl &D1, const TagDecl &D2)
static bool IsRecordContextStructurallyEquivalent(StructuralEquivalenceContext &Context, RecordDecl *D1, RecordDecl *D2)
Determine if context of a class is equivalent.
static bool IsEquivalentExceptionSpec(StructuralEquivalenceContext &Context, const FunctionProtoType *Proto1, const FunctionProtoType *Proto2)
Check the equivalence of exception specifications.
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, QualType T1, QualType T2)
Determine structural equivalence of two types.
static bool IsArrayStructurallyEquivalent(StructuralEquivalenceContext &Context, const ArrayType *Array1, const ArrayType *Array2)
Determine structural equivalence for the common part of array types.
static Decl::Kind getKind(const Decl *D)
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
This file defines OpenMP nodes for declarative directives.
Defines the C++ template declaration subclasses.
Defines the ExceptionSpecificationType enumeration and various utility functions.
Defines the clang::Expr interface and subclasses for C++ expressions.
Defines Expressions and AST nodes for C++2a concepts.
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
static QualType getUnderlyingType(const SubRegion *R)
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
Defines the clang::SourceLocation class and associated facilities.
Defines the Objective-C statement AST node classes.
This file defines OpenACC AST classes for statement-level contructs.
This file defines OpenMP AST classes for executable directives and clauses.
This file defines SYCL AST classes used to represent calls to SYCL kernels.
static QualType getPointeeType(const MemRegion *R)
C Language Family Type Representation.
llvm::APInt getValue() const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl, ObjCInterfaceDecl *PrevDecl=nullptr) const
getObjCInterfaceType - Return the unique reference to the type for the specified ObjC interface decl.
QualType getRecordType(const RecordDecl *Decl) const
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
QualType getTypeDeclType(const TypeDecl *Decl, const TypeDecl *PrevDecl=nullptr) const
Return the unique reference to the type for the specified type declaration.
DiagnosticsEngine & getDiagnostics() const
ExternalASTSource * getExternalSource() const
Retrieve a pointer to the external AST source associated with this AST context, if any.
AddrLabelExpr - The GNU address of label extension, representing &&label.
LabelDecl * getLabel() const
Represents an array type, per C99 6.7.5.2 - Array Declarators.
ArraySizeModifier getSizeModifier() const
Qualifiers getIndexTypeQualifiers() const
QualType getElementType() const
A structure for storing the information associated with a name that has been assumed to be a template...
DeclarationName getDeclName() const
Get the name of the template.
AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, __atomic_load,...
A builtin binary operation expression such as "x + y" or "x <= y".
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc)
Retrieve the overloaded operator kind that corresponds to the given binary opcode.
Represents a base class of a C++ class.
SourceLocation getBeginLoc() const LLVM_READONLY
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.
A boolean literal, per ([C++ lex.bool] Boolean literals).
Represents a C++ member access expression where the actual member referenced could not be resolved be...
QualType getBaseType() const
DeclarationName getMember() const
Retrieve the name of the member that this expression refers to.
Represents a static or instance method of a struct/union/class.
bool isImplicitObjectMemberFunction() const
[C++2b][dcl.fct]/p7 An implicit object member function is a non-static member function without an exp...
RefQualifierKind getRefQualifier() const
Retrieve the ref-qualifier associated with this method.
A call to an overloaded operator written using operator syntax.
OverloadedOperatorKind getOperator() const
Returns the kind of overloaded operator that this expression refers to.
An iterator over the friend declarations of a class.
Represents a C++ struct/union/class.
bool isLambda() const
Determine whether this class describes a lambda function object.
CXXMethodDecl * getLambdaCallOperator() const
Retrieve the lambda call operator of the closure type if this is a closure type.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
unsigned getValue() const
CharacterLiteralKind getKind() const
ChooseExpr - GNU builtin-in function __builtin_choose_expr.
Declaration of a class template.
CXXRecordDecl * getTemplatedDecl() const
Get the underlying class declarations of the template.
CompoundStmt - This represents a group of statements like { stmt stmt }.
Declaration of a C++20 concept.
Expr * getConstraintExpr() const
Represents a concrete matrix type with constant number of rows and columns.
unsigned getNumColumns() const
Returns the number of columns in the matrix.
unsigned getNumRows() const
Returns the number of rows in the matrix.
specific_decl_iterator - Iterates over a subrange of declarations stored in a DeclContext,...
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 isTranslationUnit() const
bool hasExternalLexicalStorage() const
Whether this DeclContext has external storage containing additional declarations that are lexically i...
bool isInlineNamespace() const
bool isFunctionOrMethod() const
Decl::Kind getDeclKind() const
DeclContext * getNonTransparentContext()
A reference to a declared variable, function, enum, etc.
Decl - This represents one declaration (or definition), e.g.
TemplateDecl * getDescribedTemplate() const
If this is a declaration that describes some template, this method returns that template declaration.
ASTContext & getASTContext() const LLVM_READONLY
SourceLocation getLocation() const
DeclContext * getDeclContext()
AccessSpecifier getAccess() const
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
The name of a declaration.
IdentifierInfo * getAsIdentifierInfo() const
Retrieve the IdentifierInfo * stored in this declaration name, or null if this declaration name isn't...
TemplateDecl * getCXXDeductionGuideTemplate() const
If this name is the name of a C++ deduction guide, return the template associated with that name.
const IdentifierInfo * getCXXLiteralIdentifier() const
If this name is the name of a literal operator, retrieve the identifier associated with it.
OverloadedOperatorKind getCXXOverloadedOperator() const
If this name is the name of an overloadable operator in C++ (e.g., operator+), retrieve the kind of o...
@ CXXConversionFunctionName
QualType getCXXNameType() const
If this name is one of the C++ names (of a constructor, destructor, or conversion function),...
NameKind getNameKind() const
Determine what kind of name this is.
A qualified reference to a name whose declaration cannot yet be resolved.
NestedNameSpecifier * getQualifier() const
Retrieve the nested-name-specifier that qualifies this declaration.
DeclarationName getDeclName() const
Retrieve the name that this expression refers to.
Represents a matrix type where the type and the number of rows and columns is dependent on a template...
Expr * getColumnExpr() const
Expr * getRowExpr() const
Represents a dependent template name that cannot be resolved prior to template instantiation.
OverloadedOperatorKind getOperator() const
Return the overloaded operator to which this template name refers.
bool isIdentifier() const
Determine whether this template name refers to an identifier.
NestedNameSpecifier * getQualifier() const
Return the nested name specifier that qualifies this name.
const IdentifierInfo * getIdentifier() const
Returns the identifier to which this template name refers.
bool isOverloadedOperator() const
Determine whether this template name refers to an overloaded operator.
A little helper class used to produce diagnostics.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
void notePriorDiagnosticFrom(const DiagnosticsEngine &Other)
Note that the prior diagnostic was emitted by some other DiagnosticsEngine, and we may be attaching a...
An instance of this object exists for each enum constant that is defined.
llvm::APSInt getInitVal() const
const Expr * getInitExpr() const
enumerator_iterator enumerator_begin() const
EnumDecl * getDefinition() const
enumerator_iterator enumerator_end() const
This represents one expression.
An expression trait intrinsic.
ExpressionTrait getTrait() const
virtual void CompleteType(TagDecl *Tag)
Gives the external AST source an opportunity to complete an incomplete type.
Represents a member of a struct/union/class.
bool isBitField() const
Determines whether this field is a bitfield.
bool isAnonymousStructOrUnion() const
Determines whether this field is a representative for an anonymous struct or union.
Expr * getBitWidth() const
Returns the expression that represents the bit width, if this field is a bit field.
llvm::APFloat getValue() const
FriendDecl - Represents the declaration of a friend entity, which can be a function,...
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.
bool isDeleted() const
Whether this function has been deleted.
bool isPureVirtual() const
Whether this virtual function is pure, i.e.
bool isDefaulted() const
Whether this function is defaulted.
bool isOverloadedOperator() const
Whether this function declaration represents an C++ overloaded operator, e.g., "operator+".
OverloadedOperatorKind getOverloadedOperator() const
getOverloadedOperator - Which C++ overloaded operator this function represents, if any.
Represents a prototype with parameter type info, e.g.
ExceptionSpecificationType getExceptionSpecType() const
Get the kind of exception specification on this function.
QualType getExceptionType(unsigned i) const
Return the ith exception type, where 0 <= i < getNumExceptions().
unsigned getNumExceptions() const
Return the number of types in the exception specification.
Expr * getNoexceptExpr() const
Return the expression inside noexcept(expression), or a null pointer if there is none (because the ex...
Declaration of a template function.
FunctionDecl * getTemplatedDecl() const
Get the underlying function declaration of the template.
A class which abstracts out some details necessary for making a call.
CallingConv getCC() const
bool getNoCfCheck() const
unsigned getRegParm() const
bool getNoCallerSavedRegs() const
bool getHasRegParm() const
bool getProducesResult() const
Represents a C11 generic selection.
ArrayRef< TypeSourceInfo * > getAssocTypeSourceInfos() const
GotoStmt - This represents a direct goto.
LabelDecl * getLabel() const
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
Represents the declaration of a label.
QualType getElementType() const
Returns type of the elements being stored in the matrix.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
DeclAccessPair getFoundDecl() const
Retrieves the declaration found by lookup.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
Represents a C++ nested name specifier, such as "\::std::vector::".
CXXRecordDecl * getAsRecordDecl() const
Retrieve the record declaration stored in this nested name specifier.
SpecifierKind getKind() const
Determine what kind of nested name specifier is stored.
NamespaceAliasDecl * getAsNamespaceAlias() const
Retrieve the namespace alias stored in this nested name specifier.
IdentifierInfo * getAsIdentifier() const
Retrieve the identifier stored in this nested name specifier.
NestedNameSpecifier * getPrefix() const
Return the prefix of this nested name specifier.
@ NamespaceAlias
A namespace alias, stored as a NamespaceAliasDecl*.
@ TypeSpec
A type, stored as a Type*.
@ TypeSpecWithTemplate
A type that was preceded by the 'template' keyword, stored as a Type*.
@ Super
Microsoft's '__super' specifier, stored as a CXXRecordDecl* of the class it appeared in.
@ Identifier
An identifier, stored as an IdentifierInfo*.
@ Global
The global specifier '::'. There is no stored value.
@ Namespace
A namespace, stored as a NamespaceDecl*.
NamespaceDecl * getAsNamespace() const
Retrieve the namespace stored in this nested name specifier.
const Type * getAsType() const
Retrieve the type stored in this nested name specifier.
NonTypeTemplateParmDecl - Declares a non-type template parameter, e.g., "Size" in.
bool isParameterPack() const
Whether this parameter is a non-type template parameter pack.
unsigned getIndex() const
Get the index of the template parameter within its parameter list.
unsigned getDepth() const
Get the nesting depth of the template parameter.
ObjCCategoryDecl - Represents a category declaration.
ivar_iterator ivar_begin() const
ivar_iterator ivar_end() const
ObjCInterfaceDecl * getClassInterface()
protocol_iterator protocol_end() const
protocol_iterator protocol_begin() const
ObjCProtocolList::iterator protocol_iterator
method_iterator meth_begin() const
method_iterator meth_end() const
Represents an ObjC class declaration.
ObjCIvarDecl - Represents an ObjC instance variable.
AccessControl getAccessControl() const
ObjCInterfaceDecl * getContainingInterface()
Return the class interface that this ivar is logically contained in; this is either the interface whe...
ObjCMethodDecl - Represents an instance or class method declaration.
unsigned param_size() const
param_type_iterator param_type_begin() const
param_type_iterator param_type_end() const
bool isDirectMethod() const
True if the method is tagged as objc_direct.
llvm::mapped_iterator< param_const_iterator, GetTypeFn > param_type_iterator
Selector getSelector() const
bool isInstanceMethod() const
QualType getReturnType() const
ObjCStringLiteral, used for Objective-C string literals i.e.
A reference to an overloaded function set, either an UnresolvedLookupExpr or an UnresolvedMemberExpr.
NestedNameSpecifier * getQualifier() const
Fetches the nested-name qualifier, if one was given.
TemplateArgumentLoc const * getTemplateArgs() const
unsigned getNumTemplateArgs() const
DeclarationName getName() const
Gets the name looked up.
A structure for storing the information associated with an overloaded template name.
NamedDecl *const * iterator
A (possibly-)qualified type.
QualType getDesugaredType(const ASTContext &Context) const
Return the specified type with any "sugar" removed from the type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Represents a struct/union/class.
field_iterator field_end() const
RecordDecl * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
field_iterator field_begin() const
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Smart pointer class that efficiently represents Objective-C method names.
const IdentifierInfo * getIdentifierInfoForSlot(unsigned argIndex) const
Retrieve the identifier at a given position in the selector.
unsigned getNumArgs() const
Represents a function call to one of __builtin_LINE(), __builtin_COLUMN(), __builtin_FUNCTION(),...
SourceLocIdentKind getIdentKind() const
Encodes a location in the source.
StmtExpr - This is the GNU Statement Expression extension: ({int X=4; X;}).
unsigned getTemplateDepth() const
Stmt - This represents one statement.
StmtClass getStmtClass() const
StringLiteral - This represents a string literal expression, e.g.
StringRef getBytes() const
Allow access to clients that need the byte representation, such as ASTWriterStmt::VisitStringLiteral(...
Represents a reference to a non-type template parameter that has been substituted with a template arg...
std::optional< unsigned > getPackIndex() const
Decl * getAssociatedDecl() const
A template-like entity which owns the whole pattern being substituted.
unsigned getIndex() const
Returns the index of the replaced parameter in the associated declaration.
Represents a reference to a non-type template parameter pack that has been substituted with a non-tem...
TemplateArgument getArgumentPack() const
Retrieve the template argument pack containing the substituted template arguments.
A structure for storing an already-substituted template template parameter pack.
Decl * getAssociatedDecl() const
A template-like entity which owns the whole pattern being substituted.
TemplateArgument getArgumentPack() const
Retrieve the template template argument pack with which this parameter was substituted.
unsigned getIndex() const
Returns the index of the replaced parameter in the associated declaration.
Represents the declaration of a struct/union/class/enum.
bool isBeingDefined() const
Return true if this decl is currently being defined.
TagKind getTagKind() const
Location wrapper for a TemplateArgument.
const TemplateArgument & getArgument() const
Represents a template argument.
Expr * getAsExpr() const
Retrieve the template argument as an expression.
QualType getAsType() const
Retrieve the type for a type template argument.
llvm::APSInt getAsIntegral() const
Retrieve the template argument as an integral value.
TemplateName getAsTemplate() const
Retrieve the template name for a template name argument.
bool structurallyEquals(const TemplateArgument &Other) const
Determines whether two template arguments are superficially the same.
QualType getIntegralType() const
Retrieve the type of the integral value.
ValueDecl * getAsDecl() const
Retrieve the declaration for a declaration non-type template argument.
ArrayRef< TemplateArgument > pack_elements() const
Iterator range referencing all of the elements of a template argument pack.
@ Declaration
The template argument is a declaration that was provided for a pointer, reference,...
@ Template
The template argument is a template name that was provided for a template template parameter.
@ StructuralValue
The template argument is a non-type template argument that can't be represented by the special-case D...
@ Pack
The template argument is actually a parameter pack.
@ TemplateExpansion
The template argument is a pack expansion of a template name that was provided for a template templat...
@ NullPtr
The template argument is a null pointer or null pointer to member that was provided for a non-type te...
@ Type
The template argument is a type.
@ Null
Represents an empty template argument, e.g., one that has not been deduced.
@ Integral
The template argument is an integral value stored in an llvm::APSInt that was provided for an integra...
@ Expression
The template argument is an expression, and we've not resolved it to one of the other forms yet,...
ArgKind getKind() const
Return the kind of stored template argument.
TemplateName getAsTemplateOrTemplatePattern() const
Retrieve the template argument as a template name; if the argument is a pack expansion,...
The base class of all kinds of template declarations (e.g., class, function, etc.).
TemplateParameterList * getTemplateParameters() const
Get the list of template parameters.
Represents a C++ template name within the type system.
TemplateDecl * getAsTemplateDecl(bool IgnoreDeduced=false) const
Retrieve the underlying template declaration that this template name refers to, if known.
DependentTemplateName * getAsDependentTemplateName() const
Retrieve the underlying dependent template name structure, if any.
OverloadedTemplateStorage * getAsOverloadedTemplate() const
Retrieve the underlying, overloaded function template declarations that this template name refers to,...
AssumedTemplateStorage * getAsAssumedTemplateName() const
Retrieve information on a name that has been assumed to be a template-name in order to permit a call ...
@ UsingTemplate
A template name that refers to a template declaration found through a specific using shadow declarati...
@ OverloadedTemplate
A set of overloaded template declarations.
@ Template
A single template declaration.
@ DependentTemplate
A dependent template name that has not been resolved to a template (or set of templates).
@ SubstTemplateTemplateParm
A template template parameter that has been substituted for some other template name.
@ SubstTemplateTemplateParmPack
A template template parameter pack that has been substituted for a template template argument pack,...
@ DeducedTemplate
A template name that refers to another TemplateName with deduced default arguments.
@ QualifiedTemplate
A qualified template name, where the qualification is kept to describe the source code as written.
@ AssumedTemplate
An unqualified-id that has been assumed to name a function template that will be found by ADL.
SubstTemplateTemplateParmPackStorage * getAsSubstTemplateTemplateParmPack() const
Retrieve the substituted template template parameter pack, if known.
Stores a list of template parameters for a TemplateDecl and its derived classes.
NamedDecl * getParam(unsigned Idx)
SourceLocation getTemplateLoc() const
TemplateTemplateParmDecl - Declares a template template parameter, e.g., "T" in.
bool isParameterPack() const
Whether this template template parameter is a template parameter pack.
Declaration of a template type parameter.
bool isParameterPack() const
Returns whether this is a parameter pack.
Declaration of an alias template.
TypeAliasDecl * getTemplatedDecl() const
Get the underlying function declaration of the template.
QualType getType() const
Return the type wrapped by this type source info.
A type trait used in the implementation of various C++11 and Library TR1 trait templates.
ArrayRef< TypeSourceInfo * > getArgs() const
Retrieve the argument types.
TypeTrait getTrait() const
Determine which type trait this expression uses.
const T * castAs() const
Member-template castAs.
TypeClass getTypeClass() const
Base class for declarations which introduce a typedef-name.
QualType getUnderlyingType() const
UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated) expression operand.
QualType getTypeOfArgument() const
Gets the argument type, or the type of the argument expression, whichever is appropriate.
UnaryExprOrTypeTrait getKind() const
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Expr * getSubExpr() const
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc)
Retrieve the overloaded operator kind that corresponds to the given unary opcode.
Represents a call to the builtin function __builtin_va_arg.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
DefinitionKind isThisDeclarationADefinition(ASTContext &) const
Check whether this declaration is a definition.
const Expr * getInit() const
StorageClass getStorageClass() const
Returns the storage class as written in the source.
The JSON file list parser is used to communicate input to InstallAPI.
bool isUnresolvedExceptionSpec(ExceptionSpecificationType ESpecType)
bool isComputedNoexcept(ExceptionSpecificationType ESpecType)
@ EST_Dynamic
throw(T1, T2)
ASTContext & FromCtx
AST contexts for which we are checking structural equivalence.
bool LastDiagFromC2
true if the last diagnostic came from ToCtx.
std::queue< std::pair< Decl *, Decl * > > DeclsToCheck
llvm::DenseSet< std::pair< Decl *, Decl * > > VisitedDecls
bool IgnoreTemplateParmDepth
Whether to ignore comparing the depth of template param(TemplateTypeParm)
bool ErrorOnTagTypeMismatch
Whether warn or error on tag type mismatches.
static std::optional< unsigned > findUntaggedStructOrUnionIndex(RecordDecl *Anon)
Find the index of the given anonymous struct/union within its context.
NonEquivalentDeclSet & NonEquivalentDecls
Declaration (from, to) pairs that are known not to be equivalent (which we have already complained ab...
bool Complain
Whether to complain about failures.
DiagnosticBuilder Diag2(SourceLocation Loc, unsigned DiagID)
unsigned getApplicableDiagnostic(unsigned ErrorDiagnostic)
DiagnosticBuilder Diag1(SourceLocation Loc, unsigned DiagID)
bool IsEquivalent(Decl *D1, Decl *D2)
Determine whether the two declarations are structurally equivalent.