89#include "llvm/ADT/APInt.h"
90#include "llvm/ADT/APSInt.h"
91#include "llvm/ADT/StringExtras.h"
92#include "llvm/Support/Compiler.h"
93#include "llvm/Support/ErrorHandling.h"
162 llvm_unreachable(
"Unhandled kind of DeclarationName");
193 if (
static_cast<bool>(Callee1) !=
static_cast<bool>(Callee2))
197 if (!
static_cast<bool>(Callee1))
225 if (!Decl1 || !Decl2)
240 bool IsStmtEquivalent(
const Expr *E1,
const Expr *E2) {
257 std::optional<TypeSourceInfo *> Child1 = std::get<0>(Pair);
258 std::optional<TypeSourceInfo *> Child2 = std::get<1>(Pair);
260 if (!Child1 || !Child2)
264 (*Child2)->getType()))
292 bool IsStmtEquivalent(
const Stmt *S1,
const Stmt *S2) {
return true; }
302 return ::IsStructurallyEquivalent(Name1, Name2);
340 std::optional<TypeSourceInfo *> Child1 = std::get<0>(Pair);
341 std::optional<TypeSourceInfo *> Child2 = std::get<1>(Pair);
343 if (!Child1 || !Child2)
347 (*Child2)->getType()))
408 bool TraverseStmt(
const Stmt *S1,
const Stmt *S2) {
return true; }
415#define STMT(CLASS, PARENT) \
416 bool TraverseStmt(const CLASS *S1, const CLASS *S2) { \
417 if (!TraverseStmt(static_cast<const PARENT *>(S1), \
418 static_cast<const PARENT *>(S2))) \
420 return IsStmtEquivalent(S1, S2); \
422#include "clang/AST/StmtNodes.inc"
430 bool IsEquivalent(
const Stmt *S1,
const Stmt *S2) {
441 llvm_unreachable(
"Can't traverse NoStmtClass");
442#define STMT(CLASS, PARENT) \
443 case Stmt::StmtClass::CLASS##Class: \
444 return TraverseStmt(static_cast<const CLASS *>(S1), \
445 static_cast<const CLASS *>(S2));
446#define ABSTRACT_STMT(S)
447#include "clang/AST/StmtNodes.inc"
449 llvm_unreachable(
"Invalid statement kind");
457 const Decl *PrimaryDecl =
nullptr) {
468 const Attr *D1Attr =
nullptr, *D2Attr =
nullptr;
474 const auto *DiagnoseDecl = cast<TypeDecl>(PrimaryDecl ? PrimaryDecl : D2);
475 Context.Diag2(DiagnoseDecl->getLocation(),
476 diag::warn_odr_tag_type_with_attributes)
478 << (PrimaryDecl !=
nullptr);
480 Context.Diag1(D1Attr->
getLoc(), diag::note_odr_attr_here) << D1Attr;
482 Context.Diag1(D2Attr->getLoc(), diag::note_odr_attr_here) << D2Attr;
539 if (
const auto *E2CXXOperatorCall = dyn_cast<CXXOperatorCallExpr>(S2)) {
540 if (
const auto *E1Unary = dyn_cast<UnaryOperator>(S1))
542 if (
const auto *E1Binary = dyn_cast<BinaryOperator>(S1))
545 if (
const auto *E1CXXOperatorCall = dyn_cast<CXXOperatorCallExpr>(S1)) {
546 if (
const auto *E2Unary = dyn_cast<UnaryOperator>(S2))
548 if (
const auto *E2Binary = dyn_cast<BinaryOperator>(S2))
553 StmtComparer Comparer(Context);
554 if (!Comparer.IsEquivalent(S1, S2))
559 std::optional<const Stmt *> Child1 = std::get<0>(Pair);
560 std::optional<const Stmt *> Child2 = std::get<1>(Pair);
563 if (!Child1 || !Child2)
574 if (!Name1 || !Name2)
575 return Name1 == Name2;
588 case NestedNameSpecifier::Kind::Null:
589 case NestedNameSpecifier::Kind::Global:
591 case NestedNameSpecifier::Kind::Namespace: {
600 case NestedNameSpecifier::Kind::Type:
603 case NestedNameSpecifier::Kind::MicrosoftSuper:
628 if (TemplateDeclN1 && TemplateDeclN2) {
634 }
else if (TemplateDeclN1 || TemplateDeclN2)
646 E1 = OS1->
end(), E2 = OS2->end();
647 for (; I1 != E1 && I2 != E2; ++I1, ++I2)
650 return I1 == E1 && I2 == E2;
668 P2->getArgumentPack()) &&
670 P2->getAssociatedDecl()) &&
683 llvm_unreachable(
"unimplemented");
742 llvm_unreachable(
"Invalid template argument kind");
749 if (Args1.size() != Args2.size())
751 for (
unsigned I = 0, N = Args1.size(); I != N; ++I) {
847 if (!Context.StrictTypeSpelling) {
864 TC = Type::FunctionNoProto;
867 TC = Type::FunctionNoProto;
868 else if (Context.LangOpts.C23 && !Context.StrictTypeSpelling &&
881 T1 = cast<EnumType>(T1)->getOriginalDecl()->getIntegerType();
884 T2 = cast<EnumType>(T2)->getOriginalDecl()->getIntegerType();
895 if (cast<BuiltinType>(T1)->
getKind() != cast<BuiltinType>(T2)->
getKind())
901 cast<ComplexType>(T1)->getElementType(),
902 cast<ComplexType>(T2)->getElementType()))
908 case Type::ArrayParameter:
910 cast<AdjustedType>(T1)->getOriginalType(),
911 cast<AdjustedType>(T2)->getOriginalType()))
922 case Type::BlockPointer:
929 case Type::LValueReference:
930 case Type::RValueReference: {
931 const auto *Ref1 = cast<ReferenceType>(T1);
932 const auto *Ref2 = cast<ReferenceType>(T2);
933 if (Ref1->isSpelledAsLValue() != Ref2->isSpelledAsLValue())
935 if (Ref1->isInnerRef() != Ref2->isInnerRef())
938 Ref2->getPointeeTypeAsWritten()))
943 case Type::MemberPointer: {
944 const auto *MemPtr1 = cast<MemberPointerType>(T1);
945 const auto *MemPtr2 = cast<MemberPointerType>(T2);
947 MemPtr2->getPointeeType()))
950 MemPtr2->getQualifier()))
953 *D2 = MemPtr2->getMostRecentCXXRecordDecl();
961 case Type::ConstantArray: {
962 const auto *Array1 = cast<ConstantArrayType>(T1);
963 const auto *Array2 = cast<ConstantArrayType>(T2);
964 if (!llvm::APInt::isSameValue(Array1->getSize(), Array2->getSize()))
972 case Type::IncompleteArray:
974 cast<ArrayType>(T2)))
978 case Type::VariableArray: {
979 const auto *Array1 = cast<VariableArrayType>(T1);
980 const auto *Array2 = cast<VariableArrayType>(T2);
982 Array2->getSizeExpr()))
991 case Type::DependentSizedArray: {
992 const auto *Array1 = cast<DependentSizedArrayType>(T1);
993 const auto *Array2 = cast<DependentSizedArrayType>(T2);
995 Array2->getSizeExpr()))
1004 case Type::DependentAddressSpace: {
1005 const auto *DepAddressSpace1 = cast<DependentAddressSpaceType>(T1);
1006 const auto *DepAddressSpace2 = cast<DependentAddressSpaceType>(T2);
1008 DepAddressSpace2->getAddrSpaceExpr()))
1011 DepAddressSpace2->getPointeeType()))
1017 case Type::DependentSizedExtVector: {
1018 const auto *Vec1 = cast<DependentSizedExtVectorType>(T1);
1019 const auto *Vec2 = cast<DependentSizedExtVectorType>(T2);
1021 Vec2->getSizeExpr()))
1024 Vec2->getElementType()))
1029 case Type::DependentVector: {
1030 const auto *Vec1 = cast<DependentVectorType>(T1);
1031 const auto *Vec2 = cast<DependentVectorType>(T2);
1032 if (Vec1->getVectorKind() != Vec2->getVectorKind())
1035 Vec2->getSizeExpr()))
1038 Vec2->getElementType()))
1044 case Type::ExtVector: {
1045 const auto *Vec1 = cast<VectorType>(T1);
1046 const auto *Vec2 = cast<VectorType>(T2);
1048 Vec2->getElementType()))
1050 if (Vec1->getNumElements() != Vec2->getNumElements())
1052 if (Vec1->getVectorKind() != Vec2->getVectorKind())
1057 case Type::DependentSizedMatrix: {
1072 case Type::ConstantMatrix: {
1085 case Type::FunctionProto: {
1086 const auto *Proto1 = cast<FunctionProtoType>(T1);
1087 const auto *Proto2 = cast<FunctionProtoType>(T2);
1089 if (Proto1->getNumParams() != Proto2->getNumParams())
1091 for (
unsigned I = 0, N = Proto1->getNumParams(); I != N; ++I) {
1093 Proto2->getParamType(I)))
1096 if (Proto1->isVariadic() != Proto2->isVariadic())
1099 if (Proto1->getMethodQuals() != Proto2->getMethodQuals())
1103 const auto *OrigProto1 =
1105 const auto *OrigProto2 =
1114 case Type::FunctionNoProto: {
1115 const auto *Function1 = cast<FunctionType>(T1);
1116 const auto *Function2 = cast<FunctionType>(T2);
1118 Function2->getReturnType()))
1121 Function2->getExtInfo()))
1126 case Type::UnresolvedUsing:
1128 cast<UnresolvedUsingType>(T1)->getDecl(),
1129 cast<UnresolvedUsingType>(T2)->getDecl()))
1133 case Type::Attributed:
1135 cast<AttributedType>(T1)->getModifiedType(),
1136 cast<AttributedType>(T2)->getModifiedType()))
1139 Context, cast<AttributedType>(T1)->getEquivalentType(),
1140 cast<AttributedType>(T2)->getEquivalentType()))
1144 case Type::CountAttributed:
1146 cast<CountAttributedType>(T1)->desugar(),
1147 cast<CountAttributedType>(T2)->desugar()))
1151 case Type::BTFTagAttributed:
1153 Context, cast<BTFTagAttributedType>(T1)->getWrappedType(),
1154 cast<BTFTagAttributedType>(T2)->getWrappedType()))
1158 case Type::HLSLAttributedResource:
1160 Context, cast<HLSLAttributedResourceType>(T1)->getWrappedType(),
1161 cast<HLSLAttributedResourceType>(T2)->getWrappedType()))
1164 Context, cast<HLSLAttributedResourceType>(T1)->getContainedType(),
1165 cast<HLSLAttributedResourceType>(T2)->getContainedType()))
1167 if (cast<HLSLAttributedResourceType>(T1)->getAttrs() !=
1168 cast<HLSLAttributedResourceType>(T2)->getAttrs())
1172 case Type::HLSLInlineSpirv:
1173 if (cast<HLSLInlineSpirvType>(T1)->getOpcode() !=
1174 cast<HLSLInlineSpirvType>(T2)->getOpcode() ||
1175 cast<HLSLInlineSpirvType>(T1)->getSize() !=
1176 cast<HLSLInlineSpirvType>(T2)->getSize() ||
1177 cast<HLSLInlineSpirvType>(T1)->getAlignment() !=
1178 cast<HLSLInlineSpirvType>(T2)->getAlignment())
1180 for (
size_t I = 0; I < cast<HLSLInlineSpirvType>(T1)->getOperands().size();
1182 if (cast<HLSLInlineSpirvType>(T1)->getOperands()[I] !=
1183 cast<HLSLInlineSpirvType>(T2)->getOperands()[I]) {
1191 cast<ParenType>(T2)->getInnerType()))
1195 case Type::MacroQualified:
1203 auto *U1 = cast<UsingType>(T1), *U2 = cast<UsingType>(T2);
1204 if (U1->getKeyword() != U2->getKeyword())
1207 U2->getQualifier()))
1215 case Type::Typedef: {
1216 auto *U1 = cast<TypedefType>(T1), *U2 = cast<TypedefType>(T2);
1217 if (U1->getKeyword() != U2->getKeyword())
1220 U2->getQualifier()))
1224 if (U1->typeMatchesDecl() != U2->typeMatchesDecl())
1226 if (!U1->typeMatchesDecl() &&
1232 case Type::TypeOfExpr:
1234 Context, cast<TypeOfExprType>(T1)->getUnderlyingExpr(),
1235 cast<TypeOfExprType>(T2)->getUnderlyingExpr()))
1241 cast<TypeOfType>(T1)->getUnmodifiedType(),
1242 cast<TypeOfType>(T2)->getUnmodifiedType()))
1246 case Type::UnaryTransform:
1253 case Type::Decltype:
1255 cast<DecltypeType>(T1)->getUnderlyingExpr(),
1256 cast<DecltypeType>(T2)->getUnderlyingExpr()))
1261 auto *Auto1 = cast<AutoType>(T1);
1262 auto *Auto2 = cast<AutoType>(T2);
1264 Auto2->getDeducedType()))
1266 if (Auto1->isConstrained() != Auto2->isConstrained())
1268 if (Auto1->isConstrained()) {
1269 if (Auto1->getTypeConstraintConcept() !=
1270 Auto2->getTypeConstraintConcept())
1273 Auto1->getTypeConstraintArguments(),
1274 Auto2->getTypeConstraintArguments()))
1280 case Type::DeducedTemplateSpecialization: {
1281 const auto *DT1 = cast<DeducedTemplateSpecializationType>(T1);
1282 const auto *DT2 = cast<DeducedTemplateSpecializationType>(T2);
1284 DT2->getTemplateName()))
1287 DT2->getDeducedType()))
1294 case Type::InjectedClassName: {
1295 const auto *TT1 = cast<TagType>(T1), *TT2 = cast<TagType>(T2);
1296 if (TT1->getKeyword() != TT2->getKeyword())
1298 if (TT1->isTagOwned() != TT2->isTagOwned())
1301 TT2->getQualifier()))
1304 TT2->getOriginalDecl()))
1309 case Type::TemplateTypeParm: {
1310 const auto *Parm1 = cast<TemplateTypeParmType>(T1);
1311 const auto *Parm2 = cast<TemplateTypeParmType>(T2);
1312 if (!Context.IgnoreTemplateParmDepth &&
1313 Parm1->getDepth() != Parm2->getDepth())
1315 if (Parm1->getIndex() != Parm2->getIndex())
1317 if (Parm1->isParameterPack() != Parm2->isParameterPack())
1324 case Type::SubstTemplateTypeParm: {
1325 const auto *Subst1 = cast<SubstTemplateTypeParmType>(T1);
1326 const auto *Subst2 = cast<SubstTemplateTypeParmType>(T2);
1328 Subst2->getReplacementType()))
1331 Subst2->getAssociatedDecl()))
1333 if (Subst1->getIndex() != Subst2->getIndex())
1335 if (Subst1->getPackIndex() != Subst2->getPackIndex())
1340 case Type::SubstBuiltinTemplatePack: {
1341 const auto *Subst1 = cast<SubstBuiltinTemplatePackType>(T1);
1342 const auto *Subst2 = cast<SubstBuiltinTemplatePackType>(T2);
1344 Subst2->getArgumentPack()))
1348 case Type::SubstTemplateTypeParmPack: {
1349 const auto *Subst1 = cast<SubstTemplateTypeParmPackType>(T1);
1350 const auto *Subst2 = cast<SubstTemplateTypeParmPackType>(T2);
1352 Subst2->getAssociatedDecl()))
1354 if (Subst1->getIndex() != Subst2->getIndex())
1357 Subst2->getArgumentPack()))
1362 case Type::TemplateSpecialization: {
1363 const auto *Spec1 = cast<TemplateSpecializationType>(T1);
1364 const auto *Spec2 = cast<TemplateSpecializationType>(T2);
1366 Spec2->getTemplateName()))
1369 Spec2->template_arguments()))
1374 case Type::DependentName: {
1375 const auto *Typename1 = cast<DependentNameType>(T1);
1376 const auto *Typename2 = cast<DependentNameType>(T2);
1378 Typename2->getQualifier()))
1381 Typename2->getIdentifier()))
1387 case Type::DependentTemplateSpecialization: {
1388 const auto *Spec1 = cast<DependentTemplateSpecializationType>(T1);
1389 const auto *Spec2 = cast<DependentTemplateSpecializationType>(T2);
1390 if (Spec1->getKeyword() != Spec2->getKeyword())
1393 Spec2->getDependentTemplateName()))
1396 Spec2->template_arguments()))
1401 case Type::PackExpansion:
1403 cast<PackExpansionType>(T1)->getPattern(),
1404 cast<PackExpansionType>(T2)->getPattern()))
1408 case Type::PackIndexing:
1410 cast<PackIndexingType>(T1)->getPattern(),
1411 cast<PackIndexingType>(T2)->getPattern()))
1413 cast<PackIndexingType>(T1)->getIndexExpr(),
1414 cast<PackIndexingType>(T2)->getIndexExpr()))
1418 case Type::ObjCInterface: {
1419 const auto *Iface1 = cast<ObjCInterfaceType>(T1);
1420 const auto *Iface2 = cast<ObjCInterfaceType>(T2);
1427 case Type::ObjCTypeParam: {
1428 const auto *Obj1 = cast<ObjCTypeParamType>(T1);
1429 const auto *Obj2 = cast<ObjCTypeParamType>(T2);
1433 if (Obj1->getNumProtocols() != Obj2->getNumProtocols())
1435 for (
unsigned I = 0, N = Obj1->getNumProtocols(); I != N; ++I) {
1437 Obj2->getProtocol(I)))
1443 case Type::ObjCObject: {
1444 const auto *Obj1 = cast<ObjCObjectType>(T1);
1445 const auto *Obj2 = cast<ObjCObjectType>(T2);
1447 Obj2->getBaseType()))
1449 if (Obj1->getNumProtocols() != Obj2->getNumProtocols())
1451 for (
unsigned I = 0, N = Obj1->getNumProtocols(); I != N; ++I) {
1453 Obj2->getProtocol(I)))
1459 case Type::ObjCObjectPointer: {
1460 const auto *Ptr1 = cast<ObjCObjectPointerType>(T1);
1461 const auto *Ptr2 = cast<ObjCObjectPointerType>(T2);
1463 Ptr2->getPointeeType()))
1470 cast<AtomicType>(T2)->getValueType()))
1476 cast<PipeType>(T2)->getElementType()))
1479 case Type::BitInt: {
1480 const auto *Int1 = cast<BitIntType>(T1);
1481 const auto *Int2 = cast<BitIntType>(T2);
1483 if (Int1->isUnsigned() != Int2->isUnsigned() ||
1484 Int1->getNumBits() != Int2->getNumBits())
1488 case Type::DependentBitInt: {
1489 const auto *Int1 = cast<DependentBitIntType>(T1);
1490 const auto *Int2 = cast<DependentBitIntType>(T2);
1492 if (Int1->isUnsigned() != Int2->isUnsigned() ||
1494 Int2->getNumBitsExpr()))
1498 case Type::PredefinedSugar: {
1499 const auto *TP1 = cast<PredefinedSugarType>(T1);
1500 const auto *TP2 = cast<PredefinedSugarType>(T2);
1501 if (TP1->getKind() != TP2->getKind())
1539 if (Context.LangOpts.C23 &&
1557 if (Context.Complain) {
1559 Owner2->getLocation(),
1560 Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent))
1561 << Owner2Type << (&Context.FromCtx != &Context.ToCtx);
1562 Context.Diag2(Field2->
getLocation(), diag::note_odr_field_name)
1564 Context.Diag1(Field1->
getLocation(), diag::note_odr_field_name)
1572 if (Context.Complain) {
1574 Owner2->getLocation(),
1575 Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent))
1576 << Owner2Type << (&Context.FromCtx != &Context.ToCtx);
1577 Context.Diag2(Field2->
getLocation(), diag::note_odr_field)
1579 Context.Diag1(Field1->
getLocation(), diag::note_odr_field)
1591 bool Diagnose =
true;
1595 if (Diagnose && Context.Complain) {
1596 auto DiagNote = [&](
const FieldDecl *FD,
1604 (Context.*
Diag)(FD->
getLocation(), diag::note_odr_field_not_bit_field)
1610 Owner2->getLocation(),
1611 Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent))
1612 << Owner2Type << (&Context.FromCtx != &Context.ToCtx);
1634 if (!Method1 && !Method2)
1636 if (!Method1 || !Method2)
1639 bool PropertiesEqual =
1653 if (!PropertiesEqual)
1657 if (
auto *Constructor1 = dyn_cast<CXXConstructorDecl>(Method1)) {
1658 auto *Constructor2 = cast<CXXConstructorDecl>(Method2);
1659 if (!Constructor1->getExplicitSpecifier().isEquivalent(
1660 Constructor2->getExplicitSpecifier()))
1664 if (
auto *Conversion1 = dyn_cast<CXXConversionDecl>(Method1)) {
1665 auto *Conversion2 = cast<CXXConversionDecl>(Method2);
1666 if (!Conversion1->getExplicitSpecifier().isEquivalent(
1667 Conversion2->getExplicitSpecifier()))
1670 Conversion2->getConversionType()))
1694 "Must be called on lambda classes");
1725 if (
const auto *ND1 = dyn_cast<NamedDecl>(DC1)) {
1726 const auto *ND2 = cast<NamedDecl>(DC2);
1732 if (
auto *D1Spec = dyn_cast<ClassTemplateSpecializationDecl>(DC1)) {
1733 auto *D2Spec = dyn_cast<ClassTemplateSpecializationDecl>(DC2);
1750 return TypedefName->getIdentifier();
1797 if (Context.Complain) {
1798 Context.Diag2(D2->
getLocation(), Context.getApplicableDiagnostic(
1799 diag::err_odr_tag_type_inconsistent))
1801 << (&Context.FromCtx != &Context.ToCtx);
1802 Context.Diag1(D1->
getLocation(), diag::note_odr_tag_kind_here)
1816 if (*Index1 != *Index2)
1824 if (Context.LangOpts.C23 &&
1833 if (!Context.LangOpts.C23 &&
1839 const auto *Spec1 = dyn_cast<ClassTemplateSpecializationDecl>(D1);
1840 const auto *Spec2 = dyn_cast<ClassTemplateSpecializationDecl>(D2);
1841 if (Spec1 && Spec2) {
1844 Spec2->getSpecializedTemplate()))
1848 if (Spec1->getTemplateArgs().size() != Spec2->getTemplateArgs().size())
1851 for (
unsigned I = 0, N = Spec1->getTemplateArgs().size(); I != N; ++I)
1853 Spec2->getTemplateArgs().get(I)))
1858 else if (Spec1 || Spec2)
1867 return !Context.LangOpts.C23;
1874 if (Context.EqKind == StructuralEquivalenceKind::Minimal)
1883 if (
auto *D1CXX = dyn_cast<CXXRecordDecl>(D1)) {
1884 if (
auto *D2CXX = dyn_cast<CXXRecordDecl>(D2)) {
1885 if (D1CXX->hasExternalLexicalStorage() &&
1886 !D1CXX->isCompleteDefinition()) {
1887 D1CXX->getASTContext().getExternalSource()->CompleteType(D1CXX);
1890 if (D1CXX->isLambda() != D2CXX->isLambda())
1892 if (D1CXX->isLambda()) {
1897 if (D1CXX->getNumBases() != D2CXX->getNumBases()) {
1898 if (Context.Complain) {
1900 Context.getApplicableDiagnostic(
1901 diag::err_odr_tag_type_inconsistent))
1903 << (&Context.FromCtx != &Context.ToCtx);
1904 Context.Diag2(D2->
getLocation(), diag::note_odr_number_of_bases)
1905 << D2CXX->getNumBases();
1906 Context.Diag1(D1->
getLocation(), diag::note_odr_number_of_bases)
1907 << D1CXX->getNumBases();
1914 BaseEnd1 = D1CXX->bases_end(),
1915 Base2 = D2CXX->bases_begin();
1916 Base1 != BaseEnd1; ++Base1, ++Base2) {
1918 Base2->getType())) {
1919 if (Context.Complain) {
1921 Context.getApplicableDiagnostic(
1922 diag::err_odr_tag_type_inconsistent))
1924 << (&Context.FromCtx != &Context.ToCtx);
1925 Context.Diag2(Base2->getBeginLoc(), diag::note_odr_base)
1926 << Base2->getType() << Base2->getSourceRange();
1927 Context.Diag1(Base1->getBeginLoc(), diag::note_odr_base)
1928 << Base1->getType() << Base1->getSourceRange();
1934 if (Base1->isVirtual() != Base2->isVirtual()) {
1935 if (Context.Complain) {
1937 Context.getApplicableDiagnostic(
1938 diag::err_odr_tag_type_inconsistent))
1940 << (&Context.FromCtx != &Context.ToCtx);
1941 Context.Diag2(Base2->getBeginLoc(), diag::note_odr_virtual_base)
1942 << Base2->isVirtual() << Base2->getSourceRange();
1943 Context.Diag1(Base1->getBeginLoc(), diag::note_odr_base)
1944 << Base1->isVirtual() << Base1->getSourceRange();
1952 Friend2End = D2CXX->friend_end();
1954 Friend1End = D1CXX->friend_end();
1955 Friend1 != Friend1End; ++Friend1, ++Friend2) {
1956 if (Friend2 == Friend2End) {
1957 if (Context.Complain) {
1959 Context.getApplicableDiagnostic(
1960 diag::err_odr_tag_type_inconsistent))
1962 << (&Context.FromCtx != &Context.ToCtx);
1963 Context.Diag1((*Friend1)->getFriendLoc(), diag::note_odr_friend);
1964 Context.Diag2(D2->
getLocation(), diag::note_odr_missing_friend);
1970 if (Context.Complain) {
1972 Context.getApplicableDiagnostic(
1973 diag::err_odr_tag_type_inconsistent))
1975 << (&Context.FromCtx != &Context.ToCtx);
1976 Context.Diag1((*Friend1)->getFriendLoc(), diag::note_odr_friend);
1977 Context.Diag2((*Friend2)->getFriendLoc(), diag::note_odr_friend);
1983 if (Friend2 != Friend2End) {
1984 if (Context.Complain) {
1986 Context.getApplicableDiagnostic(
1987 diag::err_odr_tag_type_inconsistent))
1989 << (&Context.FromCtx != &Context.ToCtx);
1990 Context.Diag2((*Friend2)->getFriendLoc(), diag::note_odr_friend);
1991 Context.Diag1(D1->
getLocation(), diag::note_odr_missing_friend);
1995 }
else if (D1CXX->getNumBases() > 0) {
1996 if (Context.Complain) {
1998 Context.getApplicableDiagnostic(
1999 diag::err_odr_tag_type_inconsistent))
2001 << (&Context.FromCtx != &Context.ToCtx);
2003 Context.Diag1(Base1->
getBeginLoc(), diag::note_odr_base)
2005 Context.Diag2(D2->
getLocation(), diag::note_odr_missing_base);
2017 Field1 != Field1End; ++Field1, ++Field2) {
2018 if (Field2 == Field2End) {
2019 if (Context.Complain) {
2021 Context.getApplicableDiagnostic(
2022 diag::err_odr_tag_type_inconsistent))
2024 << (&Context.FromCtx != &Context.ToCtx);
2025 Context.Diag1(Field1->getLocation(), diag::note_odr_field)
2026 << Field1->getDeclName() << Field1->getType();
2027 Context.Diag2(D2->
getLocation(), diag::note_odr_missing_field);
2036 if (Field2 != Field2End) {
2037 if (Context.Complain) {
2038 Context.Diag2(D2->
getLocation(), Context.getApplicableDiagnostic(
2039 diag::err_odr_tag_type_inconsistent))
2041 << (&Context.FromCtx != &Context.ToCtx);
2042 Context.Diag2(Field2->getLocation(), diag::note_odr_field)
2043 << Field2->getDeclName() << Field2->getType();
2044 Context.Diag1(D1->
getLocation(), diag::note_odr_missing_field);
2055 const llvm::APSInt &FromVal = D1->
getInitVal();
2056 const llvm::APSInt &ToVal = D2->
getInitVal();
2057 if (FromVal.isSigned() != ToVal.isSigned())
2059 if (FromVal.getBitWidth() != ToVal.getBitWidth())
2061 if (FromVal != ToVal)
2088 if (Context.LangOpts.C23 &&
2094 if (Context.LangOpts.C23) {
2096 if (Context.Complain) {
2098 Context.getApplicableDiagnostic(
2099 diag::err_odr_tag_type_inconsistent))
2101 << (&Context.FromCtx != &Context.ToCtx);
2104 ? diag::note_odr_fixed_underlying_type
2105 : diag::note_odr_missing_fixed_underlying_type)
2109 ? diag::note_odr_fixed_underlying_type
2110 : diag::note_odr_missing_fixed_underlying_type)
2116 assert(D2->
isFixed() &&
"enums expected to have fixed underlying types");
2119 if (Context.Complain) {
2121 Context.getApplicableDiagnostic(
2122 diag::err_odr_tag_type_inconsistent))
2124 << (&Context.FromCtx != &Context.ToCtx);
2126 diag::note_odr_incompatible_fixed_underlying_type)
2135 auto CopyEnumerators =
2138 Cont.push_back(ECD);
2145 if (Context.LangOpts.C23) {
2147 return LHS->
getName() < RHS->getName();
2149 llvm::sort(D1Enums, Sorter);
2150 llvm::sort(D2Enums, Sorter);
2153 auto EC2 = D2Enums.begin(), EC2End = D2Enums.end();
2154 for (
auto EC1 = D1Enums.begin(), EC1End = D1Enums.end(); EC1 != EC1End;
2156 if (EC2 == EC2End) {
2157 if (Context.Complain) {
2159 Context.getApplicableDiagnostic(
2160 diag::err_odr_tag_type_inconsistent))
2162 << (&Context.FromCtx != &Context.ToCtx);
2163 Context.Diag1((*EC1)->getLocation(), diag::note_odr_enumerator)
2164 << (*EC1)->getDeclName() <<
toString((*EC1)->getInitVal(), 10);
2165 Context.Diag2(D2->
getLocation(), diag::note_odr_missing_enumerator);
2170 llvm::APSInt Val1 = (*EC1)->getInitVal();
2171 llvm::APSInt Val2 = (*EC2)->getInitVal();
2172 if (!llvm::APSInt::isSameValue(Val1, Val2) ||
2174 (*EC2)->getIdentifier())) {
2175 if (Context.Complain) {
2177 Context.getApplicableDiagnostic(
2178 diag::err_odr_tag_type_inconsistent))
2180 << (&Context.FromCtx != &Context.ToCtx);
2181 Context.Diag2((*EC2)->getLocation(), diag::note_odr_enumerator)
2182 << (*EC2)->getDeclName() <<
toString((*EC2)->getInitVal(), 10);
2183 Context.Diag1((*EC1)->getLocation(), diag::note_odr_enumerator)
2184 << (*EC1)->getDeclName() <<
toString((*EC1)->getInitVal(), 10);
2188 if (Context.LangOpts.C23 &&
2193 if (EC2 != EC2End) {
2194 if (Context.Complain) {
2195 Context.Diag2(D2->
getLocation(), Context.getApplicableDiagnostic(
2196 diag::err_odr_tag_type_inconsistent))
2198 << (&Context.FromCtx != &Context.ToCtx);
2199 Context.Diag2((*EC2)->getLocation(), diag::note_odr_enumerator)
2200 << (*EC2)->getDeclName() <<
toString((*EC2)->getInitVal(), 10);
2201 Context.Diag1(D1->
getLocation(), diag::note_odr_missing_enumerator);
2212 if (Params1->
size() != Params2->
size()) {
2213 if (Context.Complain) {
2215 Context.getApplicableDiagnostic(
2216 diag::err_odr_different_num_template_parameters))
2217 << Params1->
size() << Params2->
size();
2219 diag::note_odr_template_parameter_list);
2224 for (
unsigned I = 0, N = Params1->
size(); I != N; ++I) {
2226 if (Context.Complain) {
2228 Context.getApplicableDiagnostic(
2229 diag::err_odr_different_template_parameter_kind));
2231 diag::note_odr_template_parameter_here);
2248 if (Context.Complain) {
2250 Context.getApplicableDiagnostic(
2251 diag::err_odr_parameter_pack_non_pack))
2253 Context.Diag1(D1->
getLocation(), diag::note_odr_parameter_pack_non_pack)
2266 if (Context.Complain) {
2268 Context.getApplicableDiagnostic(
2269 diag::err_odr_parameter_pack_non_pack))
2271 Context.Diag1(D1->
getLocation(), diag::note_odr_parameter_pack_non_pack)
2282 if (Context.Complain) {
2284 Context.getApplicableDiagnostic(
2285 diag::err_odr_non_type_parameter_type_inconsistent))
2287 Context.Diag1(D1->
getLocation(), diag::note_odr_value_here)
2300 if (Context.Complain) {
2302 Context.getApplicableDiagnostic(
2303 diag::err_odr_parameter_pack_non_pack))
2305 Context.Diag1(D1->
getLocation(), diag::note_odr_parameter_pack_non_pack)
2427 cast<FieldDecl>(D2), Owner2Type);
2440 bool PropertiesEqual =
2444 if (!PropertiesEqual)
2451 if (NumArgs != Selector2.getNumArgs())
2455 unsigned SlotsToCheck = NumArgs > 0 ? NumArgs : 1;
2456 for (
unsigned I = 0; I < SlotsToCheck; ++I) {
2458 Selector2.getIdentifierInfoForSlot(I)))
2468 "Same number of arguments should be already enforced in Selector checks");
2474 (ParamT1 != ParamT1End) && (ParamT2 != ParamT2End);
2475 ++ParamT1, ++ParamT2) {
2491 if ((!Intf1 || !Intf2) && (Intf1 != Intf2))
2503 Protocol1 != Protocol1End; ++Protocol1, ++Protocol2) {
2504 if (Protocol2 == Protocol2End)
2507 (*Protocol2)->getIdentifier()))
2510 if (Protocol2 != Protocol2End)
2520 Ivar1 != Ivar1End; ++Ivar1, ++Ivar2) {
2521 if (Ivar2 == Ivar2End)
2526 if (Ivar2 != Ivar2End)
2534 Method1 != Method1End; ++Method1, ++Method2) {
2535 if (Method2 == Method2End)
2540 if (Method2 != Method2End)
2553 std::pair<Decl *, Decl *>
P{D1, D2};
2557 if (Context.NonEquivalentDecls.count(
2558 std::make_tuple(D1, D2, Context.IgnoreTemplateParmDepth)))
2564 bool Inserted = Context.VisitedDecls.insert(
P).second;
2568 Context.DeclsToCheck.push(
P);
2575 assert(
Complain &&
"Not allowed to complain");
2584 assert(
Complain &&
"Not allowed to complain");
2596 const auto *Owner = dyn_cast<RecordDecl>(Anon->
getDeclContext());
2598 return std::nullopt;
2601 for (
const auto *
D : Owner->noload_decls()) {
2602 const auto *F = dyn_cast<FieldDecl>(
D);
2606 if (F->isAnonymousStructOrUnion()) {
2616 if (
const auto *RecType = dyn_cast<RecordType>(FieldType)) {
2617 const RecordDecl *RecDecl = RecType->getOriginalDecl();
2631 unsigned ErrorDiagnostic) {
2633 return ErrorDiagnostic;
2635 switch (ErrorDiagnostic) {
2636 case diag::err_odr_variable_type_inconsistent:
2637 return diag::warn_odr_variable_type_inconsistent;
2638 case diag::err_odr_variable_multiple_def:
2639 return diag::warn_odr_variable_multiple_def;
2640 case diag::err_odr_function_type_inconsistent:
2641 return diag::warn_odr_function_type_inconsistent;
2642 case diag::err_odr_tag_type_inconsistent:
2643 return diag::warn_odr_tag_type_inconsistent;
2644 case diag::err_odr_field_type_inconsistent:
2645 return diag::warn_odr_field_type_inconsistent;
2646 case diag::err_odr_ivar_type_inconsistent:
2647 return diag::warn_odr_ivar_type_inconsistent;
2648 case diag::err_odr_objc_superclass_inconsistent:
2649 return diag::warn_odr_objc_superclass_inconsistent;
2650 case diag::err_odr_objc_method_result_type_inconsistent:
2651 return diag::warn_odr_objc_method_result_type_inconsistent;
2652 case diag::err_odr_objc_method_num_params_inconsistent:
2653 return diag::warn_odr_objc_method_num_params_inconsistent;
2654 case diag::err_odr_objc_method_param_type_inconsistent:
2655 return diag::warn_odr_objc_method_param_type_inconsistent;
2656 case diag::err_odr_objc_method_variadic_inconsistent:
2657 return diag::warn_odr_objc_method_variadic_inconsistent;
2658 case diag::err_odr_objc_property_type_inconsistent:
2659 return diag::warn_odr_objc_property_type_inconsistent;
2660 case diag::err_odr_objc_property_impl_kind_inconsistent:
2661 return diag::warn_odr_objc_property_impl_kind_inconsistent;
2662 case diag::err_odr_objc_synthesize_ivar_inconsistent:
2663 return diag::warn_odr_objc_synthesize_ivar_inconsistent;
2664 case diag::err_odr_different_num_template_parameters:
2665 return diag::warn_odr_different_num_template_parameters;
2666 case diag::err_odr_different_template_parameter_kind:
2667 return diag::warn_odr_different_template_parameter_kind;
2668 case diag::err_odr_parameter_pack_non_pack:
2669 return diag::warn_odr_parameter_pack_non_pack;
2670 case diag::err_odr_non_type_parameter_type_inconsistent:
2671 return diag::warn_odr_non_type_parameter_type_inconsistent;
2673 llvm_unreachable(
"Diagnostic kind not handled in preceding switch");
2713bool StructuralEquivalenceContext::CheckCommonEquivalence(
Decl *D1,
Decl *D2) {
2717 if ((Template1 !=
nullptr) != (Template2 !=
nullptr))
2727bool StructuralEquivalenceContext::CheckKindSpecificEquivalence(
2737#define ABSTRACT_DECL(DECL)
2738#define DECL(DERIVED, BASE) \
2739 case Decl::Kind::DERIVED: \
2740 return ::IsStructurallyEquivalent(*this, static_cast<DERIVED##Decl *>(D1), \
2741 static_cast<DERIVED##Decl *>(D2));
2742#include "clang/AST/DeclNodes.inc"
2747bool StructuralEquivalenceContext::Finish() {
2754 Decl *D2 =
P.second;
2757 CheckCommonEquivalence(D1, D2) && CheckKindSpecificEquivalence(D1, D2);
Defines the clang::ASTContext interface.
static bool IsTemplateDeclCommonStructurallyEquivalent(StructuralEquivalenceContext &Ctx, TemplateDecl *D1, TemplateDecl *D2)
static bool CheckStructurallyEquivalentAttributes(StructuralEquivalenceContext &Context, const Decl *D1, const Decl *D2, const Decl *PrimaryDecl=nullptr)
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 OpenACC nodes for declarative directives.
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 DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
static QualType getUnderlyingType(const SubRegion *R)
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
Defines the clang::SourceLocation class and associated facilities.
Defines the Objective-C statement AST node classes.
This file defines OpenACC AST classes for statement-level contructs.
This file defines OpenMP AST classes for executable directives and clauses.
This file defines SYCL AST classes used to represent calls to SYCL kernels.
static QualType getPointeeType(const MemRegion *R)
C Language Family Type Representation.
llvm::APInt getValue() const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl, ObjCInterfaceDecl *PrevDecl=nullptr) const
getObjCInterfaceType - Return the unique reference to the type for the specified ObjC interface decl.
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.
TemplateName getDependentTemplateName(const DependentTemplateStorage &Name) const
Retrieve the template name that represents a dependent template name such as MetaFun::template operat...
QualType getTypeDeclType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier Qualifier, const TypeDecl *Decl) const
DiagnosticsEngine & getDiagnostics() const
CanQualType getCanonicalTagType(const TagDecl *TD) const
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,...
Attr - This represents one attribute.
SourceLocation getLoc() const
A builtin binary operation expression such as "x + y" or "x <= y".
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc)
Retrieve the overloaded operator kind that corresponds to the given binary opcode.
Represents a base class of a C++ class.
SourceLocation getBeginLoc() const LLVM_READONLY
QualType getType() const
Retrieves the type of the base class.
SourceRange getSourceRange() const LLVM_READONLY
Retrieves the source range that contains the entire base specifier.
A boolean literal, per ([C++ lex.bool] Boolean literals).
Represents a C++ member access expression where the actual member referenced could not be resolved be...
QualType getBaseType() const
DeclarationName getMember() const
Retrieve the name of the member that this expression refers to.
Represents a static or instance method of a struct/union/class.
bool isImplicitObjectMemberFunction() const
[C++2b][dcl.fct]/p7 An implicit object member function is a non-static member function without an exp...
RefQualifierKind getRefQualifier() const
Retrieve the ref-qualifier associated with this method.
A call to an overloaded operator written using operator syntax.
OverloadedOperatorKind getOperator() const
Returns the kind of overloaded operator that this expression refers to.
An iterator over the friend declarations of a class.
Represents a C++ struct/union/class.
bool isLambda() const
Determine whether this class describes a lambda function object.
CXXMethodDecl * getLambdaCallOperator() const
Retrieve the lambda call operator of the closure type if this is a closure type.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
unsigned getValue() const
CharacterLiteralKind getKind() const
ChooseExpr - GNU builtin-in function __builtin_choose_expr.
Declaration of a class template.
CXXRecordDecl * getTemplatedDecl() const
Get the underlying class declarations of the template.
CompoundStmt - This represents a group of statements like { stmt stmt }.
Declaration of a C++20 concept.
Expr * getConstraintExpr() const
Represents a concrete matrix type with constant number of rows and columns.
unsigned getNumColumns() const
Returns the number of columns in the matrix.
unsigned getNumRows() const
Returns the number of rows in the matrix.
specific_decl_iterator - Iterates over a subrange of declarations stored in a DeclContext,...
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
DeclContext * getParent()
getParent - Returns the containing DeclContext.
bool isTranslationUnit() const
bool hasExternalLexicalStorage() const
Whether this DeclContext has external storage containing additional declarations that are lexically i...
bool isInlineNamespace() const
bool isFunctionOrMethod() const
Decl::Kind getDeclKind() const
DeclContext * getNonTransparentContext()
A reference to a declared variable, function, enum, etc.
Decl - This represents one declaration (or definition), e.g.
TemplateDecl * getDescribedTemplate() const
If this is a declaration that describes some template, this method returns that template declaration.
ASTContext & getASTContext() const LLVM_READONLY
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
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.
IdentifierOrOverloadedOperator getName() const
NestedNameSpecifier getQualifier() const
Return the nested name specifier that qualifies this name.
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_range enumerators() const
bool isFixed() const
Returns true if this is an Objective-C, C++11, or Microsoft-style enumeration with a fixed underlying...
QualType getIntegerType() const
Return the integer type this enum decl corresponds to.
EnumDecl * getDefinition() const
This represents one expression.
An expression trait intrinsic.
ExpressionTrait getTrait() const
Represents a member of a struct/union/class.
bool isBitField() const
Determines whether this field is a bitfield.
unsigned getBitWidthValue() const
Computes the bit width of this field, if this is a bit field.
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.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
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 C++ namespaces and their aliases.
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
CXXRecordDecl * getAsMicrosoftSuper() const
NamespaceAndPrefix getAsNamespaceAndPrefix() const
const Type * getAsType() const
NonTypeTemplateParmDecl - Declares a non-type template parameter, e.g., "Size" in.
bool isParameterPack() const
Whether this parameter is a non-type template parameter pack.
unsigned getIndex() const
Get the index of the template parameter within its parameter list.
unsigned getDepth() const
Get the nesting depth of the template parameter.
ObjCCategoryDecl - Represents a category declaration.
ivar_iterator ivar_begin() const
ivar_iterator ivar_end() const
ObjCInterfaceDecl * getClassInterface()
protocol_iterator protocol_end() const
protocol_iterator protocol_begin() const
ObjCProtocolList::iterator protocol_iterator
method_iterator meth_begin() const
method_iterator meth_end() const
Represents an ObjC class declaration.
ObjCIvarDecl - Represents an ObjC instance variable.
AccessControl getAccessControl() const
ObjCInterfaceDecl * getContainingInterface()
Return the class interface that this ivar is logically contained in; this is either the interface whe...
ObjCMethodDecl - Represents an instance or class method declaration.
unsigned param_size() const
param_type_iterator param_type_begin() const
param_type_iterator param_type_end() const
bool isDirectMethod() const
True if the method is tagged as objc_direct.
llvm::mapped_iterator< param_const_iterator, GetTypeFn > param_type_iterator
Selector getSelector() const
bool isInstanceMethod() const
QualType getReturnType() const
ObjCStringLiteral, used for Objective-C string literals i.e.
A reference to an overloaded function set, either an UnresolvedLookupExpr or an UnresolvedMemberExpr.
NestedNameSpecifier getQualifier() const
Fetches the nested-name qualifier, if one was given.
TemplateArgumentLoc const * getTemplateArgs() const
unsigned getNumTemplateArgs() const
DeclarationName getName() const
Gets the name looked up.
A structure for storing the information associated with an overloaded template name.
NamedDecl *const * iterator
A (possibly-)qualified type.
QualType getDesugaredType(const ASTContext &Context) const
Return the specified type with any "sugar" removed from the type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Represents a struct/union/class.
field_iterator field_end() const
RecordDecl * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
field_iterator field_begin() const
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Smart pointer class that efficiently represents Objective-C method names.
const IdentifierInfo * getIdentifierInfoForSlot(unsigned argIndex) const
Retrieve the identifier at a given position in the selector.
unsigned getNumArgs() const
Represents a function call to one of __builtin_LINE(), __builtin_COLUMN(), __builtin_FUNCTION(),...
SourceLocIdentKind getIdentKind() const
Encodes a location in the source.
StmtExpr - This is the GNU Statement Expression extension: ({int X=4; X;}).
unsigned getTemplateDepth() const
Stmt - This represents one statement.
StmtClass getStmtClass() const
StringLiteral - This represents a string literal expression, e.g.
StringRef getBytes() const
Allow access to clients that need the byte representation, such as ASTWriterStmt::VisitStringLiteral(...
Represents a reference to a non-type template parameter that has been substituted with a template arg...
Decl * getAssociatedDecl() const
A template-like entity which owns the whole pattern being substituted.
UnsignedOrNone getPackIndex() const
unsigned getIndex() const
Returns the index of the replaced parameter in the associated declaration.
Represents a reference to a non-type template parameter pack that has been substituted with a non-tem...
TemplateArgument getArgumentPack() const
Retrieve the template argument pack containing the substituted template arguments.
A structure for storing an already-substituted template template parameter pack.
Decl * getAssociatedDecl() const
A template-like entity which owns the whole pattern being substituted.
TemplateArgument getArgumentPack() const
Retrieve the template template argument pack with which this parameter was substituted.
unsigned getIndex() const
Returns the index of the replaced parameter in the associated declaration.
Represents the declaration of a struct/union/class/enum.
bool isBeingDefined() const
Return true if this decl is currently being defined.
TagKind getTagKind() const
Location wrapper for a TemplateArgument.
const TemplateArgument & getArgument() const
Represents a template argument.
Expr * getAsExpr() const
Retrieve the template argument as an expression.
QualType getAsType() const
Retrieve the type for a type template argument.
llvm::APSInt getAsIntegral() const
Retrieve the template argument as an integral value.
TemplateName getAsTemplate() const
Retrieve the template name for a template name argument.
bool structurallyEquals(const TemplateArgument &Other) const
Determines whether two template arguments are superficially the same.
QualType getIntegralType() const
Retrieve the type of the integral value.
ValueDecl * getAsDecl() const
Retrieve the declaration for a declaration non-type template argument.
ArrayRef< TemplateArgument > pack_elements() const
Iterator range referencing all of the elements of a template argument pack.
@ Declaration
The template argument is a declaration that was provided for a pointer, reference,...
@ Template
The template argument is a template name that was provided for a template template parameter.
@ StructuralValue
The template argument is a non-type template argument that can't be represented by the special-case D...
@ Pack
The template argument is actually a parameter pack.
@ TemplateExpansion
The template argument is a pack expansion of a template name that was provided for a template templat...
@ NullPtr
The template argument is a null pointer or null pointer to member that was provided for a non-type te...
@ Type
The template argument is a type.
@ Null
Represents an empty template argument, e.g., one that has not been deduced.
@ Integral
The template argument is an integral value stored in an llvm::APSInt that was provided for an integra...
@ Expression
The template argument is an expression, and we've not resolved it to one of the other forms yet,...
ArgKind getKind() const
Return the kind of stored template argument.
TemplateName getAsTemplateOrTemplatePattern() const
Retrieve the template argument as a template name; if the argument is a pack expansion,...
The base class of all kinds of template declarations (e.g., class, function, etc.).
TemplateParameterList * getTemplateParameters() const
Get the list of template parameters.
Represents a C++ template name within the type system.
TemplateDecl * getAsTemplateDecl(bool IgnoreDeduced=false) const
Retrieve the underlying template declaration that this template name refers to, if known.
DependentTemplateName * getAsDependentTemplateName() const
Retrieve the underlying dependent template name structure, if any.
OverloadedTemplateStorage * getAsOverloadedTemplate() const
Retrieve the underlying, overloaded function template declarations that this template name refers to,...
AssumedTemplateStorage * getAsAssumedTemplateName() const
Retrieve information on a name that has been assumed to be a template-name in order to permit a call ...
@ UsingTemplate
A template name that refers to a template declaration found through a specific using shadow declarati...
@ OverloadedTemplate
A set of overloaded template declarations.
@ Template
A single template declaration.
@ DependentTemplate
A dependent template name that has not been resolved to a template (or set of templates).
@ SubstTemplateTemplateParm
A template template parameter that has been substituted for some other template name.
@ SubstTemplateTemplateParmPack
A template template parameter pack that has been substituted for a template template argument pack,...
@ DeducedTemplate
A template name that refers to another TemplateName with deduced default arguments.
@ QualifiedTemplate
A qualified template name, where the qualification is kept to describe the source code as written.
@ AssumedTemplate
An unqualified-id that has been assumed to name a function template that will be found by ADL.
SubstTemplateTemplateParmPackStorage * getAsSubstTemplateTemplateParmPack() const
Retrieve the substituted template template parameter pack, if known.
Stores a list of template parameters for a TemplateDecl and its derived classes.
NamedDecl * getParam(unsigned Idx)
SourceLocation getTemplateLoc() const
TemplateTemplateParmDecl - Declares a template template parameter, e.g., "T" in.
TemplateNameKind templateParameterKind() const
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>.
bool isBuiltinType() const
Helper methods to distinguish type categories.
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)
const IdentifierInfo * getIdentifier() const
Returns the identifier to which this template name refers.
OverloadedOperatorKind getOperator() const
Return the overloaded operator to which this template name refers.
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
static UnsignedOrNone findUntaggedStructOrUnionIndex(RecordDecl *Anon)
Find the index of the given anonymous struct/union within its context.
bool IgnoreTemplateParmDepth
Whether to ignore comparing the depth of template param(TemplateTypeParm)
bool ErrorOnTagTypeMismatch
Whether warn or error on tag type mismatches.
NonEquivalentDeclSet & NonEquivalentDecls
Declaration (from, to) pairs that are known not to be equivalent (which we have already complained ab...
bool Complain
Whether to complain about failures.
DiagnosticBuilder Diag2(SourceLocation Loc, unsigned DiagID)
unsigned getApplicableDiagnostic(unsigned ErrorDiagnostic)
DiagnosticBuilder Diag1(SourceLocation Loc, unsigned DiagID)
bool IsEquivalent(Decl *D1, Decl *D2)
Determine whether the two declarations are structurally equivalent.