2829 lines · cpp
1//===----- SemaTypeTraits.cpp - Semantic Analysis for C++ Type Traits -----===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements semantic analysis for C++ type traits.10//11//===----------------------------------------------------------------------===//12 13#include "clang/AST/DeclCXX.h"14#include "clang/AST/TemplateBase.h"15#include "clang/AST/Type.h"16#include "clang/Basic/DiagnosticIDs.h"17#include "clang/Basic/DiagnosticParse.h"18#include "clang/Basic/DiagnosticSema.h"19#include "clang/Basic/Specifiers.h"20#include "clang/Basic/TypeTraits.h"21#include "clang/Sema/EnterExpressionEvaluationContext.h"22#include "clang/Sema/Initialization.h"23#include "clang/Sema/Lookup.h"24#include "clang/Sema/Overload.h"25#include "clang/Sema/Sema.h"26#include "clang/Sema/SemaHLSL.h"27#include "llvm/ADT/STLExtras.h"28 29using namespace clang;30 31static CXXMethodDecl *LookupSpecialMemberFromXValue(Sema &SemaRef,32 const CXXRecordDecl *RD,33 bool Assign) {34 RD = RD->getDefinition();35 SourceLocation LookupLoc = RD->getLocation();36 37 CanQualType CanTy = SemaRef.getASTContext().getCanonicalTagType(RD);38 DeclarationName Name;39 Expr *Arg = nullptr;40 unsigned NumArgs;41 42 QualType ArgType = CanTy;43 ExprValueKind VK = clang::VK_XValue;44 45 if (Assign)46 Name =47 SemaRef.getASTContext().DeclarationNames.getCXXOperatorName(OO_Equal);48 else49 Name =50 SemaRef.getASTContext().DeclarationNames.getCXXConstructorName(CanTy);51 52 OpaqueValueExpr FakeArg(LookupLoc, ArgType, VK);53 NumArgs = 1;54 Arg = &FakeArg;55 56 // Create the object argument57 QualType ThisTy = CanTy;58 Expr::Classification Classification =59 OpaqueValueExpr(LookupLoc, ThisTy, VK_LValue)60 .Classify(SemaRef.getASTContext());61 62 // Now we perform lookup on the name we computed earlier and do overload63 // resolution. Lookup is only performed directly into the class since there64 // will always be a (possibly implicit) declaration to shadow any others.65 OverloadCandidateSet OCS(LookupLoc, OverloadCandidateSet::CSK_Normal);66 DeclContext::lookup_result R = RD->lookup(Name);67 68 if (R.empty())69 return nullptr;70 71 // Copy the candidates as our processing of them may load new declarations72 // from an external source and invalidate lookup_result.73 SmallVector<NamedDecl *, 8> Candidates(R.begin(), R.end());74 75 for (NamedDecl *CandDecl : Candidates) {76 if (CandDecl->isInvalidDecl())77 continue;78 79 DeclAccessPair Cand = DeclAccessPair::make(CandDecl, clang::AS_none);80 auto CtorInfo = getConstructorInfo(Cand);81 if (CXXMethodDecl *M = dyn_cast<CXXMethodDecl>(Cand->getUnderlyingDecl())) {82 if (Assign)83 SemaRef.AddMethodCandidate(M, Cand, const_cast<CXXRecordDecl *>(RD),84 ThisTy, Classification,85 llvm::ArrayRef(&Arg, NumArgs), OCS, true);86 else {87 assert(CtorInfo);88 SemaRef.AddOverloadCandidate(CtorInfo.Constructor, CtorInfo.FoundDecl,89 llvm::ArrayRef(&Arg, NumArgs), OCS,90 /*SuppressUserConversions*/ true);91 }92 } else if (FunctionTemplateDecl *Tmpl =93 dyn_cast<FunctionTemplateDecl>(Cand->getUnderlyingDecl())) {94 if (Assign)95 SemaRef.AddMethodTemplateCandidate(96 Tmpl, Cand, const_cast<CXXRecordDecl *>(RD), nullptr, ThisTy,97 Classification, llvm::ArrayRef(&Arg, NumArgs), OCS, true);98 else {99 assert(CtorInfo);100 SemaRef.AddTemplateOverloadCandidate(101 CtorInfo.ConstructorTmpl, CtorInfo.FoundDecl, nullptr,102 llvm::ArrayRef(&Arg, NumArgs), OCS, true);103 }104 }105 }106 107 OverloadCandidateSet::iterator Best;108 switch (OCS.BestViableFunction(SemaRef, LookupLoc, Best)) {109 case OR_Success:110 case OR_Deleted:111 return cast<CXXMethodDecl>(Best->Function)->getCanonicalDecl();112 default:113 return nullptr;114 }115}116 117static bool hasSuitableConstructorForRelocation(Sema &SemaRef,118 const CXXRecordDecl *D,119 bool AllowUserDefined) {120 assert(D->hasDefinition() && !D->isInvalidDecl());121 122 if (D->hasSimpleMoveConstructor() || D->hasSimpleCopyConstructor())123 return true;124 125 CXXMethodDecl *Decl =126 LookupSpecialMemberFromXValue(SemaRef, D, /*Assign=*/false);127 return Decl && (AllowUserDefined || !Decl->isUserProvided()) &&128 !Decl->isDeleted();129}130 131static bool hasSuitableMoveAssignmentOperatorForRelocation(132 Sema &SemaRef, const CXXRecordDecl *D, bool AllowUserDefined) {133 assert(D->hasDefinition() && !D->isInvalidDecl());134 135 if (D->hasSimpleMoveAssignment() || D->hasSimpleCopyAssignment())136 return true;137 138 CXXMethodDecl *Decl =139 LookupSpecialMemberFromXValue(SemaRef, D, /*Assign=*/true);140 if (!Decl)141 return false;142 143 return Decl && (AllowUserDefined || !Decl->isUserProvided()) &&144 !Decl->isDeleted();145}146 147// [C++26][class.prop]148// A class C is default-movable if149// - overload resolution for direct-initializing an object of type C150// from an xvalue of type C selects a constructor that is a direct member of C151// and is neither user-provided nor deleted,152// - overload resolution for assigning to an lvalue of type C from an xvalue of153// type C selects an assignment operator function that is a direct member of C154// and is neither user-provided nor deleted, and C has a destructor that is155// neither user-provided nor deleted.156static bool IsDefaultMovable(Sema &SemaRef, const CXXRecordDecl *D) {157 if (!hasSuitableConstructorForRelocation(SemaRef, D,158 /*AllowUserDefined=*/false))159 return false;160 161 if (!hasSuitableMoveAssignmentOperatorForRelocation(162 SemaRef, D, /*AllowUserDefined=*/false))163 return false;164 165 CXXDestructorDecl *Dtr = D->getDestructor();166 167 if (!Dtr)168 return true;169 170 Dtr = Dtr->getCanonicalDecl();171 172 if (Dtr->isUserProvided() && (!Dtr->isDefaulted() || Dtr->isDeleted()))173 return false;174 175 return !Dtr->isDeleted();176}177 178// [C++26][class.prop]179// A class is eligible for trivial relocation unless it...180static bool IsEligibleForTrivialRelocation(Sema &SemaRef,181 const CXXRecordDecl *D) {182 183 for (const CXXBaseSpecifier &B : D->bases()) {184 const auto *BaseDecl = B.getType()->getAsCXXRecordDecl();185 if (!BaseDecl)186 continue;187 // ... has any virtual base classes188 // ... has a base class that is not a trivially relocatable class189 if (B.isVirtual() || (!BaseDecl->isDependentType() &&190 !SemaRef.IsCXXTriviallyRelocatableType(B.getType())))191 return false;192 }193 194 bool IsUnion = D->isUnion();195 for (const FieldDecl *Field : D->fields()) {196 if (Field->getType()->isDependentType())197 continue;198 if (Field->getType()->isReferenceType())199 continue;200 // ... has a non-static data member of an object type that is not201 // of a trivially relocatable type202 if (!SemaRef.IsCXXTriviallyRelocatableType(Field->getType()))203 return false;204 205 // A union contains values with address discriminated pointer auth206 // cannot be relocated.207 if (IsUnion && SemaRef.Context.containsAddressDiscriminatedPointerAuth(208 Field->getType()))209 return false;210 }211 return !D->hasDeletedDestructor();212}213 214// [C++26][class.prop]215// A class C is eligible for replacement unless216static bool IsEligibleForReplacement(Sema &SemaRef, const CXXRecordDecl *D) {217 218 for (const CXXBaseSpecifier &B : D->bases()) {219 const auto *BaseDecl = B.getType()->getAsCXXRecordDecl();220 if (!BaseDecl)221 continue;222 // it has a base class that is not a replaceable class223 if (!BaseDecl->isDependentType() &&224 !SemaRef.IsCXXReplaceableType(B.getType()))225 return false;226 }227 228 for (const FieldDecl *Field : D->fields()) {229 if (Field->getType()->isDependentType())230 continue;231 232 // it has a non-static data member that is not of a replaceable type,233 if (!SemaRef.IsCXXReplaceableType(Field->getType()))234 return false;235 }236 return !D->hasDeletedDestructor();237}238 239ASTContext::CXXRecordDeclRelocationInfo240Sema::CheckCXX2CRelocatableAndReplaceable(const CXXRecordDecl *D) {241 ASTContext::CXXRecordDeclRelocationInfo Info{false, false};242 243 if (!getLangOpts().CPlusPlus || D->isInvalidDecl())244 return Info;245 246 assert(D->hasDefinition());247 248 // This is part of "eligible for replacement", however we defer it249 // to avoid extraneous computations.250 auto HasSuitableSMP = [&] {251 return hasSuitableConstructorForRelocation(*this, D,252 /*AllowUserDefined=*/true) &&253 hasSuitableMoveAssignmentOperatorForRelocation(254 *this, D, /*AllowUserDefined=*/true);255 };256 257 auto IsUnion = [&, Is = std::optional<bool>{}]() mutable {258 if (!Is.has_value())259 Is = D->isUnion() && !D->hasUserDeclaredCopyConstructor() &&260 !D->hasUserDeclaredCopyAssignment() &&261 !D->hasUserDeclaredMoveOperation() &&262 !D->hasUserDeclaredDestructor();263 return *Is;264 };265 266 auto IsDefaultMovable = [&, Is = std::optional<bool>{}]() mutable {267 if (!Is.has_value())268 Is = ::IsDefaultMovable(*this, D);269 return *Is;270 };271 272 Info.IsRelocatable = [&] {273 if (D->isDependentType())274 return false;275 276 // if it is eligible for trivial relocation277 if (!IsEligibleForTrivialRelocation(*this, D))278 return false;279 280 // has the trivially_relocatable_if_eligible class-property-specifier,281 if (D->hasAttr<TriviallyRelocatableAttr>())282 return true;283 284 // is a union with no user-declared special member functions, or285 if (IsUnion())286 return true;287 288 // is default-movable.289 return IsDefaultMovable();290 }();291 292 Info.IsReplaceable = [&] {293 if (D->isDependentType())294 return false;295 296 // A class C is a replaceable class if it is eligible for replacement297 if (!IsEligibleForReplacement(*this, D))298 return false;299 300 // has the replaceable_if_eligible class-property-specifier301 if (D->hasAttr<ReplaceableAttr>())302 return HasSuitableSMP();303 304 // is a union with no user-declared special member functions, or305 if (IsUnion())306 return HasSuitableSMP();307 308 // is default-movable.309 return IsDefaultMovable();310 }();311 312 return Info;313}314 315bool Sema::IsCXXTriviallyRelocatableType(const CXXRecordDecl &RD) {316 if (std::optional<ASTContext::CXXRecordDeclRelocationInfo> Info =317 getASTContext().getRelocationInfoForCXXRecord(&RD))318 return Info->IsRelocatable;319 ASTContext::CXXRecordDeclRelocationInfo Info =320 CheckCXX2CRelocatableAndReplaceable(&RD);321 getASTContext().setRelocationInfoForCXXRecord(&RD, Info);322 return Info.IsRelocatable;323}324 325bool Sema::IsCXXTriviallyRelocatableType(QualType Type) {326 QualType BaseElementType = getASTContext().getBaseElementType(Type);327 328 if (Type->isVariableArrayType())329 return false;330 331 if (BaseElementType.hasNonTrivialObjCLifetime())332 return false;333 334 if (BaseElementType->isIncompleteType())335 return false;336 337 if (Context.containsNonRelocatablePointerAuth(Type))338 return false;339 340 if (BaseElementType->isScalarType() || BaseElementType->isVectorType())341 return true;342 343 if (const auto *RD = BaseElementType->getAsCXXRecordDecl())344 return IsCXXTriviallyRelocatableType(*RD);345 346 return false;347}348 349static bool IsCXXReplaceableType(Sema &S, const CXXRecordDecl *RD) {350 if (std::optional<ASTContext::CXXRecordDeclRelocationInfo> Info =351 S.getASTContext().getRelocationInfoForCXXRecord(RD))352 return Info->IsReplaceable;353 ASTContext::CXXRecordDeclRelocationInfo Info =354 S.CheckCXX2CRelocatableAndReplaceable(RD);355 S.getASTContext().setRelocationInfoForCXXRecord(RD, Info);356 return Info.IsReplaceable;357}358 359bool Sema::IsCXXReplaceableType(QualType Type) {360 if (Type.isConstQualified() || Type.isVolatileQualified())361 return false;362 363 if (Type->isVariableArrayType())364 return false;365 366 QualType BaseElementType =367 getASTContext().getBaseElementType(Type.getUnqualifiedType());368 if (BaseElementType->isIncompleteType())369 return false;370 if (BaseElementType->isScalarType())371 return true;372 if (const auto *RD = BaseElementType->getAsCXXRecordDecl())373 return ::IsCXXReplaceableType(*this, RD);374 return false;375}376 377/// Checks that type T is not a VLA.378///379/// @returns @c true if @p T is VLA and a diagnostic was emitted,380/// @c false otherwise.381static bool DiagnoseVLAInCXXTypeTrait(Sema &S, const TypeSourceInfo *T,382 clang::tok::TokenKind TypeTraitID) {383 if (!T->getType()->isVariableArrayType())384 return false;385 386 S.Diag(T->getTypeLoc().getBeginLoc(), diag::err_vla_unsupported)387 << 1 << TypeTraitID;388 return true;389}390 391/// Checks that type T is not an atomic type (_Atomic).392///393/// @returns @c true if @p T is VLA and a diagnostic was emitted,394/// @c false otherwise.395static bool DiagnoseAtomicInCXXTypeTrait(Sema &S, const TypeSourceInfo *T,396 clang::tok::TokenKind TypeTraitID) {397 if (!T->getType()->isAtomicType())398 return false;399 400 S.Diag(T->getTypeLoc().getBeginLoc(), diag::err_atomic_unsupported)401 << TypeTraitID;402 return true;403}404 405/// Check the completeness of a type in a unary type trait.406///407/// If the particular type trait requires a complete type, tries to complete408/// it. If completing the type fails, a diagnostic is emitted and false409/// returned. If completing the type succeeds or no completion was required,410/// returns true.411static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT,412 SourceLocation Loc,413 QualType ArgTy) {414 // C++0x [meta.unary.prop]p3:415 // For all of the class templates X declared in this Clause, instantiating416 // that template with a template argument that is a class template417 // specialization may result in the implicit instantiation of the template418 // argument if and only if the semantics of X require that the argument419 // must be a complete type.420 // We apply this rule to all the type trait expressions used to implement421 // these class templates. We also try to follow any GCC documented behavior422 // in these expressions to ensure portability of standard libraries.423 switch (UTT) {424 default:425 llvm_unreachable("not a UTT");426 // is_complete_type somewhat obviously cannot require a complete type.427 case UTT_IsCompleteType:428 // Fall-through429 430 // These traits are modeled on the type predicates in C++0x431 // [meta.unary.cat] and [meta.unary.comp]. They are not specified as432 // requiring a complete type, as whether or not they return true cannot be433 // impacted by the completeness of the type.434 case UTT_IsVoid:435 case UTT_IsIntegral:436 case UTT_IsFloatingPoint:437 case UTT_IsArray:438 case UTT_IsBoundedArray:439 case UTT_IsPointer:440 case UTT_IsLvalueReference:441 case UTT_IsRvalueReference:442 case UTT_IsMemberFunctionPointer:443 case UTT_IsMemberObjectPointer:444 case UTT_IsEnum:445 case UTT_IsScopedEnum:446 case UTT_IsUnion:447 case UTT_IsClass:448 case UTT_IsFunction:449 case UTT_IsReference:450 case UTT_IsArithmetic:451 case UTT_IsFundamental:452 case UTT_IsObject:453 case UTT_IsScalar:454 case UTT_IsCompound:455 case UTT_IsMemberPointer:456 case UTT_IsTypedResourceElementCompatible:457 // Fall-through458 459 // These traits are modeled on type predicates in C++0x [meta.unary.prop]460 // which requires some of its traits to have the complete type. However,461 // the completeness of the type cannot impact these traits' semantics, and462 // so they don't require it. This matches the comments on these traits in463 // Table 49.464 case UTT_IsConst:465 case UTT_IsVolatile:466 case UTT_IsSigned:467 case UTT_IsUnboundedArray:468 case UTT_IsUnsigned:469 470 // This type trait always returns false, checking the type is moot.471 case UTT_IsInterfaceClass:472 return true;473 474 // We diagnose incomplete class types later.475 case UTT_StructuredBindingSize:476 return true;477 478 // C++14 [meta.unary.prop]:479 // If T is a non-union class type, T shall be a complete type.480 case UTT_IsEmpty:481 case UTT_IsPolymorphic:482 case UTT_IsAbstract:483 if (const auto *RD = ArgTy->getAsCXXRecordDecl())484 if (!RD->isUnion())485 return !S.RequireCompleteType(486 Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);487 return true;488 489 // C++14 [meta.unary.prop]:490 // If T is a class type, T shall be a complete type.491 case UTT_IsFinal:492 case UTT_IsSealed:493 if (ArgTy->getAsCXXRecordDecl())494 return !S.RequireCompleteType(495 Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);496 return true;497 498 // LWG3823: T shall be an array type, a complete type, or cv void.499 case UTT_IsAggregate:500 case UTT_IsImplicitLifetime:501 if (ArgTy->isArrayType() || ArgTy->isVoidType())502 return true;503 504 return !S.RequireCompleteType(505 Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);506 507 // has_unique_object_representations<T>508 // remove_all_extents_t<T> shall be a complete type or cv void (LWG4113).509 case UTT_HasUniqueObjectRepresentations:510 ArgTy = QualType(ArgTy->getBaseElementTypeUnsafe(), 0);511 if (ArgTy->isVoidType())512 return true;513 return !S.RequireCompleteType(514 Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);515 516 // C++1z [meta.unary.prop]:517 // remove_all_extents_t<T> shall be a complete type or cv void.518 case UTT_IsTrivial:519 case UTT_IsTriviallyCopyable:520 case UTT_IsStandardLayout:521 case UTT_IsPOD:522 case UTT_IsLiteral:523 case UTT_IsBitwiseCloneable:524 // By analogy, is_trivially_relocatable and is_trivially_equality_comparable525 // impose the same constraints.526 case UTT_IsTriviallyRelocatable:527 case UTT_IsTriviallyEqualityComparable:528 case UTT_IsCppTriviallyRelocatable:529 case UTT_IsReplaceable:530 case UTT_CanPassInRegs:531 // Per the GCC type traits documentation, T shall be a complete type, cv void,532 // or an array of unknown bound. But GCC actually imposes the same constraints533 // as above.534 case UTT_HasNothrowAssign:535 case UTT_HasNothrowMoveAssign:536 case UTT_HasNothrowConstructor:537 case UTT_HasNothrowCopy:538 case UTT_HasTrivialAssign:539 case UTT_HasTrivialMoveAssign:540 case UTT_HasTrivialDefaultConstructor:541 case UTT_HasTrivialMoveConstructor:542 case UTT_HasTrivialCopy:543 case UTT_HasTrivialDestructor:544 case UTT_HasVirtualDestructor:545 ArgTy = QualType(ArgTy->getBaseElementTypeUnsafe(), 0);546 [[fallthrough]];547 // C++1z [meta.unary.prop]:548 // T shall be a complete type, cv void, or an array of unknown bound.549 case UTT_IsDestructible:550 case UTT_IsNothrowDestructible:551 case UTT_IsTriviallyDestructible:552 case UTT_IsIntangibleType:553 if (ArgTy->isIncompleteArrayType() || ArgTy->isVoidType())554 return true;555 556 return !S.RequireCompleteType(557 Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);558 }559}560 561static bool HasNoThrowOperator(CXXRecordDecl *RD, OverloadedOperatorKind Op,562 Sema &Self, SourceLocation KeyLoc, ASTContext &C,563 bool (CXXRecordDecl::*HasTrivial)() const,564 bool (CXXRecordDecl::*HasNonTrivial)() const,565 bool (CXXMethodDecl::*IsDesiredOp)() const) {566 if ((RD->*HasTrivial)() && !(RD->*HasNonTrivial)())567 return true;568 569 DeclarationName Name = C.DeclarationNames.getCXXOperatorName(Op);570 DeclarationNameInfo NameInfo(Name, KeyLoc);571 LookupResult Res(Self, NameInfo, Sema::LookupOrdinaryName);572 if (Self.LookupQualifiedName(Res, RD)) {573 bool FoundOperator = false;574 Res.suppressDiagnostics();575 for (LookupResult::iterator Op = Res.begin(), OpEnd = Res.end();576 Op != OpEnd; ++Op) {577 if (isa<FunctionTemplateDecl>(*Op))578 continue;579 580 CXXMethodDecl *Operator = cast<CXXMethodDecl>(*Op);581 if ((Operator->*IsDesiredOp)()) {582 FoundOperator = true;583 auto *CPT = Operator->getType()->castAs<FunctionProtoType>();584 CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);585 if (!CPT || !CPT->isNothrow())586 return false;587 }588 }589 return FoundOperator;590 }591 return false;592}593 594static bool HasNonDeletedDefaultedEqualityComparison(Sema &S,595 const CXXRecordDecl *Decl,596 SourceLocation KeyLoc) {597 if (Decl->isUnion())598 return false;599 if (Decl->isLambda())600 return Decl->isCapturelessLambda();601 602 CanQualType T = S.Context.getCanonicalTagType(Decl);603 {604 EnterExpressionEvaluationContext UnevaluatedContext(605 S, Sema::ExpressionEvaluationContext::Unevaluated);606 Sema::SFINAETrap SFINAE(S, /*ForValidityCheck=*/true);607 Sema::ContextRAII TUContext(S, S.Context.getTranslationUnitDecl());608 609 // const ClassT& obj;610 OpaqueValueExpr Operand(KeyLoc, T.withConst(), ExprValueKind::VK_LValue);611 UnresolvedSet<16> Functions;612 // obj == obj;613 S.LookupBinOp(S.TUScope, {}, BinaryOperatorKind::BO_EQ, Functions);614 615 auto Result = S.CreateOverloadedBinOp(KeyLoc, BinaryOperatorKind::BO_EQ,616 Functions, &Operand, &Operand);617 if (Result.isInvalid() || SFINAE.hasErrorOccurred())618 return false;619 620 const auto *CallExpr = dyn_cast<CXXOperatorCallExpr>(Result.get());621 if (!CallExpr)622 return false;623 const auto *Callee = CallExpr->getDirectCallee();624 auto ParamT = Callee->getParamDecl(0)->getType();625 if (!Callee->isDefaulted())626 return false;627 if (!ParamT->isReferenceType() && !Decl->isTriviallyCopyable())628 return false;629 if (!S.Context.hasSameUnqualifiedType(ParamT.getNonReferenceType(), T))630 return false;631 }632 633 return llvm::all_of(Decl->bases(),634 [&](const CXXBaseSpecifier &BS) {635 if (const auto *RD = BS.getType()->getAsCXXRecordDecl())636 return HasNonDeletedDefaultedEqualityComparison(637 S, RD, KeyLoc);638 return true;639 }) &&640 llvm::all_of(Decl->fields(), [&](const FieldDecl *FD) {641 auto Type = FD->getType();642 if (Type->isArrayType())643 Type = Type->getBaseElementTypeUnsafe()644 ->getCanonicalTypeUnqualified();645 646 if (Type->isReferenceType() || Type->isEnumeralType())647 return false;648 if (const auto *RD = Type->getAsCXXRecordDecl())649 return HasNonDeletedDefaultedEqualityComparison(S, RD, KeyLoc);650 return true;651 });652}653 654static bool isTriviallyEqualityComparableType(Sema &S, QualType Type,655 SourceLocation KeyLoc) {656 QualType CanonicalType = Type.getCanonicalType();657 if (CanonicalType->isIncompleteType() || CanonicalType->isDependentType() ||658 CanonicalType->isEnumeralType() || CanonicalType->isArrayType())659 return false;660 661 if (const auto *RD = CanonicalType->getAsCXXRecordDecl()) {662 if (!HasNonDeletedDefaultedEqualityComparison(S, RD, KeyLoc))663 return false;664 }665 666 return S.getASTContext().hasUniqueObjectRepresentations(667 CanonicalType, /*CheckIfTriviallyCopyable=*/false);668}669 670static bool IsTriviallyRelocatableType(Sema &SemaRef, QualType T) {671 QualType BaseElementType = SemaRef.getASTContext().getBaseElementType(T);672 673 if (BaseElementType->isIncompleteType())674 return false;675 if (!BaseElementType->isObjectType())676 return false;677 678 // The deprecated __builtin_is_trivially_relocatable does not have679 // an equivalent to __builtin_trivially_relocate, so there is no680 // safe way to use it if there are any address discriminated values.681 if (SemaRef.getASTContext().containsAddressDiscriminatedPointerAuth(T))682 return false;683 684 if (const auto *RD = BaseElementType->getAsCXXRecordDecl();685 RD && !RD->isPolymorphic() && SemaRef.IsCXXTriviallyRelocatableType(*RD))686 return true;687 688 if (const auto *RD = BaseElementType->getAsRecordDecl())689 return RD->canPassInRegisters();690 691 if (BaseElementType.isTriviallyCopyableType(SemaRef.getASTContext()))692 return true;693 694 switch (T.isNonTrivialToPrimitiveDestructiveMove()) {695 case QualType::PCK_Trivial:696 return !T.isDestructedType();697 case QualType::PCK_ARCStrong:698 return true;699 default:700 return false;701 }702}703 704static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,705 SourceLocation KeyLoc,706 TypeSourceInfo *TInfo) {707 QualType T = TInfo->getType();708 assert(!T->isDependentType() && "Cannot evaluate traits of dependent type");709 710 ASTContext &C = Self.Context;711 switch (UTT) {712 default:713 llvm_unreachable("not a UTT");714 // Type trait expressions corresponding to the primary type category715 // predicates in C++0x [meta.unary.cat].716 case UTT_IsVoid:717 return T->isVoidType();718 case UTT_IsIntegral:719 return T->isIntegralType(C);720 case UTT_IsFloatingPoint:721 return T->isFloatingType();722 case UTT_IsArray:723 // Zero-sized arrays aren't considered arrays in partial specializations,724 // so __is_array shouldn't consider them arrays either.725 if (const auto *CAT = C.getAsConstantArrayType(T))726 return CAT->getSize() != 0;727 return T->isArrayType();728 case UTT_IsBoundedArray:729 if (DiagnoseVLAInCXXTypeTrait(Self, TInfo, tok::kw___is_bounded_array))730 return false;731 // Zero-sized arrays aren't considered arrays in partial specializations,732 // so __is_bounded_array shouldn't consider them arrays either.733 if (const auto *CAT = C.getAsConstantArrayType(T))734 return CAT->getSize() != 0;735 return T->isArrayType() && !T->isIncompleteArrayType();736 case UTT_IsUnboundedArray:737 if (DiagnoseVLAInCXXTypeTrait(Self, TInfo, tok::kw___is_unbounded_array))738 return false;739 return T->isIncompleteArrayType();740 case UTT_IsPointer:741 return T->isAnyPointerType();742 case UTT_IsLvalueReference:743 return T->isLValueReferenceType();744 case UTT_IsRvalueReference:745 return T->isRValueReferenceType();746 case UTT_IsMemberFunctionPointer:747 return T->isMemberFunctionPointerType();748 case UTT_IsMemberObjectPointer:749 return T->isMemberDataPointerType();750 case UTT_IsEnum:751 return T->isEnumeralType();752 case UTT_IsScopedEnum:753 return T->isScopedEnumeralType();754 case UTT_IsUnion:755 return T->isUnionType();756 case UTT_IsClass:757 return T->isClassType() || T->isStructureType() || T->isInterfaceType();758 case UTT_IsFunction:759 return T->isFunctionType();760 761 // Type trait expressions which correspond to the convenient composition762 // predicates in C++0x [meta.unary.comp].763 case UTT_IsReference:764 return T->isReferenceType();765 case UTT_IsArithmetic:766 return T->isArithmeticType() && !T->isEnumeralType();767 case UTT_IsFundamental:768 return T->isFundamentalType();769 case UTT_IsObject:770 return T->isObjectType();771 case UTT_IsScalar:772 // Note: semantic analysis depends on Objective-C lifetime types to be773 // considered scalar types. However, such types do not actually behave774 // like scalar types at run time (since they may require retain/release775 // operations), so we report them as non-scalar.776 if (T->isObjCLifetimeType()) {777 switch (T.getObjCLifetime()) {778 case Qualifiers::OCL_None:779 case Qualifiers::OCL_ExplicitNone:780 return true;781 782 case Qualifiers::OCL_Strong:783 case Qualifiers::OCL_Weak:784 case Qualifiers::OCL_Autoreleasing:785 return false;786 }787 }788 789 return T->isScalarType();790 case UTT_IsCompound:791 return T->isCompoundType();792 case UTT_IsMemberPointer:793 return T->isMemberPointerType();794 795 // Type trait expressions which correspond to the type property predicates796 // in C++0x [meta.unary.prop].797 case UTT_IsConst:798 return T.isConstQualified();799 case UTT_IsVolatile:800 return T.isVolatileQualified();801 case UTT_IsTrivial:802 return T.isTrivialType(C);803 case UTT_IsTriviallyCopyable:804 return T.isTriviallyCopyableType(C);805 case UTT_IsStandardLayout:806 return T->isStandardLayoutType();807 case UTT_IsPOD:808 return T.isPODType(C);809 case UTT_IsLiteral:810 return T->isLiteralType(C);811 case UTT_IsEmpty:812 if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())813 return !RD->isUnion() && RD->isEmpty();814 return false;815 case UTT_IsPolymorphic:816 if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())817 return !RD->isUnion() && RD->isPolymorphic();818 return false;819 case UTT_IsAbstract:820 if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())821 return !RD->isUnion() && RD->isAbstract();822 return false;823 case UTT_IsAggregate:824 // Report vector extensions and complex types as aggregates because they825 // support aggregate initialization. GCC mirrors this behavior for vectors826 // but not _Complex.827 return T->isAggregateType() || T->isVectorType() || T->isExtVectorType() ||828 T->isAnyComplexType();829 // __is_interface_class only returns true when CL is invoked in /CLR mode and830 // even then only when it is used with the 'interface struct ...' syntax831 // Clang doesn't support /CLR which makes this type trait moot.832 case UTT_IsInterfaceClass:833 return false;834 case UTT_IsFinal:835 case UTT_IsSealed:836 if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())837 return RD->hasAttr<FinalAttr>();838 return false;839 case UTT_IsSigned:840 // Enum types should always return false.841 // Floating points should always return true.842 return T->isFloatingType() ||843 (T->isSignedIntegerType() && !T->isEnumeralType());844 case UTT_IsUnsigned:845 // Enum types should always return false.846 return T->isUnsignedIntegerType() && !T->isEnumeralType();847 848 // Type trait expressions which query classes regarding their construction,849 // destruction, and copying. Rather than being based directly on the850 // related type predicates in the standard, they are specified by both851 // GCC[1] and the Embarcadero C++ compiler[2], and Clang implements those852 // specifications.853 //854 // 1: http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html855 // 2:856 // http://docwiki.embarcadero.com/RADStudio/XE/en/Type_Trait_Functions_(C%2B%2B0x)_Index857 //858 // Note that these builtins do not behave as documented in g++: if a class859 // has both a trivial and a non-trivial special member of a particular kind,860 // they return false! For now, we emulate this behavior.861 // FIXME: This appears to be a g++ bug: more complex cases reveal that it862 // does not correctly compute triviality in the presence of multiple special863 // members of the same kind. Revisit this once the g++ bug is fixed.864 case UTT_HasTrivialDefaultConstructor:865 // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:866 // If __is_pod (type) is true then the trait is true, else if type is867 // a cv class or union type (or array thereof) with a trivial default868 // constructor ([class.ctor]) then the trait is true, else it is false.869 if (T.isPODType(C))870 return true;871 if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl())872 return RD->hasTrivialDefaultConstructor() &&873 !RD->hasNonTrivialDefaultConstructor();874 return false;875 case UTT_HasTrivialMoveConstructor:876 // This trait is implemented by MSVC 2012 and needed to parse the877 // standard library headers. Specifically this is used as the logic878 // behind std::is_trivially_move_constructible (20.9.4.3).879 if (T.isPODType(C))880 return true;881 if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl())882 return RD->hasTrivialMoveConstructor() &&883 !RD->hasNonTrivialMoveConstructor();884 return false;885 case UTT_HasTrivialCopy:886 // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:887 // If __is_pod (type) is true or type is a reference type then888 // the trait is true, else if type is a cv class or union type889 // with a trivial copy constructor ([class.copy]) then the trait890 // is true, else it is false.891 if (T.isPODType(C) || T->isReferenceType())892 return true;893 if (CXXRecordDecl *RD = T->getAsCXXRecordDecl())894 return RD->hasTrivialCopyConstructor() &&895 !RD->hasNonTrivialCopyConstructor();896 return false;897 case UTT_HasTrivialMoveAssign:898 // This trait is implemented by MSVC 2012 and needed to parse the899 // standard library headers. Specifically it is used as the logic900 // behind std::is_trivially_move_assignable (20.9.4.3)901 if (T.isPODType(C))902 return true;903 if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl())904 return RD->hasTrivialMoveAssignment() &&905 !RD->hasNonTrivialMoveAssignment();906 return false;907 case UTT_HasTrivialAssign:908 // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:909 // If type is const qualified or is a reference type then the910 // trait is false. Otherwise if __is_pod (type) is true then the911 // trait is true, else if type is a cv class or union type with912 // a trivial copy assignment ([class.copy]) then the trait is913 // true, else it is false.914 // Note: the const and reference restrictions are interesting,915 // given that const and reference members don't prevent a class916 // from having a trivial copy assignment operator (but do cause917 // errors if the copy assignment operator is actually used, q.v.918 // [class.copy]p12).919 920 if (T.isConstQualified())921 return false;922 if (T.isPODType(C))923 return true;924 if (CXXRecordDecl *RD = T->getAsCXXRecordDecl())925 return RD->hasTrivialCopyAssignment() &&926 !RD->hasNonTrivialCopyAssignment();927 return false;928 case UTT_IsDestructible:929 case UTT_IsTriviallyDestructible:930 case UTT_IsNothrowDestructible:931 // C++14 [meta.unary.prop]:932 // For reference types, is_destructible<T>::value is true.933 if (T->isReferenceType())934 return true;935 936 // Objective-C++ ARC: autorelease types don't require destruction.937 if (T->isObjCLifetimeType() &&938 T.getObjCLifetime() == Qualifiers::OCL_Autoreleasing)939 return true;940 941 // C++14 [meta.unary.prop]:942 // For incomplete types and function types, is_destructible<T>::value is943 // false.944 if (T->isIncompleteType() || T->isFunctionType())945 return false;946 947 // A type that requires destruction (via a non-trivial destructor or ARC948 // lifetime semantics) is not trivially-destructible.949 if (UTT == UTT_IsTriviallyDestructible && T.isDestructedType())950 return false;951 952 // C++14 [meta.unary.prop]:953 // For object types and given U equal to remove_all_extents_t<T>, if the954 // expression std::declval<U&>().~U() is well-formed when treated as an955 // unevaluated operand (Clause 5), then is_destructible<T>::value is true956 if (auto *RD = C.getBaseElementType(T)->getAsCXXRecordDecl()) {957 CXXDestructorDecl *Destructor = Self.LookupDestructor(RD);958 if (!Destructor)959 return false;960 // C++14 [dcl.fct.def.delete]p2:961 // A program that refers to a deleted function implicitly or962 // explicitly, other than to declare it, is ill-formed.963 if (Destructor->isDeleted())964 return false;965 if (C.getLangOpts().AccessControl && Destructor->getAccess() != AS_public)966 return false;967 if (UTT == UTT_IsNothrowDestructible) {968 auto *CPT = Destructor->getType()->castAs<FunctionProtoType>();969 CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);970 if (!CPT || !CPT->isNothrow())971 return false;972 }973 }974 return true;975 976 case UTT_HasTrivialDestructor:977 // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html978 // If __is_pod (type) is true or type is a reference type979 // then the trait is true, else if type is a cv class or union980 // type (or array thereof) with a trivial destructor981 // ([class.dtor]) then the trait is true, else it is982 // false.983 if (T.isPODType(C) || T->isReferenceType())984 return true;985 986 // Objective-C++ ARC: autorelease types don't require destruction.987 if (T->isObjCLifetimeType() &&988 T.getObjCLifetime() == Qualifiers::OCL_Autoreleasing)989 return true;990 991 if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl())992 return RD->hasTrivialDestructor();993 return false;994 // TODO: Propagate nothrowness for implicitly declared special members.995 case UTT_HasNothrowAssign:996 // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:997 // If type is const qualified or is a reference type then the998 // trait is false. Otherwise if __has_trivial_assign (type)999 // is true then the trait is true, else if type is a cv class1000 // or union type with copy assignment operators that are known1001 // not to throw an exception then the trait is true, else it is1002 // false.1003 if (C.getBaseElementType(T).isConstQualified())1004 return false;1005 if (T->isReferenceType())1006 return false;1007 if (T.isPODType(C) || T->isObjCLifetimeType())1008 return true;1009 1010 if (auto *RD = T->getAsCXXRecordDecl())1011 return HasNoThrowOperator(RD, OO_Equal, Self, KeyLoc, C,1012 &CXXRecordDecl::hasTrivialCopyAssignment,1013 &CXXRecordDecl::hasNonTrivialCopyAssignment,1014 &CXXMethodDecl::isCopyAssignmentOperator);1015 return false;1016 case UTT_HasNothrowMoveAssign:1017 // This trait is implemented by MSVC 2012 and needed to parse the1018 // standard library headers. Specifically this is used as the logic1019 // behind std::is_nothrow_move_assignable (20.9.4.3).1020 if (T.isPODType(C))1021 return true;1022 1023 if (auto *RD = C.getBaseElementType(T)->getAsCXXRecordDecl())1024 return HasNoThrowOperator(RD, OO_Equal, Self, KeyLoc, C,1025 &CXXRecordDecl::hasTrivialMoveAssignment,1026 &CXXRecordDecl::hasNonTrivialMoveAssignment,1027 &CXXMethodDecl::isMoveAssignmentOperator);1028 return false;1029 case UTT_HasNothrowCopy:1030 // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:1031 // If __has_trivial_copy (type) is true then the trait is true, else1032 // if type is a cv class or union type with copy constructors that are1033 // known not to throw an exception then the trait is true, else it is1034 // false.1035 if (T.isPODType(C) || T->isReferenceType() || T->isObjCLifetimeType())1036 return true;1037 if (CXXRecordDecl *RD = T->getAsCXXRecordDecl()) {1038 if (RD->hasTrivialCopyConstructor() &&1039 !RD->hasNonTrivialCopyConstructor())1040 return true;1041 1042 bool FoundConstructor = false;1043 unsigned FoundTQs;1044 for (const auto *ND : Self.LookupConstructors(RD)) {1045 // A template constructor is never a copy constructor.1046 // FIXME: However, it may actually be selected at the actual overload1047 // resolution point.1048 if (isa<FunctionTemplateDecl>(ND->getUnderlyingDecl()))1049 continue;1050 // UsingDecl itself is not a constructor1051 if (isa<UsingDecl>(ND))1052 continue;1053 auto *Constructor = cast<CXXConstructorDecl>(ND->getUnderlyingDecl());1054 if (Constructor->isCopyConstructor(FoundTQs)) {1055 FoundConstructor = true;1056 auto *CPT = Constructor->getType()->castAs<FunctionProtoType>();1057 CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);1058 if (!CPT)1059 return false;1060 // TODO: check whether evaluating default arguments can throw.1061 // For now, we'll be conservative and assume that they can throw.1062 if (!CPT->isNothrow() || CPT->getNumParams() > 1)1063 return false;1064 }1065 }1066 1067 return FoundConstructor;1068 }1069 return false;1070 case UTT_HasNothrowConstructor:1071 // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html1072 // If __has_trivial_constructor (type) is true then the trait is1073 // true, else if type is a cv class or union type (or array1074 // thereof) with a default constructor that is known not to1075 // throw an exception then the trait is true, else it is false.1076 if (T.isPODType(C) || T->isObjCLifetimeType())1077 return true;1078 if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl()) {1079 if (RD->hasTrivialDefaultConstructor())1080 return true;1081 1082 bool FoundConstructor = false;1083 for (const auto *ND : Self.LookupConstructors(RD)) {1084 // FIXME: In C++0x, a constructor template can be a default constructor.1085 if (isa<FunctionTemplateDecl>(ND->getUnderlyingDecl()))1086 continue;1087 // UsingDecl itself is not a constructor1088 if (isa<UsingDecl>(ND))1089 continue;1090 auto *Constructor = cast<CXXConstructorDecl>(ND->getUnderlyingDecl());1091 if (Constructor->isDefaultConstructor()) {1092 FoundConstructor = true;1093 auto *CPT = Constructor->getType()->castAs<FunctionProtoType>();1094 CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);1095 if (!CPT)1096 return false;1097 // FIXME: check whether evaluating default arguments can throw.1098 // For now, we'll be conservative and assume that they can throw.1099 if (!CPT->isNothrow() || CPT->getNumParams() > 0)1100 return false;1101 }1102 }1103 return FoundConstructor;1104 }1105 return false;1106 case UTT_HasVirtualDestructor:1107 // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:1108 // If type is a class type with a virtual destructor ([class.dtor])1109 // then the trait is true, else it is false.1110 if (CXXRecordDecl *RD = T->getAsCXXRecordDecl())1111 if (CXXDestructorDecl *Destructor = Self.LookupDestructor(RD))1112 return Destructor->isVirtual();1113 return false;1114 1115 // These type trait expressions are modeled on the specifications for the1116 // Embarcadero C++0x type trait functions:1117 // http://docwiki.embarcadero.com/RADStudio/XE/en/Type_Trait_Functions_(C%2B%2B0x)_Index1118 case UTT_IsCompleteType:1119 // http://docwiki.embarcadero.com/RADStudio/XE/en/Is_complete_type_(typename_T_):1120 // Returns True if and only if T is a complete type at the point of the1121 // function call.1122 return !T->isIncompleteType();1123 case UTT_HasUniqueObjectRepresentations:1124 return C.hasUniqueObjectRepresentations(T);1125 case UTT_IsTriviallyRelocatable:1126 return IsTriviallyRelocatableType(Self, T);1127 case UTT_IsBitwiseCloneable:1128 return T.isBitwiseCloneableType(C);1129 case UTT_IsCppTriviallyRelocatable:1130 return Self.IsCXXTriviallyRelocatableType(T);1131 case UTT_IsReplaceable:1132 return Self.IsCXXReplaceableType(T);1133 case UTT_CanPassInRegs:1134 if (CXXRecordDecl *RD = T->getAsCXXRecordDecl(); RD && !T.hasQualifiers())1135 return RD->canPassInRegisters();1136 Self.Diag(KeyLoc, diag::err_builtin_pass_in_regs_non_class) << T;1137 return false;1138 case UTT_IsTriviallyEqualityComparable:1139 return isTriviallyEqualityComparableType(Self, T, KeyLoc);1140 case UTT_IsImplicitLifetime: {1141 DiagnoseVLAInCXXTypeTrait(Self, TInfo,1142 tok::kw___builtin_is_implicit_lifetime);1143 DiagnoseAtomicInCXXTypeTrait(Self, TInfo,1144 tok::kw___builtin_is_implicit_lifetime);1145 1146 // [basic.types.general] p91147 // Scalar types, implicit-lifetime class types ([class.prop]),1148 // array types, and cv-qualified versions of these types1149 // are collectively called implicit-lifetime types.1150 QualType UnqualT = T->getCanonicalTypeUnqualified();1151 if (UnqualT->isScalarType())1152 return true;1153 if (UnqualT->isArrayType() || UnqualT->isVectorType())1154 return true;1155 const CXXRecordDecl *RD = UnqualT->getAsCXXRecordDecl();1156 if (!RD)1157 return false;1158 1159 // [class.prop] p91160 // A class S is an implicit-lifetime class if1161 // - it is an aggregate whose destructor is not user-provided or1162 // - it has at least one trivial eligible constructor and a trivial,1163 // non-deleted destructor.1164 const CXXDestructorDecl *Dtor = RD->getDestructor();1165 if (UnqualT->isAggregateType() && (!Dtor || !Dtor->isUserProvided()))1166 return true;1167 bool HasTrivialNonDeletedDtr =1168 RD->hasTrivialDestructor() && (!Dtor || !Dtor->isDeleted());1169 if (!HasTrivialNonDeletedDtr)1170 return false;1171 for (CXXConstructorDecl *Ctr : RD->ctors()) {1172 if (Ctr->isIneligibleOrNotSelected() || Ctr->isDeleted())1173 continue;1174 if (Ctr->isTrivial())1175 return true;1176 }1177 if (RD->needsImplicitDefaultConstructor() &&1178 RD->hasTrivialDefaultConstructor() &&1179 !RD->hasNonTrivialDefaultConstructor())1180 return true;1181 if (RD->needsImplicitCopyConstructor() && RD->hasTrivialCopyConstructor() &&1182 !RD->defaultedCopyConstructorIsDeleted())1183 return true;1184 if (RD->needsImplicitMoveConstructor() && RD->hasTrivialMoveConstructor() &&1185 !RD->defaultedMoveConstructorIsDeleted())1186 return true;1187 return false;1188 }1189 case UTT_IsIntangibleType:1190 assert(Self.getLangOpts().HLSL && "intangible types are HLSL-only feature");1191 if (!T->isVoidType() && !T->isIncompleteArrayType())1192 if (Self.RequireCompleteType(TInfo->getTypeLoc().getBeginLoc(), T,1193 diag::err_incomplete_type))1194 return false;1195 if (DiagnoseVLAInCXXTypeTrait(Self, TInfo,1196 tok::kw___builtin_hlsl_is_intangible))1197 return false;1198 return T->isHLSLIntangibleType();1199 1200 case UTT_IsTypedResourceElementCompatible:1201 assert(Self.getLangOpts().HLSL &&1202 "typed resource element compatible types are an HLSL-only feature");1203 if (T->isIncompleteType())1204 return false;1205 1206 return Self.HLSL().IsTypedResourceElementCompatible(T);1207 }1208}1209 1210static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT,1211 const TypeSourceInfo *Lhs,1212 const TypeSourceInfo *Rhs,1213 SourceLocation KeyLoc);1214 1215static APValue EvaluateSizeTTypeTrait(Sema &S, TypeTrait Kind,1216 SourceLocation KWLoc,1217 ArrayRef<TypeSourceInfo *> Args,1218 SourceLocation RParenLoc,1219 bool IsDependent) {1220 if (IsDependent)1221 return APValue();1222 1223 switch (Kind) {1224 case TypeTrait::UTT_StructuredBindingSize: {1225 QualType T = Args[0]->getType();1226 SourceRange ArgRange = Args[0]->getTypeLoc().getSourceRange();1227 UnsignedOrNone Size =1228 S.GetDecompositionElementCount(T, ArgRange.getBegin());1229 if (!Size) {1230 S.Diag(KWLoc, diag::err_arg_is_not_destructurable) << T << ArgRange;1231 return APValue();1232 }1233 return APValue(1234 S.getASTContext().MakeIntValue(*Size, S.getASTContext().getSizeType()));1235 break;1236 }1237 default:1238 llvm_unreachable("Not a SizeT type trait");1239 }1240}1241 1242static bool EvaluateBooleanTypeTrait(Sema &S, TypeTrait Kind,1243 SourceLocation KWLoc,1244 ArrayRef<TypeSourceInfo *> Args,1245 SourceLocation RParenLoc,1246 bool IsDependent) {1247 if (IsDependent)1248 return false;1249 1250 if (Kind <= UTT_Last)1251 return EvaluateUnaryTypeTrait(S, Kind, KWLoc, Args[0]);1252 1253 // Evaluate ReferenceBindsToTemporary and ReferenceConstructsFromTemporary1254 // alongside the IsConstructible traits to avoid duplication.1255 if (Kind <= BTT_Last && Kind != BTT_ReferenceBindsToTemporary &&1256 Kind != BTT_ReferenceConstructsFromTemporary &&1257 Kind != BTT_ReferenceConvertsFromTemporary)1258 return EvaluateBinaryTypeTrait(S, Kind, Args[0], Args[1], RParenLoc);1259 1260 switch (Kind) {1261 case clang::BTT_ReferenceBindsToTemporary:1262 case clang::BTT_ReferenceConstructsFromTemporary:1263 case clang::BTT_ReferenceConvertsFromTemporary:1264 case clang::TT_IsConstructible:1265 case clang::TT_IsNothrowConstructible:1266 case clang::TT_IsTriviallyConstructible: {1267 // C++11 [meta.unary.prop]:1268 // is_trivially_constructible is defined as:1269 //1270 // is_constructible<T, Args...>::value is true and the variable1271 // definition for is_constructible, as defined below, is known to call1272 // no operation that is not trivial.1273 //1274 // The predicate condition for a template specialization1275 // is_constructible<T, Args...> shall be satisfied if and only if the1276 // following variable definition would be well-formed for some invented1277 // variable t:1278 //1279 // T t(create<Args>()...);1280 assert(!Args.empty());1281 1282 // Precondition: T and all types in the parameter pack Args shall be1283 // complete types, (possibly cv-qualified) void, or arrays of1284 // unknown bound.1285 for (const auto *TSI : Args) {1286 QualType ArgTy = TSI->getType();1287 if (ArgTy->isVoidType() || ArgTy->isIncompleteArrayType())1288 continue;1289 1290 if (S.RequireCompleteType(1291 KWLoc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr))1292 return false;1293 }1294 1295 // Make sure the first argument is not incomplete nor a function type.1296 QualType T = Args[0]->getType();1297 if (T->isIncompleteType() || T->isFunctionType())1298 return false;1299 1300 // Make sure the first argument is not an abstract type.1301 CXXRecordDecl *RD = T->getAsCXXRecordDecl();1302 if (RD && RD->isAbstract())1303 return false;1304 1305 // LWG3819: For reference_meows_from_temporary traits, && is not added to1306 // the source object type.1307 // Otherwise, compute the result of add_rvalue_reference_t.1308 bool UseRawObjectType =1309 Kind == clang::BTT_ReferenceBindsToTemporary ||1310 Kind == clang::BTT_ReferenceConstructsFromTemporary ||1311 Kind == clang::BTT_ReferenceConvertsFromTemporary;1312 1313 llvm::BumpPtrAllocator OpaqueExprAllocator;1314 SmallVector<Expr *, 2> ArgExprs;1315 ArgExprs.reserve(Args.size() - 1);1316 for (unsigned I = 1, N = Args.size(); I != N; ++I) {1317 QualType ArgTy = Args[I]->getType();1318 if ((ArgTy->isObjectType() && !UseRawObjectType) ||1319 ArgTy->isFunctionType())1320 ArgTy = S.Context.getRValueReferenceType(ArgTy);1321 ArgExprs.push_back(1322 new (OpaqueExprAllocator.Allocate<OpaqueValueExpr>())1323 OpaqueValueExpr(Args[I]->getTypeLoc().getBeginLoc(),1324 ArgTy.getNonLValueExprType(S.Context),1325 Expr::getValueKindForType(ArgTy)));1326 }1327 1328 // Perform the initialization in an unevaluated context within a SFINAE1329 // trap at translation unit scope.1330 EnterExpressionEvaluationContext Unevaluated(1331 S, Sema::ExpressionEvaluationContext::Unevaluated);1332 Sema::SFINAETrap SFINAE(S, /*ForValidityCheck=*/true);1333 Sema::ContextRAII TUContext(S, S.Context.getTranslationUnitDecl());1334 InitializedEntity To(1335 InitializedEntity::InitializeTemporary(S.Context, Args[0]));1336 InitializationKind InitKind(1337 Kind == clang::BTT_ReferenceConvertsFromTemporary1338 ? InitializationKind::CreateCopy(KWLoc, KWLoc)1339 : InitializationKind::CreateDirect(KWLoc, KWLoc, RParenLoc));1340 InitializationSequence Init(S, To, InitKind, ArgExprs);1341 if (Init.Failed())1342 return false;1343 1344 ExprResult Result = Init.Perform(S, To, InitKind, ArgExprs);1345 if (Result.isInvalid() || SFINAE.hasErrorOccurred())1346 return false;1347 1348 if (Kind == clang::TT_IsConstructible)1349 return true;1350 1351 if (Kind == clang::BTT_ReferenceBindsToTemporary ||1352 Kind == clang::BTT_ReferenceConstructsFromTemporary ||1353 Kind == clang::BTT_ReferenceConvertsFromTemporary) {1354 if (!T->isReferenceType())1355 return false;1356 1357 // A function reference never binds to a temporary object.1358 if (T.getNonReferenceType()->isFunctionType())1359 return false;1360 1361 if (!Init.isDirectReferenceBinding())1362 return true;1363 1364 if (Kind == clang::BTT_ReferenceBindsToTemporary)1365 return false;1366 1367 QualType U = Args[1]->getType();1368 if (U->isReferenceType())1369 return false;1370 1371 TypeSourceInfo *TPtr = S.Context.CreateTypeSourceInfo(1372 S.Context.getPointerType(T.getNonReferenceType()));1373 TypeSourceInfo *UPtr = S.Context.CreateTypeSourceInfo(1374 S.Context.getPointerType(U.getNonReferenceType()));1375 return S.BuiltinIsConvertible(UPtr->getType(), TPtr->getType(),1376 RParenLoc);1377 }1378 1379 if (Kind == clang::TT_IsNothrowConstructible)1380 return S.canThrow(Result.get()) == CT_Cannot;1381 1382 if (Kind == clang::TT_IsTriviallyConstructible) {1383 // Under Objective-C ARC and Weak, if the destination has non-trivial1384 // Objective-C lifetime, this is a non-trivial construction.1385 if (T.getNonReferenceType().hasNonTrivialObjCLifetime())1386 return false;1387 1388 // The initialization succeeded; now make sure there are no non-trivial1389 // calls.1390 return !Result.get()->hasNonTrivialCall(S.Context);1391 }1392 1393 llvm_unreachable("unhandled type trait");1394 return false;1395 }1396 default:1397 llvm_unreachable("not a TT");1398 }1399 1400 return false;1401}1402 1403namespace {1404void DiagnoseBuiltinDeprecation(Sema &S, TypeTrait Kind, SourceLocation KWLoc) {1405 TypeTrait Replacement;1406 switch (Kind) {1407 case UTT_HasNothrowAssign:1408 case UTT_HasNothrowMoveAssign:1409 Replacement = BTT_IsNothrowAssignable;1410 break;1411 case UTT_HasNothrowCopy:1412 case UTT_HasNothrowConstructor:1413 Replacement = TT_IsNothrowConstructible;1414 break;1415 case UTT_HasTrivialAssign:1416 case UTT_HasTrivialMoveAssign:1417 Replacement = BTT_IsTriviallyAssignable;1418 break;1419 case UTT_HasTrivialCopy:1420 Replacement = UTT_IsTriviallyCopyable;1421 break;1422 case UTT_HasTrivialDefaultConstructor:1423 case UTT_HasTrivialMoveConstructor:1424 Replacement = TT_IsTriviallyConstructible;1425 break;1426 case UTT_HasTrivialDestructor:1427 Replacement = UTT_IsTriviallyDestructible;1428 break;1429 case UTT_IsTriviallyRelocatable:1430 Replacement = clang::UTT_IsCppTriviallyRelocatable;1431 break;1432 case BTT_ReferenceBindsToTemporary:1433 Replacement = clang::BTT_ReferenceConstructsFromTemporary;1434 break;1435 default:1436 return;1437 }1438 S.Diag(KWLoc, diag::warn_deprecated_builtin)1439 << getTraitSpelling(Kind) << getTraitSpelling(Replacement);1440}1441} // namespace1442 1443bool Sema::CheckTypeTraitArity(unsigned Arity, SourceLocation Loc, size_t N) {1444 if (Arity && N != Arity) {1445 Diag(Loc, diag::err_type_trait_arity)1446 << Arity << 0 << (Arity > 1) << (int)N << SourceRange(Loc);1447 return false;1448 }1449 1450 if (!Arity && N == 0) {1451 Diag(Loc, diag::err_type_trait_arity)1452 << 1 << 1 << 1 << (int)N << SourceRange(Loc);1453 return false;1454 }1455 return true;1456}1457 1458enum class TypeTraitReturnType {1459 Bool,1460 SizeT,1461};1462 1463static TypeTraitReturnType GetReturnType(TypeTrait Kind) {1464 if (Kind == TypeTrait::UTT_StructuredBindingSize)1465 return TypeTraitReturnType::SizeT;1466 return TypeTraitReturnType::Bool;1467}1468 1469ExprResult Sema::BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc,1470 ArrayRef<TypeSourceInfo *> Args,1471 SourceLocation RParenLoc) {1472 if (!CheckTypeTraitArity(getTypeTraitArity(Kind), KWLoc, Args.size()))1473 return ExprError();1474 1475 if (Kind <= UTT_Last && !CheckUnaryTypeTraitTypeCompleteness(1476 *this, Kind, KWLoc, Args[0]->getType()))1477 return ExprError();1478 1479 DiagnoseBuiltinDeprecation(*this, Kind, KWLoc);1480 1481 bool Dependent = false;1482 for (unsigned I = 0, N = Args.size(); I != N; ++I) {1483 if (Args[I]->getType()->isDependentType()) {1484 Dependent = true;1485 break;1486 }1487 }1488 1489 switch (GetReturnType(Kind)) {1490 case TypeTraitReturnType::Bool: {1491 bool Result = EvaluateBooleanTypeTrait(*this, Kind, KWLoc, Args, RParenLoc,1492 Dependent);1493 return TypeTraitExpr::Create(Context, Context.getLogicalOperationType(),1494 KWLoc, Kind, Args, RParenLoc, Result);1495 }1496 case TypeTraitReturnType::SizeT: {1497 APValue Result =1498 EvaluateSizeTTypeTrait(*this, Kind, KWLoc, Args, RParenLoc, Dependent);1499 return TypeTraitExpr::Create(Context, Context.getSizeType(), KWLoc, Kind,1500 Args, RParenLoc, Result);1501 }1502 }1503 llvm_unreachable("unhandled type trait return type");1504}1505 1506ExprResult Sema::ActOnTypeTrait(TypeTrait Kind, SourceLocation KWLoc,1507 ArrayRef<ParsedType> Args,1508 SourceLocation RParenLoc) {1509 SmallVector<TypeSourceInfo *, 4> ConvertedArgs;1510 ConvertedArgs.reserve(Args.size());1511 1512 for (unsigned I = 0, N = Args.size(); I != N; ++I) {1513 TypeSourceInfo *TInfo;1514 QualType T = GetTypeFromParser(Args[I], &TInfo);1515 if (!TInfo)1516 TInfo = Context.getTrivialTypeSourceInfo(T, KWLoc);1517 1518 ConvertedArgs.push_back(TInfo);1519 }1520 1521 return BuildTypeTrait(Kind, KWLoc, ConvertedArgs, RParenLoc);1522}1523 1524bool Sema::BuiltinIsBaseOf(SourceLocation RhsTLoc, QualType LhsT,1525 QualType RhsT) {1526 // C++0x [meta.rel]p21527 // Base is a base class of Derived without regard to cv-qualifiers or1528 // Base and Derived are not unions and name the same class type without1529 // regard to cv-qualifiers.1530 1531 const RecordType *lhsRecord = LhsT->getAsCanonical<RecordType>();1532 const RecordType *rhsRecord = RhsT->getAsCanonical<RecordType>();1533 if (!rhsRecord || !lhsRecord) {1534 const ObjCObjectType *LHSObjTy = LhsT->getAs<ObjCObjectType>();1535 const ObjCObjectType *RHSObjTy = RhsT->getAs<ObjCObjectType>();1536 if (!LHSObjTy || !RHSObjTy)1537 return false;1538 1539 ObjCInterfaceDecl *BaseInterface = LHSObjTy->getInterface();1540 ObjCInterfaceDecl *DerivedInterface = RHSObjTy->getInterface();1541 if (!BaseInterface || !DerivedInterface)1542 return false;1543 1544 if (RequireCompleteType(RhsTLoc, RhsT,1545 diag::err_incomplete_type_used_in_type_trait_expr))1546 return false;1547 1548 return BaseInterface->isSuperClassOf(DerivedInterface);1549 }1550 1551 assert(Context.hasSameUnqualifiedType(LhsT, RhsT) ==1552 (lhsRecord == rhsRecord));1553 1554 // Unions are never base classes, and never have base classes.1555 // It doesn't matter if they are complete or not. See PR#418431556 if (lhsRecord && lhsRecord->getDecl()->isUnion())1557 return false;1558 if (rhsRecord && rhsRecord->getDecl()->isUnion())1559 return false;1560 1561 if (lhsRecord == rhsRecord)1562 return true;1563 1564 // C++0x [meta.rel]p2:1565 // If Base and Derived are class types and are different types1566 // (ignoring possible cv-qualifiers) then Derived shall be a1567 // complete type.1568 if (RequireCompleteType(RhsTLoc, RhsT,1569 diag::err_incomplete_type_used_in_type_trait_expr))1570 return false;1571 1572 return cast<CXXRecordDecl>(rhsRecord->getDecl())1573 ->isDerivedFrom(cast<CXXRecordDecl>(lhsRecord->getDecl()));1574}1575 1576static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT,1577 const TypeSourceInfo *Lhs,1578 const TypeSourceInfo *Rhs,1579 SourceLocation KeyLoc) {1580 QualType LhsT = Lhs->getType();1581 QualType RhsT = Rhs->getType();1582 1583 assert(!LhsT->isDependentType() && !RhsT->isDependentType() &&1584 "Cannot evaluate traits of dependent types");1585 1586 switch (BTT) {1587 case BTT_IsBaseOf:1588 return Self.BuiltinIsBaseOf(Rhs->getTypeLoc().getBeginLoc(), LhsT, RhsT);1589 1590 case BTT_IsVirtualBaseOf: {1591 const RecordType *BaseRecord = LhsT->getAsCanonical<RecordType>();1592 const RecordType *DerivedRecord = RhsT->getAsCanonical<RecordType>();1593 1594 if (!BaseRecord || !DerivedRecord) {1595 DiagnoseVLAInCXXTypeTrait(Self, Lhs,1596 tok::kw___builtin_is_virtual_base_of);1597 DiagnoseVLAInCXXTypeTrait(Self, Rhs,1598 tok::kw___builtin_is_virtual_base_of);1599 return false;1600 }1601 1602 if (BaseRecord->isUnionType() || DerivedRecord->isUnionType())1603 return false;1604 1605 if (!BaseRecord->isStructureOrClassType() ||1606 !DerivedRecord->isStructureOrClassType())1607 return false;1608 1609 if (Self.RequireCompleteType(Rhs->getTypeLoc().getBeginLoc(), RhsT,1610 diag::err_incomplete_type))1611 return false;1612 1613 return cast<CXXRecordDecl>(DerivedRecord->getDecl())1614 ->isVirtuallyDerivedFrom(cast<CXXRecordDecl>(BaseRecord->getDecl()));1615 }1616 case BTT_IsSame:1617 return Self.Context.hasSameType(LhsT, RhsT);1618 case BTT_TypeCompatible: {1619 // GCC ignores cv-qualifiers on arrays for this builtin.1620 Qualifiers LhsQuals, RhsQuals;1621 QualType Lhs = Self.getASTContext().getUnqualifiedArrayType(LhsT, LhsQuals);1622 QualType Rhs = Self.getASTContext().getUnqualifiedArrayType(RhsT, RhsQuals);1623 return Self.Context.typesAreCompatible(Lhs, Rhs);1624 }1625 case BTT_IsConvertible:1626 case BTT_IsConvertibleTo:1627 case BTT_IsNothrowConvertible:1628 return Self.BuiltinIsConvertible(LhsT, RhsT, KeyLoc,1629 BTT == BTT_IsNothrowConvertible);1630 1631 case BTT_IsAssignable:1632 case BTT_IsNothrowAssignable:1633 case BTT_IsTriviallyAssignable: {1634 // C++11 [meta.unary.prop]p3:1635 // is_trivially_assignable is defined as:1636 // is_assignable<T, U>::value is true and the assignment, as defined by1637 // is_assignable, is known to call no operation that is not trivial1638 //1639 // is_assignable is defined as:1640 // The expression declval<T>() = declval<U>() is well-formed when1641 // treated as an unevaluated operand (Clause 5).1642 //1643 // For both, T and U shall be complete types, (possibly cv-qualified)1644 // void, or arrays of unknown bound.1645 if (!LhsT->isVoidType() && !LhsT->isIncompleteArrayType() &&1646 Self.RequireCompleteType(1647 Lhs->getTypeLoc().getBeginLoc(), LhsT,1648 diag::err_incomplete_type_used_in_type_trait_expr))1649 return false;1650 if (!RhsT->isVoidType() && !RhsT->isIncompleteArrayType() &&1651 Self.RequireCompleteType(1652 Rhs->getTypeLoc().getBeginLoc(), RhsT,1653 diag::err_incomplete_type_used_in_type_trait_expr))1654 return false;1655 1656 // cv void is never assignable.1657 if (LhsT->isVoidType() || RhsT->isVoidType())1658 return false;1659 1660 // Build expressions that emulate the effect of declval<T>() and1661 // declval<U>().1662 auto createDeclValExpr = [&](QualType Ty) -> OpaqueValueExpr {1663 if (Ty->isObjectType() || Ty->isFunctionType())1664 Ty = Self.Context.getRValueReferenceType(Ty);1665 return {KeyLoc, Ty.getNonLValueExprType(Self.Context),1666 Expr::getValueKindForType(Ty)};1667 };1668 1669 auto Lhs = createDeclValExpr(LhsT);1670 auto Rhs = createDeclValExpr(RhsT);1671 1672 // Attempt the assignment in an unevaluated context within a SFINAE1673 // trap at translation unit scope.1674 EnterExpressionEvaluationContext Unevaluated(1675 Self, Sema::ExpressionEvaluationContext::Unevaluated);1676 Sema::SFINAETrap SFINAE(Self, /*ForValidityCheck=*/true);1677 Sema::ContextRAII TUContext(Self, Self.Context.getTranslationUnitDecl());1678 ExprResult Result =1679 Self.BuildBinOp(/*S=*/nullptr, KeyLoc, BO_Assign, &Lhs, &Rhs);1680 if (Result.isInvalid())1681 return false;1682 1683 // Treat the assignment as unused for the purpose of -Wdeprecated-volatile.1684 Self.CheckUnusedVolatileAssignment(Result.get());1685 1686 if (SFINAE.hasErrorOccurred())1687 return false;1688 1689 if (BTT == BTT_IsAssignable)1690 return true;1691 1692 if (BTT == BTT_IsNothrowAssignable)1693 return Self.canThrow(Result.get()) == CT_Cannot;1694 1695 if (BTT == BTT_IsTriviallyAssignable) {1696 // Under Objective-C ARC and Weak, if the destination has non-trivial1697 // Objective-C lifetime, this is a non-trivial assignment.1698 if (LhsT.getNonReferenceType().hasNonTrivialObjCLifetime())1699 return false;1700 const ASTContext &Context = Self.getASTContext();1701 if (Context.containsAddressDiscriminatedPointerAuth(LhsT) ||1702 Context.containsAddressDiscriminatedPointerAuth(RhsT))1703 return false;1704 return !Result.get()->hasNonTrivialCall(Self.Context);1705 }1706 1707 llvm_unreachable("unhandled type trait");1708 return false;1709 }1710 case BTT_IsLayoutCompatible: {1711 if (!LhsT->isVoidType() && !LhsT->isIncompleteArrayType())1712 Self.RequireCompleteType(Lhs->getTypeLoc().getBeginLoc(), LhsT,1713 diag::err_incomplete_type);1714 if (!RhsT->isVoidType() && !RhsT->isIncompleteArrayType())1715 Self.RequireCompleteType(Rhs->getTypeLoc().getBeginLoc(), RhsT,1716 diag::err_incomplete_type);1717 1718 DiagnoseVLAInCXXTypeTrait(Self, Lhs, tok::kw___is_layout_compatible);1719 DiagnoseVLAInCXXTypeTrait(Self, Rhs, tok::kw___is_layout_compatible);1720 1721 return Self.IsLayoutCompatible(LhsT, RhsT);1722 }1723 case BTT_IsPointerInterconvertibleBaseOf: {1724 if (LhsT->isStructureOrClassType() && RhsT->isStructureOrClassType() &&1725 !Self.getASTContext().hasSameUnqualifiedType(LhsT, RhsT)) {1726 Self.RequireCompleteType(Rhs->getTypeLoc().getBeginLoc(), RhsT,1727 diag::err_incomplete_type);1728 }1729 1730 DiagnoseVLAInCXXTypeTrait(Self, Lhs,1731 tok::kw___is_pointer_interconvertible_base_of);1732 DiagnoseVLAInCXXTypeTrait(Self, Rhs,1733 tok::kw___is_pointer_interconvertible_base_of);1734 1735 return Self.IsPointerInterconvertibleBaseOf(Lhs, Rhs);1736 }1737 case BTT_IsDeducible: {1738 const auto *TSTToBeDeduced = cast<DeducedTemplateSpecializationType>(LhsT);1739 sema::TemplateDeductionInfo Info(KeyLoc);1740 return Self.DeduceTemplateArgumentsFromType(1741 TSTToBeDeduced->getTemplateName().getAsTemplateDecl(), RhsT,1742 Info) == TemplateDeductionResult::Success;1743 }1744 case BTT_IsScalarizedLayoutCompatible: {1745 if (!LhsT->isVoidType() && !LhsT->isIncompleteArrayType() &&1746 Self.RequireCompleteType(Lhs->getTypeLoc().getBeginLoc(), LhsT,1747 diag::err_incomplete_type))1748 return true;1749 if (!RhsT->isVoidType() && !RhsT->isIncompleteArrayType() &&1750 Self.RequireCompleteType(Rhs->getTypeLoc().getBeginLoc(), RhsT,1751 diag::err_incomplete_type))1752 return true;1753 1754 DiagnoseVLAInCXXTypeTrait(1755 Self, Lhs, tok::kw___builtin_hlsl_is_scalarized_layout_compatible);1756 DiagnoseVLAInCXXTypeTrait(1757 Self, Rhs, tok::kw___builtin_hlsl_is_scalarized_layout_compatible);1758 1759 return Self.HLSL().IsScalarizedLayoutCompatible(LhsT, RhsT);1760 }1761 case BTT_LtSynthesizesFromSpaceship:1762 case BTT_LeSynthesizesFromSpaceship:1763 case BTT_GtSynthesizesFromSpaceship:1764 case BTT_GeSynthesizesFromSpaceship: {1765 EnterExpressionEvaluationContext UnevaluatedContext(1766 Self, Sema::ExpressionEvaluationContext::Unevaluated);1767 Sema::SFINAETrap SFINAE(Self, /*ForValidityCheck=*/true);1768 Sema::ContextRAII TUContext(Self, Self.Context.getTranslationUnitDecl());1769 1770 OpaqueValueExpr LHS(KeyLoc, LhsT.getNonReferenceType(),1771 LhsT->isLValueReferenceType() ? ExprValueKind::VK_LValue1772 : LhsT->isRValueReferenceType()1773 ? ExprValueKind::VK_XValue1774 : ExprValueKind::VK_PRValue);1775 OpaqueValueExpr RHS(KeyLoc, RhsT.getNonReferenceType(),1776 RhsT->isLValueReferenceType() ? ExprValueKind::VK_LValue1777 : RhsT->isRValueReferenceType()1778 ? ExprValueKind::VK_XValue1779 : ExprValueKind::VK_PRValue);1780 1781 auto OpKind = [&] {1782 switch (BTT) {1783 case BTT_LtSynthesizesFromSpaceship:1784 return BinaryOperatorKind::BO_LT;1785 case BTT_LeSynthesizesFromSpaceship:1786 return BinaryOperatorKind::BO_LE;1787 case BTT_GtSynthesizesFromSpaceship:1788 return BinaryOperatorKind::BO_GT;1789 case BTT_GeSynthesizesFromSpaceship:1790 return BinaryOperatorKind::BO_GE;1791 default:1792 llvm_unreachable("Trying to Synthesize non-comparison operator?");1793 }1794 }();1795 1796 UnresolvedSet<16> Functions;1797 Self.LookupBinOp(Self.TUScope, KeyLoc, OpKind, Functions);1798 1799 ExprResult Result =1800 Self.CreateOverloadedBinOp(KeyLoc, OpKind, Functions, &LHS, &RHS);1801 if (Result.isInvalid() || SFINAE.hasErrorOccurred())1802 return false;1803 1804 return isa<CXXRewrittenBinaryOperator>(Result.get());1805 }1806 default:1807 llvm_unreachable("not a BTT");1808 }1809 llvm_unreachable("Unknown type trait or not implemented");1810}1811 1812ExprResult Sema::ActOnArrayTypeTrait(ArrayTypeTrait ATT, SourceLocation KWLoc,1813 ParsedType Ty, Expr *DimExpr,1814 SourceLocation RParen) {1815 TypeSourceInfo *TSInfo;1816 QualType T = GetTypeFromParser(Ty, &TSInfo);1817 if (!TSInfo)1818 TSInfo = Context.getTrivialTypeSourceInfo(T);1819 1820 return BuildArrayTypeTrait(ATT, KWLoc, TSInfo, DimExpr, RParen);1821}1822 1823static uint64_t EvaluateArrayTypeTrait(Sema &Self, ArrayTypeTrait ATT,1824 QualType T, Expr *DimExpr,1825 SourceLocation KeyLoc) {1826 assert(!T->isDependentType() && "Cannot evaluate traits of dependent type");1827 1828 switch (ATT) {1829 case ATT_ArrayRank:1830 if (T->isArrayType()) {1831 unsigned Dim = 0;1832 while (const ArrayType *AT = Self.Context.getAsArrayType(T)) {1833 ++Dim;1834 T = AT->getElementType();1835 }1836 return Dim;1837 }1838 return 0;1839 1840 case ATT_ArrayExtent: {1841 llvm::APSInt Value;1842 uint64_t Dim;1843 if (Self.VerifyIntegerConstantExpression(1844 DimExpr, &Value, diag::err_dimension_expr_not_constant_integer)1845 .isInvalid())1846 return 0;1847 if (Value.isSigned() && Value.isNegative()) {1848 Self.Diag(KeyLoc, diag::err_dimension_expr_not_constant_integer)1849 << DimExpr->getSourceRange();1850 return 0;1851 }1852 Dim = Value.getLimitedValue();1853 1854 if (T->isArrayType()) {1855 unsigned D = 0;1856 bool Matched = false;1857 while (const ArrayType *AT = Self.Context.getAsArrayType(T)) {1858 if (Dim == D) {1859 Matched = true;1860 break;1861 }1862 ++D;1863 T = AT->getElementType();1864 }1865 1866 if (Matched && T->isArrayType()) {1867 if (const ConstantArrayType *CAT =1868 Self.Context.getAsConstantArrayType(T))1869 return CAT->getLimitedSize();1870 }1871 }1872 return 0;1873 }1874 }1875 llvm_unreachable("Unknown type trait or not implemented");1876}1877 1878ExprResult Sema::BuildArrayTypeTrait(ArrayTypeTrait ATT, SourceLocation KWLoc,1879 TypeSourceInfo *TSInfo, Expr *DimExpr,1880 SourceLocation RParen) {1881 QualType T = TSInfo->getType();1882 1883 // FIXME: This should likely be tracked as an APInt to remove any host1884 // assumptions about the width of size_t on the target.1885 uint64_t Value = 0;1886 if (!T->isDependentType())1887 Value = EvaluateArrayTypeTrait(*this, ATT, T, DimExpr, KWLoc);1888 1889 // While the specification for these traits from the Embarcadero C++1890 // compiler's documentation says the return type is 'unsigned int', Clang1891 // returns 'size_t'. On Windows, the primary platform for the Embarcadero1892 // compiler, there is no difference. On several other platforms this is an1893 // important distinction.1894 return new (Context) ArrayTypeTraitExpr(KWLoc, ATT, TSInfo, Value, DimExpr,1895 RParen, Context.getSizeType());1896}1897 1898ExprResult Sema::ActOnExpressionTrait(ExpressionTrait ET, SourceLocation KWLoc,1899 Expr *Queried, SourceLocation RParen) {1900 // If error parsing the expression, ignore.1901 if (!Queried)1902 return ExprError();1903 1904 ExprResult Result = BuildExpressionTrait(ET, KWLoc, Queried, RParen);1905 1906 return Result;1907}1908 1909static bool EvaluateExpressionTrait(ExpressionTrait ET, Expr *E) {1910 switch (ET) {1911 case ET_IsLValueExpr:1912 return E->isLValue();1913 case ET_IsRValueExpr:1914 return E->isPRValue();1915 }1916 llvm_unreachable("Expression trait not covered by switch");1917}1918 1919ExprResult Sema::BuildExpressionTrait(ExpressionTrait ET, SourceLocation KWLoc,1920 Expr *Queried, SourceLocation RParen) {1921 if (Queried->isTypeDependent()) {1922 // Delay type-checking for type-dependent expressions.1923 } else if (Queried->hasPlaceholderType()) {1924 ExprResult PE = CheckPlaceholderExpr(Queried);1925 if (PE.isInvalid())1926 return ExprError();1927 return BuildExpressionTrait(ET, KWLoc, PE.get(), RParen);1928 }1929 1930 bool Value = EvaluateExpressionTrait(ET, Queried);1931 1932 return new (Context)1933 ExpressionTraitExpr(KWLoc, ET, Queried, Value, RParen, Context.BoolTy);1934}1935 1936static std::optional<TypeTrait> StdNameToTypeTrait(StringRef Name) {1937 return llvm::StringSwitch<std::optional<TypeTrait>>(Name)1938 .Case("is_trivially_relocatable",1939 TypeTrait::UTT_IsCppTriviallyRelocatable)1940 .Case("is_replaceable", TypeTrait::UTT_IsReplaceable)1941 .Case("is_trivially_copyable", TypeTrait::UTT_IsTriviallyCopyable)1942 .Case("is_assignable", TypeTrait::BTT_IsAssignable)1943 .Case("is_empty", TypeTrait::UTT_IsEmpty)1944 .Case("is_standard_layout", TypeTrait::UTT_IsStandardLayout)1945 .Case("is_aggregate", TypeTrait::UTT_IsAggregate)1946 .Case("is_constructible", TypeTrait::TT_IsConstructible)1947 .Case("is_final", TypeTrait::UTT_IsFinal)1948 .Case("is_abstract", TypeTrait::UTT_IsAbstract)1949 .Default(std::nullopt);1950}1951 1952using ExtractedTypeTraitInfo =1953 std::optional<std::pair<TypeTrait, llvm::SmallVector<QualType, 1>>>;1954 1955// Recognize type traits that are builting type traits, or known standard1956// type traits in <type_traits>. Note that at this point we assume the1957// trait evaluated to false, so we need only to recognize the shape of the1958// outer-most symbol.1959static ExtractedTypeTraitInfo ExtractTypeTraitFromExpression(const Expr *E) {1960 llvm::SmallVector<QualType, 1> Args;1961 std::optional<TypeTrait> Trait;1962 1963 // builtins1964 if (const auto *TraitExpr = dyn_cast<TypeTraitExpr>(E)) {1965 Trait = TraitExpr->getTrait();1966 for (const auto *Arg : TraitExpr->getArgs())1967 Args.push_back(Arg->getType());1968 return {{Trait.value(), std::move(Args)}};1969 }1970 const auto *Ref = dyn_cast<DeclRefExpr>(E);1971 if (!Ref)1972 return std::nullopt;1973 1974 // std::is_xxx_v<>1975 if (const auto *VD =1976 dyn_cast<VarTemplateSpecializationDecl>(Ref->getDecl())) {1977 if (!VD->isInStdNamespace())1978 return std::nullopt;1979 StringRef Name = VD->getIdentifier()->getName();1980 if (!Name.consume_back("_v"))1981 return std::nullopt;1982 Trait = StdNameToTypeTrait(Name);1983 if (!Trait)1984 return std::nullopt;1985 for (const auto &Arg : VD->getTemplateArgs().asArray()) {1986 if (Arg.getKind() == TemplateArgument::ArgKind::Pack) {1987 for (const auto &InnerArg : Arg.pack_elements())1988 Args.push_back(InnerArg.getAsType());1989 } else if (Arg.getKind() == TemplateArgument::ArgKind::Type) {1990 Args.push_back(Arg.getAsType());1991 } else {1992 llvm_unreachable("Unexpected kind");1993 }1994 }1995 return {{Trait.value(), std::move(Args)}};1996 }1997 1998 // std::is_xxx<>::value1999 if (const auto *VD = dyn_cast<VarDecl>(Ref->getDecl());2000 Ref->hasQualifier() && VD && VD->getIdentifier()->isStr("value")) {2001 NestedNameSpecifier Qualifier = Ref->getQualifier();2002 if (Qualifier.getKind() != NestedNameSpecifier::Kind::Type)2003 return std::nullopt;2004 const auto *Ts = Qualifier.getAsType()->getAs<TemplateSpecializationType>();2005 if (!Ts)2006 return std::nullopt;2007 const TemplateDecl *D = Ts->getTemplateName().getAsTemplateDecl();2008 if (!D || !D->isInStdNamespace())2009 return std::nullopt;2010 Trait = StdNameToTypeTrait(D->getIdentifier()->getName());2011 if (!Trait)2012 return std::nullopt;2013 for (const auto &Arg : Ts->template_arguments())2014 Args.push_back(Arg.getAsType());2015 return {{Trait.value(), std::move(Args)}};2016 }2017 return std::nullopt;2018}2019 2020static void DiagnoseNonDefaultMovable(Sema &SemaRef, SourceLocation Loc,2021 const CXXRecordDecl *D) {2022 if (D->isUnion()) {2023 auto DiagSPM = [&](CXXSpecialMemberKind K, bool Has) {2024 if (Has)2025 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2026 << diag::TraitNotSatisfiedReason::UnionWithUserDeclaredSMF << K;2027 };2028 DiagSPM(CXXSpecialMemberKind::CopyConstructor,2029 D->hasUserDeclaredCopyConstructor());2030 DiagSPM(CXXSpecialMemberKind::CopyAssignment,2031 D->hasUserDeclaredCopyAssignment());2032 DiagSPM(CXXSpecialMemberKind::MoveConstructor,2033 D->hasUserDeclaredMoveConstructor());2034 DiagSPM(CXXSpecialMemberKind::MoveAssignment,2035 D->hasUserDeclaredMoveAssignment());2036 return;2037 }2038 2039 if (!D->hasSimpleMoveConstructor() && !D->hasSimpleCopyConstructor()) {2040 const auto *Decl = cast_or_null<CXXConstructorDecl>(2041 LookupSpecialMemberFromXValue(SemaRef, D, /*Assign=*/false));2042 if (Decl && Decl->isUserProvided())2043 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2044 << diag::TraitNotSatisfiedReason::UserProvidedCtr2045 << Decl->isMoveConstructor() << Decl->getSourceRange();2046 }2047 if (!D->hasSimpleMoveAssignment() && !D->hasSimpleCopyAssignment()) {2048 CXXMethodDecl *Decl =2049 LookupSpecialMemberFromXValue(SemaRef, D, /*Assign=*/true);2050 if (Decl && Decl->isUserProvided())2051 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2052 << diag::TraitNotSatisfiedReason::UserProvidedAssign2053 << Decl->isMoveAssignmentOperator() << Decl->getSourceRange();2054 }2055 if (CXXDestructorDecl *Dtr = D->getDestructor()) {2056 Dtr = Dtr->getCanonicalDecl();2057 if (Dtr->isUserProvided() && !Dtr->isDefaulted())2058 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2059 << diag::TraitNotSatisfiedReason::DeletedDtr << /*User Provided*/ 12060 << Dtr->getSourceRange();2061 }2062}2063 2064static void DiagnoseNonTriviallyRelocatableReason(Sema &SemaRef,2065 SourceLocation Loc,2066 const CXXRecordDecl *D) {2067 for (const CXXBaseSpecifier &B : D->bases()) {2068 assert(B.getType()->getAsCXXRecordDecl() && "invalid base?");2069 if (B.isVirtual())2070 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2071 << diag::TraitNotSatisfiedReason::VBase << B.getType()2072 << B.getSourceRange();2073 if (!SemaRef.IsCXXTriviallyRelocatableType(B.getType()))2074 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2075 << diag::TraitNotSatisfiedReason::NTRBase << B.getType()2076 << B.getSourceRange();2077 }2078 for (const FieldDecl *Field : D->fields()) {2079 if (!Field->getType()->isReferenceType() &&2080 !SemaRef.IsCXXTriviallyRelocatableType(Field->getType()))2081 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2082 << diag::TraitNotSatisfiedReason::NTRField << Field2083 << Field->getType() << Field->getSourceRange();2084 }2085 if (D->hasDeletedDestructor())2086 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2087 << diag::TraitNotSatisfiedReason::DeletedDtr << /*Deleted*/ 02088 << D->getDestructor()->getSourceRange();2089 2090 if (D->hasAttr<TriviallyRelocatableAttr>())2091 return;2092 DiagnoseNonDefaultMovable(SemaRef, Loc, D);2093}2094 2095static void DiagnoseNonTriviallyRelocatableReason(Sema &SemaRef,2096 SourceLocation Loc,2097 QualType T) {2098 SemaRef.Diag(Loc, diag::note_unsatisfied_trait)2099 << T << diag::TraitName::TriviallyRelocatable;2100 if (T->isVariablyModifiedType())2101 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2102 << diag::TraitNotSatisfiedReason::VLA;2103 2104 if (T->isReferenceType())2105 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2106 << diag::TraitNotSatisfiedReason::Ref;2107 T = T.getNonReferenceType();2108 2109 if (T.hasNonTrivialObjCLifetime())2110 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2111 << diag::TraitNotSatisfiedReason::HasArcLifetime;2112 2113 const CXXRecordDecl *D = T->getAsCXXRecordDecl();2114 if (!D || D->isInvalidDecl())2115 return;2116 2117 if (D->hasDefinition())2118 DiagnoseNonTriviallyRelocatableReason(SemaRef, Loc, D);2119 2120 SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D;2121}2122 2123static void DiagnoseNonReplaceableReason(Sema &SemaRef, SourceLocation Loc,2124 const CXXRecordDecl *D) {2125 for (const CXXBaseSpecifier &B : D->bases()) {2126 assert(B.getType()->getAsCXXRecordDecl() && "invalid base?");2127 if (!SemaRef.IsCXXReplaceableType(B.getType()))2128 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2129 << diag::TraitNotSatisfiedReason::NonReplaceableBase << B.getType()2130 << B.getSourceRange();2131 }2132 for (const FieldDecl *Field : D->fields()) {2133 if (!SemaRef.IsCXXReplaceableType(Field->getType()))2134 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2135 << diag::TraitNotSatisfiedReason::NonReplaceableField << Field2136 << Field->getType() << Field->getSourceRange();2137 }2138 if (D->hasDeletedDestructor())2139 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2140 << diag::TraitNotSatisfiedReason::DeletedDtr << /*Deleted*/ 02141 << D->getDestructor()->getSourceRange();2142 2143 if (!D->hasSimpleMoveConstructor() && !D->hasSimpleCopyConstructor()) {2144 const auto *Decl = cast<CXXConstructorDecl>(2145 LookupSpecialMemberFromXValue(SemaRef, D, /*Assign=*/false));2146 if (Decl && Decl->isDeleted())2147 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2148 << diag::TraitNotSatisfiedReason::DeletedCtr2149 << Decl->isMoveConstructor() << Decl->getSourceRange();2150 }2151 if (!D->hasSimpleMoveAssignment() && !D->hasSimpleCopyAssignment()) {2152 CXXMethodDecl *Decl =2153 LookupSpecialMemberFromXValue(SemaRef, D, /*Assign=*/true);2154 if (Decl && Decl->isDeleted())2155 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2156 << diag::TraitNotSatisfiedReason::DeletedAssign2157 << Decl->isMoveAssignmentOperator() << Decl->getSourceRange();2158 }2159 2160 if (D->hasAttr<ReplaceableAttr>())2161 return;2162 DiagnoseNonDefaultMovable(SemaRef, Loc, D);2163}2164 2165static void DiagnoseNonReplaceableReason(Sema &SemaRef, SourceLocation Loc,2166 QualType T) {2167 SemaRef.Diag(Loc, diag::note_unsatisfied_trait)2168 << T << diag::TraitName::Replaceable;2169 2170 if (T->isVariablyModifiedType())2171 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2172 << diag::TraitNotSatisfiedReason::VLA;2173 2174 if (T->isReferenceType())2175 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2176 << diag::TraitNotSatisfiedReason::Ref;2177 T = T.getNonReferenceType();2178 2179 if (T.isConstQualified())2180 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2181 << diag::TraitNotSatisfiedReason::Const;2182 2183 if (T.isVolatileQualified())2184 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2185 << diag::TraitNotSatisfiedReason::Volatile;2186 2187 bool IsArray = T->isArrayType();2188 T = SemaRef.getASTContext().getBaseElementType(T.getUnqualifiedType());2189 2190 if (T->isScalarType())2191 return;2192 2193 const CXXRecordDecl *D = T->getAsCXXRecordDecl();2194 if (!D) {2195 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2196 << diag::TraitNotSatisfiedReason::NotScalarOrClass << IsArray;2197 return;2198 }2199 2200 if (D->isInvalidDecl())2201 return;2202 2203 if (D->hasDefinition())2204 DiagnoseNonReplaceableReason(SemaRef, Loc, D);2205 2206 SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D;2207}2208 2209static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef,2210 SourceLocation Loc,2211 const CXXRecordDecl *D) {2212 for (const CXXBaseSpecifier &B : D->bases()) {2213 assert(B.getType()->getAsCXXRecordDecl() && "invalid base?");2214 if (B.isVirtual())2215 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2216 << diag::TraitNotSatisfiedReason::VBase << B.getType()2217 << B.getSourceRange();2218 if (!B.getType().isTriviallyCopyableType(D->getASTContext())) {2219 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2220 << diag::TraitNotSatisfiedReason::NTCBase << B.getType()2221 << B.getSourceRange();2222 }2223 }2224 for (const FieldDecl *Field : D->fields()) {2225 if (!Field->getType().isTriviallyCopyableType(Field->getASTContext()))2226 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2227 << diag::TraitNotSatisfiedReason::NTCField << Field2228 << Field->getType() << Field->getSourceRange();2229 }2230 CXXDestructorDecl *Dtr = D->getDestructor();2231 if (D->hasDeletedDestructor() || (Dtr && !Dtr->isTrivial()))2232 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2233 << diag::TraitNotSatisfiedReason::DeletedDtr2234 << !D->hasDeletedDestructor() << D->getDestructor()->getSourceRange();2235 2236 for (const CXXMethodDecl *Method : D->methods()) {2237 if (Method->isTrivial() || !Method->isUserProvided()) {2238 continue;2239 }2240 auto SpecialMemberKind =2241 SemaRef.getDefaultedFunctionKind(Method).asSpecialMember();2242 switch (SpecialMemberKind) {2243 case CXXSpecialMemberKind::CopyConstructor:2244 case CXXSpecialMemberKind::MoveConstructor:2245 case CXXSpecialMemberKind::CopyAssignment:2246 case CXXSpecialMemberKind::MoveAssignment: {2247 bool IsAssignment =2248 SpecialMemberKind == CXXSpecialMemberKind::CopyAssignment ||2249 SpecialMemberKind == CXXSpecialMemberKind::MoveAssignment;2250 bool IsMove =2251 SpecialMemberKind == CXXSpecialMemberKind::MoveConstructor ||2252 SpecialMemberKind == CXXSpecialMemberKind::MoveAssignment;2253 2254 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2255 << (IsAssignment ? diag::TraitNotSatisfiedReason::UserProvidedAssign2256 : diag::TraitNotSatisfiedReason::UserProvidedCtr)2257 << IsMove << Method->getSourceRange();2258 break;2259 }2260 default:2261 break;2262 }2263 }2264}2265 2266static void DiagnoseNonConstructibleReason(2267 Sema &SemaRef, SourceLocation Loc,2268 const llvm::SmallVector<clang::QualType, 1> &Ts) {2269 if (Ts.empty()) {2270 return;2271 }2272 2273 bool ContainsVoid = false;2274 for (const QualType &ArgTy : Ts) {2275 ContainsVoid |= ArgTy->isVoidType();2276 }2277 2278 if (ContainsVoid)2279 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2280 << diag::TraitNotSatisfiedReason::CVVoidType;2281 2282 QualType T = Ts[0];2283 if (T->isFunctionType())2284 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2285 << diag::TraitNotSatisfiedReason::FunctionType;2286 2287 if (T->isIncompleteArrayType())2288 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2289 << diag::TraitNotSatisfiedReason::IncompleteArrayType;2290 2291 const CXXRecordDecl *D = T->getAsCXXRecordDecl();2292 if (!D || D->isInvalidDecl() || !D->hasDefinition())2293 return;2294 2295 llvm::BumpPtrAllocator OpaqueExprAllocator;2296 SmallVector<Expr *, 2> ArgExprs;2297 ArgExprs.reserve(Ts.size() - 1);2298 for (unsigned I = 1, N = Ts.size(); I != N; ++I) {2299 QualType ArgTy = Ts[I];2300 if (ArgTy->isObjectType() || ArgTy->isFunctionType())2301 ArgTy = SemaRef.Context.getRValueReferenceType(ArgTy);2302 ArgExprs.push_back(2303 new (OpaqueExprAllocator.Allocate<OpaqueValueExpr>())2304 OpaqueValueExpr(Loc, ArgTy.getNonLValueExprType(SemaRef.Context),2305 Expr::getValueKindForType(ArgTy)));2306 }2307 2308 EnterExpressionEvaluationContext Unevaluated(2309 SemaRef, Sema::ExpressionEvaluationContext::Unevaluated);2310 Sema::ContextRAII TUContext(SemaRef,2311 SemaRef.Context.getTranslationUnitDecl());2312 InitializedEntity To(InitializedEntity::InitializeTemporary(T));2313 InitializationKind InitKind(InitializationKind::CreateDirect(Loc, Loc, Loc));2314 InitializationSequence Init(SemaRef, To, InitKind, ArgExprs);2315 2316 Init.Diagnose(SemaRef, To, InitKind, ArgExprs);2317 SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D;2318}2319 2320static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef,2321 SourceLocation Loc, QualType T) {2322 SemaRef.Diag(Loc, diag::note_unsatisfied_trait)2323 << T << diag::TraitName::TriviallyCopyable;2324 2325 if (T->isReferenceType())2326 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2327 << diag::TraitNotSatisfiedReason::Ref;2328 2329 const CXXRecordDecl *D = T->getAsCXXRecordDecl();2330 if (!D || D->isInvalidDecl())2331 return;2332 2333 if (D->hasDefinition())2334 DiagnoseNonTriviallyCopyableReason(SemaRef, Loc, D);2335 2336 SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D;2337}2338 2339static void DiagnoseNonAssignableReason(Sema &SemaRef, SourceLocation Loc,2340 QualType T, QualType U) {2341 const CXXRecordDecl *D = T->getAsCXXRecordDecl();2342 2343 auto createDeclValExpr = [&](QualType Ty) -> OpaqueValueExpr {2344 if (Ty->isObjectType() || Ty->isFunctionType())2345 Ty = SemaRef.Context.getRValueReferenceType(Ty);2346 return {Loc, Ty.getNonLValueExprType(SemaRef.Context),2347 Expr::getValueKindForType(Ty)};2348 };2349 2350 auto LHS = createDeclValExpr(T);2351 auto RHS = createDeclValExpr(U);2352 2353 EnterExpressionEvaluationContext Unevaluated(2354 SemaRef, Sema::ExpressionEvaluationContext::Unevaluated);2355 Sema::ContextRAII TUContext(SemaRef,2356 SemaRef.Context.getTranslationUnitDecl());2357 SemaRef.BuildBinOp(/*S=*/nullptr, Loc, BO_Assign, &LHS, &RHS);2358 2359 if (!D || D->isInvalidDecl())2360 return;2361 2362 SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D;2363}2364 2365static void DiagnoseIsEmptyReason(Sema &S, SourceLocation Loc,2366 const CXXRecordDecl *D) {2367 // Non-static data members (ignore zero-width bit‐fields).2368 for (const auto *Field : D->fields()) {2369 if (Field->isZeroLengthBitField())2370 continue;2371 if (Field->isBitField()) {2372 S.Diag(Loc, diag::note_unsatisfied_trait_reason)2373 << diag::TraitNotSatisfiedReason::NonZeroLengthField << Field2374 << Field->getSourceRange();2375 continue;2376 }2377 S.Diag(Loc, diag::note_unsatisfied_trait_reason)2378 << diag::TraitNotSatisfiedReason::NonEmptyMember << Field2379 << Field->getType() << Field->getSourceRange();2380 }2381 2382 // Virtual functions.2383 for (const auto *M : D->methods()) {2384 if (M->isVirtual()) {2385 S.Diag(Loc, diag::note_unsatisfied_trait_reason)2386 << diag::TraitNotSatisfiedReason::VirtualFunction << M2387 << M->getSourceRange();2388 break;2389 }2390 }2391 2392 // Virtual bases and non-empty bases.2393 for (const auto &B : D->bases()) {2394 const auto *BR = B.getType()->getAsCXXRecordDecl();2395 if (!BR || BR->isInvalidDecl())2396 continue;2397 if (B.isVirtual()) {2398 S.Diag(Loc, diag::note_unsatisfied_trait_reason)2399 << diag::TraitNotSatisfiedReason::VBase << B.getType()2400 << B.getSourceRange();2401 }2402 if (!BR->isEmpty()) {2403 S.Diag(Loc, diag::note_unsatisfied_trait_reason)2404 << diag::TraitNotSatisfiedReason::NonEmptyBase << B.getType()2405 << B.getSourceRange();2406 }2407 }2408}2409 2410static void DiagnoseIsEmptyReason(Sema &S, SourceLocation Loc, QualType T) {2411 // Emit primary "not empty" diagnostic.2412 S.Diag(Loc, diag::note_unsatisfied_trait) << T << diag::TraitName::Empty;2413 2414 // While diagnosing is_empty<T>, we want to look at the actual type, not a2415 // reference or an array of it. So we need to massage the QualType param to2416 // strip refs and arrays.2417 if (T->isReferenceType())2418 S.Diag(Loc, diag::note_unsatisfied_trait_reason)2419 << diag::TraitNotSatisfiedReason::Ref;2420 T = T.getNonReferenceType();2421 2422 if (auto *AT = S.Context.getAsArrayType(T))2423 T = AT->getElementType();2424 2425 if (auto *D = T->getAsCXXRecordDecl()) {2426 if (D->hasDefinition()) {2427 DiagnoseIsEmptyReason(S, Loc, D);2428 S.Diag(D->getLocation(), diag::note_defined_here) << D;2429 }2430 }2431}2432 2433static void DiagnoseIsFinalReason(Sema &S, SourceLocation Loc,2434 const CXXRecordDecl *D) {2435 if (!D || D->isInvalidDecl())2436 return;2437 2438 // Complete record but not 'final'.2439 if (!D->isEffectivelyFinal()) {2440 S.Diag(Loc, diag::note_unsatisfied_trait_reason)2441 << diag::TraitNotSatisfiedReason::NotMarkedFinal;2442 S.Diag(D->getLocation(), diag::note_defined_here) << D;2443 return;2444 }2445}2446 2447static void DiagnoseIsFinalReason(Sema &S, SourceLocation Loc, QualType T) {2448 // Primary: “%0 is not final”2449 S.Diag(Loc, diag::note_unsatisfied_trait) << T << diag::TraitName::Final;2450 if (T->isReferenceType()) {2451 S.Diag(Loc, diag::note_unsatisfied_trait_reason)2452 << diag::TraitNotSatisfiedReason::Ref;2453 S.Diag(Loc, diag::note_unsatisfied_trait_reason)2454 << diag::TraitNotSatisfiedReason::NotClassOrUnion;2455 return;2456 }2457 // Arrays / functions / non-records → not a class/union.2458 if (S.Context.getAsArrayType(T)) {2459 S.Diag(Loc, diag::note_unsatisfied_trait_reason)2460 << diag::TraitNotSatisfiedReason::NotClassOrUnion;2461 return;2462 }2463 if (T->isFunctionType()) {2464 S.Diag(Loc, diag::note_unsatisfied_trait_reason)2465 << diag::TraitNotSatisfiedReason::FunctionType;2466 S.Diag(Loc, diag::note_unsatisfied_trait_reason)2467 << diag::TraitNotSatisfiedReason::NotClassOrUnion;2468 return;2469 }2470 if (!T->isRecordType()) {2471 S.Diag(Loc, diag::note_unsatisfied_trait_reason)2472 << diag::TraitNotSatisfiedReason::NotClassOrUnion;2473 return;2474 }2475 if (const auto *D = T->getAsCXXRecordDecl())2476 DiagnoseIsFinalReason(S, Loc, D);2477}2478 2479static bool hasMultipleDataBaseClassesWithFields(const CXXRecordDecl *D) {2480 int NumBasesWithFields = 0;2481 for (const CXXBaseSpecifier &Base : D->bases()) {2482 const CXXRecordDecl *BaseRD = Base.getType()->getAsCXXRecordDecl();2483 if (!BaseRD || BaseRD->isInvalidDecl())2484 continue;2485 2486 for (const FieldDecl *Field : BaseRD->fields()) {2487 if (!Field->isUnnamedBitField()) {2488 if (++NumBasesWithFields > 1)2489 return true; // found more than one base class with fields2490 break; // no need to check further fields in this base class2491 }2492 }2493 }2494 return false;2495}2496 2497static void DiagnoseNonStandardLayoutReason(Sema &SemaRef, SourceLocation Loc,2498 const CXXRecordDecl *D) {2499 for (const CXXBaseSpecifier &B : D->bases()) {2500 assert(B.getType()->getAsCXXRecordDecl() && "invalid base?");2501 if (B.isVirtual()) {2502 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2503 << diag::TraitNotSatisfiedReason::VBase << B.getType()2504 << B.getSourceRange();2505 }2506 if (!B.getType()->isStandardLayoutType()) {2507 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2508 << diag::TraitNotSatisfiedReason::NonStandardLayoutBase << B.getType()2509 << B.getSourceRange();2510 }2511 }2512 // Check for mixed access specifiers in fields.2513 const FieldDecl *FirstField = nullptr;2514 AccessSpecifier FirstAccess = AS_none;2515 2516 for (const FieldDecl *Field : D->fields()) {2517 if (Field->isUnnamedBitField())2518 continue;2519 2520 // Record the first field we see2521 if (!FirstField) {2522 FirstField = Field;2523 FirstAccess = Field->getAccess();2524 continue;2525 }2526 2527 // Check if the field has a different access specifier than the first one.2528 if (Field->getAccess() != FirstAccess) {2529 // Emit a diagnostic about mixed access specifiers.2530 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2531 << diag::TraitNotSatisfiedReason::MixedAccess;2532 2533 SemaRef.Diag(FirstField->getLocation(), diag::note_defined_here)2534 << FirstField;2535 2536 SemaRef.Diag(Field->getLocation(), diag::note_unsatisfied_trait_reason)2537 << diag::TraitNotSatisfiedReason::MixedAccessField << Field2538 << FirstField;2539 2540 // No need to check further fields, as we already found mixed access.2541 break;2542 }2543 }2544 if (hasMultipleDataBaseClassesWithFields(D)) {2545 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2546 << diag::TraitNotSatisfiedReason::MultipleDataBase;2547 }2548 if (D->isPolymorphic()) {2549 // Find the best location to point “defined here” at.2550 const CXXMethodDecl *VirtualMD = nullptr;2551 // First, look for a virtual method.2552 for (const auto *M : D->methods()) {2553 if (M->isVirtual()) {2554 VirtualMD = M;2555 break;2556 }2557 }2558 if (VirtualMD) {2559 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2560 << diag::TraitNotSatisfiedReason::VirtualFunction << VirtualMD;2561 SemaRef.Diag(VirtualMD->getLocation(), diag::note_defined_here)2562 << VirtualMD;2563 } else {2564 // If no virtual method, point to the record declaration itself.2565 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2566 << diag::TraitNotSatisfiedReason::VirtualFunction << D;2567 SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D;2568 }2569 }2570 for (const FieldDecl *Field : D->fields()) {2571 if (!Field->getType()->isStandardLayoutType()) {2572 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2573 << diag::TraitNotSatisfiedReason::NonStandardLayoutMember << Field2574 << Field->getType() << Field->getSourceRange();2575 }2576 }2577 // Find any indirect base classes that have fields.2578 if (D->hasDirectFields()) {2579 const CXXRecordDecl *Indirect = nullptr;2580 D->forallBases([&](const CXXRecordDecl *BaseDef) {2581 if (BaseDef->hasDirectFields()) {2582 Indirect = BaseDef;2583 return false; // stop traversal2584 }2585 return true; // continue to the next base2586 });2587 if (Indirect) {2588 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2589 << diag::TraitNotSatisfiedReason::IndirectBaseWithFields << Indirect2590 << Indirect->getSourceRange();2591 }2592 }2593}2594 2595static void DiagnoseNonStandardLayoutReason(Sema &SemaRef, SourceLocation Loc,2596 QualType T) {2597 SemaRef.Diag(Loc, diag::note_unsatisfied_trait)2598 << T << diag::TraitName::StandardLayout;2599 2600 // Check type-level exclusion first.2601 if (T->isVariablyModifiedType()) {2602 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2603 << diag::TraitNotSatisfiedReason::VLA;2604 return;2605 }2606 2607 if (T->isReferenceType()) {2608 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2609 << diag::TraitNotSatisfiedReason::Ref;2610 return;2611 }2612 T = T.getNonReferenceType();2613 const CXXRecordDecl *D = T->getAsCXXRecordDecl();2614 if (!D || D->isInvalidDecl())2615 return;2616 2617 if (D->hasDefinition())2618 DiagnoseNonStandardLayoutReason(SemaRef, Loc, D);2619 2620 SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D;2621}2622 2623static void DiagnoseNonAggregateReason(Sema &SemaRef, SourceLocation Loc,2624 const CXXRecordDecl *D) {2625 for (const CXXConstructorDecl *Ctor : D->ctors()) {2626 if (Ctor->isUserProvided())2627 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2628 << diag::TraitNotSatisfiedReason::UserDeclaredCtr;2629 if (Ctor->isInheritingConstructor())2630 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2631 << diag::TraitNotSatisfiedReason::InheritedCtr;2632 }2633 2634 if (llvm::any_of(D->decls(), [](auto const *Sub) {2635 return isa<ConstructorUsingShadowDecl>(Sub);2636 })) {2637 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2638 << diag::TraitNotSatisfiedReason::InheritedCtr;2639 }2640 2641 if (D->isPolymorphic())2642 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2643 << diag::TraitNotSatisfiedReason::PolymorphicType2644 << D->getSourceRange();2645 2646 for (const CXXBaseSpecifier &B : D->bases()) {2647 if (B.isVirtual()) {2648 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2649 << diag::TraitNotSatisfiedReason::VBase << B.getType()2650 << B.getSourceRange();2651 continue;2652 }2653 auto AccessSpecifier = B.getAccessSpecifier();2654 switch (AccessSpecifier) {2655 case AS_private:2656 case AS_protected:2657 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2658 << diag::TraitNotSatisfiedReason::PrivateProtectedDirectBase2659 << (AccessSpecifier == AS_protected);2660 break;2661 default:2662 break;2663 }2664 }2665 2666 for (const CXXMethodDecl *Method : D->methods()) {2667 if (Method->isVirtual()) {2668 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2669 << diag::TraitNotSatisfiedReason::VirtualFunction << Method2670 << Method->getSourceRange();2671 }2672 }2673 2674 for (const FieldDecl *Field : D->fields()) {2675 auto AccessSpecifier = Field->getAccess();2676 switch (AccessSpecifier) {2677 case AS_private:2678 case AS_protected:2679 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2680 << diag::TraitNotSatisfiedReason::PrivateProtectedDirectDataMember2681 << (AccessSpecifier == AS_protected);2682 break;2683 default:2684 break;2685 }2686 }2687 2688 SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D;2689}2690 2691static void DiagnoseNonAggregateReason(Sema &SemaRef, SourceLocation Loc,2692 QualType T) {2693 SemaRef.Diag(Loc, diag::note_unsatisfied_trait)2694 << T << diag::TraitName::Aggregate;2695 2696 if (T->isVoidType())2697 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2698 << diag::TraitNotSatisfiedReason::CVVoidType;2699 2700 T = T.getNonReferenceType();2701 const CXXRecordDecl *D = T->getAsCXXRecordDecl();2702 if (!D || D->isInvalidDecl())2703 return;2704 2705 if (D->hasDefinition())2706 DiagnoseNonAggregateReason(SemaRef, Loc, D);2707}2708 2709static void DiagnoseNonAbstractReason(Sema &SemaRef, SourceLocation Loc,2710 const CXXRecordDecl *D) {2711 // If this type has any abstract base classes, their respective virtual2712 // functions must have been overridden.2713 for (const CXXBaseSpecifier &B : D->bases()) {2714 if (B.getType()->castAsCXXRecordDecl()->isAbstract()) {2715 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2716 << diag::TraitNotSatisfiedReason::OverridesAllPureVirtual2717 << B.getType() << B.getSourceRange();2718 }2719 }2720}2721 2722static void DiagnoseNonAbstractReason(Sema &SemaRef, SourceLocation Loc,2723 QualType T) {2724 SemaRef.Diag(Loc, diag::note_unsatisfied_trait)2725 << T << diag::TraitName::Abstract;2726 2727 if (T->isReferenceType()) {2728 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2729 << diag::TraitNotSatisfiedReason::Ref;2730 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2731 << diag::TraitNotSatisfiedReason::NotStructOrClass;2732 return;2733 }2734 2735 if (T->isUnionType()) {2736 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2737 << diag::TraitNotSatisfiedReason::UnionType;2738 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2739 << diag::TraitNotSatisfiedReason::NotStructOrClass;2740 return;2741 }2742 2743 if (SemaRef.Context.getAsArrayType(T)) {2744 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2745 << diag::TraitNotSatisfiedReason::ArrayType;2746 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2747 << diag::TraitNotSatisfiedReason::NotStructOrClass;2748 return;2749 }2750 2751 if (T->isFunctionType()) {2752 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2753 << diag::TraitNotSatisfiedReason::FunctionType;2754 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2755 << diag::TraitNotSatisfiedReason::NotStructOrClass;2756 return;2757 }2758 2759 if (T->isPointerType()) {2760 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2761 << diag::TraitNotSatisfiedReason::PointerType;2762 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2763 << diag::TraitNotSatisfiedReason::NotStructOrClass;2764 return;2765 }2766 2767 if (!T->isStructureOrClassType()) {2768 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)2769 << diag::TraitNotSatisfiedReason::NotStructOrClass;2770 return;2771 }2772 2773 const CXXRecordDecl *D = T->getAsCXXRecordDecl();2774 if (D->hasDefinition())2775 DiagnoseNonAbstractReason(SemaRef, Loc, D);2776}2777 2778void Sema::DiagnoseTypeTraitDetails(const Expr *E) {2779 E = E->IgnoreParenImpCasts();2780 if (E->containsErrors())2781 return;2782 2783 ExtractedTypeTraitInfo TraitInfo = ExtractTypeTraitFromExpression(E);2784 if (!TraitInfo)2785 return;2786 2787 const auto &[Trait, Args] = TraitInfo.value();2788 switch (Trait) {2789 case UTT_IsCppTriviallyRelocatable:2790 DiagnoseNonTriviallyRelocatableReason(*this, E->getBeginLoc(), Args[0]);2791 break;2792 case UTT_IsReplaceable:2793 DiagnoseNonReplaceableReason(*this, E->getBeginLoc(), Args[0]);2794 break;2795 case UTT_IsTriviallyCopyable:2796 DiagnoseNonTriviallyCopyableReason(*this, E->getBeginLoc(), Args[0]);2797 break;2798 case BTT_IsAssignable:2799 DiagnoseNonAssignableReason(*this, E->getBeginLoc(), Args[0], Args[1]);2800 break;2801 case UTT_IsEmpty:2802 DiagnoseIsEmptyReason(*this, E->getBeginLoc(), Args[0]);2803 break;2804 case UTT_IsStandardLayout:2805 DiagnoseNonStandardLayoutReason(*this, E->getBeginLoc(), Args[0]);2806 break;2807 case TT_IsConstructible:2808 DiagnoseNonConstructibleReason(*this, E->getBeginLoc(), Args);2809 break;2810 case UTT_IsAggregate:2811 DiagnoseNonAggregateReason(*this, E->getBeginLoc(), Args[0]);2812 break;2813 case UTT_IsFinal: {2814 QualType QT = Args[0];2815 if (QT->isDependentType())2816 break;2817 const auto *RD = QT->getAsCXXRecordDecl();2818 if (!RD || !RD->isEffectivelyFinal())2819 DiagnoseIsFinalReason(*this, E->getBeginLoc(), QT); // unsatisfied2820 break;2821 }2822 case UTT_IsAbstract:2823 DiagnoseNonAbstractReason(*this, E->getBeginLoc(), Args[0]);2824 break;2825 default:2826 break;2827 }2828}2829