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