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