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