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

2506 Decl *D1 = P.first;

2507 Decl *D2 = P.second;

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.