27#include "llvm/ADT/STLExtras.h"
76 if (CandDecl->isInvalidDecl())
84 ThisTy, Classification,
101 CtorInfo.ConstructorTmpl, CtorInfo.FoundDecl,
nullptr,
119 bool AllowUserDefined) {
127 return Decl && (AllowUserDefined || !
Decl->isUserProvided()) &&
143 return Decl && (AllowUserDefined || !
Decl->isUserProvided()) &&
184 const auto *BaseDecl = B.getType()->getAsCXXRecordDecl();
189 if (B.isVirtual() || (!BaseDecl->isDependentType() &&
196 if (Field->getType()->isDependentType())
198 if (Field->getType()->isReferenceType())
223 auto IsUnion = [&, Is = std::optional<bool>{}]()
mutable {
258 if (std::optional<ASTContext::CXXRecordDeclRelocationInfo> Info =
260 return Info->IsRelocatable;
278 if (
Context.containsNonRelocatablePointerAuth(
Type))
296 if (!T->getType()->isVariableArrayType())
299 S.
Diag(T->getTypeLoc().getBeginLoc(), diag::err_vla_unsupported)
310 if (!T->getType()->isAtomicType())
313 S.
Diag(T->getTypeLoc().getBeginLoc(), diag::err_atomic_unsupported)
338 llvm_unreachable(
"not a UTT");
340 case UTT_IsCompleteType:
349 case UTT_IsFloatingPoint:
351 case UTT_IsBoundedArray:
353 case UTT_IsLvalueReference:
354 case UTT_IsRvalueReference:
355 case UTT_IsMemberFunctionPointer:
356 case UTT_IsMemberObjectPointer:
358 case UTT_IsScopedEnum:
362 case UTT_IsReference:
363 case UTT_IsArithmetic:
364 case UTT_IsFundamental:
368 case UTT_IsMemberPointer:
369 case UTT_IsTypedResourceElementCompatible:
380 case UTT_IsUnboundedArray:
384 case UTT_IsInterfaceClass:
388 case UTT_StructuredBindingSize:
394 case UTT_IsPolymorphic:
399 Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);
408 Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);
412 case UTT_IsAggregate:
413 case UTT_IsImplicitLifetime:
418 Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);
422 case UTT_HasUniqueObjectRepresentations:
427 Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);
432 case UTT_IsTriviallyCopyable:
433 case UTT_IsStandardLayout:
436 case UTT_IsBitwiseCloneable:
439 case UTT_IsTriviallyRelocatable:
440 case UTT_IsTriviallyEqualityComparable:
441 case UTT_IsCppTriviallyRelocatable:
442 case UTT_CanPassInRegs:
446 case UTT_HasNothrowAssign:
447 case UTT_HasNothrowMoveAssign:
448 case UTT_HasNothrowConstructor:
449 case UTT_HasNothrowCopy:
450 case UTT_HasTrivialAssign:
451 case UTT_HasTrivialMoveAssign:
452 case UTT_HasTrivialDefaultConstructor:
453 case UTT_HasTrivialMoveConstructor:
454 case UTT_HasTrivialCopy:
455 case UTT_HasTrivialDestructor:
456 case UTT_HasVirtualDestructor:
461 case UTT_IsDestructible:
462 case UTT_IsNothrowDestructible:
463 case UTT_IsTriviallyDestructible:
464 case UTT_IsIntangibleType:
469 Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);
478 if ((RD->*HasTrivial)() && !(RD->*HasNonTrivial)())
484 if (
Self.LookupQualifiedName(Res, RD)) {
485 bool FoundOperator =
false;
493 if ((Operator->*IsDesiredOp)()) {
494 FoundOperator =
true;
496 CPT =
Self.ResolveExceptionSpec(KeyLoc, CPT);
501 return FoundOperator;
522 Functions, &Operand, &Operand);
526 const auto *
CallExpr = dyn_cast<CXXOperatorCallExpr>(Result.get());
530 auto ParamT = Callee->getParamDecl(0)->getType();
531 if (!Callee->isDefaulted())
533 if (!ParamT->isReferenceType()) {
546 if (
Decl->isLambda())
547 return Decl->isCapturelessLambda();
552 return llvm::all_of(
Decl->bases(),
554 if (const auto *RD = BS.getType()->getAsCXXRecordDecl())
555 return HasNonDeletedDefaultedEqualityComparison(
560 auto Type = FD->getType();
561 if (Type->isArrayType())
562 Type = Type->getBaseElementTypeUnsafe()
563 ->getCanonicalTypeUnqualified();
565 if (Type->isReferenceType())
567 if (Type->isEnumeralType()) {
569 Type->castAs<EnumType>()->getDecl()->getDefinitionOrSelf();
570 return equalityComparisonIsDefaulted(S, ED, KeyLoc);
586 CanonicalType->
castAs<EnumType>()->getDecl()->getDefinitionOrSelf();
596 CanonicalType,
false);
623 switch (T.isNonTrivialToPrimitiveDestructiveMove()) {
625 return !T.isDestructedType();
637 assert(!T->isDependentType() &&
"Cannot evaluate traits of dependent type");
642 llvm_unreachable(
"not a UTT");
646 return T->isVoidType();
648 return T->isIntegralType(
C);
649 case UTT_IsFloatingPoint:
650 return T->isFloatingType();
654 if (
const auto *CAT =
C.getAsConstantArrayType(T))
655 return CAT->getSize() != 0;
656 return T->isArrayType();
657 case UTT_IsBoundedArray:
662 if (
const auto *CAT =
C.getAsConstantArrayType(T))
663 return CAT->getSize() != 0;
664 return T->isArrayType() && !T->isIncompleteArrayType();
665 case UTT_IsUnboundedArray:
668 return T->isIncompleteArrayType();
670 return T->isAnyPointerType();
671 case UTT_IsLvalueReference:
672 return T->isLValueReferenceType();
673 case UTT_IsRvalueReference:
674 return T->isRValueReferenceType();
675 case UTT_IsMemberFunctionPointer:
676 return T->isMemberFunctionPointerType();
677 case UTT_IsMemberObjectPointer:
678 return T->isMemberDataPointerType();
680 return T->isEnumeralType();
681 case UTT_IsScopedEnum:
682 return T->isScopedEnumeralType();
684 return T->isUnionType();
686 return T->isClassType() || T->isStructureType() || T->isInterfaceType();
688 return T->isFunctionType();
692 case UTT_IsReference:
693 return T->isReferenceType();
694 case UTT_IsArithmetic:
695 return T->isArithmeticType() && !T->isEnumeralType();
696 case UTT_IsFundamental:
697 return T->isFundamentalType();
699 return T->isObjectType();
705 if (T->isObjCLifetimeType()) {
706 switch (T.getObjCLifetime()) {
718 return T->isScalarType();
720 return T->isCompoundType();
721 case UTT_IsMemberPointer:
722 return T->isMemberPointerType();
727 return T.isConstQualified();
729 return T.isVolatileQualified();
731 return T.isTrivialType(
C);
732 case UTT_IsTriviallyCopyable:
733 return T.isTriviallyCopyableType(
C);
734 case UTT_IsStandardLayout:
735 return T->isStandardLayoutType();
737 return T.isPODType(
C);
739 return T->isLiteralType(
C);
744 case UTT_IsPolymorphic:
752 case UTT_IsAggregate:
756 return T->isAggregateType() || T->isVectorType() || T->isExtVectorType() ||
757 T->isAnyComplexType();
761 case UTT_IsInterfaceClass:
766 return RD->
hasAttr<FinalAttr>();
771 return T->isFloatingType() ||
772 (T->isSignedIntegerType() && !T->isEnumeralType());
775 return T->isUnsignedIntegerType() && !T->isEnumeralType();
793 case UTT_HasTrivialDefaultConstructor:
800 if (
CXXRecordDecl *RD =
C.getBaseElementType(T)->getAsCXXRecordDecl())
804 case UTT_HasTrivialMoveConstructor:
810 if (
CXXRecordDecl *RD =
C.getBaseElementType(T)->getAsCXXRecordDecl())
814 case UTT_HasTrivialCopy:
820 if (T.isPODType(
C) || T->isReferenceType())
826 case UTT_HasTrivialMoveAssign:
832 if (
CXXRecordDecl *RD =
C.getBaseElementType(T)->getAsCXXRecordDecl())
836 case UTT_HasTrivialAssign:
849 if (T.isConstQualified())
857 case UTT_IsDestructible:
858 case UTT_IsTriviallyDestructible:
859 case UTT_IsNothrowDestructible:
862 if (T->isReferenceType())
866 if (T->isObjCLifetimeType() &&
873 if (T->isIncompleteType() || T->isFunctionType())
878 if (UTT == UTT_IsTriviallyDestructible && T.isDestructedType())
885 if (
auto *RD =
C.getBaseElementType(T)->getAsCXXRecordDecl()) {
896 if (UTT == UTT_IsNothrowDestructible) {
898 CPT =
Self.ResolveExceptionSpec(KeyLoc, CPT);
905 case UTT_HasTrivialDestructor:
912 if (T.isPODType(
C) || T->isReferenceType())
916 if (T->isObjCLifetimeType() &&
920 if (
CXXRecordDecl *RD =
C.getBaseElementType(T)->getAsCXXRecordDecl())
924 case UTT_HasNothrowAssign:
932 if (
C.getBaseElementType(T).isConstQualified())
934 if (T->isReferenceType())
936 if (T.isPODType(
C) || T->isObjCLifetimeType())
939 if (
auto *RD = T->getAsCXXRecordDecl())
945 case UTT_HasNothrowMoveAssign:
952 if (
auto *RD =
C.getBaseElementType(T)->getAsCXXRecordDecl())
958 case UTT_HasNothrowCopy:
964 if (T.isPODType(
C) || T->isReferenceType() || T->isObjCLifetimeType())
971 bool FoundConstructor =
false;
973 for (
const auto *ND :
Self.LookupConstructors(RD)) {
984 FoundConstructor =
true;
986 CPT =
Self.ResolveExceptionSpec(KeyLoc, CPT);
996 return FoundConstructor;
999 case UTT_HasNothrowConstructor:
1005 if (T.isPODType(
C) || T->isObjCLifetimeType())
1007 if (
CXXRecordDecl *RD =
C.getBaseElementType(T)->getAsCXXRecordDecl()) {
1011 bool FoundConstructor =
false;
1012 for (
const auto *ND :
Self.LookupConstructors(RD)) {
1021 FoundConstructor =
true;
1023 CPT =
Self.ResolveExceptionSpec(KeyLoc, CPT);
1032 return FoundConstructor;
1035 case UTT_HasVirtualDestructor:
1047 case UTT_IsCompleteType:
1051 return !T->isIncompleteType();
1052 case UTT_HasUniqueObjectRepresentations:
1053 return C.hasUniqueObjectRepresentations(T);
1054 case UTT_IsTriviallyRelocatable:
1056 case UTT_IsBitwiseCloneable:
1057 return T.isBitwiseCloneableType(
C);
1058 case UTT_IsCppTriviallyRelocatable:
1059 return Self.IsCXXTriviallyRelocatableType(T);
1060 case UTT_CanPassInRegs:
1061 if (
CXXRecordDecl *RD = T->getAsCXXRecordDecl(); RD && !T.hasQualifiers())
1063 Self.Diag(KeyLoc, diag::err_builtin_pass_in_regs_non_class) << T;
1065 case UTT_IsTriviallyEqualityComparable:
1067 case UTT_IsImplicitLifetime: {
1069 tok::kw___builtin_is_implicit_lifetime);
1071 tok::kw___builtin_is_implicit_lifetime);
1094 bool HasTrivialNonDeletedDtr =
1096 if (!HasTrivialNonDeletedDtr)
1099 if (Ctr->isIneligibleOrNotSelected() || Ctr->isDeleted())
1101 if (Ctr->isTrivial())
1116 case UTT_IsIntangibleType:
1117 assert(
Self.getLangOpts().HLSL &&
"intangible types are HLSL-only feature");
1118 if (!T->isVoidType() && !T->isIncompleteArrayType())
1120 diag::err_incomplete_type))
1123 tok::kw___builtin_hlsl_is_intangible))
1125 return T->isHLSLIntangibleType();
1127 case UTT_IsTypedResourceElementCompatible:
1128 assert(
Self.getLangOpts().HLSL &&
1129 "typed resource element compatible types are an HLSL-only feature");
1130 if (T->isIncompleteType())
1133 return Self.HLSL().IsTypedResourceElementCompatible(T);
1144 SourceLocation KeyLoc, llvm::BumpPtrAllocator &OpaqueExprAllocator) {
1185 LhsT =
Self.Context.getRValueReferenceType(LhsT);
1221 case TypeTrait::UTT_StructuredBindingSize: {
1223 SourceRange ArgRange = Args[0]->getTypeLoc().getSourceRange();
1227 S.
Diag(KWLoc, diag::err_arg_is_not_destructurable) << T << ArgRange;
1235 llvm_unreachable(
"Not a SizeT type trait");
1252 if (Kind <=
BTT_Last && Kind != BTT_ReferenceBindsToTemporary &&
1253 Kind != BTT_ReferenceConstructsFromTemporary &&
1254 Kind != BTT_ReferenceConvertsFromTemporary)
1258 case clang::BTT_ReferenceBindsToTemporary:
1259 case clang::BTT_ReferenceConstructsFromTemporary:
1260 case clang::BTT_ReferenceConvertsFromTemporary:
1261 case clang::TT_IsConstructible:
1262 case clang::TT_IsNothrowConstructible:
1263 case clang::TT_IsTriviallyConstructible: {
1277 assert(!Args.empty());
1282 for (
const auto *TSI : Args) {
1288 KWLoc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr))
1294 if (T->isIncompleteType() || T->isFunctionType())
1305 bool UseRawObjectType =
1306 Kind == clang::BTT_ReferenceBindsToTemporary ||
1307 Kind == clang::BTT_ReferenceConstructsFromTemporary ||
1308 Kind == clang::BTT_ReferenceConvertsFromTemporary;
1310 llvm::BumpPtrAllocator OpaqueExprAllocator;
1312 ArgExprs.reserve(Args.size() - 1);
1313 for (
unsigned I = 1, N = Args.size(); I != N; ++I) {
1314 QualType ArgTy = Args[I]->getType();
1334 Kind == clang::BTT_ReferenceConvertsFromTemporary
1345 if (Kind == clang::TT_IsConstructible)
1348 if (Kind == clang::BTT_ReferenceBindsToTemporary ||
1349 Kind == clang::BTT_ReferenceConstructsFromTemporary ||
1350 Kind == clang::BTT_ReferenceConvertsFromTemporary) {
1351 if (!T->isReferenceType())
1355 if (T.getNonReferenceType()->isFunctionType())
1358 if (!
Init.isDirectReferenceBinding())
1361 if (Kind == clang::BTT_ReferenceBindsToTemporary)
1365 if (
U->isReferenceType())
1373 OpaqueExprAllocator)
1377 if (Kind == clang::TT_IsNothrowConstructible)
1380 if (Kind == clang::TT_IsTriviallyConstructible) {
1383 if (T.getNonReferenceType().hasNonTrivialObjCLifetime())
1388 return !Result.get()->hasNonTrivialCall(S.
Context);
1391 llvm_unreachable(
"unhandled type trait");
1395 llvm_unreachable(
"not a TT");
1405 case UTT_HasNothrowAssign:
1406 case UTT_HasNothrowMoveAssign:
1407 Replacement = BTT_IsNothrowAssignable;
1409 case UTT_HasNothrowCopy:
1410 case UTT_HasNothrowConstructor:
1411 Replacement = TT_IsNothrowConstructible;
1413 case UTT_HasTrivialAssign:
1414 case UTT_HasTrivialMoveAssign:
1415 Replacement = BTT_IsTriviallyAssignable;
1417 case UTT_HasTrivialCopy:
1418 Replacement = UTT_IsTriviallyCopyable;
1420 case UTT_HasTrivialDefaultConstructor:
1421 case UTT_HasTrivialMoveConstructor:
1422 Replacement = TT_IsTriviallyConstructible;
1424 case UTT_HasTrivialDestructor:
1425 Replacement = UTT_IsTriviallyDestructible;
1427 case UTT_IsTriviallyRelocatable:
1428 Replacement = clang::UTT_IsCppTriviallyRelocatable;
1430 case BTT_ReferenceBindsToTemporary:
1431 Replacement = clang::BTT_ReferenceConstructsFromTemporary;
1436 S.
Diag(KWLoc, diag::warn_deprecated_builtin)
1442 if (Arity && N != Arity) {
1443 Diag(Loc, diag::err_type_trait_arity)
1444 << Arity << 0 << (Arity > 1) << (
int)N <<
SourceRange(Loc);
1448 if (!Arity && N == 0) {
1449 Diag(Loc, diag::err_type_trait_arity)
1462 if (Kind == TypeTrait::UTT_StructuredBindingSize)
1474 *
this, Kind, KWLoc, Args[0]->
getType()))
1477 DiagnoseBuiltinDeprecation(*
this, Kind, KWLoc);
1480 for (
unsigned I = 0, N = Args.size(); I != N; ++I) {
1481 if (Args[I]->
getType()->isDependentType()) {
1492 KWLoc, Kind, Args, RParenLoc,
Result);
1498 Args, RParenLoc,
Result);
1501 llvm_unreachable(
"unhandled type trait return type");
1508 ConvertedArgs.reserve(Args.size());
1510 for (
unsigned I = 0, N = Args.size(); I != N; ++I) {
1514 TInfo =
Context.getTrivialTypeSourceInfo(T, KWLoc);
1516 ConvertedArgs.push_back(TInfo);
1529 const RecordType *lhsRecord = LhsT->
getAsCanonical<RecordType>();
1530 const RecordType *rhsRecord = RhsT->
getAsCanonical<RecordType>();
1531 if (!rhsRecord || !lhsRecord) {
1534 if (!LHSObjTy || !RHSObjTy)
1539 if (!BaseInterface || !DerivedInterface)
1543 diag::err_incomplete_type_used_in_type_trait_expr))
1549 assert(
Context.hasSameUnqualifiedType(LhsT, RhsT) ==
1550 (lhsRecord == rhsRecord));
1554 if (lhsRecord && lhsRecord->getDecl()->isUnion())
1556 if (rhsRecord && rhsRecord->getDecl()->isUnion())
1559 if (lhsRecord == rhsRecord)
1567 diag::err_incomplete_type_used_in_type_trait_expr))
1582 "Cannot evaluate traits of dependent types");
1588 case BTT_IsVirtualBaseOf: {
1589 const RecordType *BaseRecord = LhsT->
getAsCanonical<RecordType>();
1590 const RecordType *DerivedRecord = RhsT->
getAsCanonical<RecordType>();
1592 if (!BaseRecord || !DerivedRecord) {
1594 tok::kw___builtin_is_virtual_base_of);
1596 tok::kw___builtin_is_virtual_base_of);
1600 if (BaseRecord->isUnionType() || DerivedRecord->isUnionType())
1603 if (!BaseRecord->isStructureOrClassType() ||
1604 !DerivedRecord->isStructureOrClassType())
1608 diag::err_incomplete_type))
1615 return Self.Context.hasSameType(LhsT, RhsT);
1616 case BTT_TypeCompatible: {
1619 QualType Lhs =
Self.getASTContext().getUnqualifiedArrayType(LhsT, LhsQuals);
1620 QualType Rhs =
Self.getASTContext().getUnqualifiedArrayType(RhsT, RhsQuals);
1621 return Self.Context.typesAreCompatible(Lhs, Rhs);
1623 case BTT_IsConvertible:
1624 case BTT_IsConvertibleTo:
1625 case BTT_IsNothrowConvertible: {
1628 llvm::BumpPtrAllocator OpaqueExprAllocator;
1630 OpaqueExprAllocator);
1631 if (Result.isInvalid())
1634 if (BTT != BTT_IsNothrowConvertible)
1640 case BTT_IsAssignable:
1641 case BTT_IsNothrowAssignable:
1642 case BTT_IsTriviallyAssignable: {
1655 Self.RequireCompleteType(
1657 diag::err_incomplete_type_used_in_type_trait_expr))
1660 Self.RequireCompleteType(
1662 diag::err_incomplete_type_used_in_type_trait_expr))
1672 if (Ty->isObjectType() || Ty->isFunctionType())
1673 Ty =
Self.Context.getRValueReferenceType(Ty);
1674 return {KeyLoc, Ty.getNonLValueExprType(
Self.Context),
1678 auto Lhs = createDeclValExpr(LhsT);
1679 auto Rhs = createDeclValExpr(RhsT);
1688 Self.BuildBinOp(
nullptr, KeyLoc, BO_Assign, &Lhs, &Rhs);
1689 if (Result.isInvalid())
1693 Self.CheckUnusedVolatileAssignment(Result.get());
1698 if (BTT == BTT_IsAssignable)
1701 if (BTT == BTT_IsNothrowAssignable)
1704 if (BTT == BTT_IsTriviallyAssignable) {
1710 if (Context.containsAddressDiscriminatedPointerAuth(LhsT) ||
1711 Context.containsAddressDiscriminatedPointerAuth(RhsT))
1713 return !Result.get()->hasNonTrivialCall(
Self.Context);
1716 llvm_unreachable(
"unhandled type trait");
1719 case BTT_IsLayoutCompatible: {
1722 diag::err_incomplete_type);
1725 diag::err_incomplete_type);
1730 return Self.IsLayoutCompatible(LhsT, RhsT);
1732 case BTT_IsPointerInterconvertibleBaseOf: {
1734 !
Self.getASTContext().hasSameUnqualifiedType(LhsT, RhsT)) {
1736 diag::err_incomplete_type);
1740 tok::kw___is_pointer_interconvertible_base_of);
1742 tok::kw___is_pointer_interconvertible_base_of);
1744 return Self.IsPointerInterconvertibleBaseOf(Lhs, Rhs);
1746 case BTT_IsDeducible: {
1749 return Self.DeduceTemplateArgumentsFromType(
1750 TSTToBeDeduced->getTemplateName().getAsTemplateDecl(), RhsT,
1753 case BTT_IsScalarizedLayoutCompatible: {
1756 diag::err_incomplete_type))
1760 diag::err_incomplete_type))
1764 Self, Lhs, tok::kw___builtin_hlsl_is_scalarized_layout_compatible);
1766 Self, Rhs, tok::kw___builtin_hlsl_is_scalarized_layout_compatible);
1768 return Self.HLSL().IsScalarizedLayoutCompatible(LhsT, RhsT);
1770 case BTT_LtSynthesizesFromSpaceship:
1771 case BTT_LeSynthesizesFromSpaceship:
1772 case BTT_GtSynthesizesFromSpaceship:
1773 case BTT_GeSynthesizesFromSpaceship: {
1792 case BTT_LtSynthesizesFromSpaceship:
1793 return BinaryOperatorKind::BO_LT;
1794 case BTT_LeSynthesizesFromSpaceship:
1795 return BinaryOperatorKind::BO_LE;
1796 case BTT_GtSynthesizesFromSpaceship:
1797 return BinaryOperatorKind::BO_GT;
1798 case BTT_GeSynthesizesFromSpaceship:
1799 return BinaryOperatorKind::BO_GE;
1801 llvm_unreachable(
"Trying to Synthesize non-comparison operator?");
1806 Self.LookupBinOp(
Self.TUScope, KeyLoc, OpKind, Functions);
1809 Self.CreateOverloadedBinOp(KeyLoc, OpKind, Functions, &LHS, &RHS);
1816 llvm_unreachable(
"not a BTT");
1818 llvm_unreachable(
"Unknown type trait or not implemented");
1827 TSInfo =
Context.getTrivialTypeSourceInfo(T);
1835 assert(!T->isDependentType() &&
"Cannot evaluate traits of dependent type");
1839 if (T->isArrayType()) {
1841 while (
const ArrayType *AT =
Self.Context.getAsArrayType(T)) {
1843 T = AT->getElementType();
1849 case ATT_ArrayExtent: {
1852 if (
Self.VerifyIntegerConstantExpression(
1853 DimExpr, &
Value, diag::err_dimension_expr_not_constant_integer)
1856 if (
Value.isSigned() &&
Value.isNegative()) {
1857 Self.Diag(KeyLoc, diag::err_dimension_expr_not_constant_integer)
1863 if (T->isArrayType()) {
1865 bool Matched =
false;
1866 while (
const ArrayType *AT =
Self.Context.getAsArrayType(T)) {
1872 T = AT->getElementType();
1875 if (Matched && T->isArrayType()) {
1877 Self.Context.getAsConstantArrayType(T))
1878 return CAT->getLimitedSize();
1884 llvm_unreachable(
"Unknown type trait or not implemented");
1895 if (!T->isDependentType())
1904 RParen,
Context.getSizeType());
1920 case ET_IsLValueExpr:
1922 case ET_IsRValueExpr:
1925 llvm_unreachable(
"Expression trait not covered by switch");
1946 return llvm::StringSwitch<std::optional<TypeTrait>>(Name)
1947 .Case(
"is_trivially_relocatable",
1948 TypeTrait::UTT_IsCppTriviallyRelocatable)
1949 .Case(
"is_trivially_copyable", TypeTrait::UTT_IsTriviallyCopyable)
1950 .Case(
"is_assignable", TypeTrait::BTT_IsAssignable)
1951 .Case(
"is_empty", TypeTrait::UTT_IsEmpty)
1952 .Case(
"is_standard_layout", TypeTrait::UTT_IsStandardLayout)
1953 .Case(
"is_aggregate", TypeTrait::UTT_IsAggregate)
1954 .Case(
"is_constructible", TypeTrait::TT_IsConstructible)
1955 .Case(
"is_final", TypeTrait::UTT_IsFinal)
1956 .Case(
"is_abstract", TypeTrait::UTT_IsAbstract)
1957 .Default(std::nullopt);
1961 std::optional<std::pair<TypeTrait, llvm::SmallVector<QualType, 1>>>;
1969 std::optional<TypeTrait> Trait;
1972 if (
const auto *TraitExpr = dyn_cast<TypeTraitExpr>(E)) {
1973 Trait = TraitExpr->getTrait();
1974 for (
const auto *Arg : TraitExpr->getArgs())
1975 Args.push_back(Arg->getType());
1976 return {{Trait.value(), std::move(Args)}};
1978 const auto *Ref = dyn_cast<DeclRefExpr>(E);
1980 return std::nullopt;
1983 if (
const auto *VD =
1984 dyn_cast<VarTemplateSpecializationDecl>(Ref->getDecl())) {
1985 if (!VD->isInStdNamespace())
1986 return std::nullopt;
1987 StringRef Name = VD->getIdentifier()->getName();
1988 if (!Name.consume_back(
"_v"))
1989 return std::nullopt;
1992 return std::nullopt;
1993 for (
const auto &Arg : VD->getTemplateArgs().asArray()) {
1995 for (
const auto &InnerArg : Arg.pack_elements())
1996 Args.push_back(InnerArg.getAsType());
1998 Args.push_back(Arg.getAsType());
2000 llvm_unreachable(
"Unexpected kind");
2003 return {{Trait.value(), std::move(Args)}};
2007 if (
const auto *VD = dyn_cast<VarDecl>(Ref->getDecl());
2008 Ref->hasQualifier() && VD && VD->getIdentifier()->isStr(
"value")) {
2011 return std::nullopt;
2012 const auto *Ts = Qualifier.getAsType()->getAs<TemplateSpecializationType>();
2014 return std::nullopt;
2015 const TemplateDecl *D = Ts->getTemplateName().getAsTemplateDecl();
2017 return std::nullopt;
2020 return std::nullopt;
2021 for (
const auto &Arg : Ts->template_arguments())
2022 Args.push_back(Arg.getAsType());
2023 return {{Trait.value(), std::move(Args)}};
2025 return std::nullopt;
2033 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2034 << diag::TraitNotSatisfiedReason::UnionWithUserDeclaredSMF << K;
2048 const auto *
Decl = cast_or_null<CXXConstructorDecl>(
2050 if (
Decl &&
Decl->isUserProvided())
2051 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2052 << diag::TraitNotSatisfiedReason::UserProvidedCtr
2058 if (
Decl &&
Decl->isUserProvided())
2059 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2060 << diag::TraitNotSatisfiedReason::UserProvidedAssign
2064 Dtr = Dtr->getCanonicalDecl();
2065 if (Dtr->isUserProvided() && !Dtr->isDefaulted())
2066 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2067 << diag::TraitNotSatisfiedReason::DeletedDtr << 1
2068 << Dtr->getSourceRange();
2076 assert(B.getType()->getAsCXXRecordDecl() &&
"invalid base?");
2078 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2079 << diag::TraitNotSatisfiedReason::VBase << B.getType()
2080 << B.getSourceRange();
2082 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2083 << diag::TraitNotSatisfiedReason::NTRBase << B.getType()
2084 << B.getSourceRange();
2087 if (!Field->getType()->isReferenceType() &&
2089 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2090 << diag::TraitNotSatisfiedReason::NTRField << Field
2091 << Field->getType() << Field->getSourceRange();
2094 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2095 << diag::TraitNotSatisfiedReason::DeletedDtr << 0
2104 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait)
2105 << T << diag::TraitName::TriviallyRelocatable;
2106 if (T->isVariablyModifiedType())
2107 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2108 << diag::TraitNotSatisfiedReason::VLA;
2110 if (T->isReferenceType())
2111 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2112 << diag::TraitNotSatisfiedReason::Ref;
2113 T = T.getNonReferenceType();
2115 if (T.hasNonTrivialObjCLifetime())
2116 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2117 << diag::TraitNotSatisfiedReason::HasArcLifetime;
2133 assert(B.getType()->getAsCXXRecordDecl() &&
"invalid base?");
2135 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2136 << diag::TraitNotSatisfiedReason::VBase << B.getType()
2137 << B.getSourceRange();
2138 if (!B.getType().isTriviallyCopyableType(D->
getASTContext())) {
2139 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2140 << diag::TraitNotSatisfiedReason::NTCBase << B.getType()
2141 << B.getSourceRange();
2145 if (!Field->getType().isTriviallyCopyableType(Field->getASTContext()))
2146 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2147 << diag::TraitNotSatisfiedReason::NTCField << Field
2148 << Field->getType() << Field->getSourceRange();
2152 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2153 << diag::TraitNotSatisfiedReason::DeletedDtr
2157 if (Method->isTrivial() || !Method->isUserProvided()) {
2160 auto SpecialMemberKind =
2162 switch (SpecialMemberKind) {
2174 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2175 << (IsAssignment ? diag::TraitNotSatisfiedReason::UserProvidedAssign
2176 : diag::TraitNotSatisfiedReason::UserProvidedCtr)
2177 << IsMove << Method->getSourceRange();
2193 bool ContainsVoid =
false;
2195 ContainsVoid |= ArgTy->isVoidType();
2199 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2200 << diag::TraitNotSatisfiedReason::CVVoidType;
2203 if (T->isFunctionType())
2204 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2205 << diag::TraitNotSatisfiedReason::FunctionType;
2207 if (T->isIncompleteArrayType())
2208 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2209 << diag::TraitNotSatisfiedReason::IncompleteArrayType;
2215 llvm::BumpPtrAllocator OpaqueExprAllocator;
2217 ArgExprs.reserve(Ts.size() - 1);
2218 for (
unsigned I = 1, N = Ts.size(); I != N; ++I) {
2236 Init.Diagnose(SemaRef, To, InitKind, ArgExprs);
2242 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait)
2243 << T << diag::TraitName::TriviallyCopyable;
2245 if (T->isReferenceType())
2246 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2247 << diag::TraitNotSatisfiedReason::Ref;
2264 if (Ty->isObjectType() || Ty->isFunctionType())
2266 return {Loc, Ty.getNonLValueExprType(SemaRef.
Context),
2270 auto LHS = createDeclValExpr(T);
2271 auto RHS = createDeclValExpr(
U);
2277 SemaRef.
BuildBinOp(
nullptr, Loc, BO_Assign, &LHS, &RHS);
2288 for (
const auto *Field : D->
fields()) {
2289 if (Field->isZeroLengthBitField())
2291 if (Field->isBitField()) {
2292 S.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2293 << diag::TraitNotSatisfiedReason::NonZeroLengthField << Field
2294 << Field->getSourceRange();
2297 S.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2298 << diag::TraitNotSatisfiedReason::NonEmptyMember << Field
2299 << Field->getType() << Field->getSourceRange();
2303 for (
const auto *M : D->
methods()) {
2304 if (M->isVirtual()) {
2305 S.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2306 << diag::TraitNotSatisfiedReason::VirtualFunction << M
2307 << M->getSourceRange();
2313 for (
const auto &B : D->
bases()) {
2314 const auto *BR = B.getType()->getAsCXXRecordDecl();
2315 if (!BR || BR->isInvalidDecl())
2317 if (B.isVirtual()) {
2318 S.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2319 << diag::TraitNotSatisfiedReason::VBase << B.getType()
2320 << B.getSourceRange();
2322 if (!BR->isEmpty()) {
2323 S.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2324 << diag::TraitNotSatisfiedReason::NonEmptyBase << B.getType()
2325 << B.getSourceRange();
2332 S.
Diag(Loc, diag::note_unsatisfied_trait) << T << diag::TraitName::Empty;
2337 if (T->isReferenceType())
2338 S.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2339 << diag::TraitNotSatisfiedReason::Ref;
2340 T = T.getNonReferenceType();
2343 T = AT->getElementType();
2345 if (
auto *D = T->getAsCXXRecordDecl()) {
2346 if (D->hasDefinition()) {
2348 S.
Diag(D->getLocation(), diag::note_defined_here) << D;
2360 S.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2361 << diag::TraitNotSatisfiedReason::NotMarkedFinal;
2369 S.
Diag(Loc, diag::note_unsatisfied_trait) << T << diag::TraitName::Final;
2370 if (T->isReferenceType()) {
2371 S.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2372 << diag::TraitNotSatisfiedReason::Ref;
2373 S.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2374 << diag::TraitNotSatisfiedReason::NotClassOrUnion;
2379 S.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2380 << diag::TraitNotSatisfiedReason::NotClassOrUnion;
2383 if (T->isFunctionType()) {
2384 S.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2385 << diag::TraitNotSatisfiedReason::FunctionType;
2386 S.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2387 << diag::TraitNotSatisfiedReason::NotClassOrUnion;
2390 if (!T->isRecordType()) {
2391 S.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2392 << diag::TraitNotSatisfiedReason::NotClassOrUnion;
2395 if (
const auto *D = T->getAsCXXRecordDecl())
2400 int NumBasesWithFields = 0;
2407 if (!Field->isUnnamedBitField()) {
2408 if (++NumBasesWithFields > 1)
2420 assert(B.getType()->getAsCXXRecordDecl() &&
"invalid base?");
2421 if (B.isVirtual()) {
2422 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2423 << diag::TraitNotSatisfiedReason::VBase << B.getType()
2424 << B.getSourceRange();
2426 if (!B.getType()->isStandardLayoutType()) {
2427 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2428 << diag::TraitNotSatisfiedReason::NonStandardLayoutBase << B.getType()
2429 << B.getSourceRange();
2437 if (Field->isUnnamedBitField())
2448 if (Field->getAccess() != FirstAccess) {
2450 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2451 << diag::TraitNotSatisfiedReason::MixedAccess;
2456 SemaRef.
Diag(Field->getLocation(), diag::note_unsatisfied_trait_reason)
2457 << diag::TraitNotSatisfiedReason::MixedAccessField << Field
2465 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2466 << diag::TraitNotSatisfiedReason::MultipleDataBase;
2472 for (
const auto *M : D->
methods()) {
2473 if (M->isVirtual()) {
2479 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2480 << diag::TraitNotSatisfiedReason::VirtualFunction << VirtualMD;
2481 SemaRef.
Diag(VirtualMD->getLocation(), diag::note_defined_here)
2485 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2486 << diag::TraitNotSatisfiedReason::VirtualFunction << D;
2487 SemaRef.
Diag(D->getLocation(), diag::note_defined_here) << D;
2491 if (!Field->getType()->isStandardLayoutType()) {
2492 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2493 << diag::TraitNotSatisfiedReason::NonStandardLayoutMember << Field
2494 << Field->getType() << Field->getSourceRange();
2508 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2509 << diag::TraitNotSatisfiedReason::IndirectBaseWithFields << Indirect
2517 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait)
2518 << T << diag::TraitName::StandardLayout;
2521 if (T->isVariablyModifiedType()) {
2522 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2523 << diag::TraitNotSatisfiedReason::VLA;
2527 if (T->isReferenceType()) {
2528 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2529 << diag::TraitNotSatisfiedReason::Ref;
2532 T = T.getNonReferenceType();
2546 if (Ctor->isUserProvided())
2547 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2548 << diag::TraitNotSatisfiedReason::UserDeclaredCtr;
2549 if (Ctor->isInheritingConstructor())
2550 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2551 << diag::TraitNotSatisfiedReason::InheritedCtr;
2554 if (llvm::any_of(D->
decls(), [](
auto const *Sub) {
2555 return isa<ConstructorUsingShadowDecl>(Sub);
2557 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2558 << diag::TraitNotSatisfiedReason::InheritedCtr;
2562 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2563 << diag::TraitNotSatisfiedReason::PolymorphicType
2567 if (B.isVirtual()) {
2568 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2569 << diag::TraitNotSatisfiedReason::VBase << B.getType()
2570 << B.getSourceRange();
2577 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2578 << diag::TraitNotSatisfiedReason::PrivateProtectedDirectBase
2587 if (Method->isVirtual()) {
2588 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2589 << diag::TraitNotSatisfiedReason::VirtualFunction << Method
2590 << Method->getSourceRange();
2599 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2600 << diag::TraitNotSatisfiedReason::PrivateProtectedDirectDataMember
2613 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait)
2614 << T << diag::TraitName::Aggregate;
2616 if (T->isVoidType())
2617 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2618 << diag::TraitNotSatisfiedReason::CVVoidType;
2620 T = T.getNonReferenceType();
2634 if (B.getType()->castAsCXXRecordDecl()->isAbstract()) {
2635 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2636 << diag::TraitNotSatisfiedReason::OverridesAllPureVirtual
2637 << B.getType() << B.getSourceRange();
2644 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait)
2645 << T << diag::TraitName::Abstract;
2647 if (T->isReferenceType()) {
2648 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2649 << diag::TraitNotSatisfiedReason::Ref;
2650 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2651 << diag::TraitNotSatisfiedReason::NotStructOrClass;
2655 if (T->isUnionType()) {
2656 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2657 << diag::TraitNotSatisfiedReason::UnionType;
2658 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2659 << diag::TraitNotSatisfiedReason::NotStructOrClass;
2664 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2665 << diag::TraitNotSatisfiedReason::ArrayType;
2666 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2667 << diag::TraitNotSatisfiedReason::NotStructOrClass;
2671 if (T->isFunctionType()) {
2672 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2673 << diag::TraitNotSatisfiedReason::FunctionType;
2674 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2675 << diag::TraitNotSatisfiedReason::NotStructOrClass;
2679 if (T->isPointerType()) {
2680 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2681 << diag::TraitNotSatisfiedReason::PointerType;
2682 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2683 << diag::TraitNotSatisfiedReason::NotStructOrClass;
2687 if (!T->isStructureOrClassType()) {
2688 SemaRef.
Diag(Loc, diag::note_unsatisfied_trait_reason)
2689 << diag::TraitNotSatisfiedReason::NotStructOrClass;
2707 const auto &[Trait, Args] = TraitInfo.value();
2709 case UTT_IsCppTriviallyRelocatable:
2712 case UTT_IsTriviallyCopyable:
2715 case BTT_IsAssignable:
2721 case UTT_IsStandardLayout:
2724 case TT_IsConstructible:
2727 case UTT_IsAggregate:
2739 case UTT_IsAbstract:
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.
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 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 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)
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.
Defines enumerations for the type traits support.
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
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.
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.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
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.
CXXSpecialMemberKind asSpecialMember() const
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.
DefaultedFunctionKind getDefaultedFunctionKind(const FunctionDecl *FD)
Determine the kind of defaulting that would be done for a given function.
@ 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
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...
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.
CanQualType getCanonicalTypeUnqualified() const
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.
The JSON file list parser is used to communicate input to InstallAPI.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
bool isa(CodeGen::Address addr)
ArrayTypeTrait
Names for the array type traits.
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...
@ Result
The result type of a method or function.
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.
const char * getTraitSpelling(ExpressionTrait T) LLVM_READONLY
Return the spelling of the type trait TT. Never null.
@ 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
TypeTrait
Names for traits that operate specifically on types.
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...