86#include "llvm/ADT/APInt.h"
87#include "llvm/ADT/APSInt.h"
88#include "llvm/ADT/StringExtras.h"
89#include "llvm/Support/Compiler.h"
90#include "llvm/Support/ErrorHandling.h"
159 llvm_unreachable(
"Unhandled kind of DeclarationName");
190 if (
static_cast<bool>(Callee1) !=
static_cast<bool>(Callee2))
194 if (!
static_cast<bool>(Callee1))
222 if (!Decl1 || !Decl2)
237 bool IsStmtEquivalent(
const Expr *E1,
const Expr *E2) {
254 std::optional<TypeSourceInfo *> Child1 = std::get<0>(Pair);
255 std::optional<TypeSourceInfo *> Child2 = std::get<1>(Pair);
257 if (!Child1 || !Child2)
261 (*Child2)->getType()))
289 bool IsStmtEquivalent(
const Stmt *S1,
const Stmt *S2) {
return true; }
299 return ::IsStructurallyEquivalent(Name1, Name2);
337 std::optional<TypeSourceInfo *> Child1 = std::get<0>(Pair);
338 std::optional<TypeSourceInfo *> Child2 = std::get<1>(Pair);
340 if (!Child1 || !Child2)
344 (*Child2)->getType()))
405 bool TraverseStmt(
const Stmt *S1,
const Stmt *S2) {
return true; }
412#define STMT(CLASS, PARENT) \
413 bool TraverseStmt(const CLASS *S1, const CLASS *S2) { \
414 if (!TraverseStmt(static_cast<const PARENT *>(S1), \
415 static_cast<const PARENT *>(S2))) \
417 return IsStmtEquivalent(S1, S2); \
419#include "clang/AST/StmtNodes.inc"
427 bool IsEquivalent(
const Stmt *S1,
const Stmt *S2) {
438 llvm_unreachable(
"Can't traverse NoStmtClass");
439#define STMT(CLASS, PARENT) \
440 case Stmt::StmtClass::CLASS##Class: \
441 return TraverseStmt(static_cast<const CLASS *>(S1), \
442 static_cast<const CLASS *>(S2));
443#define ABSTRACT_STMT(S)
444#include "clang/AST/StmtNodes.inc"
446 llvm_unreachable(
"Invalid statement kind");
499 if (
const auto *E2CXXOperatorCall = dyn_cast<CXXOperatorCallExpr>(S2)) {
500 if (
const auto *E1Unary = dyn_cast<UnaryOperator>(S1))
502 if (
const auto *E1Binary = dyn_cast<BinaryOperator>(S1))
505 if (
const auto *E1CXXOperatorCall = dyn_cast<CXXOperatorCallExpr>(S1)) {
506 if (
const auto *E2Unary = dyn_cast<UnaryOperator>(S2))
508 if (
const auto *E2Binary = dyn_cast<BinaryOperator>(S2))
513 StmtComparer Comparer(Context);
514 if (!Comparer.IsEquivalent(S1, S2))
519 std::optional<const Stmt *> Child1 = std::get<0>(Pair);
520 std::optional<const Stmt *> Child2 = std::get<1>(Pair);
523 if (!Child1 || !Child2)
534 if (!Name1 || !Name2)
535 return Name1 == Name2;
549 if ((
bool)Prefix1 != (
bool)Prefix2)
584 if (TemplateDeclN1 && TemplateDeclN2) {
590 }
else if (TemplateDeclN1 || TemplateDeclN2)
602 E1 = OS1->
end(), E2 = OS2->end();
603 for (; I1 != E1 && I2 != E2; ++I1, ++I2)
606 return I1 == E1 && I2 == E2;
619 DN2->getQualifier()))
623 DN2->getIdentifier());
634 P2->getArgumentPack()) &&
636 P2->getAssociatedDecl()) &&
649 llvm_unreachable(
"unimplemented");
708 llvm_unreachable(
"Invalid template argument kind");
715 if (Args1.size() != Args2.size())
717 for (
unsigned I = 0, N = Args1.size(); I != N; ++I) {
813 if (!Context.StrictTypeSpelling) {
830 TC = Type::FunctionNoProto;
833 TC = Type::FunctionNoProto;
841 if (cast<BuiltinType>(T1)->
getKind() != cast<BuiltinType>(T2)->
getKind())
847 cast<ComplexType>(T1)->getElementType(),
848 cast<ComplexType>(T2)->getElementType()))
854 case Type::ArrayParameter:
856 cast<AdjustedType>(T1)->getOriginalType(),
857 cast<AdjustedType>(T2)->getOriginalType()))
868 case Type::BlockPointer:
875 case Type::LValueReference:
876 case Type::RValueReference: {
877 const auto *Ref1 = cast<ReferenceType>(T1);
878 const auto *Ref2 = cast<ReferenceType>(T2);
879 if (Ref1->isSpelledAsLValue() != Ref2->isSpelledAsLValue())
881 if (Ref1->isInnerRef() != Ref2->isInnerRef())
884 Ref2->getPointeeTypeAsWritten()))
889 case Type::MemberPointer: {
890 const auto *MemPtr1 = cast<MemberPointerType>(T1);
891 const auto *MemPtr2 = cast<MemberPointerType>(T2);
893 MemPtr2->getPointeeType()))
901 case Type::ConstantArray: {
902 const auto *Array1 = cast<ConstantArrayType>(T1);
903 const auto *Array2 = cast<ConstantArrayType>(T2);
904 if (!llvm::APInt::isSameValue(Array1->getSize(), Array2->getSize()))
912 case Type::IncompleteArray:
914 cast<ArrayType>(T2)))
918 case Type::VariableArray: {
919 const auto *Array1 = cast<VariableArrayType>(T1);
920 const auto *Array2 = cast<VariableArrayType>(T2);
922 Array2->getSizeExpr()))
931 case Type::DependentSizedArray: {
932 const auto *Array1 = cast<DependentSizedArrayType>(T1);
933 const auto *Array2 = cast<DependentSizedArrayType>(T2);
935 Array2->getSizeExpr()))
944 case Type::DependentAddressSpace: {
945 const auto *DepAddressSpace1 = cast<DependentAddressSpaceType>(T1);
946 const auto *DepAddressSpace2 = cast<DependentAddressSpaceType>(T2);
948 DepAddressSpace2->getAddrSpaceExpr()))
951 DepAddressSpace2->getPointeeType()))
957 case Type::DependentSizedExtVector: {
958 const auto *Vec1 = cast<DependentSizedExtVectorType>(T1);
959 const auto *Vec2 = cast<DependentSizedExtVectorType>(T2);
961 Vec2->getSizeExpr()))
964 Vec2->getElementType()))
969 case Type::DependentVector: {
970 const auto *Vec1 = cast<DependentVectorType>(T1);
971 const auto *Vec2 = cast<DependentVectorType>(T2);
972 if (Vec1->getVectorKind() != Vec2->getVectorKind())
975 Vec2->getSizeExpr()))
978 Vec2->getElementType()))
984 case Type::ExtVector: {
985 const auto *Vec1 = cast<VectorType>(T1);
986 const auto *Vec2 = cast<VectorType>(T2);
988 Vec2->getElementType()))
990 if (Vec1->getNumElements() != Vec2->getNumElements())
992 if (Vec1->getVectorKind() != Vec2->getVectorKind())
997 case Type::DependentSizedMatrix: {
1012 case Type::ConstantMatrix: {
1025 case Type::FunctionProto: {
1026 const auto *Proto1 = cast<FunctionProtoType>(T1);
1027 const auto *Proto2 = cast<FunctionProtoType>(T2);
1029 if (Proto1->getNumParams() != Proto2->getNumParams())
1031 for (
unsigned I = 0, N = Proto1->getNumParams(); I != N; ++I) {
1033 Proto2->getParamType(I)))
1036 if (Proto1->isVariadic() != Proto2->isVariadic())
1039 if (Proto1->getMethodQuals() != Proto2->getMethodQuals())
1043 const auto *OrigProto1 =
1045 const auto *OrigProto2 =
1054 case Type::FunctionNoProto: {
1055 const auto *Function1 = cast<FunctionType>(T1);
1056 const auto *Function2 = cast<FunctionType>(T2);
1058 Function2->getReturnType()))
1061 Function2->getExtInfo()))
1066 case Type::UnresolvedUsing:
1068 cast<UnresolvedUsingType>(T1)->getDecl(),
1069 cast<UnresolvedUsingType>(T2)->getDecl()))
1073 case Type::Attributed:
1075 cast<AttributedType>(T1)->getModifiedType(),
1076 cast<AttributedType>(T2)->getModifiedType()))
1079 Context, cast<AttributedType>(T1)->getEquivalentType(),
1080 cast<AttributedType>(T2)->getEquivalentType()))
1084 case Type::CountAttributed:
1086 cast<CountAttributedType>(T1)->desugar(),
1087 cast<CountAttributedType>(T2)->desugar()))
1091 case Type::BTFTagAttributed:
1093 Context, cast<BTFTagAttributedType>(T1)->getWrappedType(),
1094 cast<BTFTagAttributedType>(T2)->getWrappedType()))
1098 case Type::HLSLAttributedResource:
1100 Context, cast<HLSLAttributedResourceType>(T1)->getWrappedType(),
1101 cast<HLSLAttributedResourceType>(T2)->getWrappedType()))
1104 Context, cast<HLSLAttributedResourceType>(T1)->getContainedType(),
1105 cast<HLSLAttributedResourceType>(T2)->getContainedType()))
1107 if (cast<HLSLAttributedResourceType>(T1)->getAttrs() !=
1108 cast<HLSLAttributedResourceType>(T2)->getAttrs())
1114 cast<ParenType>(T2)->getInnerType()))
1118 case Type::MacroQualified:
1127 cast<UsingType>(T2)->getFoundDecl()))
1137 cast<TypedefType>(T2)->getDecl()) ||
1139 cast<TypedefType>(T2)->desugar()))
1143 case Type::TypeOfExpr:
1145 Context, cast<TypeOfExprType>(T1)->getUnderlyingExpr(),
1146 cast<TypeOfExprType>(T2)->getUnderlyingExpr()))
1152 cast<TypeOfType>(T1)->getUnmodifiedType(),
1153 cast<TypeOfType>(T2)->getUnmodifiedType()))
1157 case Type::UnaryTransform:
1164 case Type::Decltype:
1166 cast<DecltypeType>(T1)->getUnderlyingExpr(),
1167 cast<DecltypeType>(T2)->getUnderlyingExpr()))
1172 auto *Auto1 = cast<AutoType>(T1);
1173 auto *Auto2 = cast<AutoType>(T2);
1175 Auto2->getDeducedType()))
1177 if (Auto1->isConstrained() != Auto2->isConstrained())
1179 if (Auto1->isConstrained()) {
1180 if (Auto1->getTypeConstraintConcept() !=
1181 Auto2->getTypeConstraintConcept())
1184 Auto1->getTypeConstraintArguments(),
1185 Auto2->getTypeConstraintArguments()))
1191 case Type::DeducedTemplateSpecialization: {
1192 const auto *DT1 = cast<DeducedTemplateSpecializationType>(T1);
1193 const auto *DT2 = cast<DeducedTemplateSpecializationType>(T2);
1195 DT2->getTemplateName()))
1198 DT2->getDeducedType()))
1206 cast<TagType>(T2)->getDecl()))
1210 case Type::TemplateTypeParm: {
1211 const auto *Parm1 = cast<TemplateTypeParmType>(T1);
1212 const auto *Parm2 = cast<TemplateTypeParmType>(T2);
1213 if (!Context.IgnoreTemplateParmDepth &&
1214 Parm1->getDepth() != Parm2->getDepth())
1216 if (Parm1->getIndex() != Parm2->getIndex())
1218 if (Parm1->isParameterPack() != Parm2->isParameterPack())
1225 case Type::SubstTemplateTypeParm: {
1226 const auto *Subst1 = cast<SubstTemplateTypeParmType>(T1);
1227 const auto *Subst2 = cast<SubstTemplateTypeParmType>(T2);
1229 Subst2->getReplacementType()))
1232 Subst2->getAssociatedDecl()))
1234 if (Subst1->getIndex() != Subst2->getIndex())
1236 if (Subst1->getPackIndex() != Subst2->getPackIndex())
1241 case Type::SubstTemplateTypeParmPack: {
1242 const auto *Subst1 = cast<SubstTemplateTypeParmPackType>(T1);
1243 const auto *Subst2 = cast<SubstTemplateTypeParmPackType>(T2);
1245 Subst2->getAssociatedDecl()))
1247 if (Subst1->getIndex() != Subst2->getIndex())
1250 Subst2->getArgumentPack()))
1255 case Type::TemplateSpecialization: {
1256 const auto *Spec1 = cast<TemplateSpecializationType>(T1);
1257 const auto *Spec2 = cast<TemplateSpecializationType>(T2);
1259 Spec2->getTemplateName()))
1262 Spec2->template_arguments()))
1267 case Type::Elaborated: {
1268 const auto *Elab1 = cast<ElaboratedType>(T1);
1269 const auto *Elab2 = cast<ElaboratedType>(T2);
1273 if (Elab1->getKeyword() != Elab2->getKeyword())
1276 Elab2->getQualifier()))
1279 Elab2->getNamedType()))
1284 case Type::InjectedClassName: {
1285 const auto *Inj1 = cast<InjectedClassNameType>(T1);
1286 const auto *Inj2 = cast<InjectedClassNameType>(T2);
1288 Inj1->getInjectedSpecializationType(),
1289 Inj2->getInjectedSpecializationType()))
1294 case Type::DependentName: {
1295 const auto *Typename1 = cast<DependentNameType>(T1);
1296 const auto *Typename2 = cast<DependentNameType>(T2);
1298 Typename2->getQualifier()))
1301 Typename2->getIdentifier()))
1307 case Type::DependentTemplateSpecialization: {
1308 const auto *Spec1 = cast<DependentTemplateSpecializationType>(T1);
1309 const auto *Spec2 = cast<DependentTemplateSpecializationType>(T2);
1311 Spec2->getQualifier()))
1314 Spec2->getIdentifier()))
1317 Spec2->template_arguments()))
1322 case Type::PackExpansion:
1324 cast<PackExpansionType>(T1)->getPattern(),
1325 cast<PackExpansionType>(T2)->getPattern()))
1329 case Type::PackIndexing:
1331 cast<PackIndexingType>(T1)->getPattern(),
1332 cast<PackIndexingType>(T2)->getPattern()))
1334 cast<PackIndexingType>(T1)->getIndexExpr(),
1335 cast<PackIndexingType>(T2)->getIndexExpr()))
1339 case Type::ObjCInterface: {
1340 const auto *Iface1 = cast<ObjCInterfaceType>(T1);
1341 const auto *Iface2 = cast<ObjCInterfaceType>(T2);
1348 case Type::ObjCTypeParam: {
1349 const auto *Obj1 = cast<ObjCTypeParamType>(T1);
1350 const auto *Obj2 = cast<ObjCTypeParamType>(T2);
1354 if (Obj1->getNumProtocols() != Obj2->getNumProtocols())
1356 for (
unsigned I = 0, N = Obj1->getNumProtocols(); I != N; ++I) {
1358 Obj2->getProtocol(I)))
1364 case Type::ObjCObject: {
1365 const auto *Obj1 = cast<ObjCObjectType>(T1);
1366 const auto *Obj2 = cast<ObjCObjectType>(T2);
1368 Obj2->getBaseType()))
1370 if (Obj1->getNumProtocols() != Obj2->getNumProtocols())
1372 for (
unsigned I = 0, N = Obj1->getNumProtocols(); I != N; ++I) {
1374 Obj2->getProtocol(I)))
1380 case Type::ObjCObjectPointer: {
1381 const auto *Ptr1 = cast<ObjCObjectPointerType>(T1);
1382 const auto *Ptr2 = cast<ObjCObjectPointerType>(T2);
1384 Ptr2->getPointeeType()))
1391 cast<AtomicType>(T2)->getValueType()))
1397 cast<PipeType>(T2)->getElementType()))
1400 case Type::BitInt: {
1401 const auto *Int1 = cast<BitIntType>(T1);
1402 const auto *Int2 = cast<BitIntType>(T2);
1404 if (Int1->isUnsigned() != Int2->isUnsigned() ||
1405 Int1->getNumBits() != Int2->getNumBits())
1409 case Type::DependentBitInt: {
1410 const auto *Int1 = cast<DependentBitIntType>(T1);
1411 const auto *Int2 = cast<DependentBitIntType>(T2);
1413 if (Int1->isUnsigned() != Int2->isUnsigned() ||
1415 Int2->getNumBitsExpr()))
1465 if (Context.Complain) {
1467 Owner2->getLocation(),
1468 Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent))
1470 Context.Diag2(Field2->
getLocation(), diag::note_odr_field_name)
1472 Context.Diag1(Field1->
getLocation(), diag::note_odr_field_name)
1480 if (Context.Complain) {
1482 Owner2->getLocation(),
1483 Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent))
1485 Context.Diag2(Field2->
getLocation(), diag::note_odr_field)
1487 Context.Diag1(Field1->
getLocation(), diag::note_odr_field)
1512 bool PropertiesEqual =
1526 if (!PropertiesEqual)
1530 if (
auto *Constructor1 = dyn_cast<CXXConstructorDecl>(Method1)) {
1531 auto *Constructor2 = cast<CXXConstructorDecl>(Method2);
1532 if (!Constructor1->getExplicitSpecifier().isEquivalent(
1533 Constructor2->getExplicitSpecifier()))
1537 if (
auto *Conversion1 = dyn_cast<CXXConversionDecl>(Method1)) {
1538 auto *Conversion2 = cast<CXXConversionDecl>(Method2);
1539 if (!Conversion1->getExplicitSpecifier().isEquivalent(
1540 Conversion2->getExplicitSpecifier()))
1543 Conversion2->getConversionType()))
1567 "Must be called on lambda classes");
1598 if (
const auto *ND1 = dyn_cast<NamedDecl>(DC1)) {
1599 const auto *ND2 = cast<NamedDecl>(DC2);
1605 if (
auto *D1Spec = dyn_cast<ClassTemplateSpecializationDecl>(DC1)) {
1606 auto *D2Spec = dyn_cast<ClassTemplateSpecializationDecl>(DC2);
1623 return TypedefName->getIdentifier();
1637 if (Context.Complain) {
1638 Context.Diag2(D2->
getLocation(), Context.getApplicableDiagnostic(
1639 diag::err_odr_tag_type_inconsistent))
1641 Context.Diag1(D1->
getLocation(), diag::note_odr_tag_kind_here)
1650 if (std::optional<unsigned> Index1 =
1652 if (std::optional<unsigned> Index2 =
1655 if (*Index1 != *Index2)
1669 const auto *Spec1 = dyn_cast<ClassTemplateSpecializationDecl>(D1);
1670 const auto *Spec2 = dyn_cast<ClassTemplateSpecializationDecl>(D2);
1671 if (Spec1 && Spec2) {
1674 Spec2->getSpecializedTemplate()))
1678 if (Spec1->getTemplateArgs().size() != Spec2->getTemplateArgs().size())
1681 for (
unsigned I = 0, N = Spec1->getTemplateArgs().size(); I != N; ++I)
1683 Spec2->getTemplateArgs().get(I)))
1688 else if (Spec1 || Spec2)
1704 if (Context.EqKind == StructuralEquivalenceKind::Minimal)
1713 if (
auto *D1CXX = dyn_cast<CXXRecordDecl>(D1)) {
1714 if (
auto *D2CXX = dyn_cast<CXXRecordDecl>(D2)) {
1715 if (D1CXX->hasExternalLexicalStorage() &&
1716 !D1CXX->isCompleteDefinition()) {
1720 if (D1CXX->isLambda() != D2CXX->isLambda())
1722 if (D1CXX->isLambda()) {
1727 if (D1CXX->getNumBases() != D2CXX->getNumBases()) {
1728 if (Context.Complain) {
1730 Context.getApplicableDiagnostic(
1731 diag::err_odr_tag_type_inconsistent))
1733 Context.Diag2(D2->
getLocation(), diag::note_odr_number_of_bases)
1734 << D2CXX->getNumBases();
1735 Context.Diag1(D1->
getLocation(), diag::note_odr_number_of_bases)
1736 << D1CXX->getNumBases();
1743 BaseEnd1 = D1CXX->bases_end(),
1744 Base2 = D2CXX->bases_begin();
1745 Base1 != BaseEnd1; ++Base1, ++Base2) {
1747 Base2->getType())) {
1748 if (Context.Complain) {
1750 Context.getApplicableDiagnostic(
1751 diag::err_odr_tag_type_inconsistent))
1753 Context.Diag2(Base2->getBeginLoc(), diag::note_odr_base)
1754 << Base2->getType() << Base2->getSourceRange();
1755 Context.Diag1(Base1->getBeginLoc(), diag::note_odr_base)
1756 << Base1->getType() << Base1->getSourceRange();
1762 if (Base1->isVirtual() != Base2->isVirtual()) {
1763 if (Context.Complain) {
1765 Context.getApplicableDiagnostic(
1766 diag::err_odr_tag_type_inconsistent))
1768 Context.Diag2(Base2->getBeginLoc(), diag::note_odr_virtual_base)
1769 << Base2->isVirtual() << Base2->getSourceRange();
1770 Context.Diag1(Base1->getBeginLoc(), diag::note_odr_base)
1771 << Base1->isVirtual() << Base1->getSourceRange();
1779 Friend2End = D2CXX->friend_end();
1781 Friend1End = D1CXX->friend_end();
1782 Friend1 != Friend1End; ++Friend1, ++Friend2) {
1783 if (Friend2 == Friend2End) {
1784 if (Context.Complain) {
1786 Context.getApplicableDiagnostic(
1787 diag::err_odr_tag_type_inconsistent))
1789 Context.Diag1((*Friend1)->getFriendLoc(), diag::note_odr_friend);
1790 Context.Diag2(D2->
getLocation(), diag::note_odr_missing_friend);
1796 if (Context.Complain) {
1798 Context.getApplicableDiagnostic(
1799 diag::err_odr_tag_type_inconsistent))
1801 Context.Diag1((*Friend1)->getFriendLoc(), diag::note_odr_friend);
1802 Context.Diag2((*Friend2)->getFriendLoc(), diag::note_odr_friend);
1808 if (Friend2 != Friend2End) {
1809 if (Context.Complain) {
1811 Context.getApplicableDiagnostic(
1812 diag::err_odr_tag_type_inconsistent))
1814 Context.Diag2((*Friend2)->getFriendLoc(), diag::note_odr_friend);
1815 Context.Diag1(D1->
getLocation(), diag::note_odr_missing_friend);
1819 }
else if (D1CXX->getNumBases() > 0) {
1820 if (Context.Complain) {
1822 Context.getApplicableDiagnostic(
1823 diag::err_odr_tag_type_inconsistent))
1826 Context.Diag1(Base1->
getBeginLoc(), diag::note_odr_base)
1828 Context.Diag2(D2->
getLocation(), diag::note_odr_missing_base);
1840 Field1 != Field1End; ++Field1, ++Field2) {
1841 if (Field2 == Field2End) {
1842 if (Context.Complain) {
1844 Context.getApplicableDiagnostic(
1845 diag::err_odr_tag_type_inconsistent))
1847 Context.Diag1(Field1->getLocation(), diag::note_odr_field)
1848 << Field1->getDeclName() << Field1->getType();
1849 Context.Diag2(D2->
getLocation(), diag::note_odr_missing_field);
1858 if (Field2 != Field2End) {
1859 if (Context.Complain) {
1860 Context.Diag2(D2->
getLocation(), Context.getApplicableDiagnostic(
1861 diag::err_odr_tag_type_inconsistent))
1863 Context.Diag2(Field2->getLocation(), diag::note_odr_field)
1864 << Field2->getDeclName() << Field2->getType();
1865 Context.Diag1(D1->
getLocation(), diag::note_odr_missing_field);
1876 const llvm::APSInt &FromVal = D1->
getInitVal();
1877 const llvm::APSInt &ToVal = D2->
getInitVal();
1878 if (FromVal.isSigned() != ToVal.isSigned())
1880 if (FromVal.getBitWidth() != ToVal.getBitWidth())
1882 if (FromVal != ToVal)
1911 EC1 != EC1End; ++EC1, ++EC2) {
1912 if (EC2 == EC2End) {
1913 if (Context.Complain) {
1915 Context.getApplicableDiagnostic(
1916 diag::err_odr_tag_type_inconsistent))
1918 Context.Diag1(EC1->getLocation(), diag::note_odr_enumerator)
1919 << EC1->getDeclName() <<
toString(EC1->getInitVal(), 10);
1920 Context.Diag2(D2->
getLocation(), diag::note_odr_missing_enumerator);
1925 llvm::APSInt Val1 = EC1->getInitVal();
1926 llvm::APSInt Val2 = EC2->getInitVal();
1927 if (!llvm::APSInt::isSameValue(Val1, Val2) ||
1929 if (Context.Complain) {
1931 Context.getApplicableDiagnostic(
1932 diag::err_odr_tag_type_inconsistent))
1934 Context.Diag2(EC2->getLocation(), diag::note_odr_enumerator)
1935 << EC2->getDeclName() <<
toString(EC2->getInitVal(), 10);
1936 Context.Diag1(EC1->getLocation(), diag::note_odr_enumerator)
1937 << EC1->getDeclName() <<
toString(EC1->getInitVal(), 10);
1943 if (EC2 != EC2End) {
1944 if (Context.Complain) {
1945 Context.Diag2(D2->
getLocation(), Context.getApplicableDiagnostic(
1946 diag::err_odr_tag_type_inconsistent))
1948 Context.Diag2(EC2->getLocation(), diag::note_odr_enumerator)
1949 << EC2->getDeclName() <<
toString(EC2->getInitVal(), 10);
1950 Context.Diag1(D1->
getLocation(), diag::note_odr_missing_enumerator);
1961 if (Params1->
size() != Params2->
size()) {
1962 if (Context.Complain) {
1964 Context.getApplicableDiagnostic(
1965 diag::err_odr_different_num_template_parameters))
1966 << Params1->
size() << Params2->
size();
1968 diag::note_odr_template_parameter_list);
1973 for (
unsigned I = 0, N = Params1->
size(); I != N; ++I) {
1975 if (Context.Complain) {
1977 Context.getApplicableDiagnostic(
1978 diag::err_odr_different_template_parameter_kind));
1980 diag::note_odr_template_parameter_here);
1997 if (Context.Complain) {
1999 Context.getApplicableDiagnostic(
2000 diag::err_odr_parameter_pack_non_pack))
2002 Context.Diag1(D1->
getLocation(), diag::note_odr_parameter_pack_non_pack)
2015 if (Context.Complain) {
2017 Context.getApplicableDiagnostic(
2018 diag::err_odr_parameter_pack_non_pack))
2020 Context.Diag1(D1->
getLocation(), diag::note_odr_parameter_pack_non_pack)
2031 if (Context.Complain) {
2033 Context.getApplicableDiagnostic(
2034 diag::err_odr_non_type_parameter_type_inconsistent))
2036 Context.Diag1(D1->
getLocation(), diag::note_odr_value_here)
2049 if (Context.Complain) {
2051 Context.getApplicableDiagnostic(
2052 diag::err_odr_parameter_pack_non_pack))
2054 Context.Diag1(D1->
getLocation(), diag::note_odr_parameter_pack_non_pack)
2175 cast<FieldDecl>(D2), Owner2Type);
2188 bool PropertiesEqual =
2192 if (!PropertiesEqual)
2199 if (NumArgs != Selector2.getNumArgs())
2203 unsigned SlotsToCheck = NumArgs > 0 ? NumArgs : 1;
2204 for (
unsigned I = 0; I < SlotsToCheck; ++I) {
2206 Selector2.getIdentifierInfoForSlot(I)))
2216 "Same number of arguments should be already enforced in Selector checks");
2222 (ParamT1 != ParamT1End) && (ParamT2 != ParamT2End);
2223 ++ParamT1, ++ParamT2) {
2239 if ((!Intf1 || !Intf2) && (Intf1 != Intf2))
2251 Protocol1 != Protocol1End; ++Protocol1, ++Protocol2) {
2252 if (Protocol2 == Protocol2End)
2255 (*Protocol2)->getIdentifier()))
2258 if (Protocol2 != Protocol2End)
2268 Ivar1 != Ivar1End; ++Ivar1, ++Ivar2) {
2269 if (Ivar2 == Ivar2End)
2274 if (Ivar2 != Ivar2End)
2282 Method1 != Method1End; ++Method1, ++Method2) {
2283 if (Method2 == Method2End)
2288 if (Method2 != Method2End)
2301 std::pair<Decl *, Decl *>
P{D1, D2};
2305 if (Context.NonEquivalentDecls.count(
2306 std::make_tuple(D1, D2, Context.IgnoreTemplateParmDepth)))
2312 bool Inserted = Context.VisitedDecls.insert(
P).second;
2316 Context.DeclsToCheck.push(
P);
2323 assert(
Complain &&
"Not allowed to complain");
2332 assert(
Complain &&
"Not allowed to complain");
2339std::optional<unsigned>
2344 const auto *Owner = dyn_cast<RecordDecl>(Anon->
getDeclContext());
2346 return std::nullopt;
2349 for (
const auto *
D : Owner->noload_decls()) {
2350 const auto *F = dyn_cast<FieldDecl>(
D);
2354 if (F->isAnonymousStructOrUnion()) {
2365 while (
const auto *ElabType = dyn_cast<ElaboratedType>(FieldType))
2366 FieldType = ElabType->getNamedType();
2368 if (
const auto *RecType = dyn_cast<RecordType>(FieldType)) {
2369 const RecordDecl *RecDecl = RecType->getDecl();
2383 unsigned ErrorDiagnostic) {
2385 return ErrorDiagnostic;
2387 switch (ErrorDiagnostic) {
2388 case diag::err_odr_variable_type_inconsistent:
2389 return diag::warn_odr_variable_type_inconsistent;
2390 case diag::err_odr_variable_multiple_def:
2391 return diag::warn_odr_variable_multiple_def;
2392 case diag::err_odr_function_type_inconsistent:
2393 return diag::warn_odr_function_type_inconsistent;
2394 case diag::err_odr_tag_type_inconsistent:
2395 return diag::warn_odr_tag_type_inconsistent;
2396 case diag::err_odr_field_type_inconsistent:
2397 return diag::warn_odr_field_type_inconsistent;
2398 case diag::err_odr_ivar_type_inconsistent:
2399 return diag::warn_odr_ivar_type_inconsistent;
2400 case diag::err_odr_objc_superclass_inconsistent:
2401 return diag::warn_odr_objc_superclass_inconsistent;
2402 case diag::err_odr_objc_method_result_type_inconsistent:
2403 return diag::warn_odr_objc_method_result_type_inconsistent;
2404 case diag::err_odr_objc_method_num_params_inconsistent:
2405 return diag::warn_odr_objc_method_num_params_inconsistent;
2406 case diag::err_odr_objc_method_param_type_inconsistent:
2407 return diag::warn_odr_objc_method_param_type_inconsistent;
2408 case diag::err_odr_objc_method_variadic_inconsistent:
2409 return diag::warn_odr_objc_method_variadic_inconsistent;
2410 case diag::err_odr_objc_property_type_inconsistent:
2411 return diag::warn_odr_objc_property_type_inconsistent;
2412 case diag::err_odr_objc_property_impl_kind_inconsistent:
2413 return diag::warn_odr_objc_property_impl_kind_inconsistent;
2414 case diag::err_odr_objc_synthesize_ivar_inconsistent:
2415 return diag::warn_odr_objc_synthesize_ivar_inconsistent;
2416 case diag::err_odr_different_num_template_parameters:
2417 return diag::warn_odr_different_num_template_parameters;
2418 case diag::err_odr_different_template_parameter_kind:
2419 return diag::warn_odr_different_template_parameter_kind;
2420 case diag::err_odr_parameter_pack_non_pack:
2421 return diag::warn_odr_parameter_pack_non_pack;
2422 case diag::err_odr_non_type_parameter_type_inconsistent:
2423 return diag::warn_odr_non_type_parameter_type_inconsistent;
2425 llvm_unreachable(
"Diagnostic kind not handled in preceding switch");
2465bool StructuralEquivalenceContext::CheckCommonEquivalence(
Decl *D1,
Decl *D2) {
2469 if ((Template1 !=
nullptr) != (Template2 !=
nullptr))
2479bool StructuralEquivalenceContext::CheckKindSpecificEquivalence(
2489#define ABSTRACT_DECL(DECL)
2490#define DECL(DERIVED, BASE) \
2491 case Decl::Kind::DERIVED: \
2492 return ::IsStructurallyEquivalent(*this, static_cast<DERIVED##Decl *>(D1), \
2493 static_cast<DERIVED##Decl *>(D2));
2494#include "clang/AST/DeclNodes.inc"
2499bool StructuralEquivalenceContext::Finish() {
2506 Decl *D2 =
P.second;
2509 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.
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.