89#include "llvm/ADT/APInt.h"
90#include "llvm/ADT/APSInt.h"
91#include "llvm/ADT/STLExtras.h"
92#include "llvm/ADT/StringExtras.h"
93#include "llvm/Support/Compiler.h"
94#include "llvm/Support/ErrorHandling.h"
163 llvm_unreachable(
"Unhandled kind of DeclarationName");
170 StructuralEquivalenceContext &Context;
176 bool IsStmtEquivalent(
const AddrLabelExpr *E1,
const AddrLabelExpr *E2) {
180 bool IsStmtEquivalent(
const AtomicExpr *E1,
const AtomicExpr *E2) {
184 bool IsStmtEquivalent(
const BinaryOperator *E1,
const BinaryOperator *E2) {
188 bool IsStmtEquivalent(
const CallExpr *E1,
const CallExpr *E2) {
194 if (
static_cast<bool>(Callee1) !=
static_cast<bool>(Callee2))
198 if (!
static_cast<bool>(Callee1))
205 bool IsStmtEquivalent(
const CharacterLiteral *E1,
206 const CharacterLiteral *E2) {
210 bool IsStmtEquivalent(
const ChooseExpr *E1,
const ChooseExpr *E2) {
223 bool IsStmtEquivalent(
const DeclRefExpr *DRE1,
const DeclRefExpr *DRE2) {
224 const ValueDecl *Decl1 = DRE1->
getDecl();
225 const ValueDecl *Decl2 = DRE2->
getDecl();
226 if (!Decl1 || !Decl2)
229 const_cast<ValueDecl *
>(Decl2));
232 bool IsStmtEquivalent(
const DependentScopeDeclRefExpr *DE1,
233 const DependentScopeDeclRefExpr *DE2) {
241 bool IsStmtEquivalent(
const Expr *E1,
const Expr *E2) {
245 bool IsStmtEquivalent(
const ExpressionTraitExpr *E1,
246 const ExpressionTraitExpr *E2) {
250 bool IsStmtEquivalent(
const FloatingLiteral *E1,
const FloatingLiteral *E2) {
254 bool IsStmtEquivalent(
const GenericSelectionExpr *E1,
255 const GenericSelectionExpr *E2) {
258 std::optional<TypeSourceInfo *> Child1 = std::get<0>(Pair);
259 std::optional<TypeSourceInfo *> Child2 = std::get<1>(Pair);
261 if (!Child1 || !Child2)
265 (*Child2)->getType()))
272 bool IsStmtEquivalent(
const ImplicitCastExpr *CastE1,
273 const ImplicitCastExpr *CastE2) {
278 bool IsStmtEquivalent(
const IntegerLiteral *E1,
const IntegerLiteral *E2) {
282 bool IsStmtEquivalent(
const MemberExpr *E1,
const MemberExpr *E2) {
287 bool IsStmtEquivalent(
const ObjCStringLiteral *E1,
288 const ObjCStringLiteral *E2) {
293 bool IsStmtEquivalent(
const Stmt *S1,
const Stmt *S2) {
return true; }
295 bool IsStmtEquivalent(
const GotoStmt *S1,
const GotoStmt *S2) {
303 return ::IsStructurallyEquivalent(Name1, Name2);
306 bool IsStmtEquivalent(
const SourceLocExpr *E1,
const SourceLocExpr *E2) {
310 bool IsStmtEquivalent(
const StmtExpr *E1,
const StmtExpr *E2) {
314 bool IsStmtEquivalent(
const StringLiteral *E1,
const StringLiteral *E2) {
318 bool IsStmtEquivalent(
const SubstNonTypeTemplateParmExpr *E1,
319 const SubstNonTypeTemplateParmExpr *E2) {
330 bool IsStmtEquivalent(
const SubstNonTypeTemplateParmPackExpr *E1,
331 const SubstNonTypeTemplateParmPackExpr *E2) {
336 bool IsStmtEquivalent(
const TypeTraitExpr *E1,
const TypeTraitExpr *E2) {
341 std::optional<TypeSourceInfo *> Child1 = std::get<0>(Pair);
342 std::optional<TypeSourceInfo *> Child2 = std::get<1>(Pair);
344 if (!Child1 || !Child2)
348 (*Child2)->getType()))
354 bool IsStmtEquivalent(
const CXXDependentScopeMemberExpr *E1,
355 const CXXDependentScopeMemberExpr *E2) {
363 bool IsStmtEquivalent(
const UnaryExprOrTypeTraitExpr *E1,
364 const UnaryExprOrTypeTraitExpr *E2) {
371 bool IsStmtEquivalent(
const UnaryOperator *E1,
const UnaryOperator *E2) {
375 bool IsStmtEquivalent(
const VAArgExpr *E1,
const VAArgExpr *E2) {
380 bool IsStmtEquivalent(
const OverloadExpr *E1,
const OverloadExpr *E2) {
404 bool IsStmtEquivalent(
const CXXBoolLiteralExpr *E1,
const CXXBoolLiteralExpr *E2) {
409 bool TraverseStmt(
const Stmt *S1,
const Stmt *S2) {
return true; }
416#define STMT(CLASS, PARENT) \
417 bool TraverseStmt(const CLASS *S1, const CLASS *S2) { \
418 if (!TraverseStmt(static_cast<const PARENT *>(S1), \
419 static_cast<const PARENT *>(S2))) \
421 return IsStmtEquivalent(S1, S2); \
423#include "clang/AST/StmtNodes.inc"
431 bool IsEquivalent(
const Stmt *S1,
const Stmt *S2) {
442 llvm_unreachable(
"Can't traverse NoStmtClass");
443#define STMT(CLASS, PARENT) \
444 case Stmt::StmtClass::CLASS##Class: \
445 return TraverseStmt(static_cast<const CLASS *>(S1), \
446 static_cast<const CLASS *>(S2));
447#define ABSTRACT_STMT(S)
448#include "clang/AST/StmtNodes.inc"
450 llvm_unreachable(
"Invalid statement kind");
458struct AttrComparisonResult {
460 const Attr *A1 =
nullptr, *A2 =
nullptr;
470static AttrComparisonResult
481 auto RemoveInherited = [](
const Attr *A) {
return !A->isInherited(); };
483 llvm::copy_if(D1->
attrs(), std::back_inserter(A1), RemoveInherited);
484 llvm::copy_if(D2->
attrs(), std::back_inserter(A2), RemoveInherited);
488 auto I1 = A1.begin(), E1 = A1.end(), I2 = A2.begin(), E2 = A2.end();
489 for (; I1 != E1 && I2 != E2; ++I1, ++I2) {
490 bool R = (*I1)->isEquivalent(**I2, Context);
492 R = !Context.checkDeclQueue();
494 return {
false, *I1, *I2};
500 return {
false,
nullptr, *I2};
508 const Decl *PrimaryDecl =
nullptr) {
509 if (Context.Complain) {
512 const auto *DiagnoseDecl =
cast<TypeDecl>(PrimaryDecl ? PrimaryDecl : D2);
513 Context.Diag2(DiagnoseDecl->getLocation(),
514 diag::warn_odr_tag_type_with_attributes)
515 << Context.ToCtx.getTypeDeclType(DiagnoseDecl)
516 << (PrimaryDecl !=
nullptr);
518 Context.Diag1(R.A1->getLoc(), diag::note_odr_attr_here) << R.A1;
520 Context.Diag2(R.A2->getLoc(), diag::note_odr_attr_here) << R.A2;
578 if (
const auto *E2CXXOperatorCall = dyn_cast<CXXOperatorCallExpr>(S2)) {
579 if (
const auto *E1Unary = dyn_cast<UnaryOperator>(S1))
581 if (
const auto *E1Binary = dyn_cast<BinaryOperator>(S1))
584 if (
const auto *E1CXXOperatorCall = dyn_cast<CXXOperatorCallExpr>(S1)) {
585 if (
const auto *E2Unary = dyn_cast<UnaryOperator>(S2))
587 if (
const auto *E2Binary = dyn_cast<BinaryOperator>(S2))
592 StmtComparer Comparer(Context);
593 if (!Comparer.IsEquivalent(S1, S2))
598 std::optional<const Stmt *> Child1 = std::get<0>(Pair);
599 std::optional<const Stmt *> Child2 = std::get<1>(Pair);
602 if (!Child1 || !Child2)
618 if (!Name1 || !Name2)
619 return Name1 == Name2;
677 if (TemplateDeclN1 && TemplateDeclN2) {
683 }
else if (TemplateDeclN1 || TemplateDeclN2)
695 E1 = OS1->
end(), E2 = OS2->end();
696 for (; I1 != E1 && I2 != E2; ++I1, ++I2)
699 return I1 == E1 && I2 == E2;
717 P2->getArgumentPack()) &&
719 P2->getAssociatedDecl()) &&
732 llvm_unreachable(
"unimplemented");
791 llvm_unreachable(
"Invalid template argument kind");
798 if (Args1.size() != Args2.size())
800 for (
unsigned I = 0, N = Args1.size(); I != N; ++I) {
896 if (!Context.StrictTypeSpelling) {
913 TC = Type::FunctionNoProto;
916 TC = Type::FunctionNoProto;
917 else if (Context.LangOpts.C23 && !Context.StrictTypeSpelling &&
939 T1 = Context.FromCtx.IntTy;
945 T2 = Context.ToCtx.IntTy;
968 case Type::ArrayParameter:
982 case Type::BlockPointer:
989 case Type::LValueReference:
990 case Type::RValueReference: {
993 if (Ref1->isSpelledAsLValue() != Ref2->isSpelledAsLValue())
995 if (Ref1->isInnerRef() != Ref2->isInnerRef())
998 Ref2->getPointeeTypeAsWritten()))
1003 case Type::MemberPointer: {
1007 MemPtr2->getPointeeType()))
1010 MemPtr2->getQualifier()))
1013 *D2 = MemPtr2->getMostRecentCXXRecordDecl();
1021 case Type::ConstantArray: {
1024 if (!llvm::APInt::isSameValue(Array1->getSize(), Array2->getSize()))
1032 case Type::IncompleteArray:
1038 case Type::VariableArray: {
1042 Array2->getSizeExpr()))
1051 case Type::DependentSizedArray: {
1055 Array2->getSizeExpr()))
1064 case Type::DependentAddressSpace: {
1068 DepAddressSpace2->getAddrSpaceExpr()))
1071 DepAddressSpace2->getPointeeType()))
1077 case Type::DependentSizedExtVector: {
1081 Vec2->getSizeExpr()))
1084 Vec2->getElementType()))
1089 case Type::DependentVector: {
1092 if (Vec1->getVectorKind() != Vec2->getVectorKind())
1095 Vec2->getSizeExpr()))
1098 Vec2->getElementType()))
1104 case Type::ExtVector: {
1108 Vec2->getElementType()))
1110 if (Vec1->getNumElements() != Vec2->getNumElements())
1112 if (Vec1->getVectorKind() != Vec2->getVectorKind())
1117 case Type::DependentSizedMatrix: {
1132 case Type::ConstantMatrix: {
1145 case Type::FunctionProto: {
1149 if (Proto1->getNumParams() != Proto2->getNumParams())
1151 for (
unsigned I = 0, N = Proto1->getNumParams(); I != N; ++I) {
1153 Proto2->getParamType(I)))
1156 if (Proto1->isVariadic() != Proto2->isVariadic())
1159 if (Proto1->getMethodQuals() != Proto2->getMethodQuals())
1163 const auto *OrigProto1 =
1165 const auto *OrigProto2 =
1174 case Type::FunctionNoProto: {
1178 Function2->getReturnType()))
1181 Function2->getExtInfo()))
1186 case Type::UnresolvedUsing:
1193 case Type::Attributed:
1204 case Type::CountAttributed:
1211 case Type::LateParsedAttr:
1218 case Type::BTFTagAttributed:
1225 case Type::OverflowBehavior:
1232 case Type::HLSLAttributedResource:
1245 Res2->getSampleCountExpr()))
1247 HLSLAttributedResourceType::Attributes Attrs1 = Res1->getAttrs();
1248 HLSLAttributedResourceType::Attributes Attrs2 = Res2->getAttrs();
1249 Attrs1.SampleCountExpr = Attrs2.SampleCountExpr =
nullptr;
1250 if (Attrs1 != Attrs2)
1255 case Type::HLSLInlineSpirv:
1263 for (
size_t I = 0; I < cast<HLSLInlineSpirvType>(T1)->getOperands().size();
1278 case Type::MacroQualified:
1287 if (U1->getKeyword() != U2->getKeyword())
1290 U2->getQualifier()))
1298 case Type::Typedef: {
1300 if (U1->getKeyword() != U2->getKeyword())
1303 U2->getQualifier()))
1307 if (U1->typeMatchesDecl() != U2->typeMatchesDecl())
1309 if (!U1->typeMatchesDecl() &&
1315 case Type::TypeOfExpr:
1329 case Type::UnaryTransform:
1336 case Type::Decltype:
1347 Auto2->getDeducedType()))
1349 if (Auto1->isConstrained() != Auto2->isConstrained())
1351 if (Auto1->isConstrained()) {
1352 if (Auto1->getTypeConstraintConcept().getAsTemplateDecl() !=
1353 Auto2->getTypeConstraintConcept().getAsTemplateDecl())
1356 Auto1->getTypeConstraintArguments(),
1357 Auto2->getTypeConstraintArguments()))
1363 case Type::DeducedTemplateSpecialization: {
1367 DT2->getTemplateName()))
1370 DT2->getDeducedType()))
1377 case Type::InjectedClassName: {
1379 if (TT1->getKeyword() != TT2->getKeyword())
1381 if (TT1->isTagOwned() != TT2->isTagOwned())
1384 TT2->getQualifier()))
1391 case Type::TemplateTypeParm: {
1394 if (!Context.IgnoreTemplateParmDepth &&
1395 Parm1->getDepth() != Parm2->getDepth())
1397 if (Parm1->getIndex() != Parm2->getIndex())
1399 if (Parm1->isParameterPack() != Parm2->isParameterPack())
1406 case Type::SubstTemplateTypeParm: {
1410 Subst2->getReplacementType()))
1413 Subst2->getAssociatedDecl()))
1415 if (Subst1->getIndex() != Subst2->getIndex())
1417 if (Subst1->getPackIndex() != Subst2->getPackIndex())
1422 case Type::SubstBuiltinTemplatePack: {
1426 Subst2->getArgumentPack()))
1430 case Type::SubstTemplateTypeParmPack: {
1434 Subst2->getAssociatedDecl()))
1436 if (Subst1->getIndex() != Subst2->getIndex())
1439 Subst2->getArgumentPack()))
1444 case Type::TemplateSpecialization: {
1448 Spec2->getTemplateName()))
1451 Spec2->template_arguments()))
1456 case Type::DependentName: {
1460 Typename2->getQualifier()))
1463 Typename2->getIdentifier()))
1469 case Type::PackExpansion:
1476 case Type::PackIndexing:
1486 case Type::ObjCInterface: {
1495 case Type::ObjCTypeParam: {
1501 if (Obj1->getNumProtocols() != Obj2->getNumProtocols())
1503 for (
unsigned I = 0, N = Obj1->getNumProtocols(); I != N; ++I) {
1505 Obj2->getProtocol(I)))
1511 case Type::ObjCObject: {
1515 Obj2->getBaseType()))
1517 if (Obj1->getNumProtocols() != Obj2->getNumProtocols())
1519 for (
unsigned I = 0, N = Obj1->getNumProtocols(); I != N; ++I) {
1521 Obj2->getProtocol(I)))
1527 case Type::ObjCObjectPointer: {
1531 Ptr2->getPointeeType()))
1547 case Type::BitInt: {
1551 if (Int1->isUnsigned() != Int2->isUnsigned() ||
1552 Int1->getNumBits() != Int2->getNumBits())
1556 case Type::DependentBitInt: {
1560 if (Int1->isUnsigned() != Int2->isUnsigned() ||
1562 Int2->getNumBitsExpr()))
1566 case Type::PredefinedSugar: {
1569 if (TP1->getKind() != TP2->getKind())
1612 if (Context.LangOpts.C23 &&
1630 if (Context.Complain) {
1632 Owner2->getLocation(),
1633 Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent))
1634 << Owner2Type << (&Context.FromCtx != &Context.ToCtx);
1635 Context.Diag2(Field2->
getLocation(), diag::note_odr_field_name)
1637 Context.Diag1(Field1->
getLocation(), diag::note_odr_field_name)
1645 if (Context.Complain) {
1647 Owner2->getLocation(),
1648 Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent))
1649 << Owner2Type << (&Context.FromCtx != &Context.ToCtx);
1650 Context.Diag2(Field2->
getLocation(), diag::note_odr_field)
1652 Context.Diag1(Field1->
getLocation(), diag::note_odr_field)
1664 bool Diagnose =
true;
1668 if (Diagnose && Context.Complain) {
1669 auto DiagNote = [&](
const FieldDecl *FD,
1677 (Context.*
Diag)(FD->
getLocation(), diag::note_odr_field_not_bit_field)
1683 Owner2->getLocation(),
1684 Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent))
1685 << Owner2Type << (&Context.FromCtx != &Context.ToCtx);
1700 Context.ToCtx.getCanonicalTagType(Owner2));
1715 if (!Method1 && !Method2)
1717 if (!Method1 || !Method2)
1720 bool PropertiesEqual =
1734 if (!PropertiesEqual)
1738 if (
auto *Constructor1 = dyn_cast<CXXConstructorDecl>(Method1)) {
1740 if (!Constructor1->getExplicitSpecifier().isEquivalent(
1741 Constructor2->getExplicitSpecifier()))
1745 if (
auto *Conversion1 = dyn_cast<CXXConversionDecl>(Method1)) {
1747 if (!Conversion1->getExplicitSpecifier().isEquivalent(
1748 Conversion2->getExplicitSpecifier()))
1751 Conversion2->getConversionType()))
1775 "Must be called on lambda classes");
1806 if (
const auto *ND1 = dyn_cast<NamedDecl>(DC1)) {
1813 if (
auto *D1Spec = dyn_cast<ClassTemplateSpecializationDecl>(DC1)) {
1814 auto *D2Spec = dyn_cast<ClassTemplateSpecializationDecl>(DC2);
1830 if (
const TypedefNameDecl *TypedefName = D.getTypedefNameForAnonDecl())
1831 return TypedefName->getIdentifier();
1865 if (Context.Complain) {
1866 Context.Diag2(D2->
getLocation(), Context.getApplicableDiagnostic(
1867 diag::err_odr_tag_type_inconsistent))
1868 << Context.ToCtx.getCanonicalTagType(D2)
1869 << (&Context.FromCtx != &Context.ToCtx);
1870 Context.Diag1(D1->
getLocation(), diag::note_odr_tag_kind_here)
1884 if (*Index1 != *Index2)
1895 if (!Context.LangOpts.C23 &&
1901 const auto *Spec1 = dyn_cast<ClassTemplateSpecializationDecl>(D1);
1902 const auto *Spec2 = dyn_cast<ClassTemplateSpecializationDecl>(D2);
1903 if (Spec1 && Spec2) {
1906 Spec2->getSpecializedTemplate()))
1910 if (Spec1->getTemplateArgs().size() != Spec2->getTemplateArgs().size())
1913 for (
unsigned I = 0, N = Spec1->getTemplateArgs().size(); I != N; ++I)
1915 Spec2->getTemplateArgs().get(I)))
1920 else if (Spec1 || Spec2)
1929 return !Context.LangOpts.C23;
1933 if (Context.LangOpts.C23 &&
1951 if (
auto *D1CXX = dyn_cast<CXXRecordDecl>(D1)) {
1952 if (
auto *D2CXX = dyn_cast<CXXRecordDecl>(D2)) {
1953 if (D1CXX->hasExternalLexicalStorage() &&
1954 !D1CXX->isCompleteDefinition()) {
1955 D1CXX->getASTContext().getExternalSource()->CompleteType(D1CXX);
1958 if (D1CXX->isLambda() != D2CXX->isLambda())
1960 if (D1CXX->isLambda()) {
1965 if (D1CXX->getNumBases() != D2CXX->getNumBases()) {
1966 if (Context.Complain) {
1968 Context.getApplicableDiagnostic(
1969 diag::err_odr_tag_type_inconsistent))
1970 << Context.ToCtx.getCanonicalTagType(D2)
1971 << (&Context.FromCtx != &Context.ToCtx);
1972 Context.Diag2(D2->
getLocation(), diag::note_odr_number_of_bases)
1973 << D2CXX->getNumBases();
1974 Context.Diag1(D1->
getLocation(), diag::note_odr_number_of_bases)
1975 << D1CXX->getNumBases();
1982 BaseEnd1 = D1CXX->bases_end(),
1983 Base2 = D2CXX->bases_begin();
1984 Base1 != BaseEnd1; ++Base1, ++Base2) {
1986 Base2->getType())) {
1987 if (Context.Complain) {
1989 Context.getApplicableDiagnostic(
1990 diag::err_odr_tag_type_inconsistent))
1991 << Context.ToCtx.getCanonicalTagType(D2)
1992 << (&Context.FromCtx != &Context.ToCtx);
1993 Context.Diag2(Base2->getBeginLoc(), diag::note_odr_base)
1994 << Base2->getType() << Base2->getSourceRange();
1995 Context.Diag1(Base1->getBeginLoc(), diag::note_odr_base)
1996 << Base1->getType() << Base1->getSourceRange();
2002 if (Base1->isVirtual() != Base2->isVirtual()) {
2003 if (Context.Complain) {
2005 Context.getApplicableDiagnostic(
2006 diag::err_odr_tag_type_inconsistent))
2007 << Context.ToCtx.getCanonicalTagType(D2)
2008 << (&Context.FromCtx != &Context.ToCtx);
2009 Context.Diag2(Base2->getBeginLoc(), diag::note_odr_virtual_base)
2010 << Base2->isVirtual() << Base2->getSourceRange();
2011 Context.Diag1(Base1->getBeginLoc(), diag::note_odr_base)
2012 << Base1->isVirtual() << Base1->getSourceRange();
2020 Friend2End = D2CXX->friend_end();
2022 Friend1End = D1CXX->friend_end();
2023 Friend1 != Friend1End; ++Friend1, ++Friend2) {
2024 if (Friend2 == Friend2End) {
2025 if (Context.Complain) {
2027 Context.getApplicableDiagnostic(
2028 diag::err_odr_tag_type_inconsistent))
2029 << Context.ToCtx.getCanonicalTagType(D2CXX)
2030 << (&Context.FromCtx != &Context.ToCtx);
2031 Context.Diag1((*Friend1)->getFriendLoc(), diag::note_odr_friend);
2032 Context.Diag2(D2->
getLocation(), diag::note_odr_missing_friend);
2038 if (Context.Complain) {
2040 Context.getApplicableDiagnostic(
2041 diag::err_odr_tag_type_inconsistent))
2042 << Context.ToCtx.getCanonicalTagType(D2CXX)
2043 << (&Context.FromCtx != &Context.ToCtx);
2044 Context.Diag1((*Friend1)->getFriendLoc(), diag::note_odr_friend);
2045 Context.Diag2((*Friend2)->getFriendLoc(), diag::note_odr_friend);
2051 if (Friend2 != Friend2End) {
2052 if (Context.Complain) {
2054 Context.getApplicableDiagnostic(
2055 diag::err_odr_tag_type_inconsistent))
2056 << Context.ToCtx.getCanonicalTagType(D2)
2057 << (&Context.FromCtx != &Context.ToCtx);
2058 Context.Diag2((*Friend2)->getFriendLoc(), diag::note_odr_friend);
2059 Context.Diag1(D1->
getLocation(), diag::note_odr_missing_friend);
2063 }
else if (D1CXX->getNumBases() > 0) {
2064 if (Context.Complain) {
2066 Context.getApplicableDiagnostic(
2067 diag::err_odr_tag_type_inconsistent))
2068 << Context.ToCtx.getCanonicalTagType(D2)
2069 << (&Context.FromCtx != &Context.ToCtx);
2071 Context.Diag1(Base1->
getBeginLoc(), diag::note_odr_base)
2073 Context.Diag2(D2->
getLocation(), diag::note_odr_missing_base);
2080 CanQualType D2Type = Context.ToCtx.getCanonicalTagType(D2);
2085 Field1 != Field1End; ++Field1, ++Field2) {
2086 if (Field2 == Field2End) {
2087 if (Context.Complain) {
2089 Context.getApplicableDiagnostic(
2090 diag::err_odr_tag_type_inconsistent))
2091 << Context.ToCtx.getCanonicalTagType(D2)
2092 << (&Context.FromCtx != &Context.ToCtx);
2093 Context.Diag1(Field1->getLocation(), diag::note_odr_field)
2094 << Field1->getDeclName() << Field1->getType();
2095 Context.Diag2(D2->
getLocation(), diag::note_odr_missing_field);
2104 if (Field2 != Field2End) {
2105 if (Context.Complain) {
2106 Context.Diag2(D2->
getLocation(), Context.getApplicableDiagnostic(
2107 diag::err_odr_tag_type_inconsistent))
2108 << Context.ToCtx.getCanonicalTagType(D2)
2109 << (&Context.FromCtx != &Context.ToCtx);
2110 Context.Diag2(Field2->getLocation(), diag::note_odr_field)
2111 << Field2->getDeclName() << Field2->getType();
2112 Context.Diag1(D1->
getLocation(), diag::note_odr_missing_field);
2123 const llvm::APSInt &FromVal = D1->
getInitVal();
2124 const llvm::APSInt &ToVal = D2->
getInitVal();
2125 if (FromVal.isSigned() != ToVal.isSigned())
2127 if (FromVal.getBitWidth() != ToVal.getBitWidth())
2129 if (FromVal != ToVal)
2156 if (Context.LangOpts.C23 &&
2162 if (Context.LangOpts.C23) {
2164 if (Context.Complain) {
2166 Context.getApplicableDiagnostic(
2167 diag::err_odr_tag_type_inconsistent))
2168 << Context.ToCtx.getCanonicalTagType(D2)
2169 << (&Context.FromCtx != &Context.ToCtx);
2172 ? diag::note_odr_fixed_underlying_type
2173 : diag::note_odr_missing_fixed_underlying_type)
2177 ? diag::note_odr_fixed_underlying_type
2178 : diag::note_odr_missing_fixed_underlying_type)
2184 assert(D2->
isFixed() &&
"enums expected to have fixed underlying types");
2187 if (Context.Complain) {
2189 Context.getApplicableDiagnostic(
2190 diag::err_odr_tag_type_inconsistent))
2191 << Context.ToCtx.getCanonicalTagType(D2)
2192 << (&Context.FromCtx != &Context.ToCtx);
2194 diag::note_odr_incompatible_fixed_underlying_type)
2203 auto CopyEnumerators =
2206 Cont.push_back(ECD);
2213 if (Context.LangOpts.C23) {
2215 return LHS->
getName() < RHS->getName();
2217 llvm::sort(D1Enums, Sorter);
2218 llvm::sort(D2Enums, Sorter);
2221 auto EC2 = D2Enums.begin(), EC2End = D2Enums.end();
2222 for (
auto EC1 = D1Enums.begin(), EC1End = D1Enums.end(); EC1 != EC1End;
2224 if (EC2 == EC2End) {
2225 if (Context.Complain) {
2227 Context.getApplicableDiagnostic(
2228 diag::err_odr_tag_type_inconsistent))
2229 << Context.ToCtx.getCanonicalTagType(D2)
2230 << (&Context.FromCtx != &Context.ToCtx);
2231 Context.Diag1((*EC1)->getLocation(), diag::note_odr_enumerator)
2232 << (*EC1)->getDeclName() <<
toString((*EC1)->getInitVal(), 10);
2233 Context.Diag2(D2->
getLocation(), diag::note_odr_missing_enumerator);
2238 llvm::APSInt Val1 = (*EC1)->getInitVal();
2239 llvm::APSInt Val2 = (*EC2)->getInitVal();
2240 if (!llvm::APSInt::isSameValue(Val1, Val2) ||
2242 (*EC2)->getIdentifier())) {
2243 if (Context.Complain) {
2245 Context.getApplicableDiagnostic(
2246 diag::err_odr_tag_type_inconsistent))
2247 << Context.ToCtx.getCanonicalTagType(D2)
2248 << (&Context.FromCtx != &Context.ToCtx);
2249 Context.Diag2((*EC2)->getLocation(), diag::note_odr_enumerator)
2250 << (*EC2)->getDeclName() <<
toString((*EC2)->getInitVal(), 10);
2251 Context.Diag1((*EC1)->getLocation(), diag::note_odr_enumerator)
2252 << (*EC1)->getDeclName() <<
toString((*EC1)->getInitVal(), 10);
2256 if (Context.LangOpts.C23 &&
2261 if (EC2 != EC2End) {
2262 if (Context.Complain) {
2263 Context.Diag2(D2->
getLocation(), Context.getApplicableDiagnostic(
2264 diag::err_odr_tag_type_inconsistent))
2265 << Context.ToCtx.getCanonicalTagType(D2)
2266 << (&Context.FromCtx != &Context.ToCtx);
2267 Context.Diag2((*EC2)->getLocation(), diag::note_odr_enumerator)
2268 << (*EC2)->getDeclName() <<
toString((*EC2)->getInitVal(), 10);
2269 Context.Diag1(D1->
getLocation(), diag::note_odr_missing_enumerator);
2280 if (Params1->
size() != Params2->
size()) {
2281 if (Context.Complain) {
2283 Context.getApplicableDiagnostic(
2284 diag::err_odr_different_num_template_parameters))
2285 << Params1->
size() << Params2->
size();
2287 diag::note_odr_template_parameter_list);
2292 for (
unsigned I = 0, N = Params1->
size(); I != N; ++I) {
2294 if (Context.Complain) {
2296 Context.getApplicableDiagnostic(
2297 diag::err_odr_different_template_parameter_kind));
2299 diag::note_odr_template_parameter_here);
2317 if (Context.Complain) {
2319 Context.getApplicableDiagnostic(
2320 diag::err_odr_parameter_pack_non_pack))
2322 Context.Diag1(D1->
getLocation(), diag::note_odr_parameter_pack_non_pack)
2335 if (Context.Complain) {
2337 Context.getApplicableDiagnostic(
2338 diag::err_odr_parameter_pack_non_pack))
2340 Context.Diag1(D1->
getLocation(), diag::note_odr_parameter_pack_non_pack)
2351 if (Context.Complain) {
2353 Context.getApplicableDiagnostic(
2354 diag::err_odr_non_type_parameter_type_inconsistent))
2356 Context.Diag1(D1->
getLocation(), diag::note_odr_value_here)
2369 if (Context.Complain) {
2371 Context.getApplicableDiagnostic(
2372 diag::err_odr_parameter_pack_non_pack))
2374 Context.Diag1(D1->
getLocation(), diag::note_odr_parameter_pack_non_pack)
2501 llvm_unreachable(
"unknown friend template kind");
2552 bool PropertiesEqual =
2556 if (!PropertiesEqual)
2563 if (NumArgs != Selector2.getNumArgs())
2567 unsigned SlotsToCheck = NumArgs > 0 ? NumArgs : 1;
2568 for (
unsigned I = 0; I < SlotsToCheck; ++I) {
2570 Selector2.getIdentifierInfoForSlot(I)))
2580 "Same number of arguments should be already enforced in Selector checks");
2586 (ParamT1 != ParamT1End) && (ParamT2 != ParamT2End);
2587 ++ParamT1, ++ParamT2) {
2603 if ((!Intf1 || !Intf2) && (Intf1 != Intf2))
2615 Protocol1 != Protocol1End; ++Protocol1, ++Protocol2) {
2616 if (Protocol2 == Protocol2End)
2619 (*Protocol2)->getIdentifier()))
2622 if (Protocol2 != Protocol2End)
2627 Intf2 ? Context.ToCtx.getObjCInterfaceType(Intf2) :
QualType();
2632 Ivar1 != Ivar1End; ++Ivar1, ++Ivar2) {
2633 if (Ivar2 == Ivar2End)
2638 if (Ivar2 != Ivar2End)
2646 Method1 != Method1End; ++Method1, ++Method2) {
2647 if (Method2 == Method2End)
2652 if (Method2 != Method2End)
2669 std::pair<Decl *, Decl *> P{D1, D2};
2673 if (Context.NonEquivalentDecls.count(
2674 std::make_tuple(D1, D2, Context.IgnoreTemplateParmDepth)))
2680 bool Inserted = Context.VisitedDecls.insert(P).second;
2684 Context.DeclsToCheck.push(P);
2691 assert(
Complain &&
"Not allowed to complain");
2693 FromCtx.getDiagnostics().notePriorDiagnosticFrom(
ToCtx.getDiagnostics());
2695 return FromCtx.getDiagnostics().Report(Loc, DiagID);
2700 assert(
Complain &&
"Not allowed to complain");
2702 ToCtx.getDiagnostics().notePriorDiagnosticFrom(
FromCtx.getDiagnostics());
2704 return ToCtx.getDiagnostics().Report(Loc, DiagID);
2710 CanQualType AnonTy = Context.getCanonicalTagType(Anon);
2712 const auto *Owner = dyn_cast<RecordDecl>(Anon->
getDeclContext());
2714 return std::nullopt;
2717 for (
const auto *D : Owner->noload_decls()) {
2718 const auto *F = dyn_cast<FieldDecl>(D);
2722 if (F->isAnonymousStructOrUnion()) {
2723 if (Context.hasSameType(F->getType(), AnonTy))
2732 if (
const auto *RecType = dyn_cast<RecordType>(FieldType)) {
2733 const RecordDecl *RecDecl = RecType->getDecl();
2735 if (Context.hasSameType(FieldType, AnonTy))
2747 unsigned ErrorDiagnostic) {
2749 return ErrorDiagnostic;
2751 switch (ErrorDiagnostic) {
2752 case diag::err_odr_variable_type_inconsistent:
2753 return diag::warn_odr_variable_type_inconsistent;
2754 case diag::err_odr_variable_multiple_def:
2755 return diag::warn_odr_variable_multiple_def;
2756 case diag::err_odr_function_type_inconsistent:
2757 return diag::warn_odr_function_type_inconsistent;
2758 case diag::err_odr_tag_type_inconsistent:
2759 return diag::warn_odr_tag_type_inconsistent;
2760 case diag::err_odr_field_type_inconsistent:
2761 return diag::warn_odr_field_type_inconsistent;
2762 case diag::err_odr_ivar_type_inconsistent:
2763 return diag::warn_odr_ivar_type_inconsistent;
2764 case diag::err_odr_objc_superclass_inconsistent:
2765 return diag::warn_odr_objc_superclass_inconsistent;
2766 case diag::err_odr_objc_method_result_type_inconsistent:
2767 return diag::warn_odr_objc_method_result_type_inconsistent;
2768 case diag::err_odr_objc_method_num_params_inconsistent:
2769 return diag::warn_odr_objc_method_num_params_inconsistent;
2770 case diag::err_odr_objc_method_param_type_inconsistent:
2771 return diag::warn_odr_objc_method_param_type_inconsistent;
2772 case diag::err_odr_objc_method_variadic_inconsistent:
2773 return diag::warn_odr_objc_method_variadic_inconsistent;
2774 case diag::err_odr_objc_property_type_inconsistent:
2775 return diag::warn_odr_objc_property_type_inconsistent;
2776 case diag::err_odr_objc_property_impl_kind_inconsistent:
2777 return diag::warn_odr_objc_property_impl_kind_inconsistent;
2778 case diag::err_odr_objc_synthesize_ivar_inconsistent:
2779 return diag::warn_odr_objc_synthesize_ivar_inconsistent;
2780 case diag::err_odr_different_num_template_parameters:
2781 return diag::warn_odr_different_num_template_parameters;
2782 case diag::err_odr_different_template_parameter_kind:
2783 return diag::warn_odr_different_template_parameter_kind;
2784 case diag::err_odr_parameter_pack_non_pack:
2785 return diag::warn_odr_parameter_pack_non_pack;
2786 case diag::err_odr_non_type_parameter_type_inconsistent:
2787 return diag::warn_odr_non_type_parameter_type_inconsistent;
2789 llvm_unreachable(
"Diagnostic kind not handled in preceding switch");
2829bool StructuralEquivalenceContext::CheckCommonEquivalence(
Decl *D1,
Decl *D2) {
2833 if ((Template1 !=
nullptr) != (Template2 !=
nullptr))
2843bool StructuralEquivalenceContext::CheckKindSpecificEquivalence(
2853#define ABSTRACT_DECL(DECL)
2854#define DECL(DERIVED, BASE) \
2855 case Decl::Kind::DERIVED: \
2856 return ::IsStructurallyEquivalent(*this, static_cast<DERIVED##Decl *>(D1), \
2857 static_cast<DERIVED##Decl *>(D2));
2858#include "clang/AST/DeclNodes.inc"
2870 Decl *D2 = P.second;
2873 CheckCommonEquivalence(D1, D2) && CheckKindSpecificEquivalence(D1, D2);
2888bool StructuralEquivalenceContext::Finish() {
return checkDeclQueue(); }
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 AttrComparisonResult areDeclAttrsEquivalent(const Decl *D1, const Decl *D2, StructuralEquivalenceContext &Context)
Determines whether D1 and D2 have compatible sets of attributes for the purposes of structural equiva...
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)
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 ...
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.
Attr - This represents one attribute.
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.
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.
CXXBaseSpecifier * base_class_iterator
Iterator that traverses the base classes of a 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.
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
unsigned getValue() const
CharacterLiteralKind getKind() const
Declaration of a class template.
CXXRecordDecl * getTemplatedDecl() const
Get the underlying class declarations of the template.
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.
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
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.
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.
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
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,...
virtual 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...
bool isPackExpansion() const
Declaration of a friend template.
TemplateName getFriendTemplateName() const
FriendTemplateEntityKind getFriendKind() const
ArrayRef< TemplateParameterList * > getTemplateParameterLists() const
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
ArrayRef< TypeSourceInfo * > getAssocTypeSourceInfos() const
LabelDecl * getLabel() const
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
Represents a field injected from an anonymous union/struct into the parent scope.
FieldDecl * getAnonField() const
QualType getElementType() const
Returns type of the elements being stored in the matrix.
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
@ MicrosoftSuper
Microsoft's '__super' specifier, stored as a CXXRecordDecl* of the class it appeared in.
@ Global
The global specifier '::'. There is no stored value.
@ Type
A type, stored as a Type*.
@ Namespace
A namespace-like entity, stored as a NamespaceBaseDecl*.
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()
specific_decl_iterator< ObjCIvarDecl > ivar_iterator
protocol_iterator protocol_end() const
protocol_iterator protocol_begin() const
ObjCProtocolList::iterator protocol_iterator
method_iterator meth_begin() const
specific_decl_iterator< ObjCMethodDecl > method_iterator
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.
Selector getSelector() const
bool isInstanceMethod() const
llvm::mapped_iterator< param_const_iterator, GetTypeFn > param_type_iterator
QualType getReturnType() const
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.
QualType getCanonicalType() const
Represents a struct/union/class.
field_iterator field_end() const
RecordDecl * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
specific_decl_iterator< FieldDecl > field_iterator
field_iterator field_begin() const
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
SourceLocIdentKind getIdentKind() const
Encodes a location in the source.
unsigned getTemplateDepth() const
Stmt - This represents one statement.
StmtClass getStmtClass() const
StringRef getBytes() const
Allow access to clients that need the byte representation, such as ASTWriterStmt::VisitStringLiteral(...
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.
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.
bool isNull() const
Determine whether this template name is NULL.
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)
Expr * getRequiresClause()
The constraint-expression of the associated requires-clause.
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.
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 isEnumeralType() const
bool isBuiltinType() const
Helper methods to distinguish type categories.
TypeClass getTypeClass() const
Base class for declarations which introduce a typedef-name.
QualType getUnderlyingType() const
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 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.
bool isEquivalent(StructuralEquivalenceContext &Context, QualType T1, QualType T2)
Determine structural equivalence of two types.
std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl
All declarations that can appear in a module declaration.
Top level wrappers for InstallAPI frontend operations.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool isUnresolvedExceptionSpec(ExceptionSpecificationType ESpecType)
OptionalUnsigned< unsigned > UnsignedOrNone
bool isComputedNoexcept(ExceptionSpecificationType ESpecType)
U cast(CodeGen::Address addr)
@ 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.
RAII helper that is used to suppress diagnostics during attribute equivalence checking.
ASTContext & FromCtx
AST contexts for which we are checking structural equivalence.
bool LastDiagFromC2
true if the last diagnostic came from ToCtx.
bool checkDeclQueue()
Iterate over the decl pairs in DeclsToCheck until either an inequivalent pair is found or the queue i...
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.