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"
160 llvm_unreachable(
"Unhandled kind of DeclarationName");
191 if (
static_cast<bool>(Callee1) !=
static_cast<bool>(Callee2))
195 if (!
static_cast<bool>(Callee1))
223 if (!Decl1 || !Decl2)
238 bool IsStmtEquivalent(
const Expr *E1,
const Expr *E2) {
255 std::optional<TypeSourceInfo *> Child1 = std::get<0>(Pair);
256 std::optional<TypeSourceInfo *> Child2 = std::get<1>(Pair);
258 if (!Child1 || !Child2)
262 (*Child2)->getType()))
290 bool IsStmtEquivalent(
const Stmt *S1,
const Stmt *S2) {
return true; }
300 return ::IsStructurallyEquivalent(Name1, Name2);
338 std::optional<TypeSourceInfo *> Child1 = std::get<0>(Pair);
339 std::optional<TypeSourceInfo *> Child2 = std::get<1>(Pair);
341 if (!Child1 || !Child2)
345 (*Child2)->getType()))
406 bool TraverseStmt(
const Stmt *S1,
const Stmt *S2) {
return true; }
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))) \
418 return IsStmtEquivalent(S1, S2); \
420#include "clang/AST/StmtNodes.inc"
428 bool IsEquivalent(
const Stmt *S1,
const Stmt *S2) {
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"
447 llvm_unreachable(
"Invalid statement kind");
500 if (
const auto *E2CXXOperatorCall = dyn_cast<CXXOperatorCallExpr>(S2)) {
501 if (
const auto *E1Unary = dyn_cast<UnaryOperator>(S1))
503 if (
const auto *E1Binary = dyn_cast<BinaryOperator>(S1))
506 if (
const auto *E1CXXOperatorCall = dyn_cast<CXXOperatorCallExpr>(S1)) {
507 if (
const auto *E2Unary = dyn_cast<UnaryOperator>(S2))
509 if (
const auto *E2Binary = dyn_cast<BinaryOperator>(S2))
514 StmtComparer Comparer(Context);
515 if (!Comparer.IsEquivalent(S1, S2))
520 std::optional<const Stmt *> Child1 = std::get<0>(Pair);
521 std::optional<const Stmt *> Child2 = std::get<1>(Pair);
524 if (!Child1 || !Child2)
535 if (!Name1 || !Name2)
536 return Name1 == Name2;
550 if ((
bool)Prefix1 != (
bool)Prefix2)
585 if (TemplateDeclN1 && TemplateDeclN2) {
591 }
else if (TemplateDeclN1 || TemplateDeclN2)
603 E1 = OS1->
end(), E2 = OS2->end();
604 for (; I1 != E1 && I2 != E2; ++I1, ++I2)
607 return I1 == E1 && I2 == E2;
620 DN2->getQualifier()))
624 DN2->getIdentifier());
635 P2->getArgumentPack()) &&
637 P2->getAssociatedDecl()) &&
650 llvm_unreachable(
"unimplemented");
709 llvm_unreachable(
"Invalid template argument kind");
716 if (Args1.size() != Args2.size())
718 for (
unsigned I = 0, N = Args1.size(); I != N; ++I) {
814 if (!Context.StrictTypeSpelling) {
831 TC = Type::FunctionNoProto;
834 TC = Type::FunctionNoProto;
842 if (cast<BuiltinType>(T1)->
getKind() != cast<BuiltinType>(T2)->
getKind())
848 cast<ComplexType>(T1)->getElementType(),
849 cast<ComplexType>(T2)->getElementType()))
855 case Type::ArrayParameter:
857 cast<AdjustedType>(T1)->getOriginalType(),
858 cast<AdjustedType>(T2)->getOriginalType()))
869 case Type::BlockPointer:
876 case Type::LValueReference:
877 case Type::RValueReference: {
878 const auto *Ref1 = cast<ReferenceType>(T1);
879 const auto *Ref2 = cast<ReferenceType>(T2);
880 if (Ref1->isSpelledAsLValue() != Ref2->isSpelledAsLValue())
882 if (Ref1->isInnerRef() != Ref2->isInnerRef())
885 Ref2->getPointeeTypeAsWritten()))
890 case Type::MemberPointer: {
891 const auto *MemPtr1 = cast<MemberPointerType>(T1);
892 const auto *MemPtr2 = cast<MemberPointerType>(T2);
894 MemPtr2->getPointeeType()))
902 case Type::ConstantArray: {
903 const auto *Array1 = cast<ConstantArrayType>(T1);
904 const auto *Array2 = cast<ConstantArrayType>(T2);
905 if (!llvm::APInt::isSameValue(Array1->getSize(), Array2->getSize()))
913 case Type::IncompleteArray:
915 cast<ArrayType>(T2)))
919 case Type::VariableArray: {
920 const auto *Array1 = cast<VariableArrayType>(T1);
921 const auto *Array2 = cast<VariableArrayType>(T2);
923 Array2->getSizeExpr()))
932 case Type::DependentSizedArray: {
933 const auto *Array1 = cast<DependentSizedArrayType>(T1);
934 const auto *Array2 = cast<DependentSizedArrayType>(T2);
936 Array2->getSizeExpr()))
945 case Type::DependentAddressSpace: {
946 const auto *DepAddressSpace1 = cast<DependentAddressSpaceType>(T1);
947 const auto *DepAddressSpace2 = cast<DependentAddressSpaceType>(T2);
949 DepAddressSpace2->getAddrSpaceExpr()))
952 DepAddressSpace2->getPointeeType()))
958 case Type::DependentSizedExtVector: {
959 const auto *Vec1 = cast<DependentSizedExtVectorType>(T1);
960 const auto *Vec2 = cast<DependentSizedExtVectorType>(T2);
962 Vec2->getSizeExpr()))
965 Vec2->getElementType()))
970 case Type::DependentVector: {
971 const auto *Vec1 = cast<DependentVectorType>(T1);
972 const auto *Vec2 = cast<DependentVectorType>(T2);
973 if (Vec1->getVectorKind() != Vec2->getVectorKind())
976 Vec2->getSizeExpr()))
979 Vec2->getElementType()))
985 case Type::ExtVector: {
986 const auto *Vec1 = cast<VectorType>(T1);
987 const auto *Vec2 = cast<VectorType>(T2);
989 Vec2->getElementType()))
991 if (Vec1->getNumElements() != Vec2->getNumElements())
993 if (Vec1->getVectorKind() != Vec2->getVectorKind())
998 case Type::DependentSizedMatrix: {
1013 case Type::ConstantMatrix: {
1026 case Type::FunctionProto: {
1027 const auto *Proto1 = cast<FunctionProtoType>(T1);
1028 const auto *Proto2 = cast<FunctionProtoType>(T2);
1030 if (Proto1->getNumParams() != Proto2->getNumParams())
1032 for (
unsigned I = 0, N = Proto1->getNumParams(); I != N; ++I) {
1034 Proto2->getParamType(I)))
1037 if (Proto1->isVariadic() != Proto2->isVariadic())
1040 if (Proto1->getMethodQuals() != Proto2->getMethodQuals())
1044 const auto *OrigProto1 =
1046 const auto *OrigProto2 =
1055 case Type::FunctionNoProto: {
1056 const auto *Function1 = cast<FunctionType>(T1);
1057 const auto *Function2 = cast<FunctionType>(T2);
1059 Function2->getReturnType()))
1062 Function2->getExtInfo()))
1067 case Type::UnresolvedUsing:
1069 cast<UnresolvedUsingType>(T1)->getDecl(),
1070 cast<UnresolvedUsingType>(T2)->getDecl()))
1074 case Type::Attributed:
1076 cast<AttributedType>(T1)->getModifiedType(),
1077 cast<AttributedType>(T2)->getModifiedType()))
1080 Context, cast<AttributedType>(T1)->getEquivalentType(),
1081 cast<AttributedType>(T2)->getEquivalentType()))
1085 case Type::CountAttributed:
1087 cast<CountAttributedType>(T1)->desugar(),
1088 cast<CountAttributedType>(T2)->desugar()))
1092 case Type::BTFTagAttributed:
1094 Context, cast<BTFTagAttributedType>(T1)->getWrappedType(),
1095 cast<BTFTagAttributedType>(T2)->getWrappedType()))
1099 case Type::HLSLAttributedResource:
1101 Context, cast<HLSLAttributedResourceType>(T1)->getWrappedType(),
1102 cast<HLSLAttributedResourceType>(T2)->getWrappedType()))
1105 Context, cast<HLSLAttributedResourceType>(T1)->getContainedType(),
1106 cast<HLSLAttributedResourceType>(T2)->getContainedType()))
1108 if (cast<HLSLAttributedResourceType>(T1)->getAttrs() !=
1109 cast<HLSLAttributedResourceType>(T2)->getAttrs())
1115 cast<ParenType>(T2)->getInnerType()))
1119 case Type::MacroQualified:
1128 cast<UsingType>(T2)->getFoundDecl()))
1138 cast<TypedefType>(T2)->getDecl()) ||
1140 cast<TypedefType>(T2)->desugar()))
1144 case Type::TypeOfExpr:
1146 Context, cast<TypeOfExprType>(T1)->getUnderlyingExpr(),
1147 cast<TypeOfExprType>(T2)->getUnderlyingExpr()))
1153 cast<TypeOfType>(T1)->getUnmodifiedType(),
1154 cast<TypeOfType>(T2)->getUnmodifiedType()))
1158 case Type::UnaryTransform:
1165 case Type::Decltype:
1167 cast<DecltypeType>(T1)->getUnderlyingExpr(),
1168 cast<DecltypeType>(T2)->getUnderlyingExpr()))
1173 auto *Auto1 = cast<AutoType>(T1);
1174 auto *Auto2 = cast<AutoType>(T2);
1176 Auto2->getDeducedType()))
1178 if (Auto1->isConstrained() != Auto2->isConstrained())
1180 if (Auto1->isConstrained()) {
1181 if (Auto1->getTypeConstraintConcept() !=
1182 Auto2->getTypeConstraintConcept())
1185 Auto1->getTypeConstraintArguments(),
1186 Auto2->getTypeConstraintArguments()))
1192 case Type::DeducedTemplateSpecialization: {
1193 const auto *DT1 = cast<DeducedTemplateSpecializationType>(T1);
1194 const auto *DT2 = cast<DeducedTemplateSpecializationType>(T2);
1196 DT2->getTemplateName()))
1199 DT2->getDeducedType()))
1207 cast<TagType>(T2)->getDecl()))
1211 case Type::TemplateTypeParm: {
1212 const auto *Parm1 = cast<TemplateTypeParmType>(T1);
1213 const auto *Parm2 = cast<TemplateTypeParmType>(T2);
1214 if (!Context.IgnoreTemplateParmDepth &&
1215 Parm1->getDepth() != Parm2->getDepth())
1217 if (Parm1->getIndex() != Parm2->getIndex())
1219 if (Parm1->isParameterPack() != Parm2->isParameterPack())
1226 case Type::SubstTemplateTypeParm: {
1227 const auto *Subst1 = cast<SubstTemplateTypeParmType>(T1);
1228 const auto *Subst2 = cast<SubstTemplateTypeParmType>(T2);
1230 Subst2->getReplacementType()))
1233 Subst2->getAssociatedDecl()))
1235 if (Subst1->getIndex() != Subst2->getIndex())
1237 if (Subst1->getPackIndex() != Subst2->getPackIndex())
1242 case Type::SubstTemplateTypeParmPack: {
1243 const auto *Subst1 = cast<SubstTemplateTypeParmPackType>(T1);
1244 const auto *Subst2 = cast<SubstTemplateTypeParmPackType>(T2);
1246 Subst2->getAssociatedDecl()))
1248 if (Subst1->getIndex() != Subst2->getIndex())
1251 Subst2->getArgumentPack()))
1256 case Type::TemplateSpecialization: {
1257 const auto *Spec1 = cast<TemplateSpecializationType>(T1);
1258 const auto *Spec2 = cast<TemplateSpecializationType>(T2);
1260 Spec2->getTemplateName()))
1263 Spec2->template_arguments()))
1268 case Type::Elaborated: {
1269 const auto *Elab1 = cast<ElaboratedType>(T1);
1270 const auto *Elab2 = cast<ElaboratedType>(T2);
1274 if (Elab1->getKeyword() != Elab2->getKeyword())
1277 Elab2->getQualifier()))
1280 Elab2->getNamedType()))
1285 case Type::InjectedClassName: {
1286 const auto *Inj1 = cast<InjectedClassNameType>(T1);
1287 const auto *Inj2 = cast<InjectedClassNameType>(T2);
1289 Inj1->getInjectedSpecializationType(),
1290 Inj2->getInjectedSpecializationType()))
1295 case Type::DependentName: {
1296 const auto *Typename1 = cast<DependentNameType>(T1);
1297 const auto *Typename2 = cast<DependentNameType>(T2);
1299 Typename2->getQualifier()))
1302 Typename2->getIdentifier()))
1308 case Type::DependentTemplateSpecialization: {
1309 const auto *Spec1 = cast<DependentTemplateSpecializationType>(T1);
1310 const auto *Spec2 = cast<DependentTemplateSpecializationType>(T2);
1312 Spec2->getQualifier()))
1315 Spec2->getIdentifier()))
1318 Spec2->template_arguments()))
1323 case Type::PackExpansion:
1325 cast<PackExpansionType>(T1)->getPattern(),
1326 cast<PackExpansionType>(T2)->getPattern()))
1330 case Type::PackIndexing:
1332 cast<PackIndexingType>(T1)->getPattern(),
1333 cast<PackIndexingType>(T2)->getPattern()))
1335 cast<PackIndexingType>(T1)->getIndexExpr(),
1336 cast<PackIndexingType>(T2)->getIndexExpr()))
1340 case Type::ObjCInterface: {
1341 const auto *Iface1 = cast<ObjCInterfaceType>(T1);
1342 const auto *Iface2 = cast<ObjCInterfaceType>(T2);
1349 case Type::ObjCTypeParam: {
1350 const auto *Obj1 = cast<ObjCTypeParamType>(T1);
1351 const auto *Obj2 = cast<ObjCTypeParamType>(T2);
1355 if (Obj1->getNumProtocols() != Obj2->getNumProtocols())
1357 for (
unsigned I = 0, N = Obj1->getNumProtocols(); I != N; ++I) {
1359 Obj2->getProtocol(I)))
1365 case Type::ObjCObject: {
1366 const auto *Obj1 = cast<ObjCObjectType>(T1);
1367 const auto *Obj2 = cast<ObjCObjectType>(T2);
1369 Obj2->getBaseType()))
1371 if (Obj1->getNumProtocols() != Obj2->getNumProtocols())
1373 for (
unsigned I = 0, N = Obj1->getNumProtocols(); I != N; ++I) {
1375 Obj2->getProtocol(I)))
1381 case Type::ObjCObjectPointer: {
1382 const auto *Ptr1 = cast<ObjCObjectPointerType>(T1);
1383 const auto *Ptr2 = cast<ObjCObjectPointerType>(T2);
1385 Ptr2->getPointeeType()))
1392 cast<AtomicType>(T2)->getValueType()))
1398 cast<PipeType>(T2)->getElementType()))
1401 case Type::BitInt: {
1402 const auto *Int1 = cast<BitIntType>(T1);
1403 const auto *Int2 = cast<BitIntType>(T2);
1405 if (Int1->isUnsigned() != Int2->isUnsigned() ||
1406 Int1->getNumBits() != Int2->getNumBits())
1410 case Type::DependentBitInt: {
1411 const auto *Int1 = cast<DependentBitIntType>(T1);
1412 const auto *Int2 = cast<DependentBitIntType>(T2);
1414 if (Int1->isUnsigned() != Int2->isUnsigned() ||
1416 Int2->getNumBitsExpr()))
1466 if (Context.Complain) {
1468 Owner2->getLocation(),
1469 Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent))
1471 Context.Diag2(Field2->
getLocation(), diag::note_odr_field_name)
1473 Context.Diag1(Field1->
getLocation(), diag::note_odr_field_name)
1481 if (Context.Complain) {
1483 Owner2->getLocation(),
1484 Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent))
1486 Context.Diag2(Field2->
getLocation(), diag::note_odr_field)
1488 Context.Diag1(Field1->
getLocation(), diag::note_odr_field)
1513 bool PropertiesEqual =
1527 if (!PropertiesEqual)
1531 if (
auto *Constructor1 = dyn_cast<CXXConstructorDecl>(Method1)) {
1532 auto *Constructor2 = cast<CXXConstructorDecl>(Method2);
1533 if (!Constructor1->getExplicitSpecifier().isEquivalent(
1534 Constructor2->getExplicitSpecifier()))
1538 if (
auto *Conversion1 = dyn_cast<CXXConversionDecl>(Method1)) {
1539 auto *Conversion2 = cast<CXXConversionDecl>(Method2);
1540 if (!Conversion1->getExplicitSpecifier().isEquivalent(
1541 Conversion2->getExplicitSpecifier()))
1544 Conversion2->getConversionType()))
1568 "Must be called on lambda classes");
1599 if (
const auto *ND1 = dyn_cast<NamedDecl>(DC1)) {
1600 const auto *ND2 = cast<NamedDecl>(DC2);
1606 if (
auto *D1Spec = dyn_cast<ClassTemplateSpecializationDecl>(DC1)) {
1607 auto *D2Spec = dyn_cast<ClassTemplateSpecializationDecl>(DC2);
1624 return TypedefName->getIdentifier();
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)
1651 if (std::optional<unsigned> Index1 =
1653 if (std::optional<unsigned> Index2 =
1656 if (*Index1 != *Index2)
1670 const auto *Spec1 = dyn_cast<ClassTemplateSpecializationDecl>(D1);
1671 const auto *Spec2 = dyn_cast<ClassTemplateSpecializationDecl>(D2);
1672 if (Spec1 && Spec2) {
1675 Spec2->getSpecializedTemplate()))
1679 if (Spec1->getTemplateArgs().size() != Spec2->getTemplateArgs().size())
1682 for (
unsigned I = 0, N = Spec1->getTemplateArgs().size(); I != N; ++I)
1684 Spec2->getTemplateArgs().get(I)))
1689 else if (Spec1 || Spec2)
1705 if (Context.EqKind == StructuralEquivalenceKind::Minimal)
1714 if (
auto *D1CXX = dyn_cast<CXXRecordDecl>(D1)) {
1715 if (
auto *D2CXX = dyn_cast<CXXRecordDecl>(D2)) {
1716 if (D1CXX->hasExternalLexicalStorage() &&
1717 !D1CXX->isCompleteDefinition()) {
1721 if (D1CXX->isLambda() != D2CXX->isLambda())
1723 if (D1CXX->isLambda()) {
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();
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();
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();
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);
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);
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);
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);
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);
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);
1877 const llvm::APSInt &FromVal = D1->
getInitVal();
1878 const llvm::APSInt &ToVal = D2->
getInitVal();
1879 if (FromVal.isSigned() != ToVal.isSigned())
1881 if (FromVal.getBitWidth() != ToVal.getBitWidth())
1883 if (FromVal != ToVal)
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);
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);
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);
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);
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);
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)
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)
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)
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)
2176 cast<FieldDecl>(D2), Owner2Type);
2189 bool PropertiesEqual =
2193 if (!PropertiesEqual)
2200 if (NumArgs != Selector2.getNumArgs())
2204 unsigned SlotsToCheck = NumArgs > 0 ? NumArgs : 1;
2205 for (
unsigned I = 0; I < SlotsToCheck; ++I) {
2207 Selector2.getIdentifierInfoForSlot(I)))
2217 "Same number of arguments should be already enforced in Selector checks");
2223 (ParamT1 != ParamT1End) && (ParamT2 != ParamT2End);
2224 ++ParamT1, ++ParamT2) {
2240 if ((!Intf1 || !Intf2) && (Intf1 != Intf2))
2252 Protocol1 != Protocol1End; ++Protocol1, ++Protocol2) {
2253 if (Protocol2 == Protocol2End)
2256 (*Protocol2)->getIdentifier()))
2259 if (Protocol2 != Protocol2End)
2269 Ivar1 != Ivar1End; ++Ivar1, ++Ivar2) {
2270 if (Ivar2 == Ivar2End)
2275 if (Ivar2 != Ivar2End)
2283 Method1 != Method1End; ++Method1, ++Method2) {
2284 if (Method2 == Method2End)
2289 if (Method2 != Method2End)
2302 std::pair<Decl *, Decl *>
P{D1, D2};
2306 if (Context.NonEquivalentDecls.count(
2307 std::make_tuple(D1, D2, Context.IgnoreTemplateParmDepth)))
2313 bool Inserted = Context.VisitedDecls.insert(
P).second;
2317 Context.DeclsToCheck.push(
P);
2324 assert(
Complain &&
"Not allowed to complain");
2333 assert(
Complain &&
"Not allowed to complain");
2340std::optional<unsigned>
2345 const auto *Owner = dyn_cast<RecordDecl>(Anon->
getDeclContext());
2347 return std::nullopt;
2350 for (
const auto *
D : Owner->noload_decls()) {
2351 const auto *F = dyn_cast<FieldDecl>(
D);
2355 if (F->isAnonymousStructOrUnion()) {
2366 while (
const auto *ElabType = dyn_cast<ElaboratedType>(FieldType))
2367 FieldType = ElabType->getNamedType();
2369 if (
const auto *RecType = dyn_cast<RecordType>(FieldType)) {
2370 const RecordDecl *RecDecl = RecType->getDecl();
2384 unsigned ErrorDiagnostic) {
2386 return ErrorDiagnostic;
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;
2426 llvm_unreachable(
"Diagnostic kind not handled in preceding switch");
2466bool StructuralEquivalenceContext::CheckCommonEquivalence(
Decl *D1,
Decl *D2) {
2470 if ((Template1 !=
nullptr) != (Template2 !=
nullptr))
2480bool StructuralEquivalenceContext::CheckKindSpecificEquivalence(
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"
2500bool StructuralEquivalenceContext::Finish() {
2507 Decl *D2 =
P.second;
2510 CheckCommonEquivalence(D1, D2) && CheckKindSpecificEquivalence(D1, D2);
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<int>::".
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<specific type>.
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.