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))
226 bool IsStmtEquivalent(
const Expr *E1,
const Expr *E2) {
243 std::optional<TypeSourceInfo *> Child1 = std::get<0>(Pair);
244 std::optional<TypeSourceInfo *> Child2 = std::get<1>(Pair);
246 if (!Child1 || !Child2)
250 (*Child2)->getType()))
278 bool IsStmtEquivalent(
const Stmt *S1,
const Stmt *S2) {
return true; }
315 std::optional<TypeSourceInfo *> Child1 = std::get<0>(Pair);
316 std::optional<TypeSourceInfo *> Child2 = std::get<1>(Pair);
318 if (!Child1 || !Child2)
322 (*Child2)->getType()))
370 bool TraverseStmt(
const Stmt *S1,
const Stmt *S2) {
return true; }
377#define STMT(CLASS, PARENT) \
378 bool TraverseStmt(const CLASS *S1, const CLASS *S2) { \
379 if (!TraverseStmt(static_cast<const PARENT *>(S1), \
380 static_cast<const PARENT *>(S2))) \
382 return IsStmtEquivalent(S1, S2); \
384#include "clang/AST/StmtNodes.inc"
392 bool IsEquivalent(
const Stmt *S1,
const Stmt *S2) {
403 llvm_unreachable(
"Can't traverse NoStmtClass");
404#define STMT(CLASS, PARENT) \
405 case Stmt::StmtClass::CLASS##Class: \
406 return TraverseStmt(static_cast<const CLASS *>(S1), \
407 static_cast<const CLASS *>(S2));
408#define ABSTRACT_STMT(S)
409#include "clang/AST/StmtNodes.inc"
411 llvm_unreachable(
"Invalid statement kind");
423 StmtComparer Comparer(Context);
424 if (!Comparer.IsEquivalent(S1, S2))
429 std::optional<const Stmt *> Child1 = std::get<0>(Pair);
430 std::optional<const Stmt *> Child2 = std::get<1>(Pair);
433 if (!Child1 || !Child2)
444 if (!Name1 || !Name2)
445 return Name1 == Name2;
459 if ((
bool)Prefix1 != (
bool)Prefix2)
494 if (TemplateDeclN1 && TemplateDeclN2) {
500 }
else if (TemplateDeclN1 || TemplateDeclN2)
512 E1 = OS1->
end(), E2 = OS2->end();
513 for (; I1 != E1 && I2 != E2; ++I1, ++I2)
516 return I1 == E1 && I2 == E2;
529 DN2->getQualifier()))
533 DN2->getIdentifier());
544 P2->getArgumentPack()) &&
546 P2->getAssociatedDecl()) &&
612 llvm_unreachable(
"Invalid template argument kind");
619 if (Args1.size() != Args2.size())
621 for (
unsigned I = 0, N = Args1.size(); I != N; ++I) {
717 if (!Context.StrictTypeSpelling) {
734 TC = Type::FunctionNoProto;
737 TC = Type::FunctionNoProto;
745 if (cast<BuiltinType>(T1)->
getKind() != cast<BuiltinType>(T2)->
getKind())
751 cast<ComplexType>(T1)->getElementType(),
752 cast<ComplexType>(T2)->getElementType()))
759 cast<AdjustedType>(T1)->getOriginalType(),
760 cast<AdjustedType>(T2)->getOriginalType()))
766 cast<PointerType>(T1)->getPointeeType(),
767 cast<PointerType>(T2)->getPointeeType()))
771 case Type::BlockPointer:
773 cast<BlockPointerType>(T1)->getPointeeType(),
774 cast<BlockPointerType>(T2)->getPointeeType()))
778 case Type::LValueReference:
779 case Type::RValueReference: {
780 const auto *Ref1 = cast<ReferenceType>(T1);
781 const auto *Ref2 = cast<ReferenceType>(T2);
782 if (Ref1->isSpelledAsLValue() != Ref2->isSpelledAsLValue())
784 if (Ref1->isInnerRef() != Ref2->isInnerRef())
787 Ref2->getPointeeTypeAsWritten()))
792 case Type::MemberPointer: {
793 const auto *MemPtr1 = cast<MemberPointerType>(T1);
794 const auto *MemPtr2 = cast<MemberPointerType>(T2);
796 MemPtr2->getPointeeType()))
804 case Type::ConstantArray: {
805 const auto *Array1 = cast<ConstantArrayType>(T1);
806 const auto *Array2 = cast<ConstantArrayType>(T2);
807 if (!llvm::APInt::isSameValue(Array1->getSize(), Array2->getSize()))
815 case Type::IncompleteArray:
817 cast<ArrayType>(T2)))
821 case Type::VariableArray: {
822 const auto *Array1 = cast<VariableArrayType>(T1);
823 const auto *Array2 = cast<VariableArrayType>(T2);
825 Array2->getSizeExpr()))
834 case Type::DependentSizedArray: {
835 const auto *Array1 = cast<DependentSizedArrayType>(T1);
836 const auto *Array2 = cast<DependentSizedArrayType>(T2);
838 Array2->getSizeExpr()))
847 case Type::DependentAddressSpace: {
848 const auto *DepAddressSpace1 = cast<DependentAddressSpaceType>(T1);
849 const auto *DepAddressSpace2 = cast<DependentAddressSpaceType>(T2);
851 DepAddressSpace2->getAddrSpaceExpr()))
854 DepAddressSpace2->getPointeeType()))
860 case Type::DependentSizedExtVector: {
861 const auto *Vec1 = cast<DependentSizedExtVectorType>(T1);
862 const auto *Vec2 = cast<DependentSizedExtVectorType>(T2);
864 Vec2->getSizeExpr()))
867 Vec2->getElementType()))
872 case Type::DependentVector: {
873 const auto *Vec1 = cast<DependentVectorType>(T1);
874 const auto *Vec2 = cast<DependentVectorType>(T2);
875 if (Vec1->getVectorKind() != Vec2->getVectorKind())
878 Vec2->getSizeExpr()))
881 Vec2->getElementType()))
887 case Type::ExtVector: {
888 const auto *Vec1 = cast<VectorType>(T1);
889 const auto *Vec2 = cast<VectorType>(T2);
891 Vec2->getElementType()))
893 if (Vec1->getNumElements() != Vec2->getNumElements())
895 if (Vec1->getVectorKind() != Vec2->getVectorKind())
900 case Type::DependentSizedMatrix: {
915 case Type::ConstantMatrix: {
928 case Type::FunctionProto: {
929 const auto *Proto1 = cast<FunctionProtoType>(T1);
930 const auto *Proto2 = cast<FunctionProtoType>(T2);
932 if (Proto1->getNumParams() != Proto2->getNumParams())
934 for (
unsigned I = 0, N = Proto1->getNumParams(); I != N; ++I) {
936 Proto2->getParamType(I)))
939 if (Proto1->isVariadic() != Proto2->isVariadic())
942 if (Proto1->getMethodQuals() != Proto2->getMethodQuals())
946 const auto *OrigProto1 =
948 const auto *OrigProto2 =
957 case Type::FunctionNoProto: {
958 const auto *Function1 = cast<FunctionType>(T1);
959 const auto *Function2 = cast<FunctionType>(T2);
961 Function2->getReturnType()))
964 Function2->getExtInfo()))
969 case Type::UnresolvedUsing:
971 cast<UnresolvedUsingType>(T1)->getDecl(),
972 cast<UnresolvedUsingType>(T2)->getDecl()))
976 case Type::Attributed:
978 cast<AttributedType>(T1)->getModifiedType(),
979 cast<AttributedType>(T2)->getModifiedType()))
982 Context, cast<AttributedType>(T1)->getEquivalentType(),
983 cast<AttributedType>(T2)->getEquivalentType()))
987 case Type::BTFTagAttributed:
989 Context, cast<BTFTagAttributedType>(T1)->getWrappedType(),
990 cast<BTFTagAttributedType>(T2)->getWrappedType()))
996 cast<ParenType>(T2)->getInnerType()))
1000 case Type::MacroQualified:
1009 cast<UsingType>(T2)->getFoundDecl()))
1019 cast<TypedefType>(T2)->getDecl()) ||
1021 cast<TypedefType>(T2)->desugar()))
1025 case Type::TypeOfExpr:
1027 Context, cast<TypeOfExprType>(T1)->getUnderlyingExpr(),
1028 cast<TypeOfExprType>(T2)->getUnderlyingExpr()))
1034 cast<TypeOfType>(T1)->getUnmodifiedType(),
1035 cast<TypeOfType>(T2)->getUnmodifiedType()))
1039 case Type::UnaryTransform:
1046 case Type::Decltype:
1048 cast<DecltypeType>(T1)->getUnderlyingExpr(),
1049 cast<DecltypeType>(T2)->getUnderlyingExpr()))
1054 auto *Auto1 = cast<AutoType>(T1);
1055 auto *Auto2 = cast<AutoType>(T2);
1057 Auto2->getDeducedType()))
1059 if (Auto1->isConstrained() != Auto2->isConstrained())
1061 if (Auto1->isConstrained()) {
1062 if (Auto1->getTypeConstraintConcept() !=
1063 Auto2->getTypeConstraintConcept())
1066 Auto1->getTypeConstraintArguments(),
1067 Auto2->getTypeConstraintArguments()))
1073 case Type::DeducedTemplateSpecialization: {
1074 const auto *DT1 = cast<DeducedTemplateSpecializationType>(T1);
1075 const auto *DT2 = cast<DeducedTemplateSpecializationType>(T2);
1077 DT2->getTemplateName()))
1080 DT2->getDeducedType()))
1088 cast<TagType>(T2)->getDecl()))
1092 case Type::TemplateTypeParm: {
1093 const auto *Parm1 = cast<TemplateTypeParmType>(T1);
1094 const auto *Parm2 = cast<TemplateTypeParmType>(T2);
1095 if (Parm1->getDepth() != Parm2->getDepth())
1097 if (Parm1->getIndex() != Parm2->getIndex())
1099 if (Parm1->isParameterPack() != Parm2->isParameterPack())
1106 case Type::SubstTemplateTypeParm: {
1107 const auto *Subst1 = cast<SubstTemplateTypeParmType>(T1);
1108 const auto *Subst2 = cast<SubstTemplateTypeParmType>(T2);
1110 Subst2->getReplacementType()))
1113 Subst2->getAssociatedDecl()))
1115 if (Subst1->getIndex() != Subst2->getIndex())
1117 if (Subst1->getPackIndex() != Subst2->getPackIndex())
1122 case Type::SubstTemplateTypeParmPack: {
1123 const auto *Subst1 = cast<SubstTemplateTypeParmPackType>(T1);
1124 const auto *Subst2 = cast<SubstTemplateTypeParmPackType>(T2);
1126 Subst2->getAssociatedDecl()))
1128 if (Subst1->getIndex() != Subst2->getIndex())
1131 Subst2->getArgumentPack()))
1136 case Type::TemplateSpecialization: {
1137 const auto *Spec1 = cast<TemplateSpecializationType>(T1);
1138 const auto *Spec2 = cast<TemplateSpecializationType>(T2);
1140 Spec2->getTemplateName()))
1143 Spec2->template_arguments()))
1148 case Type::Elaborated: {
1149 const auto *Elab1 = cast<ElaboratedType>(T1);
1150 const auto *Elab2 = cast<ElaboratedType>(T2);
1152 if (Elab1->getKeyword() != Elab2->getKeyword())
1155 Elab2->getQualifier()))
1158 Elab2->getNamedType()))
1163 case Type::InjectedClassName: {
1164 const auto *Inj1 = cast<InjectedClassNameType>(T1);
1165 const auto *Inj2 = cast<InjectedClassNameType>(T2);
1167 Inj1->getInjectedSpecializationType(),
1168 Inj2->getInjectedSpecializationType()))
1173 case Type::DependentName: {
1174 const auto *Typename1 = cast<DependentNameType>(T1);
1175 const auto *Typename2 = cast<DependentNameType>(T2);
1177 Typename2->getQualifier()))
1180 Typename2->getIdentifier()))
1186 case Type::DependentTemplateSpecialization: {
1187 const auto *Spec1 = cast<DependentTemplateSpecializationType>(T1);
1188 const auto *Spec2 = cast<DependentTemplateSpecializationType>(T2);
1190 Spec2->getQualifier()))
1193 Spec2->getIdentifier()))
1196 Spec2->template_arguments()))
1201 case Type::PackExpansion:
1203 cast<PackExpansionType>(T1)->getPattern(),
1204 cast<PackExpansionType>(T2)->getPattern()))
1208 case Type::ObjCInterface: {
1209 const auto *Iface1 = cast<ObjCInterfaceType>(T1);
1210 const auto *Iface2 = cast<ObjCInterfaceType>(T2);
1217 case Type::ObjCTypeParam: {
1218 const auto *Obj1 = cast<ObjCTypeParamType>(T1);
1219 const auto *Obj2 = cast<ObjCTypeParamType>(T2);
1223 if (Obj1->getNumProtocols() != Obj2->getNumProtocols())
1225 for (
unsigned I = 0, N = Obj1->getNumProtocols(); I != N; ++I) {
1227 Obj2->getProtocol(I)))
1233 case Type::ObjCObject: {
1234 const auto *Obj1 = cast<ObjCObjectType>(T1);
1235 const auto *Obj2 = cast<ObjCObjectType>(T2);
1237 Obj2->getBaseType()))
1239 if (Obj1->getNumProtocols() != Obj2->getNumProtocols())
1241 for (
unsigned I = 0, N = Obj1->getNumProtocols(); I != N; ++I) {
1243 Obj2->getProtocol(I)))
1249 case Type::ObjCObjectPointer: {
1250 const auto *Ptr1 = cast<ObjCObjectPointerType>(T1);
1251 const auto *Ptr2 = cast<ObjCObjectPointerType>(T2);
1253 Ptr2->getPointeeType()))
1260 cast<AtomicType>(T2)->getValueType()))
1266 cast<PipeType>(T2)->getElementType()))
1269 case Type::BitInt: {
1270 const auto *Int1 = cast<BitIntType>(T1);
1271 const auto *Int2 = cast<BitIntType>(T2);
1273 if (Int1->isUnsigned() != Int2->isUnsigned() ||
1274 Int1->getNumBits() != Int2->getNumBits())
1278 case Type::DependentBitInt: {
1279 const auto *Int1 = cast<DependentBitIntType>(T1);
1280 const auto *Int2 = cast<DependentBitIntType>(T2);
1282 if (Int1->isUnsigned() != Int2->isUnsigned() ||
1284 Int2->getNumBitsExpr()))
1312 if (Context.Complain) {
1314 Owner2->getLocation(),
1315 Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent))
1317 Context.Diag2(Field2->
getLocation(), diag::note_odr_field_name)
1319 Context.Diag1(Field1->
getLocation(), diag::note_odr_field_name)
1327 if (Context.Complain) {
1329 Owner2->getLocation(),
1330 Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent))
1332 Context.Diag2(Field2->
getLocation(), diag::note_odr_field)
1334 Context.Diag1(Field1->
getLocation(), diag::note_odr_field)
1359 bool PropertiesEqual =
1371 if (!PropertiesEqual)
1375 if (
auto *Constructor1 = dyn_cast<CXXConstructorDecl>(Method1)) {
1376 auto *Constructor2 = cast<CXXConstructorDecl>(Method2);
1377 if (!Constructor1->getExplicitSpecifier().isEquivalent(
1378 Constructor2->getExplicitSpecifier()))
1382 if (
auto *Conversion1 = dyn_cast<CXXConversionDecl>(Method1)) {
1383 auto *Conversion2 = cast<CXXConversionDecl>(Method2);
1384 if (!Conversion1->getExplicitSpecifier().isEquivalent(
1385 Conversion2->getExplicitSpecifier()))
1388 Conversion2->getConversionType()))
1412 "Must be called on lambda classes");
1442 if (
const auto *ND1 = dyn_cast<NamedDecl>(DC1)) {
1443 const auto *ND2 = cast<NamedDecl>(DC2);
1471 if (Context.Complain) {
1472 Context.Diag2(D2->
getLocation(), Context.getApplicableDiagnostic(
1473 diag::err_odr_tag_type_inconsistent))
1475 Context.Diag1(D1->
getLocation(), diag::note_odr_tag_kind_here)
1484 if (std::optional<unsigned> Index1 =
1486 if (std::optional<unsigned> Index2 =
1489 if (*Index1 != *Index2)
1503 const auto *Spec1 = dyn_cast<ClassTemplateSpecializationDecl>(D1);
1504 const auto *Spec2 = dyn_cast<ClassTemplateSpecializationDecl>(D2);
1505 if (Spec1 && Spec2) {
1508 Spec2->getSpecializedTemplate()))
1512 if (Spec1->getTemplateArgs().size() != Spec2->getTemplateArgs().size())
1515 for (
unsigned I = 0, N = Spec1->getTemplateArgs().size(); I != N; ++I)
1517 Spec2->getTemplateArgs().get(I)))
1522 else if (Spec1 || Spec2)
1538 if (Context.EqKind == StructuralEquivalenceKind::Minimal)
1547 if (
auto *D1CXX = dyn_cast<CXXRecordDecl>(D1)) {
1548 if (
auto *D2CXX = dyn_cast<CXXRecordDecl>(D2)) {
1549 if (D1CXX->hasExternalLexicalStorage() &&
1550 !D1CXX->isCompleteDefinition()) {
1554 if (D1CXX->isLambda() != D2CXX->isLambda())
1556 if (D1CXX->isLambda()) {
1561 if (D1CXX->getNumBases() != D2CXX->getNumBases()) {
1562 if (Context.Complain) {
1564 Context.getApplicableDiagnostic(
1565 diag::err_odr_tag_type_inconsistent))
1567 Context.Diag2(D2->
getLocation(), diag::note_odr_number_of_bases)
1568 << D2CXX->getNumBases();
1569 Context.Diag1(D1->
getLocation(), diag::note_odr_number_of_bases)
1570 << D1CXX->getNumBases();
1577 BaseEnd1 = D1CXX->bases_end(),
1578 Base2 = D2CXX->bases_begin();
1579 Base1 != BaseEnd1; ++Base1, ++Base2) {
1581 Base2->getType())) {
1582 if (Context.Complain) {
1584 Context.getApplicableDiagnostic(
1585 diag::err_odr_tag_type_inconsistent))
1587 Context.Diag2(Base2->getBeginLoc(), diag::note_odr_base)
1588 << Base2->getType() << Base2->getSourceRange();
1589 Context.Diag1(Base1->getBeginLoc(), diag::note_odr_base)
1590 << Base1->getType() << Base1->getSourceRange();
1596 if (Base1->isVirtual() != Base2->isVirtual()) {
1597 if (Context.Complain) {
1599 Context.getApplicableDiagnostic(
1600 diag::err_odr_tag_type_inconsistent))
1602 Context.Diag2(Base2->getBeginLoc(), diag::note_odr_virtual_base)
1603 << Base2->isVirtual() << Base2->getSourceRange();
1604 Context.Diag1(Base1->getBeginLoc(), diag::note_odr_base)
1605 << Base1->isVirtual() << Base1->getSourceRange();
1613 Friend2End = D2CXX->friend_end();
1615 Friend1End = D1CXX->friend_end();
1616 Friend1 != Friend1End; ++Friend1, ++Friend2) {
1617 if (Friend2 == Friend2End) {
1618 if (Context.Complain) {
1620 Context.getApplicableDiagnostic(
1621 diag::err_odr_tag_type_inconsistent))
1623 Context.Diag1((*Friend1)->getFriendLoc(), diag::note_odr_friend);
1624 Context.Diag2(D2->
getLocation(), diag::note_odr_missing_friend);
1630 if (Context.Complain) {
1632 Context.getApplicableDiagnostic(
1633 diag::err_odr_tag_type_inconsistent))
1635 Context.Diag1((*Friend1)->getFriendLoc(), diag::note_odr_friend);
1636 Context.Diag2((*Friend2)->getFriendLoc(), diag::note_odr_friend);
1642 if (Friend2 != Friend2End) {
1643 if (Context.Complain) {
1645 Context.getApplicableDiagnostic(
1646 diag::err_odr_tag_type_inconsistent))
1648 Context.Diag2((*Friend2)->getFriendLoc(), diag::note_odr_friend);
1649 Context.Diag1(D1->
getLocation(), diag::note_odr_missing_friend);
1653 }
else if (D1CXX->getNumBases() > 0) {
1654 if (Context.Complain) {
1656 Context.getApplicableDiagnostic(
1657 diag::err_odr_tag_type_inconsistent))
1660 Context.Diag1(Base1->
getBeginLoc(), diag::note_odr_base)
1662 Context.Diag2(D2->
getLocation(), diag::note_odr_missing_base);
1674 Field1 != Field1End; ++Field1, ++Field2) {
1675 if (Field2 == Field2End) {
1676 if (Context.Complain) {
1678 Context.getApplicableDiagnostic(
1679 diag::err_odr_tag_type_inconsistent))
1681 Context.Diag1(Field1->getLocation(), diag::note_odr_field)
1682 << Field1->getDeclName() << Field1->getType();
1683 Context.Diag2(D2->
getLocation(), diag::note_odr_missing_field);
1692 if (Field2 != Field2End) {
1693 if (Context.Complain) {
1694 Context.Diag2(D2->
getLocation(), Context.getApplicableDiagnostic(
1695 diag::err_odr_tag_type_inconsistent))
1697 Context.Diag2(Field2->getLocation(), diag::note_odr_field)
1698 << Field2->getDeclName() << Field2->getType();
1699 Context.Diag1(D1->
getLocation(), diag::note_odr_missing_field);
1710 const llvm::APSInt &FromVal = D1->
getInitVal();
1711 const llvm::APSInt &ToVal = D2->
getInitVal();
1712 if (FromVal.isSigned() != ToVal.isSigned())
1714 if (FromVal.getBitWidth() != ToVal.getBitWidth())
1716 if (FromVal != ToVal)
1752 EC1 != EC1End; ++EC1, ++EC2) {
1753 if (EC2 == EC2End) {
1754 if (Context.Complain) {
1756 Context.getApplicableDiagnostic(
1757 diag::err_odr_tag_type_inconsistent))
1759 Context.Diag1(EC1->getLocation(), diag::note_odr_enumerator)
1760 << EC1->getDeclName() <<
toString(EC1->getInitVal(), 10);
1761 Context.Diag2(D2->
getLocation(), diag::note_odr_missing_enumerator);
1766 llvm::APSInt Val1 = EC1->getInitVal();
1767 llvm::APSInt Val2 = EC2->getInitVal();
1768 if (!llvm::APSInt::isSameValue(Val1, Val2) ||
1770 if (Context.Complain) {
1772 Context.getApplicableDiagnostic(
1773 diag::err_odr_tag_type_inconsistent))
1775 Context.Diag2(EC2->getLocation(), diag::note_odr_enumerator)
1776 << EC2->getDeclName() <<
toString(EC2->getInitVal(), 10);
1777 Context.Diag1(EC1->getLocation(), diag::note_odr_enumerator)
1778 << EC1->getDeclName() <<
toString(EC1->getInitVal(), 10);
1784 if (EC2 != EC2End) {
1785 if (Context.Complain) {
1786 Context.Diag2(D2->
getLocation(), Context.getApplicableDiagnostic(
1787 diag::err_odr_tag_type_inconsistent))
1789 Context.Diag2(EC2->getLocation(), diag::note_odr_enumerator)
1790 << EC2->getDeclName() <<
toString(EC2->getInitVal(), 10);
1791 Context.Diag1(D1->
getLocation(), diag::note_odr_missing_enumerator);
1802 if (Params1->
size() != Params2->
size()) {
1803 if (Context.Complain) {
1805 Context.getApplicableDiagnostic(
1806 diag::err_odr_different_num_template_parameters))
1807 << Params1->
size() << Params2->
size();
1809 diag::note_odr_template_parameter_list);
1814 for (
unsigned I = 0, N = Params1->
size(); I != N; ++I) {
1816 if (Context.Complain) {
1818 Context.getApplicableDiagnostic(
1819 diag::err_odr_different_template_parameter_kind));
1821 diag::note_odr_template_parameter_here);
1838 if (Context.Complain) {
1840 Context.getApplicableDiagnostic(
1841 diag::err_odr_parameter_pack_non_pack))
1843 Context.Diag1(D1->
getLocation(), diag::note_odr_parameter_pack_non_pack)
1856 if (Context.Complain) {
1858 Context.getApplicableDiagnostic(
1859 diag::err_odr_parameter_pack_non_pack))
1861 Context.Diag1(D1->
getLocation(), diag::note_odr_parameter_pack_non_pack)
1869 if (Context.Complain) {
1871 Context.getApplicableDiagnostic(
1872 diag::err_odr_non_type_parameter_type_inconsistent))
1874 Context.Diag1(D1->
getLocation(), diag::note_odr_value_here)
1887 if (Context.Complain) {
1889 Context.getApplicableDiagnostic(
1890 diag::err_odr_parameter_pack_non_pack))
1892 Context.Diag1(D1->
getLocation(), diag::note_odr_parameter_pack_non_pack)
2001 cast<FieldDecl>(D2), Owner2Type);
2014 bool PropertiesEqual =
2018 if (!PropertiesEqual)
2025 if (NumArgs != Selector2.getNumArgs())
2029 unsigned SlotsToCheck = NumArgs > 0 ? NumArgs : 1;
2030 for (
unsigned I = 0; I < SlotsToCheck; ++I) {
2032 Selector2.getIdentifierInfoForSlot(I)))
2042 "Same number of arguments should be already enforced in Selector checks");
2048 (ParamT1 != ParamT1End) && (ParamT2 != ParamT2End);
2049 ++ParamT1, ++ParamT2) {
2072 Protocol1 != Protocol1End; ++Protocol1, ++Protocol2) {
2073 if (Protocol2 == Protocol2End)
2076 (*Protocol2)->getIdentifier()))
2079 if (Protocol2 != Protocol2End)
2088 Ivar1 != Ivar1End; ++Ivar1, ++Ivar2) {
2089 if (Ivar2 == Ivar2End)
2094 if (Ivar2 != Ivar2End)
2102 Method1 != Method1End; ++Method1, ++Method2) {
2103 if (Method2 == Method2End)
2108 if (Method2 != Method2End)
2121 std::pair<Decl *, Decl *>
P{D1, D2};
2125 if (Context.NonEquivalentDecls.count(
P))
2131 bool Inserted = Context.VisitedDecls.insert(
P).second;
2135 Context.DeclsToCheck.push(
P);
2142 assert(
Complain &&
"Not allowed to complain");
2151 assert(
Complain &&
"Not allowed to complain");
2158std::optional<unsigned>
2163 const auto *Owner = dyn_cast<RecordDecl>(Anon->
getDeclContext());
2165 return std::nullopt;
2168 for (
const auto *D : Owner->noload_decls()) {
2169 const auto *F = dyn_cast<FieldDecl>(D);
2173 if (F->isAnonymousStructOrUnion()) {
2184 while (
const auto *ElabType = dyn_cast<ElaboratedType>(FieldType))
2185 FieldType = ElabType->getNamedType();
2187 if (
const auto *RecType = dyn_cast<RecordType>(FieldType)) {
2188 const RecordDecl *RecDecl = RecType->getDecl();
2202 unsigned ErrorDiagnostic) {
2204 return ErrorDiagnostic;
2206 switch (ErrorDiagnostic) {
2207 case diag::err_odr_variable_type_inconsistent:
2208 return diag::warn_odr_variable_type_inconsistent;
2209 case diag::err_odr_variable_multiple_def:
2210 return diag::warn_odr_variable_multiple_def;
2211 case diag::err_odr_function_type_inconsistent:
2212 return diag::warn_odr_function_type_inconsistent;
2213 case diag::err_odr_tag_type_inconsistent:
2214 return diag::warn_odr_tag_type_inconsistent;
2215 case diag::err_odr_field_type_inconsistent:
2216 return diag::warn_odr_field_type_inconsistent;
2217 case diag::err_odr_ivar_type_inconsistent:
2218 return diag::warn_odr_ivar_type_inconsistent;
2219 case diag::err_odr_objc_superclass_inconsistent:
2220 return diag::warn_odr_objc_superclass_inconsistent;
2221 case diag::err_odr_objc_method_result_type_inconsistent:
2222 return diag::warn_odr_objc_method_result_type_inconsistent;
2223 case diag::err_odr_objc_method_num_params_inconsistent:
2224 return diag::warn_odr_objc_method_num_params_inconsistent;
2225 case diag::err_odr_objc_method_param_type_inconsistent:
2226 return diag::warn_odr_objc_method_param_type_inconsistent;
2227 case diag::err_odr_objc_method_variadic_inconsistent:
2228 return diag::warn_odr_objc_method_variadic_inconsistent;
2229 case diag::err_odr_objc_property_type_inconsistent:
2230 return diag::warn_odr_objc_property_type_inconsistent;
2231 case diag::err_odr_objc_property_impl_kind_inconsistent:
2232 return diag::warn_odr_objc_property_impl_kind_inconsistent;
2233 case diag::err_odr_objc_synthesize_ivar_inconsistent:
2234 return diag::warn_odr_objc_synthesize_ivar_inconsistent;
2235 case diag::err_odr_different_num_template_parameters:
2236 return diag::warn_odr_different_num_template_parameters;
2237 case diag::err_odr_different_template_parameter_kind:
2238 return diag::warn_odr_different_template_parameter_kind;
2239 case diag::err_odr_parameter_pack_non_pack:
2240 return diag::warn_odr_parameter_pack_non_pack;
2241 case diag::err_odr_non_type_parameter_type_inconsistent:
2242 return diag::warn_odr_non_type_parameter_type_inconsistent;
2244 llvm_unreachable(
"Diagnostic kind not handled in preceding switch");
2284bool StructuralEquivalenceContext::CheckCommonEquivalence(
Decl *D1,
Decl *D2) {
2288 if ((Template1 !=
nullptr) != (Template2 !=
nullptr))
2298bool StructuralEquivalenceContext::CheckKindSpecificEquivalence(
2308#define ABSTRACT_DECL(DECL)
2309#define DECL(DERIVED, BASE) \
2310 case Decl::Kind::DERIVED: \
2311 return ::IsStructurallyEquivalent(*this, static_cast<DERIVED##Decl *>(D1), \
2312 static_cast<DERIVED##Decl *>(D2));
2313#include "clang/AST/DeclNodes.inc"
2318bool StructuralEquivalenceContext::Finish() {
2325 Decl *D2 =
P.second;
2328 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 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.
Represents a static or instance method of a struct/union/class.
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
CharacterKind 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()
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.
OverloadedOperatorKind getCXXOverloadedOperator() const
If this name is the name of an overloadable operator in C++ (e.g., operator+), retrieve the kind of o...
@ CXXConversionFunctionName
IdentifierInfo * getCXXLiteralIdentifier() const
If this name is the name of a literal operator, retrieve the identifier associated with it.
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
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
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 ...
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
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(),...
IdentKind 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.
bool isBeingDefined() const
Return true if this decl is currently being defined.
TypedefNameDecl * getTypedefNameForAnonDecl() const
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.
bool isUnresolvedExceptionSpec(ExceptionSpecificationType ESpecType)
@ C
Languages that the frontend can parse and compile.
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.