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