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

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of clang/lib/Sema/SemaTypeTraits.cpp