29#include "llvm/ADT/STLExtras.h"
78 if (CandDecl->isInvalidDecl())
86 ThisTy, Classification,
103 CtorInfo.ConstructorTmpl, CtorInfo.FoundDecl,
nullptr,
121 bool AllowUserDefined) {
129 return Decl && (AllowUserDefined || !
Decl->isUserProvided()) &&
145 return Decl && (AllowUserDefined || !
Decl->isUserProvided()) &&
186 const auto *BaseDecl = B.getType()->getAsCXXRecordDecl();
191 if (B.isVirtual() || (!BaseDecl->isDependentType() &&
198 if (Field->getType()->isDependentType())
200 if (Field->getType()->isReferenceType())
225 auto IsUnion = [&, Is = std::optional<bool>{}]()
mutable {
260 if (std::optional<ASTContext::CXXRecordDeclRelocationInfo> Info =
262 return Info->IsRelocatable;
280 if (
Context.containsNonRelocatablePointerAuth(
Type))
298 if (!
T->getType()->isVariableArrayType())
301 S.
Diag(
T->getTypeLoc().getBeginLoc(), diag::err_vla_unsupported)
312 if (!
T->getType()->isAtomicType())
315 S.
Diag(
T->getTypeLoc().getBeginLoc(), diag::err_atomic_unsupported)
340 llvm_unreachable(
"not a UTT");
342 case UTT_IsCompleteType:
351 case UTT_IsFloatingPoint:
353 case UTT_IsBoundedArray:
355 case UTT_IsLvalueReference:
356 case UTT_IsRvalueReference:
357 case UTT_IsMemberFunctionPointer:
358 case UTT_IsMemberObjectPointer:
360 case UTT_IsScopedEnum:
364 case UTT_IsReference:
365 case UTT_IsArithmetic:
366 case UTT_IsFundamental:
370 case UTT_IsMemberPointer:
371 case UTT_IsTypedResourceElementCompatible:
372 case UTT_IsConstantBufferElementCompatible:
383 case UTT_IsUnboundedArray:
387 case UTT_IsInterfaceClass:
391 case UTT_StructuredBindingSize:
397 case UTT_IsPolymorphic:
402 Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);
411 Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);
415 case UTT_IsAggregate:
416 case UTT_IsImplicitLifetime:
421 Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);
425 case UTT_HasUniqueObjectRepresentations:
430 Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);
435 case UTT_IsTriviallyCopyable:
436 case UTT_IsStandardLayout:
439 case UTT_IsBitwiseCloneable:
442 case UTT_IsTriviallyRelocatable:
443 case UTT_IsTriviallyEqualityComparable:
444 case UTT_IsCppTriviallyRelocatable:
445 case UTT_CanPassInRegs:
449 case UTT_HasNothrowAssign:
450 case UTT_HasNothrowMoveAssign:
451 case UTT_HasNothrowConstructor:
452 case UTT_HasNothrowCopy:
453 case UTT_HasTrivialAssign:
454 case UTT_HasTrivialMoveAssign:
455 case UTT_HasTrivialDefaultConstructor:
456 case UTT_HasTrivialMoveConstructor:
457 case UTT_HasTrivialCopy:
458 case UTT_HasTrivialDestructor:
459 case UTT_HasVirtualDestructor:
464 case UTT_IsDestructible:
465 case UTT_IsNothrowDestructible:
466 case UTT_IsTriviallyDestructible:
467 case UTT_IsIntangibleType:
472 Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);
481 if ((RD->*HasTrivial)() && !(RD->*HasNonTrivial)())
487 if (
Self.LookupQualifiedName(Res, RD)) {
488 bool FoundOperator =
false;
496 if ((Operator->*IsDesiredOp)()) {
497 FoundOperator =
true;
499 CPT =
Self.ResolveExceptionSpec(KeyLoc, CPT);
504 return FoundOperator;
525 Functions, &Operand, &Operand);
529 const auto *
CallExpr = dyn_cast<CXXOperatorCallExpr>(
Result.get());
533 auto ParamT = Callee->getParamDecl(0)->getType();
534 if (!Callee->isDefaulted())
536 if (!ParamT->isReferenceType()) {
549 if (
Decl->isLambda())
550 return Decl->isCapturelessLambda();
555 return llvm::all_of(
Decl->bases(),
557 if (const auto *RD = BS.getType()->getAsCXXRecordDecl())
558 return HasNonDeletedDefaultedEqualityComparison(
563 auto Type = FD->getType();
564 if (Type->isArrayType())
565 Type = Type->getBaseElementTypeUnsafe()
566 ->getCanonicalTypeUnqualified();
568 if (Type->isReferenceType())
570 if (Type->isEnumeralType()) {
572 Type->castAs<EnumType>()->getDecl()->getDefinitionOrSelf();
573 return equalityComparisonIsDefaulted(S, ED, KeyLoc);
589 CanonicalType->
castAs<EnumType>()->getDecl()->getDefinitionOrSelf();
599 CanonicalType,
false);
626 switch (
T.isNonTrivialToPrimitiveDestructiveMove()) {
628 return !
T.isDestructedType();
644 llvm::raw_svector_ostream LhsOut(LhsName), RhsOut(RhsName);
645 MC->mangleCanonicalTypeName(LHS, LhsOut);
646 MC->mangleCanonicalTypeName(RHS, RhsOut);
649 int Result = LhsName.compare(RhsName);
660 assert(!
T->isDependentType() &&
"Cannot evaluate traits of dependent type");
665 llvm_unreachable(
"not a UTT");
669 return T->isVoidType();
671 return T->isIntegralType(
C);
672 case UTT_IsFloatingPoint:
673 return T->isFloatingType();
677 if (
const auto *CAT =
C.getAsConstantArrayType(
T))
678 return CAT->getSize() != 0;
679 return T->isArrayType();
680 case UTT_IsBoundedArray:
685 if (
const auto *CAT =
C.getAsConstantArrayType(
T))
686 return CAT->getSize() != 0;
687 return T->isArrayType() && !
T->isIncompleteArrayType();
688 case UTT_IsUnboundedArray:
691 return T->isIncompleteArrayType();
693 return T->isAnyPointerType();
694 case UTT_IsLvalueReference:
695 return T->isLValueReferenceType();
696 case UTT_IsRvalueReference:
697 return T->isRValueReferenceType();
698 case UTT_IsMemberFunctionPointer:
699 return T->isMemberFunctionPointerType();
700 case UTT_IsMemberObjectPointer:
701 return T->isMemberDataPointerType();
703 return T->isEnumeralType();
704 case UTT_IsScopedEnum:
705 return T->isScopedEnumeralType();
707 return T->isUnionType();
709 return T->isClassType() ||
T->isStructureType() ||
T->isInterfaceType();
711 return T->isFunctionType();
715 case UTT_IsReference:
716 return T->isReferenceType();
717 case UTT_IsArithmetic:
718 return T->isArithmeticType() && !
T->isEnumeralType();
719 case UTT_IsFundamental:
720 return T->isFundamentalType();
722 return T->isObjectType();
728 if (
T->isObjCLifetimeType()) {
729 switch (
T.getObjCLifetime()) {
741 return T->isScalarType();
743 return T->isCompoundType();
744 case UTT_IsMemberPointer:
745 return T->isMemberPointerType();
750 return T.isConstQualified();
752 return T.isVolatileQualified();
754 return T.isTrivialType(
C);
755 case UTT_IsTriviallyCopyable:
756 return T.isTriviallyCopyableType(
C);
757 case UTT_IsStandardLayout:
758 return T->isStandardLayoutType();
760 return T.isPODType(
C);
762 return T->isLiteralType(
C);
767 case UTT_IsPolymorphic:
775 case UTT_IsAggregate:
779 return T->isAggregateType() ||
T->isVectorType() ||
T->isExtVectorType() ||
780 T->isAnyComplexType();
784 case UTT_IsInterfaceClass:
789 return RD->
hasAttr<FinalAttr>();
794 return T->isFloatingType() ||
795 (
T->isSignedIntegerType() && !
T->isEnumeralType());
798 return T->isUnsignedIntegerType() && !
T->isEnumeralType();
816 case UTT_HasTrivialDefaultConstructor:
827 case UTT_HasTrivialMoveConstructor:
837 case UTT_HasTrivialCopy:
843 if (
T.isPODType(
C) ||
T->isReferenceType())
849 case UTT_HasTrivialMoveAssign:
859 case UTT_HasTrivialAssign:
872 if (
T.isConstQualified())
880 case UTT_IsDestructible:
881 case UTT_IsTriviallyDestructible:
882 case UTT_IsNothrowDestructible:
885 if (
T->isReferenceType())
889 if (
T->isObjCLifetimeType() &&
896 if (
T->isIncompleteType() ||
T->isFunctionType())
901 if (UTT == UTT_IsTriviallyDestructible &&
T.isDestructedType())
908 if (
auto *RD =
C.getBaseElementType(
T)->getAsCXXRecordDecl()) {
919 if (UTT == UTT_IsNothrowDestructible) {
921 CPT =
Self.ResolveExceptionSpec(KeyLoc, CPT);
928 case UTT_HasTrivialDestructor:
935 if (
T.isPODType(
C) ||
T->isReferenceType())
939 if (
T->isObjCLifetimeType() &&
947 case UTT_HasNothrowAssign:
955 if (
C.getBaseElementType(
T).isConstQualified())
957 if (
T->isReferenceType())
959 if (
T.isPODType(
C) ||
T->isObjCLifetimeType())
962 if (
auto *RD =
T->getAsCXXRecordDecl())
968 case UTT_HasNothrowMoveAssign:
975 if (
auto *RD =
C.getBaseElementType(
T)->getAsCXXRecordDecl())
981 case UTT_HasNothrowCopy:
987 if (
T.isPODType(
C) ||
T->isReferenceType() ||
T->isObjCLifetimeType())
994 bool FoundConstructor =
false;
996 for (
const auto *ND :
Self.LookupConstructors(RD)) {
1007 FoundConstructor =
true;
1009 CPT =
Self.ResolveExceptionSpec(KeyLoc, CPT);
1019 return FoundConstructor;
1022 case UTT_HasNothrowConstructor:
1028 if (
T.isPODType(
C) ||
T->isObjCLifetimeType())
1030 if (
CXXRecordDecl *RD =
C.getBaseElementType(
T)->getAsCXXRecordDecl()) {
1034 bool FoundConstructor =
false;
1035 for (
const auto *ND :
Self.LookupConstructors(RD)) {
1044 FoundConstructor =
true;
1046 CPT =
Self.ResolveExceptionSpec(KeyLoc, CPT);
1055 return FoundConstructor;
1058 case UTT_HasVirtualDestructor:
1070 case UTT_IsCompleteType:
1074 return !
T->isIncompleteType();
1075 case UTT_HasUniqueObjectRepresentations:
1076 return C.hasUniqueObjectRepresentations(
T);
1077 case UTT_IsTriviallyRelocatable:
1079 case UTT_IsBitwiseCloneable:
1080 return T.isBitwiseCloneableType(
C);
1081 case UTT_IsCppTriviallyRelocatable:
1082 return Self.IsCXXTriviallyRelocatableType(
T);
1083 case UTT_CanPassInRegs:
1084 if (
CXXRecordDecl *RD =
T->getAsCXXRecordDecl(); RD && !
T.hasQualifiers())
1086 Self.Diag(KeyLoc, diag::err_builtin_pass_in_regs_non_class) <<
T;
1088 case UTT_IsTriviallyEqualityComparable:
1090 case UTT_IsImplicitLifetime: {
1092 tok::kw___builtin_is_implicit_lifetime);
1094 tok::kw___builtin_is_implicit_lifetime);
1100 QualType UnqualT =
T->getCanonicalTypeUnqualified();
1117 bool HasTrivialNonDeletedDtr =
1119 if (!HasTrivialNonDeletedDtr)
1122 if (Ctr->isIneligibleOrNotSelected() || Ctr->isDeleted())
1124 if (Ctr->isTrivial())
1139 case UTT_IsIntangibleType:
1140 assert(
Self.getLangOpts().HLSL &&
"intangible types are HLSL-only feature");
1141 if (!
T->isVoidType() && !
T->isIncompleteArrayType())
1143 diag::err_incomplete_type))
1146 tok::kw___builtin_hlsl_is_intangible))
1148 return T->isHLSLIntangibleType();
1150 case UTT_IsTypedResourceElementCompatible:
1151 assert(
Self.getLangOpts().HLSL &&
1152 "typed resource element compatible types are an HLSL-only feature");
1153 if (
T->isIncompleteType())
1156 return Self.HLSL().IsTypedResourceElementCompatible(
T);
1158 case UTT_IsConstantBufferElementCompatible:
1159 assert(
Self.getLangOpts().HLSL &&
1160 "constant buffer element compatible types are an HLSL-only feature");
1161 if (
T->isIncompleteType())
1164 return Self.HLSL().IsConstantBufferElementCompatible(
T);
1175 SourceLocation KeyLoc, llvm::BumpPtrAllocator &OpaqueExprAllocator) {
1216 LhsT =
Self.Context.getRValueReferenceType(LhsT);
1252 case TypeTrait::UTT_StructuredBindingSize: {
1254 SourceRange ArgRange = Args[0]->getTypeLoc().getSourceRange();
1258 S.
Diag(KWLoc, diag::err_arg_is_not_destructurable) <<
T << ArgRange;
1266 llvm_unreachable(
"Not a SizeT type trait");
1278 if (Kind <= UTT_Last)
1283 if (Kind <= BTT_Last && Kind != BTT_ReferenceBindsToTemporary &&
1284 Kind != BTT_ReferenceConstructsFromTemporary &&
1285 Kind != BTT_ReferenceConvertsFromTemporary)
1289 case clang::BTT_ReferenceBindsToTemporary:
1290 case clang::BTT_ReferenceConstructsFromTemporary:
1291 case clang::BTT_ReferenceConvertsFromTemporary:
1292 case clang::TT_IsConstructible:
1293 case clang::TT_IsNothrowConstructible:
1294 case clang::TT_IsTriviallyConstructible: {
1308 assert(!Args.empty());
1313 bool UseRawObjectType =
1314 Kind == clang::BTT_ReferenceBindsToTemporary ||
1315 Kind == clang::BTT_ReferenceConstructsFromTemporary ||
1316 Kind == clang::BTT_ReferenceConvertsFromTemporary;
1321 for (
const auto *TSI : Args) {
1327 KWLoc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr))
1333 if (
T->isIncompleteType() ||
T->isFunctionType() ||
1334 (UseRawObjectType && !
T->isReferenceType()))
1342 llvm::BumpPtrAllocator OpaqueExprAllocator;
1344 ArgExprs.reserve(Args.size() - 1);
1345 for (
unsigned I = 1, N = Args.size(); I != N; ++I) {
1346 QualType ArgTy = Args[I]->getType();
1366 Kind == clang::BTT_ReferenceConvertsFromTemporary
1377 if (Kind == clang::TT_IsConstructible)
1380 if (Kind == clang::BTT_ReferenceBindsToTemporary ||
1381 Kind == clang::BTT_ReferenceConstructsFromTemporary ||
1382 Kind == clang::BTT_ReferenceConvertsFromTemporary) {
1383 if (!
T->isReferenceType())
1387 if (
T.getNonReferenceType()->isFunctionType())
1390 if (!
Init.isDirectReferenceBinding())
1393 if (Kind == clang::BTT_ReferenceBindsToTemporary)
1397 if (
U->isReferenceType())
1405 OpaqueExprAllocator)
1409 if (Kind == clang::TT_IsNothrowConstructible)
1412 if (Kind == clang::TT_IsTriviallyConstructible) {
1415 if (
T.getNonReferenceType().hasNonTrivialObjCLifetime())
1423 llvm_unreachable(
"unhandled type trait");
1427 llvm_unreachable(
"not a TT");
1448 case clang::BTT_TypeOrder: {
1455 llvm_unreachable(
"not a strong_ordering type trait");
1461 TypeTrait Replacement;
1463 case UTT_HasNothrowAssign:
1464 case UTT_HasNothrowMoveAssign:
1465 Replacement = BTT_IsNothrowAssignable;
1467 case UTT_HasNothrowCopy:
1468 case UTT_HasNothrowConstructor:
1469 Replacement = TT_IsNothrowConstructible;
1471 case UTT_HasTrivialAssign:
1472 case UTT_HasTrivialMoveAssign:
1473 Replacement = BTT_IsTriviallyAssignable;
1475 case UTT_HasTrivialCopy:
1476 Replacement = UTT_IsTriviallyCopyable;
1478 case UTT_HasTrivialDefaultConstructor:
1479 case UTT_HasTrivialMoveConstructor:
1480 Replacement = TT_IsTriviallyConstructible;
1482 case UTT_HasTrivialDestructor:
1483 Replacement = UTT_IsTriviallyDestructible;
1485 case UTT_IsTriviallyRelocatable:
1486 Replacement = clang::UTT_IsCppTriviallyRelocatable;
1488 case BTT_ReferenceBindsToTemporary:
1489 Replacement = clang::BTT_ReferenceConstructsFromTemporary;
1494 S.
Diag(KWLoc, diag::warn_deprecated_builtin)
1500 if (Arity && N != Arity) {
1501 Diag(Loc, diag::err_type_trait_arity)
1502 << Arity << 0 << (Arity > 1) << (
int)N <<
SourceRange(Loc);
1506 if (!Arity && N == 0) {
1507 Diag(Loc, diag::err_type_trait_arity)
1521 if (Kind == TypeTrait::UTT_StructuredBindingSize)
1523 if (Kind == TypeTrait::BTT_TypeOrder)
1535 *
this, Kind, KWLoc, Args[0]->
getType()))
1538 DiagnoseBuiltinDeprecation(*
this, Kind, KWLoc);
1541 for (
unsigned I = 0, N = Args.size(); I != N; ++I) {
1542 if (Args[I]->
getType()->isDependentType()) {
1553 KWLoc, Kind, Args, RParenLoc,
Result);
1559 Args, RParenLoc,
Result);
1565 llvm_unreachable(
"unhandled type trait return type");
1572 ConvertedArgs.reserve(Args.size());
1574 for (
unsigned I = 0, N = Args.size(); I != N; ++I) {
1578 TInfo =
Context.getTrivialTypeSourceInfo(
T, KWLoc);
1580 ConvertedArgs.push_back(TInfo);
1593 const RecordType *lhsRecord = LhsT->
getAsCanonical<RecordType>();
1594 const RecordType *rhsRecord = RhsT->
getAsCanonical<RecordType>();
1595 if (!rhsRecord || !lhsRecord) {
1598 if (!LHSObjTy || !RHSObjTy)
1603 if (!BaseInterface || !DerivedInterface)
1607 diag::err_incomplete_type_used_in_type_trait_expr))
1613 assert(
Context.hasSameUnqualifiedType(LhsT, RhsT) ==
1614 (lhsRecord == rhsRecord));
1618 if (lhsRecord && lhsRecord->getDecl()->isUnion())
1620 if (rhsRecord && rhsRecord->getDecl()->isUnion())
1623 if (lhsRecord == rhsRecord)
1631 diag::err_incomplete_type_used_in_type_trait_expr))
1646 "Cannot evaluate traits of dependent types");
1652 case BTT_IsVirtualBaseOf: {
1653 const RecordType *BaseRecord = LhsT->
getAsCanonical<RecordType>();
1654 const RecordType *DerivedRecord = RhsT->
getAsCanonical<RecordType>();
1656 if (!BaseRecord || !DerivedRecord) {
1658 tok::kw___builtin_is_virtual_base_of);
1660 tok::kw___builtin_is_virtual_base_of);
1664 if (BaseRecord->isUnionType() || DerivedRecord->isUnionType())
1667 if (!BaseRecord->isStructureOrClassType() ||
1668 !DerivedRecord->isStructureOrClassType())
1672 diag::err_incomplete_type))
1679 return Self.Context.hasSameType(LhsT, RhsT);
1680 case BTT_TypeCompatible: {
1683 QualType Lhs =
Self.getASTContext().getUnqualifiedArrayType(LhsT, LhsQuals);
1684 QualType Rhs =
Self.getASTContext().getUnqualifiedArrayType(RhsT, RhsQuals);
1685 return Self.Context.typesAreCompatible(Lhs, Rhs);
1687 case BTT_IsConvertible:
1688 case BTT_IsConvertibleTo:
1689 case BTT_IsNothrowConvertible: {
1692 llvm::BumpPtrAllocator OpaqueExprAllocator;
1694 OpaqueExprAllocator);
1698 if (BTT != BTT_IsNothrowConvertible)
1704 case BTT_IsAssignable:
1705 case BTT_IsNothrowAssignable:
1706 case BTT_IsTriviallyAssignable: {
1719 Self.RequireCompleteType(
1721 diag::err_incomplete_type_used_in_type_trait_expr))
1724 Self.RequireCompleteType(
1726 diag::err_incomplete_type_used_in_type_trait_expr))
1736 if (Ty->isObjectType() || Ty->isFunctionType())
1737 Ty =
Self.Context.getRValueReferenceType(Ty);
1738 return {KeyLoc, Ty.getNonLValueExprType(
Self.Context),
1742 auto Lhs = createDeclValExpr(LhsT);
1743 auto Rhs = createDeclValExpr(RhsT);
1752 Self.BuildBinOp(
nullptr, KeyLoc, BO_Assign, &Lhs, &Rhs);
1757 Self.CheckUnusedVolatileAssignment(
Result.get());
1762 if (BTT == BTT_IsAssignable)
1765 if (BTT == BTT_IsNothrowAssignable)
1768 if (BTT == BTT_IsTriviallyAssignable) {
1774 if (Context.containsAddressDiscriminatedPointerAuth(LhsT) ||
1775 Context.containsAddressDiscriminatedPointerAuth(RhsT))
1777 return !
Result.get()->hasNonTrivialCall(
Self.Context);
1780 llvm_unreachable(
"unhandled type trait");
1783 case BTT_IsLayoutCompatible: {
1786 diag::err_incomplete_type);
1789 diag::err_incomplete_type);
1794 return Self.IsLayoutCompatible(LhsT, RhsT);
1796 case BTT_IsPointerInterconvertibleBaseOf: {
1798 !
Self.getASTContext().hasSameUnqualifiedType(LhsT, RhsT)) {
1800 diag::err_incomplete_type);
1804 tok::kw___is_pointer_interconvertible_base_of);
1806 tok::kw___is_pointer_interconvertible_base_of);
1808 return Self.IsPointerInterconvertibleBaseOf(Lhs, Rhs);
1810 case BTT_IsDeducible: {
1813 return Self.DeduceTemplateArgumentsFromType(
1814 TSTToBeDeduced->getTemplateName().getAsTemplateDecl(), RhsT,
1817 case BTT_IsScalarizedLayoutCompatible: {
1820 diag::err_incomplete_type))
1824 diag::err_incomplete_type))
1828 Self, Lhs, tok::kw___builtin_hlsl_is_scalarized_layout_compatible);
1830 Self, Rhs, tok::kw___builtin_hlsl_is_scalarized_layout_compatible);
1832 return Self.HLSL().IsScalarizedLayoutCompatible(LhsT, RhsT);
1834 case BTT_LtSynthesizesFromSpaceship:
1835 case BTT_LeSynthesizesFromSpaceship:
1836 case BTT_GtSynthesizesFromSpaceship:
1837 case BTT_GeSynthesizesFromSpaceship: {
1856 case BTT_LtSynthesizesFromSpaceship:
1857 return BinaryOperatorKind::BO_LT;
1858 case BTT_LeSynthesizesFromSpaceship:
1859 return BinaryOperatorKind::BO_LE;
1860 case BTT_GtSynthesizesFromSpaceship:
1861 return BinaryOperatorKind::BO_GT;
1862 case BTT_GeSynthesizesFromSpaceship:
1863 return BinaryOperatorKind::BO_GE;
1865 llvm_unreachable(
"Trying to Synthesize non-comparison operator?");
1870 Self.LookupBinOp(
Self.TUScope, KeyLoc, OpKind, Functions);
1873 Self.CreateOverloadedBinOp(KeyLoc, OpKind, Functions, &LHS, &RHS);
1880 llvm_unreachable(
"not a BTT");
1882 llvm_unreachable(
"Unknown type trait or not implemented");
1891 TSInfo =
Context.getTrivialTypeSourceInfo(
T);
1899 assert(!
T->isDependentType() &&
"Cannot evaluate traits of dependent type");
1903 if (
T->isArrayType()) {
1907 T = AT->getElementType();
1913 case ATT_ArrayExtent: {
1916 if (
Self.VerifyIntegerConstantExpression(
1917 DimExpr, &
Value, diag::err_dimension_expr_not_constant_integer)
1920 if (
Value.isSigned() &&
Value.isNegative()) {
1921 Self.Diag(KeyLoc, diag::err_dimension_expr_not_constant_integer)
1927 if (
T->isArrayType()) {
1929 bool Matched =
false;
1936 T = AT->getElementType();
1939 if (Matched &&
T->isArrayType()) {
1941 Self.Context.getAsConstantArrayType(
T))
1942 return CAT->getLimitedSize();
1948 llvm_unreachable(
"Unknown type trait or not implemented");
1959 if (!
T->isDependentType())
1968 RParen,
Context.getSizeType());
1984 case ET_IsLValueExpr:
1986 case ET_IsRValueExpr:
1989 llvm_unreachable(
"Expression trait not covered by switch");
2010 return llvm::StringSwitch<std::optional<TypeTrait>>(Name)
2012#include
"clang/Basic/BuiltinTraits.inc"
2017 std::optional<std::pair<TypeTrait, llvm::SmallVector<QualType, 1>>>;
2025 std::optional<TypeTrait> Trait;
2028 if (
const auto *TraitExpr = dyn_cast<TypeTraitExpr>(E)) {
2029 Trait = TraitExpr->getTrait();
2030 for (
const auto *Arg : TraitExpr->getArgs())
2031 Args.push_back(Arg->getType());
2032 return {{Trait.value(), std::move(Args)}};
2034 const auto *Ref = dyn_cast<DeclRefExpr>(E);
2036 return std::nullopt;
2039 if (
const auto *VD =
2040 dyn_cast<VarTemplateSpecializationDecl>(Ref->getDecl())) {
2041 if (!VD->isInStdNamespace())
2042 return std::nullopt;
2043 StringRef Name = VD->getIdentifier()->getName();
2044 if (!Name.consume_back(
"_v"))
2045 return std::nullopt;
2048 return std::nullopt;
2049 for (
const auto &Arg : VD->getTemplateArgs().asArray()) {
2051 for (
const auto &InnerArg : Arg.pack_elements())
2052 Args.push_back(InnerArg.getAsType());
2054 Args.push_back(Arg.getAsType());
2056 llvm_unreachable(
"Unexpected kind");
2059 return {{Trait.value(), std::move(Args)}};
2063 if (
const auto *VD = dyn_cast<VarDecl>(Ref->getDecl());
2064 Ref->hasQualifier() && VD && VD->getIdentifier()->isStr(
"value")) {
2067 return std::nullopt;
2068 const auto *Ts = Qualifier.getAsType()->getAs<TemplateSpecializationType>();
2070 return std::nullopt;
2071 const TemplateDecl *D = Ts->getTemplateName().getAsTemplateDecl();
2073 return std::nullopt;
2076 return std::nullopt;
2077 for (
const auto &Arg : Ts->template_arguments())
2078 Args.push_back(Arg.getAsType());
2079 return {{Trait.value(), std::move(Args)}};
2081 return std::nullopt;
2089 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2090 << diag::TraitNotSatisfiedReason::UnionWithUserDeclaredSMF << K;
2104 const auto *
Decl = cast_or_null<CXXConstructorDecl>(
2106 if (
Decl &&
Decl->isUserProvided())
2107 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2108 << diag::TraitNotSatisfiedReason::UserProvidedCtr
2114 if (
Decl &&
Decl->isUserProvided())
2115 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2116 << diag::TraitNotSatisfiedReason::UserProvidedAssign
2120 Dtr = Dtr->getCanonicalDecl();
2121 if (Dtr->isUserProvided() && !Dtr->isDefaulted())
2122 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2123 << diag::TraitNotSatisfiedReason::DeletedDtr << 1
2124 << Dtr->getSourceRange();
2132 assert(B.getType()->getAsCXXRecordDecl() &&
"invalid base?");
2134 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2135 << diag::TraitNotSatisfiedReason::VBase << B.getType()
2136 << B.getSourceRange();
2138 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2139 << diag::TraitNotSatisfiedReason::NTRBase << B.getType()
2140 << B.getSourceRange();
2143 if (!Field->getType()->isReferenceType() &&
2145 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2146 << diag::TraitNotSatisfiedReason::NTRField << Field
2147 << Field->getType() << Field->getSourceRange();
2150 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2151 << diag::TraitNotSatisfiedReason::DeletedDtr << 0
2160 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait)
2161 <<
T << diag::TraitName::TriviallyRelocatable;
2162 if (
T->isVariablyModifiedType())
2163 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2164 << diag::TraitNotSatisfiedReason::VLA;
2166 if (
T->isReferenceType())
2167 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2168 << diag::TraitNotSatisfiedReason::Ref;
2169 T =
T.getNonReferenceType();
2171 if (
T.hasNonTrivialObjCLifetime())
2172 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2173 << diag::TraitNotSatisfiedReason::HasArcLifetime;
2189 assert(B.getType()->getAsCXXRecordDecl() &&
"invalid base?");
2191 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2192 << diag::TraitNotSatisfiedReason::VBase << B.getType()
2193 << B.getSourceRange();
2194 if (!B.getType().isTriviallyCopyableType(D->
getASTContext())) {
2195 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2196 << diag::TraitNotSatisfiedReason::NTCBase << B.getType()
2197 << B.getSourceRange();
2201 if (!Field->getType().isTriviallyCopyableType(Field->getASTContext()))
2202 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2203 << diag::TraitNotSatisfiedReason::NTCField << Field
2204 << Field->getType() << Field->getSourceRange();
2208 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2209 << diag::TraitNotSatisfiedReason::DeletedDtr
2213 if (Method->isTrivial() || !Method->isUserProvided()) {
2216 auto SpecialMemberKind =
2217 Method->getDefaultedFunctionKind().asSpecialMember();
2218 switch (SpecialMemberKind) {
2230 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2231 << (IsAssignment ? diag::TraitNotSatisfiedReason::UserProvidedAssign
2232 : diag::TraitNotSatisfiedReason::UserProvidedCtr)
2233 << IsMove << Method->getSourceRange();
2249 bool ContainsVoid =
false;
2251 ContainsVoid |= ArgTy->isVoidType();
2255 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2256 << diag::TraitNotSatisfiedReason::CVVoidType;
2259 if (
T->isFunctionType())
2260 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2261 << diag::TraitNotSatisfiedReason::FunctionType;
2263 if (
T->isIncompleteArrayType())
2264 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2265 << diag::TraitNotSatisfiedReason::IncompleteArrayType;
2271 llvm::BumpPtrAllocator OpaqueExprAllocator;
2273 ArgExprs.reserve(Ts.size() - 1);
2274 for (
unsigned I = 1, N = Ts.size(); I != N; ++I) {
2292 Init.Diagnose(SemaRef, To, InitKind, ArgExprs);
2298 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait)
2299 <<
T << diag::TraitName::TriviallyCopyable;
2301 if (
T->isReferenceType())
2302 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2303 << diag::TraitNotSatisfiedReason::Ref;
2320 if (Ty->isObjectType() || Ty->isFunctionType())
2322 return {Loc, Ty.getNonLValueExprType(SemaRef.
Context),
2326 auto LHS = createDeclValExpr(
T);
2327 auto RHS = createDeclValExpr(
U);
2333 SemaRef.
BuildBinOp(
nullptr, Loc, BO_Assign, &LHS, &RHS);
2344 for (
const auto *Field : D->
fields()) {
2345 if (Field->isZeroLengthBitField())
2347 if (Field->isBitField()) {
2348 S.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2349 << diag::TraitNotSatisfiedReason::NonZeroLengthField << Field
2350 << Field->getSourceRange();
2353 S.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2354 << diag::TraitNotSatisfiedReason::NonEmptyMember << Field
2355 << Field->getType() << Field->getSourceRange();
2359 for (
const auto *M : D->
methods()) {
2360 if (M->isVirtual()) {
2361 S.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2362 << diag::TraitNotSatisfiedReason::VirtualFunction << M
2363 << M->getSourceRange();
2369 for (
const auto &B : D->
bases()) {
2370 const auto *BR = B.getType()->getAsCXXRecordDecl();
2371 if (!BR || BR->isInvalidDecl())
2373 if (B.isVirtual()) {
2374 S.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2375 << diag::TraitNotSatisfiedReason::VBase << B.getType()
2376 << B.getSourceRange();
2378 if (!BR->isEmpty()) {
2379 S.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2380 << diag::TraitNotSatisfiedReason::NonEmptyBase << B.getType()
2381 << B.getSourceRange();
2388 S.
Diag(Loc, diag::note_unsatisfied_trait) <<
T << diag::TraitName::Empty;
2393 if (
T->isReferenceType())
2394 S.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2395 << diag::TraitNotSatisfiedReason::Ref;
2396 T =
T.getNonReferenceType();
2399 T = AT->getElementType();
2401 if (
auto *D =
T->getAsCXXRecordDecl()) {
2402 if (D->hasDefinition()) {
2404 S.
Diag(D->getLocation(), diag::note_defined_here) << D;
2416 S.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2417 << diag::TraitNotSatisfiedReason::NotMarkedFinal;
2425 S.
Diag(Loc, diag::note_unsatisfied_trait) <<
T << diag::TraitName::Final;
2426 if (
T->isReferenceType()) {
2427 S.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2428 << diag::TraitNotSatisfiedReason::Ref;
2429 S.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2430 << diag::TraitNotSatisfiedReason::NotClassOrUnion;
2435 S.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2436 << diag::TraitNotSatisfiedReason::NotClassOrUnion;
2439 if (
T->isFunctionType()) {
2440 S.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2441 << diag::TraitNotSatisfiedReason::FunctionType;
2442 S.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2443 << diag::TraitNotSatisfiedReason::NotClassOrUnion;
2446 if (!
T->isRecordType()) {
2447 S.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2448 << diag::TraitNotSatisfiedReason::NotClassOrUnion;
2451 if (
const auto *D =
T->getAsCXXRecordDecl())
2456 int NumBasesWithFields = 0;
2463 if (!Field->isUnnamedBitField()) {
2464 if (++NumBasesWithFields > 1)
2476 assert(B.getType()->getAsCXXRecordDecl() &&
"invalid base?");
2477 if (B.isVirtual()) {
2478 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2479 << diag::TraitNotSatisfiedReason::VBase << B.getType()
2480 << B.getSourceRange();
2482 if (!B.getType()->isStandardLayoutType()) {
2483 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2484 << diag::TraitNotSatisfiedReason::NonStandardLayoutBase << B.getType()
2485 << B.getSourceRange();
2493 if (Field->isUnnamedBitField())
2504 if (Field->getAccess() != FirstAccess) {
2506 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2507 << diag::TraitNotSatisfiedReason::MixedAccess;
2512 SemaRef.
Diag(Field->getLocation(), diag::note_unsatisfied_trait_reason)
2513 << diag::TraitNotSatisfiedReason::MixedAccessField << Field
2521 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2522 << diag::TraitNotSatisfiedReason::MultipleDataBase;
2528 for (
const auto *M : D->
methods()) {
2529 if (M->isVirtual()) {
2535 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2536 << diag::TraitNotSatisfiedReason::VirtualFunction << VirtualMD;
2537 SemaRef.
Diag(VirtualMD->getLocation(), diag::note_defined_here)
2541 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2542 << diag::TraitNotSatisfiedReason::VirtualFunction << D;
2543 SemaRef.
Diag(D->getLocation(), diag::note_defined_here) << D;
2547 if (!Field->getType()->isStandardLayoutType()) {
2548 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2549 << diag::TraitNotSatisfiedReason::NonStandardLayoutMember << Field
2550 << Field->getType() << Field->getSourceRange();
2564 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2565 << diag::TraitNotSatisfiedReason::IndirectBaseWithFields << Indirect
2573 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait)
2574 <<
T << diag::TraitName::StandardLayout;
2577 if (
T->isVariablyModifiedType()) {
2578 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2579 << diag::TraitNotSatisfiedReason::VLA;
2583 if (
T->isReferenceType()) {
2584 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2585 << diag::TraitNotSatisfiedReason::Ref;
2588 T =
T.getNonReferenceType();
2602 if (Ctor->isUserProvided())
2603 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2604 << diag::TraitNotSatisfiedReason::UserDeclaredCtr;
2605 if (Ctor->isInheritingConstructor())
2606 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2607 << diag::TraitNotSatisfiedReason::InheritedCtr;
2610 if (llvm::any_of(D->
decls(), [](
auto const *Sub) {
2611 return isa<ConstructorUsingShadowDecl>(Sub);
2613 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2614 << diag::TraitNotSatisfiedReason::InheritedCtr;
2618 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2619 << diag::TraitNotSatisfiedReason::PolymorphicType
2623 if (B.isVirtual()) {
2624 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2625 << diag::TraitNotSatisfiedReason::VBase << B.getType()
2626 << B.getSourceRange();
2633 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2634 << diag::TraitNotSatisfiedReason::PrivateProtectedDirectBase
2643 if (Method->isVirtual()) {
2644 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2645 << diag::TraitNotSatisfiedReason::VirtualFunction << Method
2646 << Method->getSourceRange();
2655 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2656 << diag::TraitNotSatisfiedReason::PrivateProtectedDirectDataMember
2669 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait)
2670 <<
T << diag::TraitName::Aggregate;
2672 if (
T->isVoidType())
2673 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2674 << diag::TraitNotSatisfiedReason::CVVoidType;
2676 T =
T.getNonReferenceType();
2690 if (B.getType()->castAsCXXRecordDecl()->isAbstract()) {
2691 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2692 << diag::TraitNotSatisfiedReason::OverridesAllPureVirtual
2693 << B.getType() << B.getSourceRange();
2700 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait)
2701 <<
T << diag::TraitName::Abstract;
2703 if (
T->isReferenceType()) {
2704 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2705 << diag::TraitNotSatisfiedReason::Ref;
2706 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2707 << diag::TraitNotSatisfiedReason::NotStructOrClass;
2711 if (
T->isUnionType()) {
2712 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2713 << diag::TraitNotSatisfiedReason::UnionType;
2714 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2715 << diag::TraitNotSatisfiedReason::NotStructOrClass;
2720 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2721 << diag::TraitNotSatisfiedReason::ArrayType;
2722 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2723 << diag::TraitNotSatisfiedReason::NotStructOrClass;
2727 if (
T->isFunctionType()) {
2728 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2729 << diag::TraitNotSatisfiedReason::FunctionType;
2730 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2731 << diag::TraitNotSatisfiedReason::NotStructOrClass;
2735 if (
T->isPointerType()) {
2736 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2737 << diag::TraitNotSatisfiedReason::PointerType;
2738 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2739 << diag::TraitNotSatisfiedReason::NotStructOrClass;
2743 if (!
T->isStructureOrClassType()) {
2744 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2745 << diag::TraitNotSatisfiedReason::NotStructOrClass;
2762 const auto &[Trait, Args] = TraitInfo.value();
2764 case UTT_IsCppTriviallyRelocatable:
2767 case UTT_IsTriviallyCopyable:
2770 case BTT_IsAssignable:
2776 case UTT_IsStandardLayout:
2779 case TT_IsConstructible:
2782 case UTT_IsAggregate:
2794 case UTT_IsAbstract:
Defines enumerations for traits support.
static CanQualType GetReturnType(QualType RetTy)
Returns the "extra-canonicalized" return type, which discards qualifiers on the return type.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the Diagnostic IDs-related interfaces.
Result
Implement __builtin_bit_cast and related operations.
This file declares semantic analysis for HLSL constructs.
static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, const TypeSourceInfo *Lhs, const TypeSourceInfo *Rhs, SourceLocation KeyLoc)
static bool HasNonDeletedDefaultedEqualityComparison(Sema &S, const CXXRecordDecl *Decl, SourceLocation KeyLoc)
static void DiagnoseNonAbstractReason(Sema &SemaRef, SourceLocation Loc, const CXXRecordDecl *D)
static ExprResult EvaluateStrongOrderingTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc, ArrayRef< TypeSourceInfo * > Args, SourceLocation RParenLoc, bool IsDependent)
static APValue EvaluateSizeTTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc, ArrayRef< TypeSourceInfo * > Args, SourceLocation RParenLoc, bool IsDependent)
static bool DiagnoseVLAInCXXTypeTrait(Sema &S, const TypeSourceInfo *T, clang::tok::TokenKind TypeTraitID)
Checks that type T is not a VLA.
static ComparisonCategoryResult EvaluateTypeOrder(Sema &S, QualType LHS, QualType RHS)
static bool HasNoThrowOperator(CXXRecordDecl *RD, OverloadedOperatorKind Op, Sema &Self, SourceLocation KeyLoc, ASTContext &C, bool(CXXRecordDecl::*HasTrivial)() const, bool(CXXRecordDecl::*HasNonTrivial)() const, bool(CXXMethodDecl::*IsDesiredOp)() const)
static std::optional< TypeTrait > StdNameToTypeTrait(StringRef Name)
static void DiagnoseNonConstructibleReason(Sema &SemaRef, SourceLocation Loc, const llvm::SmallVector< clang::QualType, 1 > &Ts)
static bool IsEligibleForTrivialRelocation(Sema &SemaRef, const CXXRecordDecl *D)
static CXXMethodDecl * LookupSpecialMemberFromXValue(Sema &SemaRef, const CXXRecordDecl *RD, bool Assign)
static bool hasSuitableMoveAssignmentOperatorForRelocation(Sema &SemaRef, const CXXRecordDecl *D, bool AllowUserDefined)
static bool DiagnoseAtomicInCXXTypeTrait(Sema &S, const TypeSourceInfo *T, clang::tok::TokenKind TypeTraitID)
Checks that type T is not an atomic type (_Atomic).
static bool equalityComparisonIsDefaulted(Sema &S, const TagDecl *Decl, SourceLocation KeyLoc)
static void DiagnoseNonStandardLayoutReason(Sema &SemaRef, SourceLocation Loc, const CXXRecordDecl *D)
static void DiagnoseIsFinalReason(Sema &S, SourceLocation Loc, const CXXRecordDecl *D)
static void DiagnoseIsEmptyReason(Sema &S, SourceLocation Loc, const CXXRecordDecl *D)
static bool hasMultipleDataBaseClassesWithFields(const CXXRecordDecl *D)
static bool EvaluateExpressionTrait(ExpressionTrait ET, Expr *E)
static ExtractedTypeTraitInfo ExtractTypeTraitFromExpression(const Expr *E)
std::optional< std::pair< TypeTrait, llvm::SmallVector< QualType, 1 > > > ExtractedTypeTraitInfo
static void DiagnoseNonTriviallyRelocatableReason(Sema &SemaRef, SourceLocation Loc, const CXXRecordDecl *D)
static void DiagnoseNonAssignableReason(Sema &SemaRef, SourceLocation Loc, QualType T, QualType U)
static bool IsTriviallyRelocatableType(Sema &SemaRef, QualType T)
static void DiagnoseNonDefaultMovable(Sema &SemaRef, SourceLocation Loc, const CXXRecordDecl *D)
static bool IsDefaultMovable(Sema &SemaRef, const CXXRecordDecl *D)
static bool hasSuitableConstructorForRelocation(Sema &SemaRef, const CXXRecordDecl *D, bool AllowUserDefined)
static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, SourceLocation Loc, const CXXRecordDecl *D)
static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, SourceLocation KeyLoc, TypeSourceInfo *TInfo)
static uint64_t EvaluateArrayTypeTrait(Sema &Self, ArrayTypeTrait ATT, QualType T, Expr *DimExpr, SourceLocation KeyLoc)
static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT, SourceLocation Loc, QualType ArgTy)
Check the completeness of a type in a unary type trait.
static ExprResult CheckConvertibilityForTypeTraits(Sema &Self, const TypeSourceInfo *Lhs, const TypeSourceInfo *Rhs, SourceLocation KeyLoc, llvm::BumpPtrAllocator &OpaqueExprAllocator)
#define EMIT_STD_NAME_CASES
static void DiagnoseNonAggregateReason(Sema &SemaRef, SourceLocation Loc, const CXXRecordDecl *D)
static bool EvaluateBooleanTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc, ArrayRef< TypeSourceInfo * > Args, SourceLocation RParenLoc, bool IsDependent)
static bool isTriviallyEqualityComparableType(Sema &S, QualType Type, SourceLocation KeyLoc)
Defines various enumerations that describe declaration and type specifiers.
C Language Family Type Representation.
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
TranslationUnitDecl * getTranslationUnitDecl() const
QualType getRValueReferenceType(QualType T) const
Return the uniqued reference to the type for an rvalue reference to the specified type.
DeclarationNameTable DeclarationNames
MangleContext * createMangleContext(const TargetInfo *T=nullptr)
If T is null pointer, assume the target in ASTContext.
void setRelocationInfoForCXXRecord(const CXXRecordDecl *, CXXRecordDeclRelocationInfo)
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
bool containsAddressDiscriminatedPointerAuth(QualType T) const
Examines a given type, and returns whether the type itself is address discriminated,...
bool hasUniqueObjectRepresentations(QualType Ty, bool CheckIfTriviallyCopyable=true) const
Return true if the specified type has unique object representations according to (C++17 [meta....
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
TypeSourceInfo * CreateTypeSourceInfo(QualType T, unsigned Size=0) const
Allocate an uninitialized TypeSourceInfo.
static bool hasSameType(QualType T1, QualType T2)
Determine whether the given types T1 and T2 are equivalent.
llvm::APSInt MakeIntValue(uint64_t Value, QualType Type) const
Make an APSInt of the appropriate width and signedness for the given Value and integer Type.
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
CanQualType getCanonicalTagType(const TagDecl *TD) const
static bool hasSameUnqualifiedType(QualType T1, QualType T2)
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
An Embarcadero array type trait, as used in the implementation of __array_rank and __array_extent.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Represents a base class of a C++ class.
Represents a C++ constructor within a class.
Represents a C++ destructor within a class.
CXXDestructorDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Represents a static or instance method of a struct/union/class.
bool isMoveAssignmentOperator() const
Determine whether this is a move assignment operator.
bool isCopyAssignmentOperator() const
Determine whether this is a copy-assignment operator, regardless of whether it was declared implicitl...
Represents a C++ struct/union/class.
bool hasTrivialMoveAssignment() const
Determine whether this class has a trivial move assignment operator (C++11 [class....
bool isTriviallyCopyable() const
Determine whether this class is considered trivially copyable per (C++11 [class]p6).
bool hasNonTrivialCopyAssignment() const
Determine whether this class has a non-trivial copy assignment operator (C++ [class....
bool isEffectivelyFinal() const
Determine whether it's impossible for a class to be derived from this class.
bool hasSimpleMoveConstructor() const
true if we know for sure that this class has a single, accessible, unambiguous move constructor that ...
bool hasTrivialDefaultConstructor() const
Determine whether this class has a trivial default constructor (C++11 [class.ctor]p5).
bool hasTrivialDestructor() const
Determine whether this class has a trivial destructor (C++ [class.dtor]p3)
bool hasUserDeclaredDestructor() const
Determine whether this class has a user-declared destructor.
bool defaultedMoveConstructorIsDeleted() const
true if a defaulted move constructor for this class would be deleted.
bool hasUserDeclaredMoveAssignment() const
Determine whether this class has had a move assignment declared by the user.
bool hasDeletedDestructor() const
Returns the destructor decl for this class.
bool hasTrivialMoveConstructor() const
Determine whether this class has a trivial move constructor (C++11 [class.copy]p12)
bool needsImplicitDefaultConstructor() const
Determine if we need to declare a default constructor for this class.
bool needsImplicitMoveConstructor() const
Determine whether this class should get an implicit move constructor or if any existing special membe...
bool hasUserDeclaredCopyAssignment() const
Determine whether this class has a user-declared copy assignment operator.
method_range methods() const
CXXRecordDecl * getDefinition() const
bool hasTrivialCopyConstructor() const
Determine whether this class has a trivial copy constructor (C++ [class.copy]p6, C++11 [class....
bool isPolymorphic() const
Whether this class is polymorphic (C++ [class.virtual]), which means that the class contains or inher...
bool defaultedCopyConstructorIsDeleted() const
true if a defaulted copy constructor for this class would be deleted.
bool hasTrivialCopyAssignment() const
Determine whether this class has a trivial copy assignment operator (C++ [class.copy]p11,...
bool isAbstract() const
Determine whether this class has a pure virtual function.
bool needsImplicitCopyConstructor() const
Determine whether this class needs an implicit copy constructor to be lazily declared.
bool hasSimpleMoveAssignment() const
true if we know for sure that this class has a single, accessible, unambiguous move assignment operat...
bool hasNonTrivialMoveConstructor() const
Determine whether this class has a non-trivial move constructor (C++11 [class.copy]p12)
bool hasDirectFields() const
Determine whether this class has direct non-static data members.
bool hasUserDeclaredCopyConstructor() const
Determine whether this class has a user-declared copy constructor.
bool hasDefinition() const
bool hasSimpleCopyConstructor() const
true if we know for sure that this class has a single, accessible, unambiguous copy constructor that ...
bool isEmpty() const
Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).
CXXDestructorDecl * getDestructor() const
Returns the destructor decl for this class.
bool hasNonTrivialMoveAssignment() const
Determine whether this class has a non-trivial move assignment operator (C++11 [class....
bool hasUserDeclaredMoveOperation() const
Whether this class has a user-declared move constructor or assignment operator.
bool hasNonTrivialDefaultConstructor() const
Determine whether this class has a non-trivial default constructor (C++11 [class.ctor]p5).
bool hasUserDeclaredMoveConstructor() const
Determine whether this class has had a move constructor declared by the user.
bool forallBases(ForallBasesCallback BaseMatches) const
Determines if the given callback holds for all the direct or indirect base classes of this type.
bool hasNonTrivialCopyConstructor() const
Determine whether this class has a non-trivial copy constructor (C++ [class.copy]p6,...
bool hasSimpleCopyAssignment() const
true if we know for sure that this class has a single, accessible, unambiguous copy assignment operat...
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Represents the canonical version of C arrays with a specified constant size.
A POD class for pairing a NamedDecl* with an access specifier.
static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS)
DeclContextLookupResult lookup_result
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
Decl - This represents one declaration (or definition), e.g.
bool isInStdNamespace() const
ASTContext & getASTContext() const LLVM_READONLY
bool isInvalidDecl() const
SourceLocation getLocation() const
AccessSpecifier getAccess() const
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
The name of a declaration.
RAII object that enters a new expression evaluation context.
The return type of classify().
This represents one expression.
bool isTypeDependent() const
Determines whether the type of this expression depends on.
bool containsErrors() const
Whether this expression contains subexpressions which had errors.
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
Classification Classify(ASTContext &Ctx) const
Classify - Classify this expression according to the C++11 expression taxonomy.
bool hasPlaceholderType() const
Returns whether this expression has a placeholder type.
static ExprValueKind getValueKindForType(QualType T)
getValueKindForType - Given a formal return or parameter type, give its value kind.
An expression trait intrinsic.
Represents a member of a struct/union/class.
bool isTrivial() const
Whether this function is "trivial" in some specialized C++ senses.
bool isDeleted() const
Whether this function has been deleted.
bool isDefaulted() const
Whether this function is defaulted.
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
bool isUserProvided() const
True if this method is user-declared and was not deleted or defaulted on its first declaration.
Represents a prototype with parameter type info, e.g.
unsigned getNumParams() const
bool isNothrow(bool ResultIfDependent=false) const
Determine whether this function type has a non-throwing exception specification.
Declaration of a template function.
StringRef getName() const
Return the actual identifier string.
Describes the kind of initialization being performed, along with location information for tokens rela...
static InitializationKind CreateDirect(SourceLocation InitLoc, SourceLocation LParenLoc, SourceLocation RParenLoc)
Create a direct initialization.
static InitializationKind CreateCopy(SourceLocation InitLoc, SourceLocation EqualLoc, bool AllowExplicitConvs=false)
Create a copy initialization.
Describes the sequence of initializations required to initialize a given object or reference with a s...
Describes an entity that is being initialized.
static InitializedEntity InitializeTemporary(QualType Type)
Create the initialization entity for a temporary.
Represents the results of name lookup.
UnresolvedSetImpl::iterator iterator
void suppressDiagnostics()
Suppress the diagnostics that would normally fire because of this lookup.
This represents a decl that may have a name.
NamedDecl * getUnderlyingDecl()
Looks through UsingDecls and ObjCCompatibleAliasDecls for the underlying named decl.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
@ Type
A type, stored as a Type*.
Represents an ObjC class declaration.
bool isSuperClassOf(const ObjCInterfaceDecl *I) const
isSuperClassOf - Return true if this class is the specified class or is a super class of the specifie...
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
OverloadCandidateSet - A set of overload candidates, used in C++ overload resolution (C++ 13....
@ CSK_Normal
Normal lookup.
SmallVectorImpl< OverloadCandidate >::iterator iterator
OverloadingResult BestViableFunction(Sema &S, SourceLocation Loc, OverloadCandidateSet::iterator &Best)
Find the best viable function on this overload set, if it exists.
A (possibly-)qualified type.
bool isTriviallyCopyableType(const ASTContext &Context) const
Return true if this is a trivially copyable type (C++0x [basic.types]p9)
QualType getNonLValueExprType(const ASTContext &Context) const
Determine the type of a (typically non-lvalue) expression with the specified result type.
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
bool hasNonTrivialObjCLifetime() const
@ PCK_Trivial
The type does not fall into any of the following categories.
@ PCK_ARCStrong
The type is an Objective-C retainable pointer type that is qualified with the ARC __strong qualifier.
The collection of all-type qualifiers we support.
@ OCL_Strong
Assigning into this object requires the old value to be released and the new value to be retained.
@ OCL_ExplicitNone
This object can be modified without requiring retains or releases.
@ OCL_None
There is no lifetime qualification on this type.
@ OCL_Weak
Reading or writing from this object requires a barrier call.
@ OCL_Autoreleasing
Assigning into this object requires a lifetime extension.
bool canPassInRegisters() const
Determine whether this class can be passed in registers.
field_range fields() const
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
RAII class used to determine whether SFINAE has trapped any errors that occur during template argumen...
bool hasErrorOccurred() const
Determine whether any SFINAE errors have been trapped.
Sema - This implements semantic analysis and AST building for C.
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
ExprResult ActOnExpressionTrait(ExpressionTrait OET, SourceLocation KWLoc, Expr *Queried, SourceLocation RParen)
ActOnExpressionTrait - Parsed one of the unary type trait support pseudo-functions.
bool IsCXXTriviallyRelocatableType(QualType T)
Determines if a type is trivially relocatable according to the C++26 rules.
bool BuiltinIsBaseOf(SourceLocation RhsTLoc, QualType LhsT, QualType RhsT)
void DiagnoseTypeTraitDetails(const Expr *E)
If E represents a built-in type trait, or a known standard type trait, try to print more information ...
ASTContext & getASTContext() const
void LookupBinOp(Scope *S, SourceLocation OpLoc, BinaryOperatorKind Opc, UnresolvedSetImpl &Functions)
ExprResult CreateOverloadedBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc, const UnresolvedSetImpl &Fns, Expr *LHS, Expr *RHS, bool RequiresADL=true, bool AllowRewrittenCandidates=true, FunctionDecl *DefaultedFn=nullptr)
Create a binary operation that may resolve to an overloaded operator.
bool CheckTypeTraitArity(unsigned Arity, SourceLocation Loc, size_t N)
ExprResult ActOnArrayTypeTrait(ArrayTypeTrait ATT, SourceLocation KWLoc, ParsedType LhsTy, Expr *DimExpr, SourceLocation RParen)
ActOnArrayTypeTrait - Parsed one of the binary type trait support pseudo-functions.
void AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ObjectType, Expr::Classification ObjectClassification, ArrayRef< Expr * > Args, OverloadCandidateSet &CandidateSet, bool SuppressUserConversions=false, bool PartialOverloading=false, OverloadCandidateParamOrder PO={})
Add a C++ member function template as a candidate to the candidate set, using template argument deduc...
void AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef< Expr * > Args, OverloadCandidateSet &CandidateSet, bool SuppressUserConversions=false, bool PartialOverloading=false, bool AllowExplicit=true, ADLCallKind IsADLCandidate=ADLCallKind::NotADL, OverloadCandidateParamOrder PO={}, bool AggregateCandidateDeduction=false)
Add a C++ function template specialization as a candidate in the candidate set, using template argume...
const LangOptions & getLangOpts() const
QualType CheckComparisonCategoryType(ComparisonCategoryType Kind, SourceLocation Loc, ComparisonCategoryUsage Usage)
Lookup the specified comparison category types in the standard library, an check the VarDecls possibl...
void AddOverloadCandidate(FunctionDecl *Function, DeclAccessPair FoundDecl, ArrayRef< Expr * > Args, OverloadCandidateSet &CandidateSet, bool SuppressUserConversions=false, bool PartialOverloading=false, bool AllowExplicit=true, bool AllowExplicitConversion=false, ADLCallKind IsADLCandidate=ADLCallKind::NotADL, ConversionSequenceList EarlyConversions={}, OverloadCandidateParamOrder PO={}, bool AggregateCandidateDeduction=false, bool StrictPackMatch=false)
AddOverloadCandidate - Adds the given function to the set of candidate functions, using the given fun...
@ Builtin
A builtin needed 'std::strong_ordering' (eg. '__builtin_type_order').
ExprResult BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc, ArrayRef< TypeSourceInfo * > Args, SourceLocation RParenLoc)
ExprResult BuildExpressionTrait(ExpressionTrait OET, SourceLocation KWLoc, Expr *Queried, SourceLocation RParen)
ExprResult CheckPlaceholderExpr(Expr *E)
Check for operands with placeholder types and complain if found.
void AddMethodCandidate(DeclAccessPair FoundDecl, QualType ObjectType, Expr::Classification ObjectClassification, ArrayRef< Expr * > Args, OverloadCandidateSet &CandidateSet, bool SuppressUserConversion=false, OverloadCandidateParamOrder PO={})
AddMethodCandidate - Adds a named decl (which is some kind of method) as a method candidate to the gi...
CanThrowResult canThrow(const Stmt *E)
@ Unevaluated
The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7),...
bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)
Ensure that the type T is a complete type.
Scope * TUScope
Translation Unit Scope - useful to Objective-C actions that need to lookup file scope declarations in...
ASTContext::CXXRecordDeclRelocationInfo CheckCXX2CRelocatable(const clang::CXXRecordDecl *D)
ExprResult BuildBinOp(Scope *S, SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr, bool ForFoldExpression=false)
ExprResult ActOnTypeTrait(TypeTrait Kind, SourceLocation KWLoc, ArrayRef< ParsedType > Args, SourceLocation RParenLoc)
Parsed one of the type trait support pseudo-functions.
ExprResult BuildArrayTypeTrait(ArrayTypeTrait ATT, SourceLocation KWLoc, TypeSourceInfo *TSInfo, Expr *DimExpr, SourceLocation RParen)
UnsignedOrNone GetDecompositionElementCount(QualType DecompType, SourceLocation Loc)
static QualType GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo=nullptr)
Encodes a location in the source.
A trivial tuple used to represent a source range.
SourceLocation getBegin() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
SourceLocation getBeginLoc() const LLVM_READONLY
Represents the declaration of a struct/union/class/enum.
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
bool isDependentType() const
Whether this declaration declares a type that is dependent, i.e., a type that somehow depends on temp...
@ Pack
The template argument is actually a parameter pack.
@ Type
The template argument is a type.
The base class of all kinds of template declarations (e.g., class, function, etc.).
SourceLocation getBeginLoc() const
Get the begin source location.
A container of type source information.
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
QualType getType() const
Return the type wrapped by this type source info.
static TypeTraitExpr * Create(const ASTContext &C, QualType T, SourceLocation Loc, TypeTrait Kind, ArrayRef< TypeSourceInfo * > Args, SourceLocation RParenLoc, bool Value)
Create a new type trait expression.
The base class of the type hierarchy.
bool isIncompleteArrayType() const
bool isRValueReferenceType() const
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
const T * castAs() const
Member-template castAs<specific type>.
bool isEnumeralType() const
bool isScalarType() const
bool isVariableArrayType() const
bool isLValueReferenceType() const
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
const Type * getBaseElementTypeUnsafe() const
Get the base element type of this type, potentially discarding type qualifiers.
bool isObjectType() const
Determine whether this type is an object type.
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
bool isFunctionType() const
bool isStructureOrClassType() const
bool isVectorType() const
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
const T * getAs() const
Member-template getAs<specific type>'.
A set of unresolved declarations.
Provides information about an attempted template argument deduction, whose success or failure was des...
TokenKind
Provides a simple uniform namespace for tokens from all C languages.
Top level wrappers for InstallAPI frontend operations.
const char * getTraitSpelling(TypeTrait T) LLVM_READONLY
Return the spelling of the trait T. Never null.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
bool isa(CodeGen::Address addr)
unsigned getTypeTraitArity(TypeTrait T) LLVM_READONLY
Return the arity of the type trait T.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
@ OR_Deleted
Succeeded, but refers to a deleted function.
@ OR_Success
Overload resolution succeeded.
@ Self
'self' clause, allowed on Compute and Combined Constructs, plus 'update'.
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
@ Dependent
Parse the block as a dependent block, which may be used in some template instantiations but not other...
ComparisonCategoryResult
An enumeration representing the possible results of a three-way comparison.
@ Default
Set to the current date and time.
@ Result
The result type of a method or function.
OptionalUnsigned< unsigned > UnsignedOrNone
const FunctionProtoType * T
CXXSpecialMemberKind
Kinds of C++ special members.
ExprValueKind
The categorization of expression values, currently following the C++11 scheme.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
@ VK_XValue
An x-value expression is a reference to an object with independent storage but which can be "moved",...
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
@ Success
Template argument deduction was successful.
U cast(CodeGen::Address addr)
ConstructorInfo getConstructorInfo(NamedDecl *ND)
OpaquePtr< QualType > ParsedType
An opaque type for threading parsed type information through the parser.
ActionResult< Expr * > ExprResult
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...