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 // LWG3819: For reference_meows_from_temporary traits, && is not added to
1289 // the source object type.
1290 // Otherwise, compute the result of add_rvalue_reference_t.
1291 bool UseRawObjectType =
1292 Kind == clang::BTT_ReferenceBindsToTemporary ||
1293 Kind == clang::BTT_ReferenceConstructsFromTemporary ||
1294 Kind == clang::BTT_ReferenceConvertsFromTemporary;
1295
1296 // Precondition: T and all types in the parameter pack Args shall be
1297 // complete types, (possibly cv-qualified) void, or arrays of
1298 // unknown bound.
1299 for (const auto *TSI : Args) {
1300 QualType ArgTy = TSI->getType();
1301 if (ArgTy->isVoidType() || ArgTy->isIncompleteArrayType())
1302 continue;
1303
1304 if (S.RequireCompleteType(
1305 Loc: KWLoc, T: ArgTy, DiagID: diag::err_incomplete_type_used_in_type_trait_expr))
1306 return false;
1307 }
1308
1309 // Make sure the first argument is not incomplete nor a function type.
1310 QualType T = Args[0]->getType();
1311 if (T->isIncompleteType() || T->isFunctionType() ||
1312 (UseRawObjectType && !T->isReferenceType()))
1313 return false;
1314
1315 // Make sure the first argument is not an abstract type.
1316 CXXRecordDecl *RD = T->getAsCXXRecordDecl();
1317 if (RD && RD->isAbstract())
1318 return false;
1319
1320 llvm::BumpPtrAllocator OpaqueExprAllocator;
1321 SmallVector<Expr *, 2> ArgExprs;
1322 ArgExprs.reserve(N: Args.size() - 1);
1323 for (unsigned I = 1, N = Args.size(); I != N; ++I) {
1324 QualType ArgTy = Args[I]->getType();
1325 if ((ArgTy->isObjectType() && !UseRawObjectType) ||
1326 ArgTy->isFunctionType())
1327 ArgTy = S.Context.getRValueReferenceType(T: ArgTy);
1328 ArgExprs.push_back(
1329 Elt: new (OpaqueExprAllocator.Allocate<OpaqueValueExpr>())
1330 OpaqueValueExpr(Args[I]->getTypeLoc().getBeginLoc(),
1331 ArgTy.getNonLValueExprType(Context: S.Context),
1332 Expr::getValueKindForType(T: ArgTy)));
1333 }
1334
1335 // Perform the initialization in an unevaluated context within a SFINAE
1336 // trap at translation unit scope.
1337 EnterExpressionEvaluationContext Unevaluated(
1338 S, Sema::ExpressionEvaluationContext::Unevaluated);
1339 Sema::SFINAETrap SFINAE(S, /*ForValidityCheck=*/true);
1340 Sema::ContextRAII TUContext(S, S.Context.getTranslationUnitDecl());
1341 InitializedEntity To(
1342 InitializedEntity::InitializeTemporary(Context&: S.Context, TypeInfo: Args[0]));
1343 InitializationKind InitKind(
1344 Kind == clang::BTT_ReferenceConvertsFromTemporary
1345 ? InitializationKind::CreateCopy(InitLoc: KWLoc, EqualLoc: KWLoc)
1346 : InitializationKind::CreateDirect(InitLoc: KWLoc, LParenLoc: KWLoc, RParenLoc));
1347 InitializationSequence Init(S, To, InitKind, ArgExprs);
1348 if (Init.Failed())
1349 return false;
1350
1351 ExprResult Result = Init.Perform(S, Entity: To, Kind: InitKind, Args: ArgExprs);
1352 if (Result.isInvalid() || SFINAE.hasErrorOccurred())
1353 return false;
1354
1355 if (Kind == clang::TT_IsConstructible)
1356 return true;
1357
1358 if (Kind == clang::BTT_ReferenceBindsToTemporary ||
1359 Kind == clang::BTT_ReferenceConstructsFromTemporary ||
1360 Kind == clang::BTT_ReferenceConvertsFromTemporary) {
1361 if (!T->isReferenceType())
1362 return false;
1363
1364 // A function reference never binds to a temporary object.
1365 if (T.getNonReferenceType()->isFunctionType())
1366 return false;
1367
1368 if (!Init.isDirectReferenceBinding())
1369 return true;
1370
1371 if (Kind == clang::BTT_ReferenceBindsToTemporary)
1372 return false;
1373
1374 QualType U = Args[1]->getType();
1375 if (U->isReferenceType())
1376 return false;
1377
1378 TypeSourceInfo *TPtr = S.Context.CreateTypeSourceInfo(
1379 T: S.Context.getPointerType(T: T.getNonReferenceType()));
1380 TypeSourceInfo *UPtr = S.Context.CreateTypeSourceInfo(
1381 T: S.Context.getPointerType(T: U.getNonReferenceType()));
1382 return !CheckConvertibilityForTypeTraits(Self&: S, Lhs: UPtr, Rhs: TPtr, KeyLoc: RParenLoc,
1383 OpaqueExprAllocator)
1384 .isInvalid();
1385 }
1386
1387 if (Kind == clang::TT_IsNothrowConstructible)
1388 return S.canThrow(E: Result.get()) == CT_Cannot;
1389
1390 if (Kind == clang::TT_IsTriviallyConstructible) {
1391 // Under Objective-C ARC and Weak, if the destination has non-trivial
1392 // Objective-C lifetime, this is a non-trivial construction.
1393 if (T.getNonReferenceType().hasNonTrivialObjCLifetime())
1394 return false;
1395
1396 // The initialization succeeded; now make sure there are no non-trivial
1397 // calls.
1398 return !Result.get()->hasNonTrivialCall(Ctx: S.Context);
1399 }
1400
1401 llvm_unreachable("unhandled type trait");
1402 return false;
1403 }
1404 default:
1405 llvm_unreachable("not a TT");
1406 }
1407
1408 return false;
1409}
1410
1411namespace {
1412void DiagnoseBuiltinDeprecation(Sema &S, TypeTrait Kind, SourceLocation KWLoc) {
1413 TypeTrait Replacement;
1414 switch (Kind) {
1415 case UTT_HasNothrowAssign:
1416 case UTT_HasNothrowMoveAssign:
1417 Replacement = BTT_IsNothrowAssignable;
1418 break;
1419 case UTT_HasNothrowCopy:
1420 case UTT_HasNothrowConstructor:
1421 Replacement = TT_IsNothrowConstructible;
1422 break;
1423 case UTT_HasTrivialAssign:
1424 case UTT_HasTrivialMoveAssign:
1425 Replacement = BTT_IsTriviallyAssignable;
1426 break;
1427 case UTT_HasTrivialCopy:
1428 Replacement = UTT_IsTriviallyCopyable;
1429 break;
1430 case UTT_HasTrivialDefaultConstructor:
1431 case UTT_HasTrivialMoveConstructor:
1432 Replacement = TT_IsTriviallyConstructible;
1433 break;
1434 case UTT_HasTrivialDestructor:
1435 Replacement = UTT_IsTriviallyDestructible;
1436 break;
1437 case UTT_IsTriviallyRelocatable:
1438 Replacement = clang::UTT_IsCppTriviallyRelocatable;
1439 break;
1440 case BTT_ReferenceBindsToTemporary:
1441 Replacement = clang::BTT_ReferenceConstructsFromTemporary;
1442 break;
1443 default:
1444 return;
1445 }
1446 S.Diag(Loc: KWLoc, DiagID: diag::warn_deprecated_builtin)
1447 << getTraitSpelling(T: Kind) << getTraitSpelling(T: Replacement);
1448}
1449} // namespace
1450
1451bool Sema::CheckTypeTraitArity(unsigned Arity, SourceLocation Loc, size_t N) {
1452 if (Arity && N != Arity) {
1453 Diag(Loc, DiagID: diag::err_type_trait_arity)
1454 << Arity << 0 << (Arity > 1) << (int)N << SourceRange(Loc);
1455 return false;
1456 }
1457
1458 if (!Arity && N == 0) {
1459 Diag(Loc, DiagID: diag::err_type_trait_arity)
1460 << 1 << 1 << 1 << (int)N << SourceRange(Loc);
1461 return false;
1462 }
1463 return true;
1464}
1465
1466enum class TypeTraitReturnType {
1467 Bool,
1468 SizeT,
1469};
1470
1471static TypeTraitReturnType GetReturnType(TypeTrait Kind) {
1472 if (Kind == TypeTrait::UTT_StructuredBindingSize)
1473 return TypeTraitReturnType::SizeT;
1474 return TypeTraitReturnType::Bool;
1475}
1476
1477ExprResult Sema::BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
1478 ArrayRef<TypeSourceInfo *> Args,
1479 SourceLocation RParenLoc) {
1480 if (!CheckTypeTraitArity(Arity: getTypeTraitArity(T: Kind), Loc: KWLoc, N: Args.size()))
1481 return ExprError();
1482
1483 if (Kind <= UTT_Last && !CheckUnaryTypeTraitTypeCompleteness(
1484 S&: *this, UTT: Kind, Loc: KWLoc, ArgTy: Args[0]->getType()))
1485 return ExprError();
1486
1487 DiagnoseBuiltinDeprecation(S&: *this, Kind, KWLoc);
1488
1489 bool Dependent = false;
1490 for (unsigned I = 0, N = Args.size(); I != N; ++I) {
1491 if (Args[I]->getType()->isDependentType()) {
1492 Dependent = true;
1493 break;
1494 }
1495 }
1496
1497 switch (GetReturnType(Kind)) {
1498 case TypeTraitReturnType::Bool: {
1499 bool Result = EvaluateBooleanTypeTrait(S&: *this, Kind, KWLoc, Args, RParenLoc,
1500 IsDependent: Dependent);
1501 return TypeTraitExpr::Create(C: Context, T: Context.getLogicalOperationType(),
1502 Loc: KWLoc, Kind, Args, RParenLoc, Value: Result);
1503 }
1504 case TypeTraitReturnType::SizeT: {
1505 APValue Result =
1506 EvaluateSizeTTypeTrait(S&: *this, Kind, KWLoc, Args, RParenLoc, IsDependent: Dependent);
1507 return TypeTraitExpr::Create(C: Context, T: Context.getSizeType(), Loc: KWLoc, Kind,
1508 Args, RParenLoc, Value: Result);
1509 }
1510 }
1511 llvm_unreachable("unhandled type trait return type");
1512}
1513
1514ExprResult Sema::ActOnTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
1515 ArrayRef<ParsedType> Args,
1516 SourceLocation RParenLoc) {
1517 SmallVector<TypeSourceInfo *, 4> ConvertedArgs;
1518 ConvertedArgs.reserve(N: Args.size());
1519
1520 for (unsigned I = 0, N = Args.size(); I != N; ++I) {
1521 TypeSourceInfo *TInfo;
1522 QualType T = GetTypeFromParser(Ty: Args[I], TInfo: &TInfo);
1523 if (!TInfo)
1524 TInfo = Context.getTrivialTypeSourceInfo(T, Loc: KWLoc);
1525
1526 ConvertedArgs.push_back(Elt: TInfo);
1527 }
1528
1529 return BuildTypeTrait(Kind, KWLoc, Args: ConvertedArgs, RParenLoc);
1530}
1531
1532bool Sema::BuiltinIsBaseOf(SourceLocation RhsTLoc, QualType LhsT,
1533 QualType RhsT) {
1534 // C++0x [meta.rel]p2
1535 // Base is a base class of Derived without regard to cv-qualifiers or
1536 // Base and Derived are not unions and name the same class type without
1537 // regard to cv-qualifiers.
1538
1539 const RecordType *lhsRecord = LhsT->getAsCanonical<RecordType>();
1540 const RecordType *rhsRecord = RhsT->getAsCanonical<RecordType>();
1541 if (!rhsRecord || !lhsRecord) {
1542 const ObjCObjectType *LHSObjTy = LhsT->getAs<ObjCObjectType>();
1543 const ObjCObjectType *RHSObjTy = RhsT->getAs<ObjCObjectType>();
1544 if (!LHSObjTy || !RHSObjTy)
1545 return false;
1546
1547 ObjCInterfaceDecl *BaseInterface = LHSObjTy->getInterface();
1548 ObjCInterfaceDecl *DerivedInterface = RHSObjTy->getInterface();
1549 if (!BaseInterface || !DerivedInterface)
1550 return false;
1551
1552 if (RequireCompleteType(Loc: RhsTLoc, T: RhsT,
1553 DiagID: diag::err_incomplete_type_used_in_type_trait_expr))
1554 return false;
1555
1556 return BaseInterface->isSuperClassOf(I: DerivedInterface);
1557 }
1558
1559 assert(Context.hasSameUnqualifiedType(LhsT, RhsT) ==
1560 (lhsRecord == rhsRecord));
1561
1562 // Unions are never base classes, and never have base classes.
1563 // It doesn't matter if they are complete or not. See PR#41843
1564 if (lhsRecord && lhsRecord->getDecl()->isUnion())
1565 return false;
1566 if (rhsRecord && rhsRecord->getDecl()->isUnion())
1567 return false;
1568
1569 if (lhsRecord == rhsRecord)
1570 return true;
1571
1572 // C++0x [meta.rel]p2:
1573 // If Base and Derived are class types and are different types
1574 // (ignoring possible cv-qualifiers) then Derived shall be a
1575 // complete type.
1576 if (RequireCompleteType(Loc: RhsTLoc, T: RhsT,
1577 DiagID: diag::err_incomplete_type_used_in_type_trait_expr))
1578 return false;
1579
1580 return cast<CXXRecordDecl>(Val: rhsRecord->getDecl())
1581 ->isDerivedFrom(Base: cast<CXXRecordDecl>(Val: lhsRecord->getDecl()));
1582}
1583
1584static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT,
1585 const TypeSourceInfo *Lhs,
1586 const TypeSourceInfo *Rhs,
1587 SourceLocation KeyLoc) {
1588 QualType LhsT = Lhs->getType();
1589 QualType RhsT = Rhs->getType();
1590
1591 assert(!LhsT->isDependentType() && !RhsT->isDependentType() &&
1592 "Cannot evaluate traits of dependent types");
1593
1594 switch (BTT) {
1595 case BTT_IsBaseOf:
1596 return Self.BuiltinIsBaseOf(RhsTLoc: Rhs->getTypeLoc().getBeginLoc(), LhsT, RhsT);
1597
1598 case BTT_IsVirtualBaseOf: {
1599 const RecordType *BaseRecord = LhsT->getAsCanonical<RecordType>();
1600 const RecordType *DerivedRecord = RhsT->getAsCanonical<RecordType>();
1601
1602 if (!BaseRecord || !DerivedRecord) {
1603 DiagnoseVLAInCXXTypeTrait(S&: Self, T: Lhs,
1604 TypeTraitID: tok::kw___builtin_is_virtual_base_of);
1605 DiagnoseVLAInCXXTypeTrait(S&: Self, T: Rhs,
1606 TypeTraitID: tok::kw___builtin_is_virtual_base_of);
1607 return false;
1608 }
1609
1610 if (BaseRecord->isUnionType() || DerivedRecord->isUnionType())
1611 return false;
1612
1613 if (!BaseRecord->isStructureOrClassType() ||
1614 !DerivedRecord->isStructureOrClassType())
1615 return false;
1616
1617 if (Self.RequireCompleteType(Loc: Rhs->getTypeLoc().getBeginLoc(), T: RhsT,
1618 DiagID: diag::err_incomplete_type))
1619 return false;
1620
1621 return cast<CXXRecordDecl>(Val: DerivedRecord->getDecl())
1622 ->isVirtuallyDerivedFrom(Base: cast<CXXRecordDecl>(Val: BaseRecord->getDecl()));
1623 }
1624 case BTT_IsSame:
1625 return Self.Context.hasSameType(T1: LhsT, T2: RhsT);
1626 case BTT_TypeCompatible: {
1627 // GCC ignores cv-qualifiers on arrays for this builtin.
1628 Qualifiers LhsQuals, RhsQuals;
1629 QualType Lhs = Self.getASTContext().getUnqualifiedArrayType(T: LhsT, Quals&: LhsQuals);
1630 QualType Rhs = Self.getASTContext().getUnqualifiedArrayType(T: RhsT, Quals&: RhsQuals);
1631 return Self.Context.typesAreCompatible(T1: Lhs, T2: Rhs);
1632 }
1633 case BTT_IsConvertible:
1634 case BTT_IsConvertibleTo:
1635 case BTT_IsNothrowConvertible: {
1636 if (RhsT->isVoidType())
1637 return LhsT->isVoidType();
1638 llvm::BumpPtrAllocator OpaqueExprAllocator;
1639 ExprResult Result = CheckConvertibilityForTypeTraits(Self, Lhs, Rhs, KeyLoc,
1640 OpaqueExprAllocator);
1641 if (Result.isInvalid())
1642 return false;
1643
1644 if (BTT != BTT_IsNothrowConvertible)
1645 return true;
1646
1647 return Self.canThrow(E: Result.get()) == CT_Cannot;
1648 }
1649
1650 case BTT_IsAssignable:
1651 case BTT_IsNothrowAssignable:
1652 case BTT_IsTriviallyAssignable: {
1653 // C++11 [meta.unary.prop]p3:
1654 // is_trivially_assignable is defined as:
1655 // is_assignable<T, U>::value is true and the assignment, as defined by
1656 // is_assignable, is known to call no operation that is not trivial
1657 //
1658 // is_assignable is defined as:
1659 // The expression declval<T>() = declval<U>() is well-formed when
1660 // treated as an unevaluated operand (Clause 5).
1661 //
1662 // For both, T and U shall be complete types, (possibly cv-qualified)
1663 // void, or arrays of unknown bound.
1664 if (!LhsT->isVoidType() && !LhsT->isIncompleteArrayType() &&
1665 Self.RequireCompleteType(
1666 Loc: Lhs->getTypeLoc().getBeginLoc(), T: LhsT,
1667 DiagID: diag::err_incomplete_type_used_in_type_trait_expr))
1668 return false;
1669 if (!RhsT->isVoidType() && !RhsT->isIncompleteArrayType() &&
1670 Self.RequireCompleteType(
1671 Loc: Rhs->getTypeLoc().getBeginLoc(), T: RhsT,
1672 DiagID: diag::err_incomplete_type_used_in_type_trait_expr))
1673 return false;
1674
1675 // cv void is never assignable.
1676 if (LhsT->isVoidType() || RhsT->isVoidType())
1677 return false;
1678
1679 // Build expressions that emulate the effect of declval<T>() and
1680 // declval<U>().
1681 auto createDeclValExpr = [&](QualType Ty) -> OpaqueValueExpr {
1682 if (Ty->isObjectType() || Ty->isFunctionType())
1683 Ty = Self.Context.getRValueReferenceType(T: Ty);
1684 return {KeyLoc, Ty.getNonLValueExprType(Context: Self.Context),
1685 Expr::getValueKindForType(T: Ty)};
1686 };
1687
1688 auto Lhs = createDeclValExpr(LhsT);
1689 auto Rhs = createDeclValExpr(RhsT);
1690
1691 // Attempt the assignment in an unevaluated context within a SFINAE
1692 // trap at translation unit scope.
1693 EnterExpressionEvaluationContext Unevaluated(
1694 Self, Sema::ExpressionEvaluationContext::Unevaluated);
1695 Sema::SFINAETrap SFINAE(Self, /*ForValidityCheck=*/true);
1696 Sema::ContextRAII TUContext(Self, Self.Context.getTranslationUnitDecl());
1697 ExprResult Result =
1698 Self.BuildBinOp(/*S=*/nullptr, OpLoc: KeyLoc, Opc: BO_Assign, LHSExpr: &Lhs, RHSExpr: &Rhs);
1699 if (Result.isInvalid())
1700 return false;
1701
1702 // Treat the assignment as unused for the purpose of -Wdeprecated-volatile.
1703 Self.CheckUnusedVolatileAssignment(E: Result.get());
1704
1705 if (SFINAE.hasErrorOccurred())
1706 return false;
1707
1708 if (BTT == BTT_IsAssignable)
1709 return true;
1710
1711 if (BTT == BTT_IsNothrowAssignable)
1712 return Self.canThrow(E: Result.get()) == CT_Cannot;
1713
1714 if (BTT == BTT_IsTriviallyAssignable) {
1715 // Under Objective-C ARC and Weak, if the destination has non-trivial
1716 // Objective-C lifetime, this is a non-trivial assignment.
1717 if (LhsT.getNonReferenceType().hasNonTrivialObjCLifetime())
1718 return false;
1719 const ASTContext &Context = Self.getASTContext();
1720 if (Context.containsAddressDiscriminatedPointerAuth(T: LhsT) ||
1721 Context.containsAddressDiscriminatedPointerAuth(T: RhsT))
1722 return false;
1723 return !Result.get()->hasNonTrivialCall(Ctx: Self.Context);
1724 }
1725
1726 llvm_unreachable("unhandled type trait");
1727 return false;
1728 }
1729 case BTT_IsLayoutCompatible: {
1730 if (!LhsT->isVoidType() && !LhsT->isIncompleteArrayType())
1731 Self.RequireCompleteType(Loc: Lhs->getTypeLoc().getBeginLoc(), T: LhsT,
1732 DiagID: diag::err_incomplete_type);
1733 if (!RhsT->isVoidType() && !RhsT->isIncompleteArrayType())
1734 Self.RequireCompleteType(Loc: Rhs->getTypeLoc().getBeginLoc(), T: RhsT,
1735 DiagID: diag::err_incomplete_type);
1736
1737 DiagnoseVLAInCXXTypeTrait(S&: Self, T: Lhs, TypeTraitID: tok::kw___is_layout_compatible);
1738 DiagnoseVLAInCXXTypeTrait(S&: Self, T: Rhs, TypeTraitID: tok::kw___is_layout_compatible);
1739
1740 return Self.IsLayoutCompatible(T1: LhsT, T2: RhsT);
1741 }
1742 case BTT_IsPointerInterconvertibleBaseOf: {
1743 if (LhsT->isStructureOrClassType() && RhsT->isStructureOrClassType() &&
1744 !Self.getASTContext().hasSameUnqualifiedType(T1: LhsT, T2: RhsT)) {
1745 Self.RequireCompleteType(Loc: Rhs->getTypeLoc().getBeginLoc(), T: RhsT,
1746 DiagID: diag::err_incomplete_type);
1747 }
1748
1749 DiagnoseVLAInCXXTypeTrait(S&: Self, T: Lhs,
1750 TypeTraitID: tok::kw___is_pointer_interconvertible_base_of);
1751 DiagnoseVLAInCXXTypeTrait(S&: Self, T: Rhs,
1752 TypeTraitID: tok::kw___is_pointer_interconvertible_base_of);
1753
1754 return Self.IsPointerInterconvertibleBaseOf(Base: Lhs, Derived: Rhs);
1755 }
1756 case BTT_IsDeducible: {
1757 const auto *TSTToBeDeduced = cast<DeducedTemplateSpecializationType>(Val&: LhsT);
1758 sema::TemplateDeductionInfo Info(KeyLoc);
1759 return Self.DeduceTemplateArgumentsFromType(
1760 TD: TSTToBeDeduced->getTemplateName().getAsTemplateDecl(), FromType: RhsT,
1761 Info) == TemplateDeductionResult::Success;
1762 }
1763 case BTT_IsScalarizedLayoutCompatible: {
1764 if (!LhsT->isVoidType() && !LhsT->isIncompleteArrayType() &&
1765 Self.RequireCompleteType(Loc: Lhs->getTypeLoc().getBeginLoc(), T: LhsT,
1766 DiagID: diag::err_incomplete_type))
1767 return true;
1768 if (!RhsT->isVoidType() && !RhsT->isIncompleteArrayType() &&
1769 Self.RequireCompleteType(Loc: Rhs->getTypeLoc().getBeginLoc(), T: RhsT,
1770 DiagID: diag::err_incomplete_type))
1771 return true;
1772
1773 DiagnoseVLAInCXXTypeTrait(
1774 S&: Self, T: Lhs, TypeTraitID: tok::kw___builtin_hlsl_is_scalarized_layout_compatible);
1775 DiagnoseVLAInCXXTypeTrait(
1776 S&: Self, T: Rhs, TypeTraitID: tok::kw___builtin_hlsl_is_scalarized_layout_compatible);
1777
1778 return Self.HLSL().IsScalarizedLayoutCompatible(T1: LhsT, T2: RhsT);
1779 }
1780 case BTT_LtSynthesizesFromSpaceship:
1781 case BTT_LeSynthesizesFromSpaceship:
1782 case BTT_GtSynthesizesFromSpaceship:
1783 case BTT_GeSynthesizesFromSpaceship: {
1784 EnterExpressionEvaluationContext UnevaluatedContext(
1785 Self, Sema::ExpressionEvaluationContext::Unevaluated);
1786 Sema::SFINAETrap SFINAE(Self, /*ForValidityCheck=*/true);
1787 Sema::ContextRAII TUContext(Self, Self.Context.getTranslationUnitDecl());
1788
1789 OpaqueValueExpr LHS(KeyLoc, LhsT.getNonReferenceType(),
1790 LhsT->isLValueReferenceType() ? ExprValueKind::VK_LValue
1791 : LhsT->isRValueReferenceType()
1792 ? ExprValueKind::VK_XValue
1793 : ExprValueKind::VK_PRValue);
1794 OpaqueValueExpr RHS(KeyLoc, RhsT.getNonReferenceType(),
1795 RhsT->isLValueReferenceType() ? ExprValueKind::VK_LValue
1796 : RhsT->isRValueReferenceType()
1797 ? ExprValueKind::VK_XValue
1798 : ExprValueKind::VK_PRValue);
1799
1800 auto OpKind = [&] {
1801 switch (BTT) {
1802 case BTT_LtSynthesizesFromSpaceship:
1803 return BinaryOperatorKind::BO_LT;
1804 case BTT_LeSynthesizesFromSpaceship:
1805 return BinaryOperatorKind::BO_LE;
1806 case BTT_GtSynthesizesFromSpaceship:
1807 return BinaryOperatorKind::BO_GT;
1808 case BTT_GeSynthesizesFromSpaceship:
1809 return BinaryOperatorKind::BO_GE;
1810 default:
1811 llvm_unreachable("Trying to Synthesize non-comparison operator?");
1812 }
1813 }();
1814
1815 UnresolvedSet<16> Functions;
1816 Self.LookupBinOp(S: Self.TUScope, OpLoc: KeyLoc, Opc: OpKind, Functions);
1817
1818 ExprResult Result =
1819 Self.CreateOverloadedBinOp(OpLoc: KeyLoc, Opc: OpKind, Fns: Functions, LHS: &LHS, RHS: &RHS);
1820 if (Result.isInvalid() || SFINAE.hasErrorOccurred())
1821 return false;
1822
1823 return isa<CXXRewrittenBinaryOperator>(Val: Result.get());
1824 }
1825 default:
1826 llvm_unreachable("not a BTT");
1827 }
1828 llvm_unreachable("Unknown type trait or not implemented");
1829}
1830
1831ExprResult Sema::ActOnArrayTypeTrait(ArrayTypeTrait ATT, SourceLocation KWLoc,
1832 ParsedType Ty, Expr *DimExpr,
1833 SourceLocation RParen) {
1834 TypeSourceInfo *TSInfo;
1835 QualType T = GetTypeFromParser(Ty, TInfo: &TSInfo);
1836 if (!TSInfo)
1837 TSInfo = Context.getTrivialTypeSourceInfo(T);
1838
1839 return BuildArrayTypeTrait(ATT, KWLoc, TSInfo, DimExpr, RParen);
1840}
1841
1842static uint64_t EvaluateArrayTypeTrait(Sema &Self, ArrayTypeTrait ATT,
1843 QualType T, Expr *DimExpr,
1844 SourceLocation KeyLoc) {
1845 assert(!T->isDependentType() && "Cannot evaluate traits of dependent type");
1846
1847 switch (ATT) {
1848 case ATT_ArrayRank:
1849 if (T->isArrayType()) {
1850 unsigned Dim = 0;
1851 while (const ArrayType *AT = Self.Context.getAsArrayType(T)) {
1852 ++Dim;
1853 T = AT->getElementType();
1854 }
1855 return Dim;
1856 }
1857 return 0;
1858
1859 case ATT_ArrayExtent: {
1860 llvm::APSInt Value;
1861 uint64_t Dim;
1862 if (Self.VerifyIntegerConstantExpression(
1863 E: DimExpr, Result: &Value, DiagID: diag::err_dimension_expr_not_constant_integer)
1864 .isInvalid())
1865 return 0;
1866 if (Value.isSigned() && Value.isNegative()) {
1867 Self.Diag(Loc: KeyLoc, DiagID: diag::err_dimension_expr_not_constant_integer)
1868 << DimExpr->getSourceRange();
1869 return 0;
1870 }
1871 Dim = Value.getLimitedValue();
1872
1873 if (T->isArrayType()) {
1874 unsigned D = 0;
1875 bool Matched = false;
1876 while (const ArrayType *AT = Self.Context.getAsArrayType(T)) {
1877 if (Dim == D) {
1878 Matched = true;
1879 break;
1880 }
1881 ++D;
1882 T = AT->getElementType();
1883 }
1884
1885 if (Matched && T->isArrayType()) {
1886 if (const ConstantArrayType *CAT =
1887 Self.Context.getAsConstantArrayType(T))
1888 return CAT->getLimitedSize();
1889 }
1890 }
1891 return 0;
1892 }
1893 }
1894 llvm_unreachable("Unknown type trait or not implemented");
1895}
1896
1897ExprResult Sema::BuildArrayTypeTrait(ArrayTypeTrait ATT, SourceLocation KWLoc,
1898 TypeSourceInfo *TSInfo, Expr *DimExpr,
1899 SourceLocation RParen) {
1900 QualType T = TSInfo->getType();
1901
1902 // FIXME: This should likely be tracked as an APInt to remove any host
1903 // assumptions about the width of size_t on the target.
1904 uint64_t Value = 0;
1905 if (!T->isDependentType())
1906 Value = EvaluateArrayTypeTrait(Self&: *this, ATT, T, DimExpr, KeyLoc: KWLoc);
1907
1908 // While the specification for these traits from the Embarcadero C++
1909 // compiler's documentation says the return type is 'unsigned int', Clang
1910 // returns 'size_t'. On Windows, the primary platform for the Embarcadero
1911 // compiler, there is no difference. On several other platforms this is an
1912 // important distinction.
1913 return new (Context) ArrayTypeTraitExpr(KWLoc, ATT, TSInfo, Value, DimExpr,
1914 RParen, Context.getSizeType());
1915}
1916
1917ExprResult Sema::ActOnExpressionTrait(ExpressionTrait ET, SourceLocation KWLoc,
1918 Expr *Queried, SourceLocation RParen) {
1919 // If error parsing the expression, ignore.
1920 if (!Queried)
1921 return ExprError();
1922
1923 ExprResult Result = BuildExpressionTrait(OET: ET, KWLoc, Queried, RParen);
1924
1925 return Result;
1926}
1927
1928static bool EvaluateExpressionTrait(ExpressionTrait ET, Expr *E) {
1929 switch (ET) {
1930 case ET_IsLValueExpr:
1931 return E->isLValue();
1932 case ET_IsRValueExpr:
1933 return E->isPRValue();
1934 }
1935 llvm_unreachable("Expression trait not covered by switch");
1936}
1937
1938ExprResult Sema::BuildExpressionTrait(ExpressionTrait ET, SourceLocation KWLoc,
1939 Expr *Queried, SourceLocation RParen) {
1940 if (Queried->isTypeDependent()) {
1941 // Delay type-checking for type-dependent expressions.
1942 } else if (Queried->hasPlaceholderType()) {
1943 ExprResult PE = CheckPlaceholderExpr(E: Queried);
1944 if (PE.isInvalid())
1945 return ExprError();
1946 return BuildExpressionTrait(ET, KWLoc, Queried: PE.get(), RParen);
1947 }
1948
1949 bool Value = EvaluateExpressionTrait(ET, E: Queried);
1950
1951 return new (Context)
1952 ExpressionTraitExpr(KWLoc, ET, Queried, Value, RParen, Context.BoolTy);
1953}
1954
1955static std::optional<TypeTrait> StdNameToTypeTrait(StringRef Name) {
1956 return llvm::StringSwitch<std::optional<TypeTrait>>(Name)
1957#define EMIT_STD_NAME_CASES
1958#include "clang/Basic/Traits.inc"
1959 .Default(Value: std::nullopt);
1960}
1961
1962using ExtractedTypeTraitInfo =
1963 std::optional<std::pair<TypeTrait, llvm::SmallVector<QualType, 1>>>;
1964
1965// Recognize type traits that are builting type traits, or known standard
1966// type traits in <type_traits>. Note that at this point we assume the
1967// trait evaluated to false, so we need only to recognize the shape of the
1968// outer-most symbol.
1969static ExtractedTypeTraitInfo ExtractTypeTraitFromExpression(const Expr *E) {
1970 llvm::SmallVector<QualType, 1> Args;
1971 std::optional<TypeTrait> Trait;
1972
1973 // builtins
1974 if (const auto *TraitExpr = dyn_cast<TypeTraitExpr>(Val: E)) {
1975 Trait = TraitExpr->getTrait();
1976 for (const auto *Arg : TraitExpr->getArgs())
1977 Args.push_back(Elt: Arg->getType());
1978 return {{Trait.value(), std::move(Args)}};
1979 }
1980 const auto *Ref = dyn_cast<DeclRefExpr>(Val: E);
1981 if (!Ref)
1982 return std::nullopt;
1983
1984 // std::is_xxx_v<>
1985 if (const auto *VD =
1986 dyn_cast<VarTemplateSpecializationDecl>(Val: Ref->getDecl())) {
1987 if (!VD->isInStdNamespace())
1988 return std::nullopt;
1989 StringRef Name = VD->getIdentifier()->getName();
1990 if (!Name.consume_back(Suffix: "_v"))
1991 return std::nullopt;
1992 Trait = StdNameToTypeTrait(Name);
1993 if (!Trait)
1994 return std::nullopt;
1995 for (const auto &Arg : VD->getTemplateArgs().asArray()) {
1996 if (Arg.getKind() == TemplateArgument::ArgKind::Pack) {
1997 for (const auto &InnerArg : Arg.pack_elements())
1998 Args.push_back(Elt: InnerArg.getAsType());
1999 } else if (Arg.getKind() == TemplateArgument::ArgKind::Type) {
2000 Args.push_back(Elt: Arg.getAsType());
2001 } else {
2002 llvm_unreachable("Unexpected kind");
2003 }
2004 }
2005 return {{Trait.value(), std::move(Args)}};
2006 }
2007
2008 // std::is_xxx<>::value
2009 if (const auto *VD = dyn_cast<VarDecl>(Val: Ref->getDecl());
2010 Ref->hasQualifier() && VD && VD->getIdentifier()->isStr(Str: "value")) {
2011 NestedNameSpecifier Qualifier = Ref->getQualifier();
2012 if (Qualifier.getKind() != NestedNameSpecifier::Kind::Type)
2013 return std::nullopt;
2014 const auto *Ts = Qualifier.getAsType()->getAs<TemplateSpecializationType>();
2015 if (!Ts)
2016 return std::nullopt;
2017 const TemplateDecl *D = Ts->getTemplateName().getAsTemplateDecl();
2018 if (!D || !D->isInStdNamespace())
2019 return std::nullopt;
2020 Trait = StdNameToTypeTrait(Name: D->getIdentifier()->getName());
2021 if (!Trait)
2022 return std::nullopt;
2023 for (const auto &Arg : Ts->template_arguments())
2024 Args.push_back(Elt: Arg.getAsType());
2025 return {{Trait.value(), std::move(Args)}};
2026 }
2027 return std::nullopt;
2028}
2029
2030static void DiagnoseNonDefaultMovable(Sema &SemaRef, SourceLocation Loc,
2031 const CXXRecordDecl *D) {
2032 if (D->isUnion()) {
2033 auto DiagSPM = [&](CXXSpecialMemberKind K, bool Has) {
2034 if (Has)
2035 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2036 << diag::TraitNotSatisfiedReason::UnionWithUserDeclaredSMF << K;
2037 };
2038 DiagSPM(CXXSpecialMemberKind::CopyConstructor,
2039 D->hasUserDeclaredCopyConstructor());
2040 DiagSPM(CXXSpecialMemberKind::CopyAssignment,
2041 D->hasUserDeclaredCopyAssignment());
2042 DiagSPM(CXXSpecialMemberKind::MoveConstructor,
2043 D->hasUserDeclaredMoveConstructor());
2044 DiagSPM(CXXSpecialMemberKind::MoveAssignment,
2045 D->hasUserDeclaredMoveAssignment());
2046 return;
2047 }
2048
2049 if (!D->hasSimpleMoveConstructor() && !D->hasSimpleCopyConstructor()) {
2050 const auto *Decl = cast_or_null<CXXConstructorDecl>(
2051 Val: LookupSpecialMemberFromXValue(SemaRef, RD: D, /*Assign=*/false));
2052 if (Decl && Decl->isUserProvided())
2053 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2054 << diag::TraitNotSatisfiedReason::UserProvidedCtr
2055 << Decl->isMoveConstructor() << Decl->getSourceRange();
2056 }
2057 if (!D->hasSimpleMoveAssignment() && !D->hasSimpleCopyAssignment()) {
2058 CXXMethodDecl *Decl =
2059 LookupSpecialMemberFromXValue(SemaRef, RD: D, /*Assign=*/true);
2060 if (Decl && Decl->isUserProvided())
2061 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2062 << diag::TraitNotSatisfiedReason::UserProvidedAssign
2063 << Decl->isMoveAssignmentOperator() << Decl->getSourceRange();
2064 }
2065 if (CXXDestructorDecl *Dtr = D->getDestructor()) {
2066 Dtr = Dtr->getCanonicalDecl();
2067 if (Dtr->isUserProvided() && !Dtr->isDefaulted())
2068 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2069 << diag::TraitNotSatisfiedReason::DeletedDtr << /*User Provided*/ 1
2070 << Dtr->getSourceRange();
2071 }
2072}
2073
2074static void DiagnoseNonTriviallyRelocatableReason(Sema &SemaRef,
2075 SourceLocation Loc,
2076 const CXXRecordDecl *D) {
2077 for (const CXXBaseSpecifier &B : D->bases()) {
2078 assert(B.getType()->getAsCXXRecordDecl() && "invalid base?");
2079 if (B.isVirtual())
2080 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2081 << diag::TraitNotSatisfiedReason::VBase << B.getType()
2082 << B.getSourceRange();
2083 if (!SemaRef.IsCXXTriviallyRelocatableType(Type: B.getType()))
2084 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2085 << diag::TraitNotSatisfiedReason::NTRBase << B.getType()
2086 << B.getSourceRange();
2087 }
2088 for (const FieldDecl *Field : D->fields()) {
2089 if (!Field->getType()->isReferenceType() &&
2090 !SemaRef.IsCXXTriviallyRelocatableType(Type: Field->getType()))
2091 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2092 << diag::TraitNotSatisfiedReason::NTRField << Field
2093 << Field->getType() << Field->getSourceRange();
2094 }
2095 if (D->hasDeletedDestructor())
2096 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2097 << diag::TraitNotSatisfiedReason::DeletedDtr << /*Deleted*/ 0
2098 << D->getDestructor()->getSourceRange();
2099
2100 DiagnoseNonDefaultMovable(SemaRef, Loc, D);
2101}
2102
2103static void DiagnoseNonTriviallyRelocatableReason(Sema &SemaRef,
2104 SourceLocation Loc,
2105 QualType T) {
2106 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait)
2107 << T << diag::TraitName::TriviallyRelocatable;
2108 if (T->isVariablyModifiedType())
2109 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2110 << diag::TraitNotSatisfiedReason::VLA;
2111
2112 if (T->isReferenceType())
2113 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2114 << diag::TraitNotSatisfiedReason::Ref;
2115 T = T.getNonReferenceType();
2116
2117 if (T.hasNonTrivialObjCLifetime())
2118 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2119 << diag::TraitNotSatisfiedReason::HasArcLifetime;
2120
2121 const CXXRecordDecl *D = T->getAsCXXRecordDecl();
2122 if (!D || D->isInvalidDecl())
2123 return;
2124
2125 if (D->hasDefinition())
2126 DiagnoseNonTriviallyRelocatableReason(SemaRef, Loc, D);
2127
2128 SemaRef.Diag(Loc: D->getLocation(), DiagID: diag::note_defined_here) << D;
2129}
2130
2131static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef,
2132 SourceLocation Loc,
2133 const CXXRecordDecl *D) {
2134 for (const CXXBaseSpecifier &B : D->bases()) {
2135 assert(B.getType()->getAsCXXRecordDecl() && "invalid base?");
2136 if (B.isVirtual())
2137 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2138 << diag::TraitNotSatisfiedReason::VBase << B.getType()
2139 << B.getSourceRange();
2140 if (!B.getType().isTriviallyCopyableType(Context: D->getASTContext())) {
2141 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2142 << diag::TraitNotSatisfiedReason::NTCBase << B.getType()
2143 << B.getSourceRange();
2144 }
2145 }
2146 for (const FieldDecl *Field : D->fields()) {
2147 if (!Field->getType().isTriviallyCopyableType(Context: Field->getASTContext()))
2148 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2149 << diag::TraitNotSatisfiedReason::NTCField << Field
2150 << Field->getType() << Field->getSourceRange();
2151 }
2152 CXXDestructorDecl *Dtr = D->getDestructor();
2153 if (D->hasDeletedDestructor() || (Dtr && !Dtr->isTrivial()))
2154 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2155 << diag::TraitNotSatisfiedReason::DeletedDtr
2156 << !D->hasDeletedDestructor() << D->getDestructor()->getSourceRange();
2157
2158 for (const CXXMethodDecl *Method : D->methods()) {
2159 if (Method->isTrivial() || !Method->isUserProvided()) {
2160 continue;
2161 }
2162 auto SpecialMemberKind =
2163 SemaRef.getDefaultedFunctionKind(FD: Method).asSpecialMember();
2164 switch (SpecialMemberKind) {
2165 case CXXSpecialMemberKind::CopyConstructor:
2166 case CXXSpecialMemberKind::MoveConstructor:
2167 case CXXSpecialMemberKind::CopyAssignment:
2168 case CXXSpecialMemberKind::MoveAssignment: {
2169 bool IsAssignment =
2170 SpecialMemberKind == CXXSpecialMemberKind::CopyAssignment ||
2171 SpecialMemberKind == CXXSpecialMemberKind::MoveAssignment;
2172 bool IsMove =
2173 SpecialMemberKind == CXXSpecialMemberKind::MoveConstructor ||
2174 SpecialMemberKind == CXXSpecialMemberKind::MoveAssignment;
2175
2176 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2177 << (IsAssignment ? diag::TraitNotSatisfiedReason::UserProvidedAssign
2178 : diag::TraitNotSatisfiedReason::UserProvidedCtr)
2179 << IsMove << Method->getSourceRange();
2180 break;
2181 }
2182 default:
2183 break;
2184 }
2185 }
2186}
2187
2188static void DiagnoseNonConstructibleReason(
2189 Sema &SemaRef, SourceLocation Loc,
2190 const llvm::SmallVector<clang::QualType, 1> &Ts) {
2191 if (Ts.empty()) {
2192 return;
2193 }
2194
2195 bool ContainsVoid = false;
2196 for (const QualType &ArgTy : Ts) {
2197 ContainsVoid |= ArgTy->isVoidType();
2198 }
2199
2200 if (ContainsVoid)
2201 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2202 << diag::TraitNotSatisfiedReason::CVVoidType;
2203
2204 QualType T = Ts[0];
2205 if (T->isFunctionType())
2206 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2207 << diag::TraitNotSatisfiedReason::FunctionType;
2208
2209 if (T->isIncompleteArrayType())
2210 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2211 << diag::TraitNotSatisfiedReason::IncompleteArrayType;
2212
2213 const CXXRecordDecl *D = T->getAsCXXRecordDecl();
2214 if (!D || D->isInvalidDecl() || !D->hasDefinition())
2215 return;
2216
2217 llvm::BumpPtrAllocator OpaqueExprAllocator;
2218 SmallVector<Expr *, 2> ArgExprs;
2219 ArgExprs.reserve(N: Ts.size() - 1);
2220 for (unsigned I = 1, N = Ts.size(); I != N; ++I) {
2221 QualType ArgTy = Ts[I];
2222 if (ArgTy->isObjectType() || ArgTy->isFunctionType())
2223 ArgTy = SemaRef.Context.getRValueReferenceType(T: ArgTy);
2224 ArgExprs.push_back(
2225 Elt: new (OpaqueExprAllocator.Allocate<OpaqueValueExpr>())
2226 OpaqueValueExpr(Loc, ArgTy.getNonLValueExprType(Context: SemaRef.Context),
2227 Expr::getValueKindForType(T: ArgTy)));
2228 }
2229
2230 EnterExpressionEvaluationContext Unevaluated(
2231 SemaRef, Sema::ExpressionEvaluationContext::Unevaluated);
2232 Sema::ContextRAII TUContext(SemaRef,
2233 SemaRef.Context.getTranslationUnitDecl());
2234 InitializedEntity To(InitializedEntity::InitializeTemporary(Type: T));
2235 InitializationKind InitKind(InitializationKind::CreateDirect(InitLoc: Loc, LParenLoc: Loc, RParenLoc: Loc));
2236 InitializationSequence Init(SemaRef, To, InitKind, ArgExprs);
2237
2238 Init.Diagnose(S&: SemaRef, Entity: To, Kind: InitKind, Args: ArgExprs);
2239 SemaRef.Diag(Loc: D->getLocation(), DiagID: diag::note_defined_here) << D;
2240}
2241
2242static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef,
2243 SourceLocation Loc, QualType T) {
2244 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait)
2245 << T << diag::TraitName::TriviallyCopyable;
2246
2247 if (T->isReferenceType())
2248 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2249 << diag::TraitNotSatisfiedReason::Ref;
2250
2251 const CXXRecordDecl *D = T->getAsCXXRecordDecl();
2252 if (!D || D->isInvalidDecl())
2253 return;
2254
2255 if (D->hasDefinition())
2256 DiagnoseNonTriviallyCopyableReason(SemaRef, Loc, D);
2257
2258 SemaRef.Diag(Loc: D->getLocation(), DiagID: diag::note_defined_here) << D;
2259}
2260
2261static void DiagnoseNonAssignableReason(Sema &SemaRef, SourceLocation Loc,
2262 QualType T, QualType U) {
2263 const CXXRecordDecl *D = T->getAsCXXRecordDecl();
2264
2265 auto createDeclValExpr = [&](QualType Ty) -> OpaqueValueExpr {
2266 if (Ty->isObjectType() || Ty->isFunctionType())
2267 Ty = SemaRef.Context.getRValueReferenceType(T: Ty);
2268 return {Loc, Ty.getNonLValueExprType(Context: SemaRef.Context),
2269 Expr::getValueKindForType(T: Ty)};
2270 };
2271
2272 auto LHS = createDeclValExpr(T);
2273 auto RHS = createDeclValExpr(U);
2274
2275 EnterExpressionEvaluationContext Unevaluated(
2276 SemaRef, Sema::ExpressionEvaluationContext::Unevaluated);
2277 Sema::ContextRAII TUContext(SemaRef,
2278 SemaRef.Context.getTranslationUnitDecl());
2279 SemaRef.BuildBinOp(/*S=*/nullptr, OpLoc: Loc, Opc: BO_Assign, LHSExpr: &LHS, RHSExpr: &RHS);
2280
2281 if (!D || D->isInvalidDecl())
2282 return;
2283
2284 SemaRef.Diag(Loc: D->getLocation(), DiagID: diag::note_defined_here) << D;
2285}
2286
2287static void DiagnoseIsEmptyReason(Sema &S, SourceLocation Loc,
2288 const CXXRecordDecl *D) {
2289 // Non-static data members (ignore zero-width bit‐fields).
2290 for (const auto *Field : D->fields()) {
2291 if (Field->isZeroLengthBitField())
2292 continue;
2293 if (Field->isBitField()) {
2294 S.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2295 << diag::TraitNotSatisfiedReason::NonZeroLengthField << Field
2296 << Field->getSourceRange();
2297 continue;
2298 }
2299 S.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2300 << diag::TraitNotSatisfiedReason::NonEmptyMember << Field
2301 << Field->getType() << Field->getSourceRange();
2302 }
2303
2304 // Virtual functions.
2305 for (const auto *M : D->methods()) {
2306 if (M->isVirtual()) {
2307 S.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2308 << diag::TraitNotSatisfiedReason::VirtualFunction << M
2309 << M->getSourceRange();
2310 break;
2311 }
2312 }
2313
2314 // Virtual bases and non-empty bases.
2315 for (const auto &B : D->bases()) {
2316 const auto *BR = B.getType()->getAsCXXRecordDecl();
2317 if (!BR || BR->isInvalidDecl())
2318 continue;
2319 if (B.isVirtual()) {
2320 S.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2321 << diag::TraitNotSatisfiedReason::VBase << B.getType()
2322 << B.getSourceRange();
2323 }
2324 if (!BR->isEmpty()) {
2325 S.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2326 << diag::TraitNotSatisfiedReason::NonEmptyBase << B.getType()
2327 << B.getSourceRange();
2328 }
2329 }
2330}
2331
2332static void DiagnoseIsEmptyReason(Sema &S, SourceLocation Loc, QualType T) {
2333 // Emit primary "not empty" diagnostic.
2334 S.Diag(Loc, DiagID: diag::note_unsatisfied_trait) << T << diag::TraitName::Empty;
2335
2336 // While diagnosing is_empty<T>, we want to look at the actual type, not a
2337 // reference or an array of it. So we need to massage the QualType param to
2338 // strip refs and arrays.
2339 if (T->isReferenceType())
2340 S.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2341 << diag::TraitNotSatisfiedReason::Ref;
2342 T = T.getNonReferenceType();
2343
2344 if (auto *AT = S.Context.getAsArrayType(T))
2345 T = AT->getElementType();
2346
2347 if (auto *D = T->getAsCXXRecordDecl()) {
2348 if (D->hasDefinition()) {
2349 DiagnoseIsEmptyReason(S, Loc, D);
2350 S.Diag(Loc: D->getLocation(), DiagID: diag::note_defined_here) << D;
2351 }
2352 }
2353}
2354
2355static void DiagnoseIsFinalReason(Sema &S, SourceLocation Loc,
2356 const CXXRecordDecl *D) {
2357 if (!D || D->isInvalidDecl())
2358 return;
2359
2360 // Complete record but not 'final'.
2361 if (!D->isEffectivelyFinal()) {
2362 S.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2363 << diag::TraitNotSatisfiedReason::NotMarkedFinal;
2364 S.Diag(Loc: D->getLocation(), DiagID: diag::note_defined_here) << D;
2365 return;
2366 }
2367}
2368
2369static void DiagnoseIsFinalReason(Sema &S, SourceLocation Loc, QualType T) {
2370 // Primary: “%0 is not final”
2371 S.Diag(Loc, DiagID: diag::note_unsatisfied_trait) << T << diag::TraitName::Final;
2372 if (T->isReferenceType()) {
2373 S.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2374 << diag::TraitNotSatisfiedReason::Ref;
2375 S.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2376 << diag::TraitNotSatisfiedReason::NotClassOrUnion;
2377 return;
2378 }
2379 // Arrays / functions / non-records → not a class/union.
2380 if (S.Context.getAsArrayType(T)) {
2381 S.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2382 << diag::TraitNotSatisfiedReason::NotClassOrUnion;
2383 return;
2384 }
2385 if (T->isFunctionType()) {
2386 S.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2387 << diag::TraitNotSatisfiedReason::FunctionType;
2388 S.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2389 << diag::TraitNotSatisfiedReason::NotClassOrUnion;
2390 return;
2391 }
2392 if (!T->isRecordType()) {
2393 S.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2394 << diag::TraitNotSatisfiedReason::NotClassOrUnion;
2395 return;
2396 }
2397 if (const auto *D = T->getAsCXXRecordDecl())
2398 DiagnoseIsFinalReason(S, Loc, D);
2399}
2400
2401static bool hasMultipleDataBaseClassesWithFields(const CXXRecordDecl *D) {
2402 int NumBasesWithFields = 0;
2403 for (const CXXBaseSpecifier &Base : D->bases()) {
2404 const CXXRecordDecl *BaseRD = Base.getType()->getAsCXXRecordDecl();
2405 if (!BaseRD || BaseRD->isInvalidDecl())
2406 continue;
2407
2408 for (const FieldDecl *Field : BaseRD->fields()) {
2409 if (!Field->isUnnamedBitField()) {
2410 if (++NumBasesWithFields > 1)
2411 return true; // found more than one base class with fields
2412 break; // no need to check further fields in this base class
2413 }
2414 }
2415 }
2416 return false;
2417}
2418
2419static void DiagnoseNonStandardLayoutReason(Sema &SemaRef, SourceLocation Loc,
2420 const CXXRecordDecl *D) {
2421 for (const CXXBaseSpecifier &B : D->bases()) {
2422 assert(B.getType()->getAsCXXRecordDecl() && "invalid base?");
2423 if (B.isVirtual()) {
2424 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2425 << diag::TraitNotSatisfiedReason::VBase << B.getType()
2426 << B.getSourceRange();
2427 }
2428 if (!B.getType()->isStandardLayoutType()) {
2429 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2430 << diag::TraitNotSatisfiedReason::NonStandardLayoutBase << B.getType()
2431 << B.getSourceRange();
2432 }
2433 }
2434 // Check for mixed access specifiers in fields.
2435 const FieldDecl *FirstField = nullptr;
2436 AccessSpecifier FirstAccess = AS_none;
2437
2438 for (const FieldDecl *Field : D->fields()) {
2439 if (Field->isUnnamedBitField())
2440 continue;
2441
2442 // Record the first field we see
2443 if (!FirstField) {
2444 FirstField = Field;
2445 FirstAccess = Field->getAccess();
2446 continue;
2447 }
2448
2449 // Check if the field has a different access specifier than the first one.
2450 if (Field->getAccess() != FirstAccess) {
2451 // Emit a diagnostic about mixed access specifiers.
2452 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2453 << diag::TraitNotSatisfiedReason::MixedAccess;
2454
2455 SemaRef.Diag(Loc: FirstField->getLocation(), DiagID: diag::note_defined_here)
2456 << FirstField;
2457
2458 SemaRef.Diag(Loc: Field->getLocation(), DiagID: diag::note_unsatisfied_trait_reason)
2459 << diag::TraitNotSatisfiedReason::MixedAccessField << Field
2460 << FirstField;
2461
2462 // No need to check further fields, as we already found mixed access.
2463 break;
2464 }
2465 }
2466 if (hasMultipleDataBaseClassesWithFields(D)) {
2467 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2468 << diag::TraitNotSatisfiedReason::MultipleDataBase;
2469 }
2470 if (D->isPolymorphic()) {
2471 // Find the best location to point “defined here” at.
2472 const CXXMethodDecl *VirtualMD = nullptr;
2473 // First, look for a virtual method.
2474 for (const auto *M : D->methods()) {
2475 if (M->isVirtual()) {
2476 VirtualMD = M;
2477 break;
2478 }
2479 }
2480 if (VirtualMD) {
2481 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2482 << diag::TraitNotSatisfiedReason::VirtualFunction << VirtualMD;
2483 SemaRef.Diag(Loc: VirtualMD->getLocation(), DiagID: diag::note_defined_here)
2484 << VirtualMD;
2485 } else {
2486 // If no virtual method, point to the record declaration itself.
2487 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2488 << diag::TraitNotSatisfiedReason::VirtualFunction << D;
2489 SemaRef.Diag(Loc: D->getLocation(), DiagID: diag::note_defined_here) << D;
2490 }
2491 }
2492 for (const FieldDecl *Field : D->fields()) {
2493 if (!Field->getType()->isStandardLayoutType()) {
2494 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2495 << diag::TraitNotSatisfiedReason::NonStandardLayoutMember << Field
2496 << Field->getType() << Field->getSourceRange();
2497 }
2498 }
2499 // Find any indirect base classes that have fields.
2500 if (D->hasDirectFields()) {
2501 const CXXRecordDecl *Indirect = nullptr;
2502 D->forallBases(BaseMatches: [&](const CXXRecordDecl *BaseDef) {
2503 if (BaseDef->hasDirectFields()) {
2504 Indirect = BaseDef;
2505 return false; // stop traversal
2506 }
2507 return true; // continue to the next base
2508 });
2509 if (Indirect) {
2510 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2511 << diag::TraitNotSatisfiedReason::IndirectBaseWithFields << Indirect
2512 << Indirect->getSourceRange();
2513 }
2514 }
2515}
2516
2517static void DiagnoseNonStandardLayoutReason(Sema &SemaRef, SourceLocation Loc,
2518 QualType T) {
2519 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait)
2520 << T << diag::TraitName::StandardLayout;
2521
2522 // Check type-level exclusion first.
2523 if (T->isVariablyModifiedType()) {
2524 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2525 << diag::TraitNotSatisfiedReason::VLA;
2526 return;
2527 }
2528
2529 if (T->isReferenceType()) {
2530 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2531 << diag::TraitNotSatisfiedReason::Ref;
2532 return;
2533 }
2534 T = T.getNonReferenceType();
2535 const CXXRecordDecl *D = T->getAsCXXRecordDecl();
2536 if (!D || D->isInvalidDecl())
2537 return;
2538
2539 if (D->hasDefinition())
2540 DiagnoseNonStandardLayoutReason(SemaRef, Loc, D);
2541
2542 SemaRef.Diag(Loc: D->getLocation(), DiagID: diag::note_defined_here) << D;
2543}
2544
2545static void DiagnoseNonAggregateReason(Sema &SemaRef, SourceLocation Loc,
2546 const CXXRecordDecl *D) {
2547 for (const CXXConstructorDecl *Ctor : D->ctors()) {
2548 if (Ctor->isUserProvided())
2549 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2550 << diag::TraitNotSatisfiedReason::UserDeclaredCtr;
2551 if (Ctor->isInheritingConstructor())
2552 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2553 << diag::TraitNotSatisfiedReason::InheritedCtr;
2554 }
2555
2556 if (llvm::any_of(Range: D->decls(), P: [](auto const *Sub) {
2557 return isa<ConstructorUsingShadowDecl>(Sub);
2558 })) {
2559 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2560 << diag::TraitNotSatisfiedReason::InheritedCtr;
2561 }
2562
2563 if (D->isPolymorphic())
2564 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2565 << diag::TraitNotSatisfiedReason::PolymorphicType
2566 << D->getSourceRange();
2567
2568 for (const CXXBaseSpecifier &B : D->bases()) {
2569 if (B.isVirtual()) {
2570 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2571 << diag::TraitNotSatisfiedReason::VBase << B.getType()
2572 << B.getSourceRange();
2573 continue;
2574 }
2575 auto AccessSpecifier = B.getAccessSpecifier();
2576 switch (AccessSpecifier) {
2577 case AS_private:
2578 case AS_protected:
2579 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2580 << diag::TraitNotSatisfiedReason::PrivateProtectedDirectBase
2581 << (AccessSpecifier == AS_protected);
2582 break;
2583 default:
2584 break;
2585 }
2586 }
2587
2588 for (const CXXMethodDecl *Method : D->methods()) {
2589 if (Method->isVirtual()) {
2590 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2591 << diag::TraitNotSatisfiedReason::VirtualFunction << Method
2592 << Method->getSourceRange();
2593 }
2594 }
2595
2596 for (const FieldDecl *Field : D->fields()) {
2597 auto AccessSpecifier = Field->getAccess();
2598 switch (AccessSpecifier) {
2599 case AS_private:
2600 case AS_protected:
2601 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2602 << diag::TraitNotSatisfiedReason::PrivateProtectedDirectDataMember
2603 << (AccessSpecifier == AS_protected);
2604 break;
2605 default:
2606 break;
2607 }
2608 }
2609
2610 SemaRef.Diag(Loc: D->getLocation(), DiagID: diag::note_defined_here) << D;
2611}
2612
2613static void DiagnoseNonAggregateReason(Sema &SemaRef, SourceLocation Loc,
2614 QualType T) {
2615 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait)
2616 << T << diag::TraitName::Aggregate;
2617
2618 if (T->isVoidType())
2619 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2620 << diag::TraitNotSatisfiedReason::CVVoidType;
2621
2622 T = T.getNonReferenceType();
2623 const CXXRecordDecl *D = T->getAsCXXRecordDecl();
2624 if (!D || D->isInvalidDecl())
2625 return;
2626
2627 if (D->hasDefinition())
2628 DiagnoseNonAggregateReason(SemaRef, Loc, D);
2629}
2630
2631static void DiagnoseNonAbstractReason(Sema &SemaRef, SourceLocation Loc,
2632 const CXXRecordDecl *D) {
2633 // If this type has any abstract base classes, their respective virtual
2634 // functions must have been overridden.
2635 for (const CXXBaseSpecifier &B : D->bases()) {
2636 if (B.getType()->castAsCXXRecordDecl()->isAbstract()) {
2637 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2638 << diag::TraitNotSatisfiedReason::OverridesAllPureVirtual
2639 << B.getType() << B.getSourceRange();
2640 }
2641 }
2642}
2643
2644static void DiagnoseNonAbstractReason(Sema &SemaRef, SourceLocation Loc,
2645 QualType T) {
2646 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait)
2647 << T << diag::TraitName::Abstract;
2648
2649 if (T->isReferenceType()) {
2650 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2651 << diag::TraitNotSatisfiedReason::Ref;
2652 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2653 << diag::TraitNotSatisfiedReason::NotStructOrClass;
2654 return;
2655 }
2656
2657 if (T->isUnionType()) {
2658 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2659 << diag::TraitNotSatisfiedReason::UnionType;
2660 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2661 << diag::TraitNotSatisfiedReason::NotStructOrClass;
2662 return;
2663 }
2664
2665 if (SemaRef.Context.getAsArrayType(T)) {
2666 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2667 << diag::TraitNotSatisfiedReason::ArrayType;
2668 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2669 << diag::TraitNotSatisfiedReason::NotStructOrClass;
2670 return;
2671 }
2672
2673 if (T->isFunctionType()) {
2674 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2675 << diag::TraitNotSatisfiedReason::FunctionType;
2676 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2677 << diag::TraitNotSatisfiedReason::NotStructOrClass;
2678 return;
2679 }
2680
2681 if (T->isPointerType()) {
2682 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2683 << diag::TraitNotSatisfiedReason::PointerType;
2684 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2685 << diag::TraitNotSatisfiedReason::NotStructOrClass;
2686 return;
2687 }
2688
2689 if (!T->isStructureOrClassType()) {
2690 SemaRef.Diag(Loc, DiagID: diag::note_unsatisfied_trait_reason)
2691 << diag::TraitNotSatisfiedReason::NotStructOrClass;
2692 return;
2693 }
2694
2695 const CXXRecordDecl *D = T->getAsCXXRecordDecl();
2696 if (D->hasDefinition())
2697 DiagnoseNonAbstractReason(SemaRef, Loc, D);
2698}
2699
2700void Sema::DiagnoseTypeTraitDetails(const Expr *E) {
2701 E = E->IgnoreParenImpCasts();
2702 if (E->containsErrors())
2703 return;
2704
2705 ExtractedTypeTraitInfo TraitInfo = ExtractTypeTraitFromExpression(E);
2706 if (!TraitInfo)
2707 return;
2708
2709 const auto &[Trait, Args] = TraitInfo.value();
2710 switch (Trait) {
2711 case UTT_IsCppTriviallyRelocatable:
2712 DiagnoseNonTriviallyRelocatableReason(SemaRef&: *this, Loc: E->getBeginLoc(), T: Args[0]);
2713 break;
2714 case UTT_IsTriviallyCopyable:
2715 DiagnoseNonTriviallyCopyableReason(SemaRef&: *this, Loc: E->getBeginLoc(), T: Args[0]);
2716 break;
2717 case BTT_IsAssignable:
2718 DiagnoseNonAssignableReason(SemaRef&: *this, Loc: E->getBeginLoc(), T: Args[0], U: Args[1]);
2719 break;
2720 case UTT_IsEmpty:
2721 DiagnoseIsEmptyReason(S&: *this, Loc: E->getBeginLoc(), T: Args[0]);
2722 break;
2723 case UTT_IsStandardLayout:
2724 DiagnoseNonStandardLayoutReason(SemaRef&: *this, Loc: E->getBeginLoc(), T: Args[0]);
2725 break;
2726 case TT_IsConstructible:
2727 DiagnoseNonConstructibleReason(SemaRef&: *this, Loc: E->getBeginLoc(), Ts: Args);
2728 break;
2729 case UTT_IsAggregate:
2730 DiagnoseNonAggregateReason(SemaRef&: *this, Loc: E->getBeginLoc(), T: Args[0]);
2731 break;
2732 case UTT_IsFinal: {
2733 QualType QT = Args[0];
2734 if (QT->isDependentType())
2735 break;
2736 const auto *RD = QT->getAsCXXRecordDecl();
2737 if (!RD || !RD->isEffectivelyFinal())
2738 DiagnoseIsFinalReason(S&: *this, Loc: E->getBeginLoc(), T: QT); // unsatisfied
2739 break;
2740 }
2741 case UTT_IsAbstract:
2742 DiagnoseNonAbstractReason(SemaRef&: *this, Loc: E->getBeginLoc(), T: Args[0]);
2743 break;
2744 default:
2745 break;
2746 }
2747}
2748