86#include "llvm/ADT/APInt.h"
87#include "llvm/ADT/APSInt.h"
88#include "llvm/ADT/StringExtras.h"
89#include "llvm/Support/Casting.h"
90#include "llvm/Support/Compiler.h"
91#include "llvm/Support/ErrorHandling.h"
160 llvm_unreachable(
"Unhandled kind of DeclarationName");
191 if (
static_cast<bool>(Callee1) !=
static_cast<bool>(Callee2))
195 if (!
static_cast<bool>(Callee1))
223 if (!Decl1 || !Decl2)
238 bool IsStmtEquivalent(
const Expr *E1,
const Expr *E2) {
255 std::optional<TypeSourceInfo *> Child1 = std::get<0>(Pair);
256 std::optional<TypeSourceInfo *> Child2 = std::get<1>(Pair);
258 if (!Child1 || !Child2)
262 (*Child2)->getType()))
290 bool IsStmtEquivalent(
const Stmt *S1,
const Stmt *S2) {
return true; }
300 return ::IsStructurallyEquivalent(Name1, Name2);
338 std::optional<TypeSourceInfo *> Child1 = std::get<0>(Pair);
339 std::optional<TypeSourceInfo *> Child2 = std::get<1>(Pair);
341 if (!Child1 || !Child2)
345 (*Child2)->getType()))
397 bool TraverseStmt(
const Stmt *S1,
const Stmt *S2) {
return true; }
404#define STMT(CLASS, PARENT) \
405 bool TraverseStmt(const CLASS *S1, const CLASS *S2) { \
406 if (!TraverseStmt(static_cast<const PARENT *>(S1), \
407 static_cast<const PARENT *>(S2))) \
409 return IsStmtEquivalent(S1, S2); \
411#include "clang/AST/StmtNodes.inc"
419 bool IsEquivalent(
const Stmt *S1,
const Stmt *S2) {
430 llvm_unreachable(
"Can't traverse NoStmtClass");
431#define STMT(CLASS, PARENT) \
432 case Stmt::StmtClass::CLASS##Class: \
433 return TraverseStmt(static_cast<const CLASS *>(S1), \
434 static_cast<const CLASS *>(S2));
435#define ABSTRACT_STMT(S)
436#include "clang/AST/StmtNodes.inc"
438 llvm_unreachable(
"Invalid statement kind");
491 if (
const auto *E2CXXOperatorCall = dyn_cast<CXXOperatorCallExpr>(S2)) {
492 if (
const auto *E1Unary = dyn_cast<UnaryOperator>(S1))
494 if (
const auto *E1Binary = dyn_cast<BinaryOperator>(S1))
497 if (
const auto *E1CXXOperatorCall = dyn_cast<CXXOperatorCallExpr>(S1)) {
498 if (
const auto *E2Unary = dyn_cast<UnaryOperator>(S2))
500 if (
const auto *E2Binary = dyn_cast<BinaryOperator>(S2))
505 StmtComparer Comparer(Context);
506 if (!Comparer.IsEquivalent(S1, S2))
511 std::optional<const Stmt *> Child1 = std::get<0>(Pair);
512 std::optional<const Stmt *> Child2 = std::get<1>(Pair);
515 if (!Child1 || !Child2)
526 if (!Name1 || !Name2)
527 return Name1 == Name2;
541 if ((
bool)Prefix1 != (
bool)Prefix2)
576 if (TemplateDeclN1 && TemplateDeclN2) {
582 }
else if (TemplateDeclN1 || TemplateDeclN2)
594 E1 = OS1->
end(), E2 = OS2->end();
595 for (; I1 != E1 && I2 != E2; ++I1, ++I2)
598 return I1 == E1 && I2 == E2;
611 DN2->getQualifier()))
615 DN2->getIdentifier());
626 P2->getArgumentPack()) &&
628 P2->getAssociatedDecl()) &&
697 llvm_unreachable(
"Invalid template argument kind");
704 if (Args1.size() != Args2.size())
706 for (
unsigned I = 0, N = Args1.size(); I != N; ++I) {
802 if (!Context.StrictTypeSpelling) {
819 TC = Type::FunctionNoProto;
822 TC = Type::FunctionNoProto;
830 if (cast<BuiltinType>(T1)->
getKind() != cast<BuiltinType>(T2)->
getKind())
836 cast<ComplexType>(T1)->getElementType(),
837 cast<ComplexType>(T2)->getElementType()))
843 case Type::ArrayParameter:
845 cast<AdjustedType>(T1)->getOriginalType(),
846 cast<AdjustedType>(T2)->getOriginalType()))
852 cast<PointerType>(T1)->getPointeeType(),
853 cast<PointerType>(T2)->getPointeeType()))
857 case Type::BlockPointer:
859 cast<BlockPointerType>(T1)->getPointeeType(),
860 cast<BlockPointerType>(T2)->getPointeeType()))
864 case Type::LValueReference:
865 case Type::RValueReference: {
866 const auto *Ref1 = cast<ReferenceType>(T1);
867 const auto *Ref2 = cast<ReferenceType>(T2);
868 if (Ref1->isSpelledAsLValue() != Ref2->isSpelledAsLValue())
870 if (Ref1->isInnerRef() != Ref2->isInnerRef())
873 Ref2->getPointeeTypeAsWritten()))
878 case Type::MemberPointer: {
879 const auto *MemPtr1 = cast<MemberPointerType>(T1);
880 const auto *MemPtr2 = cast<MemberPointerType>(T2);
882 MemPtr2->getPointeeType()))
890 case Type::ConstantArray: {
891 const auto *Array1 = cast<ConstantArrayType>(T1);
892 const auto *Array2 = cast<ConstantArrayType>(T2);
893 if (!llvm::APInt::isSameValue(Array1->getSize(), Array2->getSize()))
901 case Type::IncompleteArray:
903 cast<ArrayType>(T2)))
907 case Type::VariableArray: {
908 const auto *Array1 = cast<VariableArrayType>(T1);
909 const auto *Array2 = cast<VariableArrayType>(T2);
911 Array2->getSizeExpr()))
920 case Type::DependentSizedArray: {
921 const auto *Array1 = cast<DependentSizedArrayType>(T1);
922 const auto *Array2 = cast<DependentSizedArrayType>(T2);
924 Array2->getSizeExpr()))
933 case Type::DependentAddressSpace: {
934 const auto *DepAddressSpace1 = cast<DependentAddressSpaceType>(T1);
935 const auto *DepAddressSpace2 = cast<DependentAddressSpaceType>(T2);
937 DepAddressSpace2->getAddrSpaceExpr()))
940 DepAddressSpace2->getPointeeType()))
946 case Type::DependentSizedExtVector: {
947 const auto *Vec1 = cast<DependentSizedExtVectorType>(T1);
948 const auto *Vec2 = cast<DependentSizedExtVectorType>(T2);
950 Vec2->getSizeExpr()))
953 Vec2->getElementType()))
958 case Type::DependentVector: {
959 const auto *Vec1 = cast<DependentVectorType>(T1);
960 const auto *Vec2 = cast<DependentVectorType>(T2);
961 if (Vec1->getVectorKind() != Vec2->getVectorKind())
964 Vec2->getSizeExpr()))
967 Vec2->getElementType()))
973 case Type::ExtVector: {
974 const auto *Vec1 = cast<VectorType>(T1);
975 const auto *Vec2 = cast<VectorType>(T2);
977 Vec2->getElementType()))
979 if (Vec1->getNumElements() != Vec2->getNumElements())
981 if (Vec1->getVectorKind() != Vec2->getVectorKind())
986 case Type::DependentSizedMatrix: {
1001 case Type::ConstantMatrix: {
1014 case Type::FunctionProto: {
1015 const auto *Proto1 = cast<FunctionProtoType>(T1);
1016 const auto *Proto2 = cast<FunctionProtoType>(T2);
1018 if (Proto1->getNumParams() != Proto2->getNumParams())
1020 for (
unsigned I = 0, N = Proto1->getNumParams(); I != N; ++I) {
1022 Proto2->getParamType(I)))
1025 if (Proto1->isVariadic() != Proto2->isVariadic())
1028 if (Proto1->getMethodQuals() != Proto2->getMethodQuals())
1032 const auto *OrigProto1 =
1034 const auto *OrigProto2 =
1043 case Type::FunctionNoProto: {
1044 const auto *Function1 = cast<FunctionType>(T1);
1045 const auto *Function2 = cast<FunctionType>(T2);
1047 Function2->getReturnType()))
1050 Function2->getExtInfo()))
1055 case Type::UnresolvedUsing:
1057 cast<UnresolvedUsingType>(T1)->getDecl(),
1058 cast<UnresolvedUsingType>(T2)->getDecl()))
1062 case Type::Attributed:
1064 cast<AttributedType>(T1)->getModifiedType(),
1065 cast<AttributedType>(T2)->getModifiedType()))
1068 Context, cast<AttributedType>(T1)->getEquivalentType(),
1069 cast<AttributedType>(T2)->getEquivalentType()))
1073 case Type::CountAttributed:
1075 cast<CountAttributedType>(T1)->desugar(),
1076 cast<CountAttributedType>(T2)->desugar()))
1080 case Type::BTFTagAttributed:
1082 Context, cast<BTFTagAttributedType>(T1)->getWrappedType(),
1083 cast<BTFTagAttributedType>(T2)->getWrappedType()))
1089 cast<ParenType>(T2)->getInnerType()))
1093 case Type::MacroQualified:
1102 cast<UsingType>(T2)->getFoundDecl()))
1112 cast<TypedefType>(T2)->getDecl()) ||
1114 cast<TypedefType>(T2)->desugar()))
1118 case Type::TypeOfExpr:
1120 Context, cast<TypeOfExprType>(T1)->getUnderlyingExpr(),
1121 cast<TypeOfExprType>(T2)->getUnderlyingExpr()))
1127 cast<TypeOfType>(T1)->getUnmodifiedType(),
1128 cast<TypeOfType>(T2)->getUnmodifiedType()))
1132 case Type::UnaryTransform:
1139 case Type::Decltype:
1141 cast<DecltypeType>(T1)->getUnderlyingExpr(),
1142 cast<DecltypeType>(T2)->getUnderlyingExpr()))
1147 auto *Auto1 = cast<AutoType>(T1);
1148 auto *Auto2 = cast<AutoType>(T2);
1150 Auto2->getDeducedType()))
1152 if (Auto1->isConstrained() != Auto2->isConstrained())
1154 if (Auto1->isConstrained()) {
1155 if (Auto1->getTypeConstraintConcept() !=
1156 Auto2->getTypeConstraintConcept())
1159 Auto1->getTypeConstraintArguments(),
1160 Auto2->getTypeConstraintArguments()))
1166 case Type::DeducedTemplateSpecialization: {
1167 const auto *DT1 = cast<DeducedTemplateSpecializationType>(T1);
1168 const auto *DT2 = cast<DeducedTemplateSpecializationType>(T2);
1170 DT2->getTemplateName()))
1173 DT2->getDeducedType()))
1181 cast<TagType>(T2)->getDecl()))
1185 case Type::TemplateTypeParm: {
1186 const auto *Parm1 = cast<TemplateTypeParmType>(T1);
1187 const auto *Parm2 = cast<TemplateTypeParmType>(T2);
1188 if (!Context.IgnoreTemplateParmDepth &&
1189 Parm1->getDepth() != Parm2->getDepth())
1191 if (Parm1->getIndex() != Parm2->getIndex())
1193 if (Parm1->isParameterPack() != Parm2->isParameterPack())
1200 case Type::SubstTemplateTypeParm: {
1201 const auto *Subst1 = cast<SubstTemplateTypeParmType>(T1);
1202 const auto *Subst2 = cast<SubstTemplateTypeParmType>(T2);
1204 Subst2->getReplacementType()))
1207 Subst2->getAssociatedDecl()))
1209 if (Subst1->getIndex() != Subst2->getIndex())
1211 if (Subst1->getPackIndex() != Subst2->getPackIndex())
1216 case Type::SubstTemplateTypeParmPack: {
1217 const auto *Subst1 = cast<SubstTemplateTypeParmPackType>(T1);
1218 const auto *Subst2 = cast<SubstTemplateTypeParmPackType>(T2);
1220 Subst2->getAssociatedDecl()))
1222 if (Subst1->getIndex() != Subst2->getIndex())
1225 Subst2->getArgumentPack()))
1230 case Type::TemplateSpecialization: {
1231 const auto *Spec1 = cast<TemplateSpecializationType>(T1);
1232 const auto *Spec2 = cast<TemplateSpecializationType>(T2);
1234 Spec2->getTemplateName()))
1237 Spec2->template_arguments()))
1242 case Type::Elaborated: {
1243 const auto *Elab1 = cast<ElaboratedType>(T1);
1244 const auto *Elab2 = cast<ElaboratedType>(T2);
1248 if (Elab1->getKeyword() != Elab2->getKeyword())
1251 Elab2->getQualifier()))
1254 Elab2->getNamedType()))
1259 case Type::InjectedClassName: {
1260 const auto *Inj1 = cast<InjectedClassNameType>(T1);
1261 const auto *Inj2 = cast<InjectedClassNameType>(T2);
1263 Inj1->getInjectedSpecializationType(),
1264 Inj2->getInjectedSpecializationType()))
1269 case Type::DependentName: {
1270 const auto *Typename1 = cast<DependentNameType>(T1);
1271 const auto *Typename2 = cast<DependentNameType>(T2);
1273 Typename2->getQualifier()))
1276 Typename2->getIdentifier()))
1282 case Type::DependentTemplateSpecialization: {
1283 const auto *Spec1 = cast<DependentTemplateSpecializationType>(T1);
1284 const auto *Spec2 = cast<DependentTemplateSpecializationType>(T2);
1286 Spec2->getQualifier()))
1289 Spec2->getIdentifier()))
1292 Spec2->template_arguments()))
1297 case Type::PackExpansion:
1299 cast<PackExpansionType>(T1)->getPattern(),
1300 cast<PackExpansionType>(T2)->getPattern()))
1304 case Type::PackIndexing:
1306 cast<PackIndexingType>(T1)->getPattern(),
1307 cast<PackIndexingType>(T2)->getPattern()))
1309 cast<PackIndexingType>(T1)->getIndexExpr(),
1310 cast<PackIndexingType>(T2)->getIndexExpr()))
1314 case Type::ObjCInterface: {
1315 const auto *Iface1 = cast<ObjCInterfaceType>(T1);
1316 const auto *Iface2 = cast<ObjCInterfaceType>(T2);
1323 case Type::ObjCTypeParam: {
1324 const auto *Obj1 = cast<ObjCTypeParamType>(T1);
1325 const auto *Obj2 = cast<ObjCTypeParamType>(T2);
1329 if (Obj1->getNumProtocols() != Obj2->getNumProtocols())
1331 for (
unsigned I = 0, N = Obj1->getNumProtocols(); I != N; ++I) {
1333 Obj2->getProtocol(I)))
1339 case Type::ObjCObject: {
1340 const auto *Obj1 = cast<ObjCObjectType>(T1);
1341 const auto *Obj2 = cast<ObjCObjectType>(T2);
1343 Obj2->getBaseType()))
1345 if (Obj1->getNumProtocols() != Obj2->getNumProtocols())
1347 for (
unsigned I = 0, N = Obj1->getNumProtocols(); I != N; ++I) {
1349 Obj2->getProtocol(I)))
1355 case Type::ObjCObjectPointer: {
1356 const auto *Ptr1 = cast<ObjCObjectPointerType>(T1);
1357 const auto *Ptr2 = cast<ObjCObjectPointerType>(T2);
1359 Ptr2->getPointeeType()))
1366 cast<AtomicType>(T2)->getValueType()))
1372 cast<PipeType>(T2)->getElementType()))
1375 case Type::BitInt: {
1376 const auto *Int1 = cast<BitIntType>(T1);
1377 const auto *Int2 = cast<BitIntType>(T2);
1379 if (Int1->isUnsigned() != Int2->isUnsigned() ||
1380 Int1->getNumBits() != Int2->getNumBits())
1384 case Type::DependentBitInt: {
1385 const auto *Int1 = cast<DependentBitIntType>(T1);
1386 const auto *Int2 = cast<DependentBitIntType>(T2);
1388 if (Int1->isUnsigned() != Int2->isUnsigned() ||
1390 Int2->getNumBitsExpr()))
1440 if (Context.Complain) {
1442 Owner2->getLocation(),
1443 Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent))
1445 Context.Diag2(Field2->
getLocation(), diag::note_odr_field_name)
1447 Context.Diag1(Field1->
getLocation(), diag::note_odr_field_name)
1455 if (Context.Complain) {
1457 Owner2->getLocation(),
1458 Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent))
1460 Context.Diag2(Field2->
getLocation(), diag::note_odr_field)
1462 Context.Diag1(Field1->
getLocation(), diag::note_odr_field)
1487 bool PropertiesEqual =
1501 if (!PropertiesEqual)
1505 if (
auto *Constructor1 = dyn_cast<CXXConstructorDecl>(Method1)) {
1506 auto *Constructor2 = cast<CXXConstructorDecl>(Method2);
1507 if (!Constructor1->getExplicitSpecifier().isEquivalent(
1508 Constructor2->getExplicitSpecifier()))
1512 if (
auto *Conversion1 = dyn_cast<CXXConversionDecl>(Method1)) {
1513 auto *Conversion2 = cast<CXXConversionDecl>(Method2);
1514 if (!Conversion1->getExplicitSpecifier().isEquivalent(
1515 Conversion2->getExplicitSpecifier()))
1518 Conversion2->getConversionType()))
1542 "Must be called on lambda classes");
1573 if (
const auto *ND1 = dyn_cast<NamedDecl>(DC1)) {
1574 const auto *ND2 = cast<NamedDecl>(DC2);
1580 if (
auto *D1Spec = dyn_cast<ClassTemplateSpecializationDecl>(DC1)) {
1581 auto *D2Spec = dyn_cast<ClassTemplateSpecializationDecl>(DC2);
1597 if (
const TypedefNameDecl *TypedefName = D.getTypedefNameForAnonDecl())
1598 return TypedefName->getIdentifier();
1612 if (Context.Complain) {
1613 Context.Diag2(D2->
getLocation(), Context.getApplicableDiagnostic(
1614 diag::err_odr_tag_type_inconsistent))
1616 Context.Diag1(D1->
getLocation(), diag::note_odr_tag_kind_here)
1625 if (std::optional<unsigned> Index1 =
1627 if (std::optional<unsigned> Index2 =
1630 if (*Index1 != *Index2)
1644 const auto *Spec1 = dyn_cast<ClassTemplateSpecializationDecl>(D1);
1645 const auto *Spec2 = dyn_cast<ClassTemplateSpecializationDecl>(D2);
1646 if (Spec1 && Spec2) {
1649 Spec2->getSpecializedTemplate()))
1653 if (Spec1->getTemplateArgs().size() != Spec2->getTemplateArgs().size())
1656 for (
unsigned I = 0, N = Spec1->getTemplateArgs().size(); I != N; ++I)
1658 Spec2->getTemplateArgs().get(I)))
1663 else if (Spec1 || Spec2)
1679 if (Context.EqKind == StructuralEquivalenceKind::Minimal)
1688 if (
auto *D1CXX = dyn_cast<CXXRecordDecl>(D1)) {
1689 if (
auto *D2CXX = dyn_cast<CXXRecordDecl>(D2)) {
1690 if (D1CXX->hasExternalLexicalStorage() &&
1691 !D1CXX->isCompleteDefinition()) {
1695 if (D1CXX->isLambda() != D2CXX->isLambda())
1697 if (D1CXX->isLambda()) {
1702 if (D1CXX->getNumBases() != D2CXX->getNumBases()) {
1703 if (Context.Complain) {
1705 Context.getApplicableDiagnostic(
1706 diag::err_odr_tag_type_inconsistent))
1708 Context.Diag2(D2->
getLocation(), diag::note_odr_number_of_bases)
1709 << D2CXX->getNumBases();
1710 Context.Diag1(D1->
getLocation(), diag::note_odr_number_of_bases)
1711 << D1CXX->getNumBases();
1718 BaseEnd1 = D1CXX->bases_end(),
1719 Base2 = D2CXX->bases_begin();
1720 Base1 != BaseEnd1; ++Base1, ++Base2) {
1722 Base2->getType())) {
1723 if (Context.Complain) {
1725 Context.getApplicableDiagnostic(
1726 diag::err_odr_tag_type_inconsistent))
1728 Context.Diag2(Base2->getBeginLoc(), diag::note_odr_base)
1729 << Base2->getType() << Base2->getSourceRange();
1730 Context.Diag1(Base1->getBeginLoc(), diag::note_odr_base)
1731 << Base1->getType() << Base1->getSourceRange();
1737 if (Base1->isVirtual() != Base2->isVirtual()) {
1738 if (Context.Complain) {
1740 Context.getApplicableDiagnostic(
1741 diag::err_odr_tag_type_inconsistent))
1743 Context.Diag2(Base2->getBeginLoc(), diag::note_odr_virtual_base)
1744 << Base2->isVirtual() << Base2->getSourceRange();
1745 Context.Diag1(Base1->getBeginLoc(), diag::note_odr_base)
1746 << Base1->isVirtual() << Base1->getSourceRange();
1754 Friend2End = D2CXX->friend_end();
1756 Friend1End = D1CXX->friend_end();
1757 Friend1 != Friend1End; ++Friend1, ++Friend2) {
1758 if (Friend2 == Friend2End) {
1759 if (Context.Complain) {
1761 Context.getApplicableDiagnostic(
1762 diag::err_odr_tag_type_inconsistent))
1764 Context.Diag1((*Friend1)->getFriendLoc(), diag::note_odr_friend);
1765 Context.Diag2(D2->
getLocation(), diag::note_odr_missing_friend);
1771 if (Context.Complain) {
1773 Context.getApplicableDiagnostic(
1774 diag::err_odr_tag_type_inconsistent))
1776 Context.Diag1((*Friend1)->getFriendLoc(), diag::note_odr_friend);
1777 Context.Diag2((*Friend2)->getFriendLoc(), diag::note_odr_friend);
1783 if (Friend2 != Friend2End) {
1784 if (Context.Complain) {
1786 Context.getApplicableDiagnostic(
1787 diag::err_odr_tag_type_inconsistent))
1789 Context.Diag2((*Friend2)->getFriendLoc(), diag::note_odr_friend);
1790 Context.Diag1(D1->
getLocation(), diag::note_odr_missing_friend);
1794 }
else if (D1CXX->getNumBases() > 0) {
1795 if (Context.Complain) {
1797 Context.getApplicableDiagnostic(
1798 diag::err_odr_tag_type_inconsistent))
1801 Context.Diag1(Base1->
getBeginLoc(), diag::note_odr_base)
1803 Context.Diag2(D2->
getLocation(), diag::note_odr_missing_base);
1815 Field1 != Field1End; ++Field1, ++Field2) {
1816 if (Field2 == Field2End) {
1817 if (Context.Complain) {
1819 Context.getApplicableDiagnostic(
1820 diag::err_odr_tag_type_inconsistent))
1822 Context.Diag1(Field1->getLocation(), diag::note_odr_field)
1823 << Field1->getDeclName() << Field1->getType();
1824 Context.Diag2(D2->
getLocation(), diag::note_odr_missing_field);
1833 if (Field2 != Field2End) {
1834 if (Context.Complain) {
1835 Context.Diag2(D2->
getLocation(), Context.getApplicableDiagnostic(
1836 diag::err_odr_tag_type_inconsistent))
1838 Context.Diag2(Field2->getLocation(), diag::note_odr_field)
1839 << Field2->getDeclName() << Field2->getType();
1840 Context.Diag1(D1->
getLocation(), diag::note_odr_missing_field);
1851 const llvm::APSInt &FromVal = D1->
getInitVal();
1852 const llvm::APSInt &ToVal = D2->
getInitVal();
1853 if (FromVal.isSigned() != ToVal.isSigned())
1855 if (FromVal.getBitWidth() != ToVal.getBitWidth())
1857 if (FromVal != ToVal)
1886 EC1 != EC1End; ++EC1, ++EC2) {
1887 if (EC2 == EC2End) {
1888 if (Context.Complain) {
1890 Context.getApplicableDiagnostic(
1891 diag::err_odr_tag_type_inconsistent))
1893 Context.Diag1(EC1->getLocation(), diag::note_odr_enumerator)
1894 << EC1->getDeclName() <<
toString(EC1->getInitVal(), 10);
1895 Context.Diag2(D2->
getLocation(), diag::note_odr_missing_enumerator);
1900 llvm::APSInt Val1 = EC1->getInitVal();
1901 llvm::APSInt Val2 = EC2->getInitVal();
1902 if (!llvm::APSInt::isSameValue(Val1, Val2) ||
1904 if (Context.Complain) {
1906 Context.getApplicableDiagnostic(
1907 diag::err_odr_tag_type_inconsistent))
1909 Context.Diag2(EC2->getLocation(), diag::note_odr_enumerator)
1910 << EC2->getDeclName() <<
toString(EC2->getInitVal(), 10);
1911 Context.Diag1(EC1->getLocation(), diag::note_odr_enumerator)
1912 << EC1->getDeclName() <<
toString(EC1->getInitVal(), 10);
1918 if (EC2 != EC2End) {
1919 if (Context.Complain) {
1920 Context.Diag2(D2->
getLocation(), Context.getApplicableDiagnostic(
1921 diag::err_odr_tag_type_inconsistent))
1923 Context.Diag2(EC2->getLocation(), diag::note_odr_enumerator)
1924 << EC2->getDeclName() <<
toString(EC2->getInitVal(), 10);
1925 Context.Diag1(D1->
getLocation(), diag::note_odr_missing_enumerator);
1936 if (Params1->
size() != Params2->
size()) {
1937 if (Context.Complain) {
1939 Context.getApplicableDiagnostic(
1940 diag::err_odr_different_num_template_parameters))
1941 << Params1->
size() << Params2->
size();
1943 diag::note_odr_template_parameter_list);
1948 for (
unsigned I = 0, N = Params1->
size(); I != N; ++I) {
1950 if (Context.Complain) {
1952 Context.getApplicableDiagnostic(
1953 diag::err_odr_different_template_parameter_kind));
1955 diag::note_odr_template_parameter_here);
1972 if (Context.Complain) {
1974 Context.getApplicableDiagnostic(
1975 diag::err_odr_parameter_pack_non_pack))
1977 Context.Diag1(D1->
getLocation(), diag::note_odr_parameter_pack_non_pack)
1990 if (Context.Complain) {
1992 Context.getApplicableDiagnostic(
1993 diag::err_odr_parameter_pack_non_pack))
1995 Context.Diag1(D1->
getLocation(), diag::note_odr_parameter_pack_non_pack)
2003 if (Context.Complain) {
2005 Context.getApplicableDiagnostic(
2006 diag::err_odr_non_type_parameter_type_inconsistent))
2008 Context.Diag1(D1->
getLocation(), diag::note_odr_value_here)
2021 if (Context.Complain) {
2023 Context.getApplicableDiagnostic(
2024 diag::err_odr_parameter_pack_non_pack))
2026 Context.Diag1(D1->
getLocation(), diag::note_odr_parameter_pack_non_pack)
2147 cast<FieldDecl>(D2), Owner2Type);
2160 bool PropertiesEqual =
2164 if (!PropertiesEqual)
2171 if (NumArgs != Selector2.getNumArgs())
2175 unsigned SlotsToCheck = NumArgs > 0 ? NumArgs : 1;
2176 for (
unsigned I = 0; I < SlotsToCheck; ++I) {
2178 Selector2.getIdentifierInfoForSlot(I)))
2188 "Same number of arguments should be already enforced in Selector checks");
2194 (ParamT1 != ParamT1End) && (ParamT2 != ParamT2End);
2195 ++ParamT1, ++ParamT2) {
2211 if ((!Intf1 || !Intf2) && (Intf1 != Intf2))
2223 Protocol1 != Protocol1End; ++Protocol1, ++Protocol2) {
2224 if (Protocol2 == Protocol2End)
2227 (*Protocol2)->getIdentifier()))
2230 if (Protocol2 != Protocol2End)
2240 Ivar1 != Ivar1End; ++Ivar1, ++Ivar2) {
2241 if (Ivar2 == Ivar2End)
2246 if (Ivar2 != Ivar2End)
2254 Method1 != Method1End; ++Method1, ++Method2) {
2255 if (Method2 == Method2End)
2260 if (Method2 != Method2End)
2273 std::pair<Decl *, Decl *>
P{D1, D2};
2277 if (Context.NonEquivalentDecls.count(
P))
2283 bool Inserted = Context.VisitedDecls.insert(
P).second;
2287 Context.DeclsToCheck.push(
P);
2294 assert(
Complain &&
"Not allowed to complain");
2303 assert(
Complain &&
"Not allowed to complain");
2310std::optional<unsigned>
2315 const auto *Owner = dyn_cast<RecordDecl>(Anon->
getDeclContext());
2317 return std::nullopt;
2320 for (
const auto *D : Owner->noload_decls()) {
2321 const auto *F = dyn_cast<FieldDecl>(D);
2325 if (F->isAnonymousStructOrUnion()) {
2336 while (
const auto *ElabType = dyn_cast<ElaboratedType>(FieldType))
2337 FieldType = ElabType->getNamedType();
2339 if (
const auto *RecType = dyn_cast<RecordType>(FieldType)) {
2340 const RecordDecl *RecDecl = RecType->getDecl();
2354 unsigned ErrorDiagnostic) {
2356 return ErrorDiagnostic;
2358 switch (ErrorDiagnostic) {
2359 case diag::err_odr_variable_type_inconsistent:
2360 return diag::warn_odr_variable_type_inconsistent;
2361 case diag::err_odr_variable_multiple_def:
2362 return diag::warn_odr_variable_multiple_def;
2363 case diag::err_odr_function_type_inconsistent:
2364 return diag::warn_odr_function_type_inconsistent;
2365 case diag::err_odr_tag_type_inconsistent:
2366 return diag::warn_odr_tag_type_inconsistent;
2367 case diag::err_odr_field_type_inconsistent:
2368 return diag::warn_odr_field_type_inconsistent;
2369 case diag::err_odr_ivar_type_inconsistent:
2370 return diag::warn_odr_ivar_type_inconsistent;
2371 case diag::err_odr_objc_superclass_inconsistent:
2372 return diag::warn_odr_objc_superclass_inconsistent;
2373 case diag::err_odr_objc_method_result_type_inconsistent:
2374 return diag::warn_odr_objc_method_result_type_inconsistent;
2375 case diag::err_odr_objc_method_num_params_inconsistent:
2376 return diag::warn_odr_objc_method_num_params_inconsistent;
2377 case diag::err_odr_objc_method_param_type_inconsistent:
2378 return diag::warn_odr_objc_method_param_type_inconsistent;
2379 case diag::err_odr_objc_method_variadic_inconsistent:
2380 return diag::warn_odr_objc_method_variadic_inconsistent;
2381 case diag::err_odr_objc_property_type_inconsistent:
2382 return diag::warn_odr_objc_property_type_inconsistent;
2383 case diag::err_odr_objc_property_impl_kind_inconsistent:
2384 return diag::warn_odr_objc_property_impl_kind_inconsistent;
2385 case diag::err_odr_objc_synthesize_ivar_inconsistent:
2386 return diag::warn_odr_objc_synthesize_ivar_inconsistent;
2387 case diag::err_odr_different_num_template_parameters:
2388 return diag::warn_odr_different_num_template_parameters;
2389 case diag::err_odr_different_template_parameter_kind:
2390 return diag::warn_odr_different_template_parameter_kind;
2391 case diag::err_odr_parameter_pack_non_pack:
2392 return diag::warn_odr_parameter_pack_non_pack;
2393 case diag::err_odr_non_type_parameter_type_inconsistent:
2394 return diag::warn_odr_non_type_parameter_type_inconsistent;
2396 llvm_unreachable(
"Diagnostic kind not handled in preceding switch");
2436bool StructuralEquivalenceContext::CheckCommonEquivalence(
Decl *D1,
Decl *D2) {
2440 if ((Template1 !=
nullptr) != (Template2 !=
nullptr))
2450bool StructuralEquivalenceContext::CheckKindSpecificEquivalence(
2460#define ABSTRACT_DECL(DECL)
2461#define DECL(DERIVED, BASE) \
2462 case Decl::Kind::DERIVED: \
2463 return ::IsStructurallyEquivalent(*this, static_cast<DERIVED##Decl *>(D1), \
2464 static_cast<DERIVED##Decl *>(D2));
2465#include "clang/AST/DeclNodes.inc"
2470bool StructuralEquivalenceContext::Finish() {
2477 Decl *D2 =
P.second;
2480 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.
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 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.
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() 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.
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)
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.