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