85#include "llvm/ADT/APInt.h"
86#include "llvm/ADT/APSInt.h"
87#include "llvm/ADT/StringExtras.h"
88#include "llvm/Support/Casting.h"
89#include "llvm/Support/Compiler.h"
90#include "llvm/Support/ErrorHandling.h"
157 llvm_unreachable(
"Unhandled kind of DeclarationName");
188 if (
static_cast<bool>(Callee1) !=
static_cast<bool>(Callee2))
192 if (!
static_cast<bool>(Callee1))
220 if (!Decl1 || !Decl2)
235 bool IsStmtEquivalent(
const Expr *E1,
const Expr *E2) {
252 std::optional<TypeSourceInfo *> Child1 = std::get<0>(Pair);
253 std::optional<TypeSourceInfo *> Child2 = std::get<1>(Pair);
255 if (!Child1 || !Child2)
259 (*Child2)->getType()))
287 bool IsStmtEquivalent(
const Stmt *S1,
const Stmt *S2) {
return true; }
297 return ::IsStructurallyEquivalent(Name1, Name2);
335 std::optional<TypeSourceInfo *> Child1 = std::get<0>(Pair);
336 std::optional<TypeSourceInfo *> Child2 = std::get<1>(Pair);
338 if (!Child1 || !Child2)
342 (*Child2)->getType()))
394 bool TraverseStmt(
const Stmt *S1,
const Stmt *S2) {
return true; }
401#define STMT(CLASS, PARENT) \
402 bool TraverseStmt(const CLASS *S1, const CLASS *S2) { \
403 if (!TraverseStmt(static_cast<const PARENT *>(S1), \
404 static_cast<const PARENT *>(S2))) \
406 return IsStmtEquivalent(S1, S2); \
408#include "clang/AST/StmtNodes.inc"
416 bool IsEquivalent(
const Stmt *S1,
const Stmt *S2) {
427 llvm_unreachable(
"Can't traverse NoStmtClass");
428#define STMT(CLASS, PARENT) \
429 case Stmt::StmtClass::CLASS##Class: \
430 return TraverseStmt(static_cast<const CLASS *>(S1), \
431 static_cast<const CLASS *>(S2));
432#define ABSTRACT_STMT(S)
433#include "clang/AST/StmtNodes.inc"
435 llvm_unreachable(
"Invalid statement kind");
447 StmtComparer Comparer(Context);
448 if (!Comparer.IsEquivalent(S1, S2))
453 std::optional<const Stmt *> Child1 = std::get<0>(Pair);
454 std::optional<const Stmt *> Child2 = std::get<1>(Pair);
457 if (!Child1 || !Child2)
468 if (!Name1 || !Name2)
469 return Name1 == Name2;
483 if ((
bool)Prefix1 != (
bool)Prefix2)
518 if (TemplateDeclN1 && TemplateDeclN2) {
524 }
else if (TemplateDeclN1 || TemplateDeclN2)
536 E1 = OS1->
end(), E2 = OS2->end();
537 for (; I1 != E1 && I2 != E2; ++I1, ++I2)
540 return I1 == E1 && I2 == E2;
553 DN2->getQualifier()))
557 DN2->getIdentifier());
568 P2->getArgumentPack()) &&
570 P2->getAssociatedDecl()) &&
636 llvm_unreachable(
"Invalid template argument kind");
643 if (Args1.size() != Args2.size())
645 for (
unsigned I = 0, N = Args1.size(); I != N; ++I) {
741 if (!Context.StrictTypeSpelling) {
758 TC = Type::FunctionNoProto;
761 TC = Type::FunctionNoProto;
769 if (cast<BuiltinType>(T1)->
getKind() != cast<BuiltinType>(T2)->
getKind())
775 cast<ComplexType>(T1)->getElementType(),
776 cast<ComplexType>(T2)->getElementType()))
783 cast<AdjustedType>(T1)->getOriginalType(),
784 cast<AdjustedType>(T2)->getOriginalType()))
790 cast<PointerType>(T1)->getPointeeType(),
791 cast<PointerType>(T2)->getPointeeType()))
795 case Type::BlockPointer:
797 cast<BlockPointerType>(T1)->getPointeeType(),
798 cast<BlockPointerType>(T2)->getPointeeType()))
802 case Type::LValueReference:
803 case Type::RValueReference: {
804 const auto *Ref1 = cast<ReferenceType>(T1);
805 const auto *Ref2 = cast<ReferenceType>(T2);
806 if (Ref1->isSpelledAsLValue() != Ref2->isSpelledAsLValue())
808 if (Ref1->isInnerRef() != Ref2->isInnerRef())
811 Ref2->getPointeeTypeAsWritten()))
816 case Type::MemberPointer: {
817 const auto *MemPtr1 = cast<MemberPointerType>(T1);
818 const auto *MemPtr2 = cast<MemberPointerType>(T2);
820 MemPtr2->getPointeeType()))
828 case Type::ConstantArray: {
829 const auto *Array1 = cast<ConstantArrayType>(T1);
830 const auto *Array2 = cast<ConstantArrayType>(T2);
831 if (!llvm::APInt::isSameValue(Array1->getSize(), Array2->getSize()))
839 case Type::IncompleteArray:
841 cast<ArrayType>(T2)))
845 case Type::VariableArray: {
846 const auto *Array1 = cast<VariableArrayType>(T1);
847 const auto *Array2 = cast<VariableArrayType>(T2);
849 Array2->getSizeExpr()))
858 case Type::DependentSizedArray: {
859 const auto *Array1 = cast<DependentSizedArrayType>(T1);
860 const auto *Array2 = cast<DependentSizedArrayType>(T2);
862 Array2->getSizeExpr()))
871 case Type::DependentAddressSpace: {
872 const auto *DepAddressSpace1 = cast<DependentAddressSpaceType>(T1);
873 const auto *DepAddressSpace2 = cast<DependentAddressSpaceType>(T2);
875 DepAddressSpace2->getAddrSpaceExpr()))
878 DepAddressSpace2->getPointeeType()))
884 case Type::DependentSizedExtVector: {
885 const auto *Vec1 = cast<DependentSizedExtVectorType>(T1);
886 const auto *Vec2 = cast<DependentSizedExtVectorType>(T2);
888 Vec2->getSizeExpr()))
891 Vec2->getElementType()))
896 case Type::DependentVector: {
897 const auto *Vec1 = cast<DependentVectorType>(T1);
898 const auto *Vec2 = cast<DependentVectorType>(T2);
899 if (Vec1->getVectorKind() != Vec2->getVectorKind())
902 Vec2->getSizeExpr()))
905 Vec2->getElementType()))
911 case Type::ExtVector: {
912 const auto *Vec1 = cast<VectorType>(T1);
913 const auto *Vec2 = cast<VectorType>(T2);
915 Vec2->getElementType()))
917 if (Vec1->getNumElements() != Vec2->getNumElements())
919 if (Vec1->getVectorKind() != Vec2->getVectorKind())
924 case Type::DependentSizedMatrix: {
939 case Type::ConstantMatrix: {
952 case Type::FunctionProto: {
953 const auto *Proto1 = cast<FunctionProtoType>(T1);
954 const auto *Proto2 = cast<FunctionProtoType>(T2);
956 if (Proto1->getNumParams() != Proto2->getNumParams())
958 for (
unsigned I = 0, N = Proto1->getNumParams(); I != N; ++I) {
960 Proto2->getParamType(I)))
963 if (Proto1->isVariadic() != Proto2->isVariadic())
966 if (Proto1->getMethodQuals() != Proto2->getMethodQuals())
970 const auto *OrigProto1 =
972 const auto *OrigProto2 =
981 case Type::FunctionNoProto: {
982 const auto *Function1 = cast<FunctionType>(T1);
983 const auto *Function2 = cast<FunctionType>(T2);
985 Function2->getReturnType()))
988 Function2->getExtInfo()))
993 case Type::UnresolvedUsing:
995 cast<UnresolvedUsingType>(T1)->getDecl(),
996 cast<UnresolvedUsingType>(T2)->getDecl()))
1000 case Type::Attributed:
1002 cast<AttributedType>(T1)->getModifiedType(),
1003 cast<AttributedType>(T2)->getModifiedType()))
1006 Context, cast<AttributedType>(T1)->getEquivalentType(),
1007 cast<AttributedType>(T2)->getEquivalentType()))
1011 case Type::BTFTagAttributed:
1013 Context, cast<BTFTagAttributedType>(T1)->getWrappedType(),
1014 cast<BTFTagAttributedType>(T2)->getWrappedType()))
1020 cast<ParenType>(T2)->getInnerType()))
1024 case Type::MacroQualified:
1033 cast<UsingType>(T2)->getFoundDecl()))
1043 cast<TypedefType>(T2)->getDecl()) ||
1045 cast<TypedefType>(T2)->desugar()))
1049 case Type::TypeOfExpr:
1051 Context, cast<TypeOfExprType>(T1)->getUnderlyingExpr(),
1052 cast<TypeOfExprType>(T2)->getUnderlyingExpr()))
1058 cast<TypeOfType>(T1)->getUnmodifiedType(),
1059 cast<TypeOfType>(T2)->getUnmodifiedType()))
1063 case Type::UnaryTransform:
1070 case Type::Decltype:
1072 cast<DecltypeType>(T1)->getUnderlyingExpr(),
1073 cast<DecltypeType>(T2)->getUnderlyingExpr()))
1078 auto *Auto1 = cast<AutoType>(T1);
1079 auto *Auto2 = cast<AutoType>(T2);
1081 Auto2->getDeducedType()))
1083 if (Auto1->isConstrained() != Auto2->isConstrained())
1085 if (Auto1->isConstrained()) {
1086 if (Auto1->getTypeConstraintConcept() !=
1087 Auto2->getTypeConstraintConcept())
1090 Auto1->getTypeConstraintArguments(),
1091 Auto2->getTypeConstraintArguments()))
1097 case Type::DeducedTemplateSpecialization: {
1098 const auto *DT1 = cast<DeducedTemplateSpecializationType>(T1);
1099 const auto *DT2 = cast<DeducedTemplateSpecializationType>(T2);
1101 DT2->getTemplateName()))
1104 DT2->getDeducedType()))
1112 cast<TagType>(T2)->getDecl()))
1116 case Type::TemplateTypeParm: {
1117 const auto *Parm1 = cast<TemplateTypeParmType>(T1);
1118 const auto *Parm2 = cast<TemplateTypeParmType>(T2);
1119 if (!Context.IgnoreTemplateParmDepth &&
1120 Parm1->getDepth() != Parm2->getDepth())
1122 if (Parm1->getIndex() != Parm2->getIndex())
1124 if (Parm1->isParameterPack() != Parm2->isParameterPack())
1131 case Type::SubstTemplateTypeParm: {
1132 const auto *Subst1 = cast<SubstTemplateTypeParmType>(T1);
1133 const auto *Subst2 = cast<SubstTemplateTypeParmType>(T2);
1135 Subst2->getReplacementType()))
1138 Subst2->getAssociatedDecl()))
1140 if (Subst1->getIndex() != Subst2->getIndex())
1142 if (Subst1->getPackIndex() != Subst2->getPackIndex())
1147 case Type::SubstTemplateTypeParmPack: {
1148 const auto *Subst1 = cast<SubstTemplateTypeParmPackType>(T1);
1149 const auto *Subst2 = cast<SubstTemplateTypeParmPackType>(T2);
1151 Subst2->getAssociatedDecl()))
1153 if (Subst1->getIndex() != Subst2->getIndex())
1156 Subst2->getArgumentPack()))
1161 case Type::TemplateSpecialization: {
1162 const auto *Spec1 = cast<TemplateSpecializationType>(T1);
1163 const auto *Spec2 = cast<TemplateSpecializationType>(T2);
1165 Spec2->getTemplateName()))
1168 Spec2->template_arguments()))
1173 case Type::Elaborated: {
1174 const auto *Elab1 = cast<ElaboratedType>(T1);
1175 const auto *Elab2 = cast<ElaboratedType>(T2);
1179 if (Elab1->getKeyword() != Elab2->getKeyword())
1182 Elab2->getQualifier()))
1185 Elab2->getNamedType()))
1190 case Type::InjectedClassName: {
1191 const auto *Inj1 = cast<InjectedClassNameType>(T1);
1192 const auto *Inj2 = cast<InjectedClassNameType>(T2);
1194 Inj1->getInjectedSpecializationType(),
1195 Inj2->getInjectedSpecializationType()))
1200 case Type::DependentName: {
1201 const auto *Typename1 = cast<DependentNameType>(T1);
1202 const auto *Typename2 = cast<DependentNameType>(T2);
1204 Typename2->getQualifier()))
1207 Typename2->getIdentifier()))
1213 case Type::DependentTemplateSpecialization: {
1214 const auto *Spec1 = cast<DependentTemplateSpecializationType>(T1);
1215 const auto *Spec2 = cast<DependentTemplateSpecializationType>(T2);
1217 Spec2->getQualifier()))
1220 Spec2->getIdentifier()))
1223 Spec2->template_arguments()))
1228 case Type::PackExpansion:
1230 cast<PackExpansionType>(T1)->getPattern(),
1231 cast<PackExpansionType>(T2)->getPattern()))
1235 case Type::ObjCInterface: {
1236 const auto *Iface1 = cast<ObjCInterfaceType>(T1);
1237 const auto *Iface2 = cast<ObjCInterfaceType>(T2);
1244 case Type::ObjCTypeParam: {
1245 const auto *Obj1 = cast<ObjCTypeParamType>(T1);
1246 const auto *Obj2 = cast<ObjCTypeParamType>(T2);
1250 if (Obj1->getNumProtocols() != Obj2->getNumProtocols())
1252 for (
unsigned I = 0, N = Obj1->getNumProtocols(); I != N; ++I) {
1254 Obj2->getProtocol(I)))
1260 case Type::ObjCObject: {
1261 const auto *Obj1 = cast<ObjCObjectType>(T1);
1262 const auto *Obj2 = cast<ObjCObjectType>(T2);
1264 Obj2->getBaseType()))
1266 if (Obj1->getNumProtocols() != Obj2->getNumProtocols())
1268 for (
unsigned I = 0, N = Obj1->getNumProtocols(); I != N; ++I) {
1270 Obj2->getProtocol(I)))
1276 case Type::ObjCObjectPointer: {
1277 const auto *Ptr1 = cast<ObjCObjectPointerType>(T1);
1278 const auto *Ptr2 = cast<ObjCObjectPointerType>(T2);
1280 Ptr2->getPointeeType()))
1287 cast<AtomicType>(T2)->getValueType()))
1293 cast<PipeType>(T2)->getElementType()))
1296 case Type::BitInt: {
1297 const auto *Int1 = cast<BitIntType>(T1);
1298 const auto *Int2 = cast<BitIntType>(T2);
1300 if (Int1->isUnsigned() != Int2->isUnsigned() ||
1301 Int1->getNumBits() != Int2->getNumBits())
1305 case Type::DependentBitInt: {
1306 const auto *Int1 = cast<DependentBitIntType>(T1);
1307 const auto *Int2 = cast<DependentBitIntType>(T2);
1309 if (Int1->isUnsigned() != Int2->isUnsigned() ||
1311 Int2->getNumBitsExpr()))
1355 if (Context.Complain) {
1357 Owner2->getLocation(),
1358 Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent))
1360 Context.Diag2(Field2->
getLocation(), diag::note_odr_field_name)
1362 Context.Diag1(Field1->
getLocation(), diag::note_odr_field_name)
1370 if (Context.Complain) {
1372 Owner2->getLocation(),
1373 Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent))
1375 Context.Diag2(Field2->
getLocation(), diag::note_odr_field)
1377 Context.Diag1(Field1->
getLocation(), diag::note_odr_field)
1402 bool PropertiesEqual =
1416 if (!PropertiesEqual)
1420 if (
auto *Constructor1 = dyn_cast<CXXConstructorDecl>(Method1)) {
1421 auto *Constructor2 = cast<CXXConstructorDecl>(Method2);
1422 if (!Constructor1->getExplicitSpecifier().isEquivalent(
1423 Constructor2->getExplicitSpecifier()))
1427 if (
auto *Conversion1 = dyn_cast<CXXConversionDecl>(Method1)) {
1428 auto *Conversion2 = cast<CXXConversionDecl>(Method2);
1429 if (!Conversion1->getExplicitSpecifier().isEquivalent(
1430 Conversion2->getExplicitSpecifier()))
1433 Conversion2->getConversionType()))
1457 "Must be called on lambda classes");
1487 if (
const auto *ND1 = dyn_cast<NamedDecl>(DC1)) {
1488 const auto *ND2 = cast<NamedDecl>(DC2);
1505 if (
const TypedefNameDecl *TypedefName = D.getTypedefNameForAnonDecl())
1506 return TypedefName->getIdentifier();
1520 if (Context.Complain) {
1521 Context.Diag2(D2->
getLocation(), Context.getApplicableDiagnostic(
1522 diag::err_odr_tag_type_inconsistent))
1524 Context.Diag1(D1->
getLocation(), diag::note_odr_tag_kind_here)
1533 if (std::optional<unsigned> Index1 =
1535 if (std::optional<unsigned> Index2 =
1538 if (*Index1 != *Index2)
1552 const auto *Spec1 = dyn_cast<ClassTemplateSpecializationDecl>(D1);
1553 const auto *Spec2 = dyn_cast<ClassTemplateSpecializationDecl>(D2);
1554 if (Spec1 && Spec2) {
1557 Spec2->getSpecializedTemplate()))
1561 if (Spec1->getTemplateArgs().size() != Spec2->getTemplateArgs().size())
1564 for (
unsigned I = 0, N = Spec1->getTemplateArgs().size(); I != N; ++I)
1566 Spec2->getTemplateArgs().get(I)))
1571 else if (Spec1 || Spec2)
1587 if (Context.EqKind == StructuralEquivalenceKind::Minimal)
1596 if (
auto *D1CXX = dyn_cast<CXXRecordDecl>(D1)) {
1597 if (
auto *D2CXX = dyn_cast<CXXRecordDecl>(D2)) {
1598 if (D1CXX->hasExternalLexicalStorage() &&
1599 !D1CXX->isCompleteDefinition()) {
1603 if (D1CXX->isLambda() != D2CXX->isLambda())
1605 if (D1CXX->isLambda()) {
1610 if (D1CXX->getNumBases() != D2CXX->getNumBases()) {
1611 if (Context.Complain) {
1613 Context.getApplicableDiagnostic(
1614 diag::err_odr_tag_type_inconsistent))
1616 Context.Diag2(D2->
getLocation(), diag::note_odr_number_of_bases)
1617 << D2CXX->getNumBases();
1618 Context.Diag1(D1->
getLocation(), diag::note_odr_number_of_bases)
1619 << D1CXX->getNumBases();
1626 BaseEnd1 = D1CXX->bases_end(),
1627 Base2 = D2CXX->bases_begin();
1628 Base1 != BaseEnd1; ++Base1, ++Base2) {
1630 Base2->getType())) {
1631 if (Context.Complain) {
1633 Context.getApplicableDiagnostic(
1634 diag::err_odr_tag_type_inconsistent))
1636 Context.Diag2(Base2->getBeginLoc(), diag::note_odr_base)
1637 << Base2->getType() << Base2->getSourceRange();
1638 Context.Diag1(Base1->getBeginLoc(), diag::note_odr_base)
1639 << Base1->getType() << Base1->getSourceRange();
1645 if (Base1->isVirtual() != Base2->isVirtual()) {
1646 if (Context.Complain) {
1648 Context.getApplicableDiagnostic(
1649 diag::err_odr_tag_type_inconsistent))
1651 Context.Diag2(Base2->getBeginLoc(), diag::note_odr_virtual_base)
1652 << Base2->isVirtual() << Base2->getSourceRange();
1653 Context.Diag1(Base1->getBeginLoc(), diag::note_odr_base)
1654 << Base1->isVirtual() << Base1->getSourceRange();
1662 Friend2End = D2CXX->friend_end();
1664 Friend1End = D1CXX->friend_end();
1665 Friend1 != Friend1End; ++Friend1, ++Friend2) {
1666 if (Friend2 == Friend2End) {
1667 if (Context.Complain) {
1669 Context.getApplicableDiagnostic(
1670 diag::err_odr_tag_type_inconsistent))
1672 Context.Diag1((*Friend1)->getFriendLoc(), diag::note_odr_friend);
1673 Context.Diag2(D2->
getLocation(), diag::note_odr_missing_friend);
1679 if (Context.Complain) {
1681 Context.getApplicableDiagnostic(
1682 diag::err_odr_tag_type_inconsistent))
1684 Context.Diag1((*Friend1)->getFriendLoc(), diag::note_odr_friend);
1685 Context.Diag2((*Friend2)->getFriendLoc(), diag::note_odr_friend);
1691 if (Friend2 != Friend2End) {
1692 if (Context.Complain) {
1694 Context.getApplicableDiagnostic(
1695 diag::err_odr_tag_type_inconsistent))
1697 Context.Diag2((*Friend2)->getFriendLoc(), diag::note_odr_friend);
1698 Context.Diag1(D1->
getLocation(), diag::note_odr_missing_friend);
1702 }
else if (D1CXX->getNumBases() > 0) {
1703 if (Context.Complain) {
1705 Context.getApplicableDiagnostic(
1706 diag::err_odr_tag_type_inconsistent))
1709 Context.Diag1(Base1->
getBeginLoc(), diag::note_odr_base)
1711 Context.Diag2(D2->
getLocation(), diag::note_odr_missing_base);
1723 Field1 != Field1End; ++Field1, ++Field2) {
1724 if (Field2 == Field2End) {
1725 if (Context.Complain) {
1727 Context.getApplicableDiagnostic(
1728 diag::err_odr_tag_type_inconsistent))
1730 Context.Diag1(Field1->getLocation(), diag::note_odr_field)
1731 << Field1->getDeclName() << Field1->getType();
1732 Context.Diag2(D2->
getLocation(), diag::note_odr_missing_field);
1741 if (Field2 != Field2End) {
1742 if (Context.Complain) {
1743 Context.Diag2(D2->
getLocation(), Context.getApplicableDiagnostic(
1744 diag::err_odr_tag_type_inconsistent))
1746 Context.Diag2(Field2->getLocation(), diag::note_odr_field)
1747 << Field2->getDeclName() << Field2->getType();
1748 Context.Diag1(D1->
getLocation(), diag::note_odr_missing_field);
1759 const llvm::APSInt &FromVal = D1->
getInitVal();
1760 const llvm::APSInt &ToVal = D2->
getInitVal();
1761 if (FromVal.isSigned() != ToVal.isSigned())
1763 if (FromVal.getBitWidth() != ToVal.getBitWidth())
1765 if (FromVal != ToVal)
1794 EC1 != EC1End; ++EC1, ++EC2) {
1795 if (EC2 == EC2End) {
1796 if (Context.Complain) {
1798 Context.getApplicableDiagnostic(
1799 diag::err_odr_tag_type_inconsistent))
1801 Context.Diag1(EC1->getLocation(), diag::note_odr_enumerator)
1802 << EC1->getDeclName() <<
toString(EC1->getInitVal(), 10);
1803 Context.Diag2(D2->
getLocation(), diag::note_odr_missing_enumerator);
1808 llvm::APSInt Val1 = EC1->getInitVal();
1809 llvm::APSInt Val2 = EC2->getInitVal();
1810 if (!llvm::APSInt::isSameValue(Val1, Val2) ||
1812 if (Context.Complain) {
1814 Context.getApplicableDiagnostic(
1815 diag::err_odr_tag_type_inconsistent))
1817 Context.Diag2(EC2->getLocation(), diag::note_odr_enumerator)
1818 << EC2->getDeclName() <<
toString(EC2->getInitVal(), 10);
1819 Context.Diag1(EC1->getLocation(), diag::note_odr_enumerator)
1820 << EC1->getDeclName() <<
toString(EC1->getInitVal(), 10);
1826 if (EC2 != EC2End) {
1827 if (Context.Complain) {
1828 Context.Diag2(D2->
getLocation(), Context.getApplicableDiagnostic(
1829 diag::err_odr_tag_type_inconsistent))
1831 Context.Diag2(EC2->getLocation(), diag::note_odr_enumerator)
1832 << EC2->getDeclName() <<
toString(EC2->getInitVal(), 10);
1833 Context.Diag1(D1->
getLocation(), diag::note_odr_missing_enumerator);
1844 if (Params1->
size() != Params2->
size()) {
1845 if (Context.Complain) {
1847 Context.getApplicableDiagnostic(
1848 diag::err_odr_different_num_template_parameters))
1849 << Params1->
size() << Params2->
size();
1851 diag::note_odr_template_parameter_list);
1856 for (
unsigned I = 0, N = Params1->
size(); I != N; ++I) {
1858 if (Context.Complain) {
1860 Context.getApplicableDiagnostic(
1861 diag::err_odr_different_template_parameter_kind));
1863 diag::note_odr_template_parameter_here);
1880 if (Context.Complain) {
1882 Context.getApplicableDiagnostic(
1883 diag::err_odr_parameter_pack_non_pack))
1885 Context.Diag1(D1->
getLocation(), diag::note_odr_parameter_pack_non_pack)
1898 if (Context.Complain) {
1900 Context.getApplicableDiagnostic(
1901 diag::err_odr_parameter_pack_non_pack))
1903 Context.Diag1(D1->
getLocation(), diag::note_odr_parameter_pack_non_pack)
1911 if (Context.Complain) {
1913 Context.getApplicableDiagnostic(
1914 diag::err_odr_non_type_parameter_type_inconsistent))
1916 Context.Diag1(D1->
getLocation(), diag::note_odr_value_here)
1929 if (Context.Complain) {
1931 Context.getApplicableDiagnostic(
1932 diag::err_odr_parameter_pack_non_pack))
1934 Context.Diag1(D1->
getLocation(), diag::note_odr_parameter_pack_non_pack)
2043 cast<FieldDecl>(D2), Owner2Type);
2056 bool PropertiesEqual =
2060 if (!PropertiesEqual)
2067 if (NumArgs != Selector2.getNumArgs())
2071 unsigned SlotsToCheck = NumArgs > 0 ? NumArgs : 1;
2072 for (
unsigned I = 0; I < SlotsToCheck; ++I) {
2074 Selector2.getIdentifierInfoForSlot(I)))
2084 "Same number of arguments should be already enforced in Selector checks");
2090 (ParamT1 != ParamT1End) && (ParamT2 != ParamT2End);
2091 ++ParamT1, ++ParamT2) {
2107 if ((!Intf1 || !Intf2) && (Intf1 != Intf2))
2119 Protocol1 != Protocol1End; ++Protocol1, ++Protocol2) {
2120 if (Protocol2 == Protocol2End)
2123 (*Protocol2)->getIdentifier()))
2126 if (Protocol2 != Protocol2End)
2136 Ivar1 != Ivar1End; ++Ivar1, ++Ivar2) {
2137 if (Ivar2 == Ivar2End)
2142 if (Ivar2 != Ivar2End)
2150 Method1 != Method1End; ++Method1, ++Method2) {
2151 if (Method2 == Method2End)
2156 if (Method2 != Method2End)
2169 std::pair<Decl *, Decl *>
P{D1, D2};
2173 if (Context.NonEquivalentDecls.count(
P))
2179 bool Inserted = Context.VisitedDecls.insert(
P).second;
2183 Context.DeclsToCheck.push(
P);
2190 assert(
Complain &&
"Not allowed to complain");
2199 assert(
Complain &&
"Not allowed to complain");
2206std::optional<unsigned>
2211 const auto *Owner = dyn_cast<RecordDecl>(Anon->
getDeclContext());
2213 return std::nullopt;
2216 for (
const auto *D : Owner->noload_decls()) {
2217 const auto *F = dyn_cast<FieldDecl>(D);
2221 if (F->isAnonymousStructOrUnion()) {
2232 while (
const auto *ElabType = dyn_cast<ElaboratedType>(FieldType))
2233 FieldType = ElabType->getNamedType();
2235 if (
const auto *RecType = dyn_cast<RecordType>(FieldType)) {
2236 const RecordDecl *RecDecl = RecType->getDecl();
2250 unsigned ErrorDiagnostic) {
2252 return ErrorDiagnostic;
2254 switch (ErrorDiagnostic) {
2255 case diag::err_odr_variable_type_inconsistent:
2256 return diag::warn_odr_variable_type_inconsistent;
2257 case diag::err_odr_variable_multiple_def:
2258 return diag::warn_odr_variable_multiple_def;
2259 case diag::err_odr_function_type_inconsistent:
2260 return diag::warn_odr_function_type_inconsistent;
2261 case diag::err_odr_tag_type_inconsistent:
2262 return diag::warn_odr_tag_type_inconsistent;
2263 case diag::err_odr_field_type_inconsistent:
2264 return diag::warn_odr_field_type_inconsistent;
2265 case diag::err_odr_ivar_type_inconsistent:
2266 return diag::warn_odr_ivar_type_inconsistent;
2267 case diag::err_odr_objc_superclass_inconsistent:
2268 return diag::warn_odr_objc_superclass_inconsistent;
2269 case diag::err_odr_objc_method_result_type_inconsistent:
2270 return diag::warn_odr_objc_method_result_type_inconsistent;
2271 case diag::err_odr_objc_method_num_params_inconsistent:
2272 return diag::warn_odr_objc_method_num_params_inconsistent;
2273 case diag::err_odr_objc_method_param_type_inconsistent:
2274 return diag::warn_odr_objc_method_param_type_inconsistent;
2275 case diag::err_odr_objc_method_variadic_inconsistent:
2276 return diag::warn_odr_objc_method_variadic_inconsistent;
2277 case diag::err_odr_objc_property_type_inconsistent:
2278 return diag::warn_odr_objc_property_type_inconsistent;
2279 case diag::err_odr_objc_property_impl_kind_inconsistent:
2280 return diag::warn_odr_objc_property_impl_kind_inconsistent;
2281 case diag::err_odr_objc_synthesize_ivar_inconsistent:
2282 return diag::warn_odr_objc_synthesize_ivar_inconsistent;
2283 case diag::err_odr_different_num_template_parameters:
2284 return diag::warn_odr_different_num_template_parameters;
2285 case diag::err_odr_different_template_parameter_kind:
2286 return diag::warn_odr_different_template_parameter_kind;
2287 case diag::err_odr_parameter_pack_non_pack:
2288 return diag::warn_odr_parameter_pack_non_pack;
2289 case diag::err_odr_non_type_parameter_type_inconsistent:
2290 return diag::warn_odr_non_type_parameter_type_inconsistent;
2292 llvm_unreachable(
"Diagnostic kind not handled in preceding switch");
2332bool StructuralEquivalenceContext::CheckCommonEquivalence(
Decl *D1,
Decl *D2) {
2336 if ((Template1 !=
nullptr) != (Template2 !=
nullptr))
2346bool StructuralEquivalenceContext::CheckKindSpecificEquivalence(
2356#define ABSTRACT_DECL(DECL)
2357#define DECL(DERIVED, BASE) \
2358 case Decl::Kind::DERIVED: \
2359 return ::IsStructurallyEquivalent(*this, static_cast<DERIVED##Decl *>(D1), \
2360 static_cast<DERIVED##Decl *>(D2));
2361#include "clang/AST/DeclNodes.inc"
2366bool StructuralEquivalenceContext::Finish() {
2373 Decl *D2 =
P.second;
2376 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 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 bool IsRecordContextStructurallyEquivalent(RecordDecl *D1, RecordDecl *D2)
Determine if context of a class is equivalent.
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 OpenMP AST classes for executable directives and clauses.
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".
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 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.
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]).
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.
const Expr * getInitExpr() const
const llvm::APSInt & getInitVal() 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 isPure() const
Whether this virtual function is pure, i.e.
bool isDeleted() const
Whether this function has been deleted.
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.
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.
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.
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.
@ 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() 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,...
@ 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.
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),...
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.
const Expr * getInit() const
StorageClass getStorageClass() const
Returns the storage class as written in the source.
bool isUnresolvedExceptionSpec(ExceptionSpecificationType ESpecType)
bool isComputedNoexcept(ExceptionSpecificationType ESpecType)
@ EST_Dynamic
throw(T1, T2)
llvm::DenseSet< std::pair< Decl *, Decl * > > & NonEquivalentDecls
Declaration (from, to) pairs that are known not to be equivalent (which we have already complained ab...
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 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.
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.