clang: lib/Sema/SemaTypeTraits.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

27#include "llvm/ADT/STLExtras.h"

28

29using namespace clang;

30

33 bool Assign) {

36

39 Expr *Arg = nullptr;

40 unsigned NumArgs;

41

44

45 if (Assign)

46 Name =

48 else

49 Name =

51

53 NumArgs = 1;

54 Arg = &FakeArg;

55

56

61

62

63

64

67

69 return nullptr;

70

71

72

74

75 for (NamedDecl *CandDecl : Candidates) {

76 if (CandDecl->isInvalidDecl())

77 continue;

78

82 if (Assign)

84 ThisTy, Classification,

86 else {

87 assert(CtorInfo);

90 true);

91 }

94 if (Assign)

96 Tmpl, Cand, const_cast<CXXRecordDecl *>(RD), nullptr, ThisTy,

97 Classification, llvm::ArrayRef(&Arg, NumArgs), OCS, true);

98 else {

99 assert(CtorInfo);

101 CtorInfo.ConstructorTmpl, CtorInfo.FoundDecl, nullptr,

103 }

104 }

105 }

106

112 default:

113 return nullptr;

114 }

115}

116

119 bool AllowUserDefined) {

121

123 return true;

124

127 return Decl && (AllowUserDefined || Decl->isUserProvided()) &&

128 Decl->isDeleted();

129}

130

134

136 return true;

137

141 return false;

142

143 return Decl && (AllowUserDefined || Decl->isUserProvided()) &&

144 Decl->isDeleted();

145}

146

147

148

149

150

151

152

153

154

155

158 false))

159 return false;

160

162 SemaRef, D, false))

163 return false;

164

166

167 if (!Dtr)

168 return true;

169

171

173 return false;

174

176}

177

178

179

182

184 const auto *BaseDecl = B.getType()->getAsCXXRecordDecl();

185 if (!BaseDecl)

186 continue;

187

188

189 if (B.isVirtual() || (!BaseDecl->isDependentType() &&

191 return false;

192 }

193

194 bool IsUnion = D->isUnion();

196 if (Field->getType()->isDependentType())

197 continue;

198 if (Field->getType()->isReferenceType())

199 continue;

200

201

203 return false;

204

205

206

208 Field->getType()))

209 return false;

210 }

212}

213

214

215

217

219 const auto *BaseDecl = B.getType()->getAsCXXRecordDecl();

220 if (!BaseDecl)

221 continue;

222

223 if (!BaseDecl->isDependentType() &&

225 return false;

226 }

227

229 if (Field->getType()->isDependentType())

230 continue;

231

232

234 return false;

235 }

237}

238

242

244 return Info;

245

247

248

249

250 auto HasSuitableSMP = [&] {

252 true) &&

254 *this, D, true);

255 };

256

257 auto IsUnion = [&, Is = std::optional{}]() mutable {

258 if (!Is.has_value())

263 return *Is;

264 };

265

266 auto IsDefaultMovable = [&, Is = std::optional{}]() mutable {

267 if (!Is.has_value())

269 return *Is;

270 };

271

274 return false;

275

276

278 return false;

279

280

281 if (D->hasAttr())

282 return true;

283

284

285 if (IsUnion())

286 return true;

287

288

290 }();

291

294 return false;

295

296

298 return false;

299

300

301 if (D->hasAttr())

302 return HasSuitableSMP();

303

304

305 if (IsUnion())

306 return HasSuitableSMP();

307

308

310 }();

311

312 return Info;

313}

314

316 if (std::optionalASTContext::CXXRecordDeclRelocationInfo Info =

317 getASTContext().getRelocationInfoForCXXRecord(&RD))

318 return Info->IsRelocatable;

323}

324

327

329 return false;

330

332 return false;

333

335 return false;

336

337 if (Context.containsNonRelocatablePointerAuth(Type))

338 return false;

339

341 return true;

342

345

346 return false;

347}

348

350 if (std::optionalASTContext::CXXRecordDeclRelocationInfo Info =

352 return Info->IsReplaceable;

357}

358

360 if (Type.isConstQualified() || Type.isVolatileQualified())

361 return false;

362

364 return false;

365

369 return false;

371 return true;

373 return ::IsCXXReplaceableType(*this, RD);

374 return false;

375}

376

377

378

379

380

383 if (T->getType()->isVariableArrayType())

384 return false;

385

386 S.Diag(T->getTypeLoc().getBeginLoc(), diag::err_vla_unsupported)

387 << 1 << TypeTraitID;

388 return true;

389}

390

391

392

393

394

397 if (T->getType()->isAtomicType())

398 return false;

399

400 S.Diag(T->getTypeLoc().getBeginLoc(), diag::err_atomic_unsupported)

401 << TypeTraitID;

402 return true;

403}

404

405

406

407

408

409

410

414

415

416

417

418

419

420

421

422

423 switch (UTT) {

424 default:

425 llvm_unreachable("not a UTT");

426

427 case UTT_IsCompleteType:

428

429

430

431

432

433

434 case UTT_IsVoid:

435 case UTT_IsIntegral:

436 case UTT_IsFloatingPoint:

437 case UTT_IsArray:

438 case UTT_IsBoundedArray:

439 case UTT_IsPointer:

440 case UTT_IsLvalueReference:

441 case UTT_IsRvalueReference:

442 case UTT_IsMemberFunctionPointer:

443 case UTT_IsMemberObjectPointer:

444 case UTT_IsEnum:

445 case UTT_IsScopedEnum:

446 case UTT_IsUnion:

447 case UTT_IsClass:

448 case UTT_IsFunction:

449 case UTT_IsReference:

450 case UTT_IsArithmetic:

451 case UTT_IsFundamental:

452 case UTT_IsObject:

453 case UTT_IsScalar:

454 case UTT_IsCompound:

455 case UTT_IsMemberPointer:

456 case UTT_IsTypedResourceElementCompatible:

457

458

459

460

461

462

463

464 case UTT_IsConst:

465 case UTT_IsVolatile:

466 case UTT_IsSigned:

467 case UTT_IsUnboundedArray:

468 case UTT_IsUnsigned:

469

470

471 case UTT_IsInterfaceClass:

472 return true;

473

474

475 case UTT_StructuredBindingSize:

476 return true;

477

478

479

480 case UTT_IsEmpty:

481 case UTT_IsPolymorphic:

482 case UTT_IsAbstract:

484 if (!RD->isUnion())

486 Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);

487 return true;

488

489

490

491 case UTT_IsFinal:

492 case UTT_IsSealed:

495 Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);

496 return true;

497

498

499 case UTT_IsAggregate:

500 case UTT_IsImplicitLifetime:

502 return true;

503

505 Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);

506

507

508

509 case UTT_HasUniqueObjectRepresentations:

512 return true;

514 Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);

515

516

517

518 case UTT_IsTrivial:

519 case UTT_IsTriviallyCopyable:

520 case UTT_IsStandardLayout:

521 case UTT_IsPOD:

522 case UTT_IsLiteral:

523 case UTT_IsBitwiseCloneable:

524

525

526 case UTT_IsTriviallyRelocatable:

527 case UTT_IsTriviallyEqualityComparable:

528 case UTT_IsCppTriviallyRelocatable:

529 case UTT_IsReplaceable:

530 case UTT_CanPassInRegs:

531

532

533

534 case UTT_HasNothrowAssign:

535 case UTT_HasNothrowMoveAssign:

536 case UTT_HasNothrowConstructor:

537 case UTT_HasNothrowCopy:

538 case UTT_HasTrivialAssign:

539 case UTT_HasTrivialMoveAssign:

540 case UTT_HasTrivialDefaultConstructor:

541 case UTT_HasTrivialMoveConstructor:

542 case UTT_HasTrivialCopy:

543 case UTT_HasTrivialDestructor:

544 case UTT_HasVirtualDestructor:

546 [[fallthrough]];

547

548

549 case UTT_IsDestructible:

550 case UTT_IsNothrowDestructible:

551 case UTT_IsTriviallyDestructible:

552 case UTT_IsIntangibleType:

554 return true;

555

557 Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);

558 }

559}

560

566 if ((RD->*HasTrivial)() && !(RD->*HasNonTrivial)())

567 return true;

568

569 DeclarationName Name = C.DeclarationNames.getCXXOperatorName(Op);

572 if (Self.LookupQualifiedName(Res, RD)) {

573 bool FoundOperator = false;

576 Op != OpEnd; ++Op) {

578 continue;

579

581 if ((Operator->*IsDesiredOp)()) {

582 FoundOperator = true;

584 CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);

586 return false;

587 }

588 }

589 return FoundOperator;

590 }

591 return false;

592}

593

597 if (Decl->isUnion())

598 return false;

599 if (Decl->isLambda())

600 return Decl->isCapturelessLambda();

601

603 {

608

609

612

614

616 Functions, &Operand, &Operand);

618 return false;

619

620 const auto *CallExpr = dyn_cast(Result.get());

622 return false;

624 auto ParamT = Callee->getParamDecl(0)->getType();

625 if (!Callee->isDefaulted())

626 return false;

627 if (!ParamT->isReferenceType() && Decl->isTriviallyCopyable())

628 return false;

630 return false;

631 }

632

633 return llvm::all_of(Decl->bases(),

635 if (const auto *RD = BS.getType()->getAsCXXRecordDecl())

636 return HasNonDeletedDefaultedEqualityComparison(

637 S, RD, KeyLoc);

638 return true;

639 }) &&

640 llvm::all_of(Decl->fields(), [&](const FieldDecl *FD) {

641 auto Type = FD->getType();

642 if (Type->isArrayType())

643 Type = Type->getBaseElementTypeUnsafe()

644 ->getCanonicalTypeUnqualified();

645

646 if (Type->isReferenceType() || Type->isEnumeralType())

647 return false;

648 if (const auto *RD = Type->getAsCXXRecordDecl())

649 return HasNonDeletedDefaultedEqualityComparison(S, RD, KeyLoc);

650 return true;

651 });

652}

653

656 QualType CanonicalType = Type.getCanonicalType();

659 return false;

660

663 return false;

664 }

665

667 CanonicalType, false);

668}

669

672

674 return false;

676 return false;

677

678

679

680

682 return false;

683

686 return true;

687

690

692 return true;

693

694 switch (T.isNonTrivialToPrimitiveDestructiveMove()) {

696 return T.isDestructedType();

698 return true;

699 default:

700 return false;

701 }

702}

703

708 assert(T->isDependentType() && "Cannot evaluate traits of dependent type");

709

711 switch (UTT) {

712 default:

713 llvm_unreachable("not a UTT");

714

715

716 case UTT_IsVoid:

717 return T->isVoidType();

718 case UTT_IsIntegral:

719 return T->isIntegralType(C);

720 case UTT_IsFloatingPoint:

721 return T->isFloatingType();

722 case UTT_IsArray:

723

724

725 if (const auto *CAT = C.getAsConstantArrayType(T))

726 return CAT->getSize() != 0;

727 return T->isArrayType();

728 case UTT_IsBoundedArray:

730 return false;

731

732

733 if (const auto *CAT = C.getAsConstantArrayType(T))

734 return CAT->getSize() != 0;

735 return T->isArrayType() && T->isIncompleteArrayType();

736 case UTT_IsUnboundedArray:

738 return false;

739 return T->isIncompleteArrayType();

740 case UTT_IsPointer:

741 return T->isAnyPointerType();

742 case UTT_IsLvalueReference:

743 return T->isLValueReferenceType();

744 case UTT_IsRvalueReference:

745 return T->isRValueReferenceType();

746 case UTT_IsMemberFunctionPointer:

747 return T->isMemberFunctionPointerType();

748 case UTT_IsMemberObjectPointer:

749 return T->isMemberDataPointerType();

750 case UTT_IsEnum:

751 return T->isEnumeralType();

752 case UTT_IsScopedEnum:

753 return T->isScopedEnumeralType();

754 case UTT_IsUnion:

755 return T->isUnionType();

756 case UTT_IsClass:

757 return T->isClassType() || T->isStructureType() || T->isInterfaceType();

758 case UTT_IsFunction:

759 return T->isFunctionType();

760

761

762

763 case UTT_IsReference:

764 return T->isReferenceType();

765 case UTT_IsArithmetic:

766 return T->isArithmeticType() && T->isEnumeralType();

767 case UTT_IsFundamental:

768 return T->isFundamentalType();

769 case UTT_IsObject:

770 return T->isObjectType();

771 case UTT_IsScalar:

772

773

774

775

776 if (T->isObjCLifetimeType()) {

777 switch (T.getObjCLifetime()) {

780 return true;

781

785 return false;

786 }

787 }

788

789 return T->isScalarType();

790 case UTT_IsCompound:

791 return T->isCompoundType();

792 case UTT_IsMemberPointer:

793 return T->isMemberPointerType();

794

795

796

797 case UTT_IsConst:

798 return T.isConstQualified();

799 case UTT_IsVolatile:

800 return T.isVolatileQualified();

801 case UTT_IsTrivial:

802 return T.isTrivialType(C);

803 case UTT_IsTriviallyCopyable:

804 return T.isTriviallyCopyableType(C);

805 case UTT_IsStandardLayout:

806 return T->isStandardLayoutType();

807 case UTT_IsPOD:

808 return T.isPODType(C);

809 case UTT_IsLiteral:

810 return T->isLiteralType(C);

811 case UTT_IsEmpty:

812 if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())

814 return false;

815 case UTT_IsPolymorphic:

816 if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())

818 return false;

819 case UTT_IsAbstract:

820 if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())

822 return false;

823 case UTT_IsAggregate:

824

825

826

827 return T->isAggregateType() || T->isVectorType() || T->isExtVectorType() ||

828 T->isAnyComplexType();

829

830

831

832 case UTT_IsInterfaceClass:

833 return false;

834 case UTT_IsFinal:

835 case UTT_IsSealed:

836 if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())

837 return RD->hasAttr();

838 return false;

839 case UTT_IsSigned:

840

841

842 return T->isFloatingType() ||

843 (T->isSignedIntegerType() && T->isEnumeralType());

844 case UTT_IsUnsigned:

845

846 return T->isUnsignedIntegerType() && T->isEnumeralType();

847

848

849

850

851

852

853

854

855

856

857

858

859

860

861

862

863

864 case UTT_HasTrivialDefaultConstructor:

865

866

867

868

869 if (T.isPODType(C))

870 return true;

871 if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl())

874 return false;

875 case UTT_HasTrivialMoveConstructor:

876

877

878

879 if (T.isPODType(C))

880 return true;

881 if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl())

884 return false;

885 case UTT_HasTrivialCopy:

886

887

888

889

890

891 if (T.isPODType(C) || T->isReferenceType())

892 return true;

896 return false;

897 case UTT_HasTrivialMoveAssign:

898

899

900

901 if (T.isPODType(C))

902 return true;

903 if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl())

906 return false;

907 case UTT_HasTrivialAssign:

908

909

910

911

912

913

914

915

916

917

918

919

920 if (T.isConstQualified())

921 return false;

922 if (T.isPODType(C))

923 return true;

927 return false;

928 case UTT_IsDestructible:

929 case UTT_IsTriviallyDestructible:

930 case UTT_IsNothrowDestructible:

931

932

933 if (T->isReferenceType())

934 return true;

935

936

937 if (T->isObjCLifetimeType() &&

939 return true;

940

941

942

943

944 if (T->isIncompleteType() || T->isFunctionType())

945 return false;

946

947

948

949 if (UTT == UTT_IsTriviallyDestructible && T.isDestructedType())

950 return false;

951

952

953

954

955

956 if (auto *RD = C.getBaseElementType(T)->getAsCXXRecordDecl()) {

959 return false;

960

961

962

964 return false;

966 return false;

967 if (UTT == UTT_IsNothrowDestructible) {

969 CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);

971 return false;

972 }

973 }

974 return true;

975

976 case UTT_HasTrivialDestructor:

977

978

979

980

981

982

983 if (T.isPODType(C) || T->isReferenceType())

984 return true;

985

986

987 if (T->isObjCLifetimeType() &&

989 return true;

990

991 if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl())

993 return false;

994

995 case UTT_HasNothrowAssign:

996

997

998

999

1000

1001

1002

1003 if (C.getBaseElementType(T).isConstQualified())

1004 return false;

1005 if (T->isReferenceType())

1006 return false;

1007 if (T.isPODType(C) || T->isObjCLifetimeType())

1008 return true;

1009

1010 if (auto *RD = T->getAsCXXRecordDecl())

1015 return false;

1016 case UTT_HasNothrowMoveAssign:

1017

1018

1019

1020 if (T.isPODType(C))

1021 return true;

1022

1023 if (auto *RD = C.getBaseElementType(T)->getAsCXXRecordDecl())

1028 return false;

1029 case UTT_HasNothrowCopy:

1030

1031

1032

1033

1034

1035 if (T.isPODType(C) || T->isReferenceType() || T->isObjCLifetimeType())

1036 return true;

1040 return true;

1041

1042 bool FoundConstructor = false;

1043 unsigned FoundTQs;

1044 for (const auto *ND : Self.LookupConstructors(RD)) {

1045

1046

1047

1049 continue;

1050

1052 continue;

1054 if (Constructor->isCopyConstructor(FoundTQs)) {

1055 FoundConstructor = true;

1057 CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);

1058 if (!CPT)

1059 return false;

1060

1061

1063 return false;

1064 }

1065 }

1066

1067 return FoundConstructor;

1068 }

1069 return false;

1070 case UTT_HasNothrowConstructor:

1071

1072

1073

1074

1075

1076 if (T.isPODType(C) || T->isObjCLifetimeType())

1077 return true;

1078 if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl()) {

1080 return true;

1081

1082 bool FoundConstructor = false;

1083 for (const auto *ND : Self.LookupConstructors(RD)) {

1084

1086 continue;

1087

1089 continue;

1091 if (Constructor->isDefaultConstructor()) {

1092 FoundConstructor = true;

1094 CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);

1095 if (!CPT)

1096 return false;

1097

1098

1100 return false;

1101 }

1102 }

1103 return FoundConstructor;

1104 }

1105 return false;

1106 case UTT_HasVirtualDestructor:

1107

1108

1109

1113 return false;

1114

1115

1116

1117

1118 case UTT_IsCompleteType:

1119

1120

1121

1122 return T->isIncompleteType();

1123 case UTT_HasUniqueObjectRepresentations:

1124 return C.hasUniqueObjectRepresentations(T);

1125 case UTT_IsTriviallyRelocatable:

1127 case UTT_IsBitwiseCloneable:

1128 return T.isBitwiseCloneableType(C);

1129 case UTT_IsCppTriviallyRelocatable:

1130 return Self.IsCXXTriviallyRelocatableType(T);

1131 case UTT_IsReplaceable:

1132 return Self.IsCXXReplaceableType(T);

1133 case UTT_CanPassInRegs:

1134 if (CXXRecordDecl *RD = T->getAsCXXRecordDecl(); RD && T.hasQualifiers())

1136 Self.Diag(KeyLoc, diag::err_builtin_pass_in_regs_non_class) << T;

1137 return false;

1138 case UTT_IsTriviallyEqualityComparable:

1140 case UTT_IsImplicitLifetime: {

1142 tok::kw___builtin_is_implicit_lifetime);

1144 tok::kw___builtin_is_implicit_lifetime);

1145

1146

1147

1148

1149

1150 QualType UnqualT = T->getCanonicalTypeUnqualified();

1152 return true;

1154 return true;

1156 if (!RD)

1157 return false;

1158

1159

1160

1161

1162

1163

1166 return true;

1167 bool HasTrivialNonDeletedDtr =

1169 if (!HasTrivialNonDeletedDtr)

1170 return false;

1172 if (Ctr->isIneligibleOrNotSelected() || Ctr->isDeleted())

1173 continue;

1174 if (Ctr->isTrivial())

1175 return true;

1176 }

1180 return true;

1183 return true;

1186 return true;

1187 return false;

1188 }

1189 case UTT_IsIntangibleType:

1190 assert(Self.getLangOpts().HLSL && "intangible types are HLSL-only feature");

1191 if (T->isVoidType() && T->isIncompleteArrayType())

1193 diag::err_incomplete_type))

1194 return false;

1196 tok::kw___builtin_hlsl_is_intangible))

1197 return false;

1198 return T->isHLSLIntangibleType();

1199

1200 case UTT_IsTypedResourceElementCompatible:

1201 assert(Self.getLangOpts().HLSL &&

1202 "typed resource element compatible types are an HLSL-only feature");

1203 if (T->isIncompleteType())

1204 return false;

1205

1206 return Self.HLSL().IsTypedResourceElementCompatible(T);

1207 }

1208}

1209

1214

1217 SourceLocation KeyLoc, llvm::BumpPtrAllocator &OpaqueExprAllocator) {

1218

1221

1222

1223

1224

1225

1226

1227

1228

1229

1230

1231

1232

1233

1234

1235

1236

1237

1238

1239

1240

1241

1242

1243

1244

1245

1246

1247

1250

1251

1255

1256

1258 LhsT = Self.Context.getRValueReferenceType(LhsT);

1259

1260

1267

1268

1269

1275 if (Init.Failed())

1277

1281

1282 return Result;

1283}

1284

1289 bool IsDependent) {

1290 if (IsDependent)

1292

1293 switch (Kind) {

1294 case TypeTrait::UTT_StructuredBindingSize: {

1295 QualType T = Args[0]->getType();

1296 SourceRange ArgRange = Args[0]->getTypeLoc().getSourceRange();

1299 if (!Size) {

1300 S.Diag(KWLoc, diag::err_arg_is_not_destructurable) << T << ArgRange;

1302 }

1305 break;

1306 }

1307 default:

1308 llvm_unreachable("Not a SizeT type trait");

1309 }

1310}

1311

1316 bool IsDependent) {

1317 if (IsDependent)

1318 return false;

1319

1322

1323

1324

1325 if (Kind <= BTT_Last && Kind != BTT_ReferenceBindsToTemporary &&

1326 Kind != BTT_ReferenceConstructsFromTemporary &&

1327 Kind != BTT_ReferenceConvertsFromTemporary)

1329

1330 switch (Kind) {

1331 case clang::BTT_ReferenceBindsToTemporary:

1332 case clang::BTT_ReferenceConstructsFromTemporary:

1333 case clang::BTT_ReferenceConvertsFromTemporary:

1334 case clang::TT_IsConstructible:

1335 case clang::TT_IsNothrowConstructible:

1336 case clang::TT_IsTriviallyConstructible: {

1337

1338

1339

1340

1341

1342

1343

1344

1345

1346

1347

1348

1349

1350 assert(!Args.empty());

1351

1352

1353

1354

1355 for (const auto *TSI : Args) {

1356 QualType ArgTy = TSI->getType();

1358 continue;

1359

1361 KWLoc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr))

1362 return false;

1363 }

1364

1365

1366 QualType T = Args[0]->getType();

1367 if (T->isIncompleteType() || T->isFunctionType())

1368 return false;

1369

1370

1373 return false;

1374

1375

1376

1377

1378 bool UseRawObjectType =

1379 Kind == clang::BTT_ReferenceBindsToTemporary ||

1380 Kind == clang::BTT_ReferenceConstructsFromTemporary ||

1381 Kind == clang::BTT_ReferenceConvertsFromTemporary;

1382

1383 llvm::BumpPtrAllocator OpaqueExprAllocator;

1385 ArgExprs.reserve(Args.size() - 1);

1386 for (unsigned I = 1, N = Args.size(); I != N; ++I) {

1387 QualType ArgTy = Args[I]->getType();

1388 if ((ArgTy->isObjectType() && !UseRawObjectType) ||

1391 ArgExprs.push_back(

1396 }

1397

1398

1399

1407 Kind == clang::BTT_ReferenceConvertsFromTemporary

1411 if (Init.Failed())

1412 return false;

1413

1414 ExprResult Result = Init.Perform(S, To, InitKind, ArgExprs);

1416 return false;

1417

1418 if (Kind == clang::TT_IsConstructible)

1419 return true;

1420

1421 if (Kind == clang::BTT_ReferenceBindsToTemporary ||

1422 Kind == clang::BTT_ReferenceConstructsFromTemporary ||

1423 Kind == clang::BTT_ReferenceConvertsFromTemporary) {

1424 if (T->isReferenceType())

1425 return false;

1426

1427

1428 if (T.getNonReferenceType()->isFunctionType())

1429 return false;

1430

1431 if (Init.isDirectReferenceBinding())

1432 return true;

1433

1434 if (Kind == clang::BTT_ReferenceBindsToTemporary)

1435 return false;

1436

1437 QualType U = Args[1]->getType();

1438 if (U->isReferenceType())

1439 return false;

1440

1446 OpaqueExprAllocator)

1448 }

1449

1450 if (Kind == clang::TT_IsNothrowConstructible)

1452

1453 if (Kind == clang::TT_IsTriviallyConstructible) {

1454

1455

1456 if (T.getNonReferenceType().hasNonTrivialObjCLifetime())

1457 return false;

1458

1459

1460

1461 return !Result.get()->hasNonTrivialCall(S.Context);

1462 }

1463

1464 llvm_unreachable("unhandled type trait");

1465 return false;

1466 }

1467 default:

1468 llvm_unreachable("not a TT");

1469 }

1470

1471 return false;

1472}

1473

1474namespace {

1477 switch (Kind) {

1478 case UTT_HasNothrowAssign:

1479 case UTT_HasNothrowMoveAssign:

1480 Replacement = BTT_IsNothrowAssignable;

1481 break;

1482 case UTT_HasNothrowCopy:

1483 case UTT_HasNothrowConstructor:

1484 Replacement = TT_IsNothrowConstructible;

1485 break;

1486 case UTT_HasTrivialAssign:

1487 case UTT_HasTrivialMoveAssign:

1488 Replacement = BTT_IsTriviallyAssignable;

1489 break;

1490 case UTT_HasTrivialCopy:

1491 Replacement = UTT_IsTriviallyCopyable;

1492 break;

1493 case UTT_HasTrivialDefaultConstructor:

1494 case UTT_HasTrivialMoveConstructor:

1495 Replacement = TT_IsTriviallyConstructible;

1496 break;

1497 case UTT_HasTrivialDestructor:

1498 Replacement = UTT_IsTriviallyDestructible;

1499 break;

1500 case UTT_IsTriviallyRelocatable:

1501 Replacement = clang::UTT_IsCppTriviallyRelocatable;

1502 break;

1503 case BTT_ReferenceBindsToTemporary:

1504 Replacement = clang::BTT_ReferenceConstructsFromTemporary;

1505 break;

1506 default:

1507 return;

1508 }

1509 S.Diag(KWLoc, diag::warn_deprecated_builtin)

1511}

1512}

1513

1515 if (Arity && N != Arity) {

1516 Diag(Loc, diag::err_type_trait_arity)

1517 << Arity << 0 << (Arity > 1) << (int)N << SourceRange(Loc);

1518 return false;

1519 }

1520

1521 if (!Arity && N == 0) {

1522 Diag(Loc, diag::err_type_trait_arity)

1523 << 1 << 1 << 1 << (int)N << SourceRange(Loc);

1524 return false;

1525 }

1526 return true;

1527}

1528

1533

1535 if (Kind == TypeTrait::UTT_StructuredBindingSize)

1538}

1539

1545

1547 *this, Kind, KWLoc, Args[0]->getType()))

1549

1550 DiagnoseBuiltinDeprecation(*this, Kind, KWLoc);

1551

1553 for (unsigned I = 0, N = Args.size(); I != N; ++I) {

1554 if (Args[I]->getType()->isDependentType()) {

1556 break;

1557 }

1558 }

1559

1565 KWLoc, Kind, Args, RParenLoc, Result);

1566 }

1571 Args, RParenLoc, Result);

1572 }

1573 }

1574 llvm_unreachable("unhandled type trait return type");

1575}

1576

1581 ConvertedArgs.reserve(Args.size());

1582

1583 for (unsigned I = 0, N = Args.size(); I != N; ++I) {

1586 if (!TInfo)

1587 TInfo = Context.getTrivialTypeSourceInfo(T, KWLoc);

1588

1589 ConvertedArgs.push_back(TInfo);

1590 }

1591

1592 return BuildTypeTrait(Kind, KWLoc, ConvertedArgs, RParenLoc);

1593}

1594

1597

1598

1599

1600

1601

1602 const RecordType *lhsRecord = LhsT->getAsCanonical();

1603 const RecordType *rhsRecord = RhsT->getAsCanonical();

1604 if (!rhsRecord || !lhsRecord) {

1607 if (!LHSObjTy || !RHSObjTy)

1608 return false;

1609

1612 if (!BaseInterface || !DerivedInterface)

1613 return false;

1614

1616 diag::err_incomplete_type_used_in_type_trait_expr))

1617 return false;

1618

1619 return BaseInterface->isSuperClassOf(DerivedInterface);

1620 }

1621

1622 assert(Context.hasSameUnqualifiedType(LhsT, RhsT) ==

1623 (lhsRecord == rhsRecord));

1624

1625

1626

1627 if (lhsRecord && lhsRecord->getDecl()->isUnion())

1628 return false;

1629 if (rhsRecord && rhsRecord->getDecl()->isUnion())

1630 return false;

1631

1632 if (lhsRecord == rhsRecord)

1633 return true;

1634

1635

1636

1637

1638

1640 diag::err_incomplete_type_used_in_type_trait_expr))

1641 return false;

1642

1645}

1646

1653

1655 "Cannot evaluate traits of dependent types");

1656

1657 switch (BTT) {

1658 case BTT_IsBaseOf:

1660

1661 case BTT_IsVirtualBaseOf: {

1662 const RecordType *BaseRecord = LhsT->getAsCanonical();

1663 const RecordType *DerivedRecord = RhsT->getAsCanonical();

1664

1665 if (!BaseRecord || !DerivedRecord) {

1667 tok::kw___builtin_is_virtual_base_of);

1669 tok::kw___builtin_is_virtual_base_of);

1670 return false;

1671 }

1672

1673 if (BaseRecord->isUnionType() || DerivedRecord->isUnionType())

1674 return false;

1675

1676 if (!BaseRecord->isStructureOrClassType() ||

1677 !DerivedRecord->isStructureOrClassType())

1678 return false;

1679

1681 diag::err_incomplete_type))

1682 return false;

1683

1686 }

1687 case BTT_IsSame:

1688 return Self.Context.hasSameType(LhsT, RhsT);

1689 case BTT_TypeCompatible: {

1690

1692 QualType Lhs = Self.getASTContext().getUnqualifiedArrayType(LhsT, LhsQuals);

1693 QualType Rhs = Self.getASTContext().getUnqualifiedArrayType(RhsT, RhsQuals);

1694 return Self.Context.typesAreCompatible(Lhs, Rhs);

1695 }

1696 case BTT_IsConvertible:

1697 case BTT_IsConvertibleTo:

1698 case BTT_IsNothrowConvertible: {

1701 llvm::BumpPtrAllocator OpaqueExprAllocator;

1703 OpaqueExprAllocator);

1704 if (Result.isInvalid())

1705 return false;

1706

1707 if (BTT != BTT_IsNothrowConvertible)

1708 return true;

1709

1710 return Self.canThrow(Result.get()) == CT_Cannot;

1711 }

1712

1713 case BTT_IsAssignable:

1714 case BTT_IsNothrowAssignable:

1715 case BTT_IsTriviallyAssignable: {

1716

1717

1718

1719

1720

1721

1722

1723

1724

1725

1726

1728 Self.RequireCompleteType(

1730 diag::err_incomplete_type_used_in_type_trait_expr))

1731 return false;

1733 Self.RequireCompleteType(

1735 diag::err_incomplete_type_used_in_type_trait_expr))

1736 return false;

1737

1738

1740 return false;

1741

1742

1743

1745 if (Ty->isObjectType() || Ty->isFunctionType())

1746 Ty = Self.Context.getRValueReferenceType(Ty);

1747 return {KeyLoc, Ty.getNonLValueExprType(Self.Context),

1749 };

1750

1751 auto Lhs = createDeclValExpr(LhsT);

1752 auto Rhs = createDeclValExpr(RhsT);

1753

1754

1755

1761 Self.BuildBinOp(nullptr, KeyLoc, BO_Assign, &Lhs, &Rhs);

1762 if (Result.isInvalid())

1763 return false;

1764

1765

1766 Self.CheckUnusedVolatileAssignment(Result.get());

1767

1769 return false;

1770

1771 if (BTT == BTT_IsAssignable)

1772 return true;

1773

1774 if (BTT == BTT_IsNothrowAssignable)

1775 return Self.canThrow(Result.get()) == CT_Cannot;

1776

1777 if (BTT == BTT_IsTriviallyAssignable) {

1778

1779

1781 return false;

1783 if (Context.containsAddressDiscriminatedPointerAuth(LhsT) ||

1784 Context.containsAddressDiscriminatedPointerAuth(RhsT))

1785 return false;

1786 return !Result.get()->hasNonTrivialCall(Self.Context);

1787 }

1788

1789 llvm_unreachable("unhandled type trait");

1790 return false;

1791 }

1792 case BTT_IsLayoutCompatible: {

1795 diag::err_incomplete_type);

1798 diag::err_incomplete_type);

1799

1802

1803 return Self.IsLayoutCompatible(LhsT, RhsT);

1804 }

1805 case BTT_IsPointerInterconvertibleBaseOf: {

1807 Self.getASTContext().hasSameUnqualifiedType(LhsT, RhsT)) {

1809 diag::err_incomplete_type);

1810 }

1811

1813 tok::kw___is_pointer_interconvertible_base_of);

1815 tok::kw___is_pointer_interconvertible_base_of);

1816

1817 return Self.IsPointerInterconvertibleBaseOf(Lhs, Rhs);

1818 }

1819 case BTT_IsDeducible: {

1822 return Self.DeduceTemplateArgumentsFromType(

1823 TSTToBeDeduced->getTemplateName().getAsTemplateDecl(), RhsT,

1825 }

1826 case BTT_IsScalarizedLayoutCompatible: {

1829 diag::err_incomplete_type))

1830 return true;

1833 diag::err_incomplete_type))

1834 return true;

1835

1837 Self, Lhs, tok::kw___builtin_hlsl_is_scalarized_layout_compatible);

1839 Self, Rhs, tok::kw___builtin_hlsl_is_scalarized_layout_compatible);

1840

1841 return Self.HLSL().IsScalarizedLayoutCompatible(LhsT, RhsT);

1842 }

1843 case BTT_LtSynthesizesFromSpaceship:

1844 case BTT_LeSynthesizesFromSpaceship:

1845 case BTT_GtSynthesizesFromSpaceship:

1846 case BTT_GeSynthesizesFromSpaceship: {

1851

1862

1863 auto OpKind = [&] {

1864 switch (BTT) {

1865 case BTT_LtSynthesizesFromSpaceship:

1866 return BinaryOperatorKind::BO_LT;

1867 case BTT_LeSynthesizesFromSpaceship:

1868 return BinaryOperatorKind::BO_LE;

1869 case BTT_GtSynthesizesFromSpaceship:

1870 return BinaryOperatorKind::BO_GT;

1871 case BTT_GeSynthesizesFromSpaceship:

1872 return BinaryOperatorKind::BO_GE;

1873 default:

1874 llvm_unreachable("Trying to Synthesize non-comparison operator?");

1875 }

1876 }();

1877

1879 Self.LookupBinOp(Self.TUScope, KeyLoc, OpKind, Functions);

1880

1882 Self.CreateOverloadedBinOp(KeyLoc, OpKind, Functions, &LHS, &RHS);

1884 return false;

1885

1887 }

1888 default:

1889 llvm_unreachable("not a BTT");

1890 }

1891 llvm_unreachable("Unknown type trait or not implemented");

1892}

1893

1899 if (!TSInfo)

1900 TSInfo = Context.getTrivialTypeSourceInfo(T);

1901

1903}

1904

1908 assert(T->isDependentType() && "Cannot evaluate traits of dependent type");

1909

1910 switch (ATT) {

1911 case ATT_ArrayRank:

1912 if (T->isArrayType()) {

1913 unsigned Dim = 0;

1914 while (const ArrayType *AT = Self.Context.getAsArrayType(T)) {

1916 T = AT->getElementType();

1917 }

1918 return Dim;

1919 }

1920 return 0;

1921

1922 case ATT_ArrayExtent: {

1923 llvm::APSInt Value;

1924 uint64_t Dim;

1925 if (Self.VerifyIntegerConstantExpression(

1926 DimExpr, &Value, diag::err_dimension_expr_not_constant_integer)

1927 .isInvalid())

1928 return 0;

1929 if (Value.isSigned() && Value.isNegative()) {

1930 Self.Diag(KeyLoc, diag::err_dimension_expr_not_constant_integer)

1932 return 0;

1933 }

1934 Dim = Value.getLimitedValue();

1935

1936 if (T->isArrayType()) {

1937 unsigned D = 0;

1938 bool Matched = false;

1939 while (const ArrayType *AT = Self.Context.getAsArrayType(T)) {

1940 if (Dim == D) {

1941 Matched = true;

1942 break;

1943 }

1944 ++D;

1945 T = AT->getElementType();

1946 }

1947

1948 if (Matched && T->isArrayType()) {

1950 Self.Context.getAsConstantArrayType(T))

1951 return CAT->getLimitedSize();

1952 }

1953 }

1954 return 0;

1955 }

1956 }

1957 llvm_unreachable("Unknown type trait or not implemented");

1958}

1959

1964

1965

1966

1967 uint64_t Value = 0;

1968 if (T->isDependentType())

1970

1971

1972

1973

1974

1975

1977 RParen, Context.getSizeType());

1978}

1979

1982

1983 if (!Queried)

1985

1987

1989}

1990

1992 switch (ET) {

1993 case ET_IsLValueExpr:

1995 case ET_IsRValueExpr:

1997 }

1998 llvm_unreachable("Expression trait not covered by switch");

1999}

2000

2004

2010 }

2011

2013

2016}

2017

2019 return llvm::StringSwitch<std::optional>(Name)

2020 .Case("is_trivially_relocatable",

2021 TypeTrait::UTT_IsCppTriviallyRelocatable)

2022 .Case("is_replaceable", TypeTrait::UTT_IsReplaceable)

2023 .Case("is_trivially_copyable", TypeTrait::UTT_IsTriviallyCopyable)

2024 .Case("is_assignable", TypeTrait::BTT_IsAssignable)

2025 .Case("is_empty", TypeTrait::UTT_IsEmpty)

2026 .Case("is_standard_layout", TypeTrait::UTT_IsStandardLayout)

2027 .Case("is_aggregate", TypeTrait::UTT_IsAggregate)

2028 .Case("is_constructible", TypeTrait::TT_IsConstructible)

2029 .Case("is_final", TypeTrait::UTT_IsFinal)

2030 .Case("is_abstract", TypeTrait::UTT_IsAbstract)

2031 .Default(std::nullopt);

2032}

2033

2035 std::optional<std::pair<TypeTrait, llvm::SmallVector<QualType, 1>>>;

2036

2037

2038

2039

2040

2043 std::optional Trait;

2044

2045

2046 if (const auto *TraitExpr = dyn_cast(E)) {

2047 Trait = TraitExpr->getTrait();

2048 for (const auto *Arg : TraitExpr->getArgs())

2049 Args.push_back(Arg->getType());

2050 return {{Trait.value(), std::move(Args)}};

2051 }

2052 const auto *Ref = dyn_cast(E);

2053 if (!Ref)

2054 return std::nullopt;

2055

2056

2057 if (const auto *VD =

2058 dyn_cast(Ref->getDecl())) {

2059 if (!VD->isInStdNamespace())

2060 return std::nullopt;

2061 StringRef Name = VD->getIdentifier()->getName();

2062 if (!Name.consume_back("_v"))

2063 return std::nullopt;

2065 if (!Trait)

2066 return std::nullopt;

2067 for (const auto &Arg : VD->getTemplateArgs().asArray()) {

2069 for (const auto &InnerArg : Arg.pack_elements())

2070 Args.push_back(InnerArg.getAsType());

2072 Args.push_back(Arg.getAsType());

2073 } else {

2074 llvm_unreachable("Unexpected kind");

2075 }

2076 }

2077 return {{Trait.value(), std::move(Args)}};

2078 }

2079

2080

2081 if (const auto *VD = dyn_cast(Ref->getDecl());

2082 Ref->hasQualifier() && VD && VD->getIdentifier()->isStr("value")) {

2085 return std::nullopt;

2086 const auto *Ts = Qualifier.getAsType()->getAs();

2087 if (!Ts)

2088 return std::nullopt;

2089 const TemplateDecl *D = Ts->getTemplateName().getAsTemplateDecl();

2091 return std::nullopt;

2093 if (!Trait)

2094 return std::nullopt;

2095 for (const auto &Arg : Ts->template_arguments())

2096 Args.push_back(Arg.getAsType());

2097 return {{Trait.value(), std::move(Args)}};

2098 }

2099 return std::nullopt;

2100}

2101

2106 if (Has)

2107 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2108 << diag::TraitNotSatisfiedReason::UnionWithUserDeclaredSMF << K;

2109 };

2118 return;

2119 }

2120

2122 const auto *Decl = cast_or_null(

2124 if (Decl && Decl->isUserProvided())

2125 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2126 << diag::TraitNotSatisfiedReason::UserProvidedCtr

2128 }

2132 if (Decl && Decl->isUserProvided())

2133 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2134 << diag::TraitNotSatisfiedReason::UserProvidedAssign

2136 }

2138 Dtr = Dtr->getCanonicalDecl();

2139 if (Dtr->isUserProvided() && !Dtr->isDefaulted())

2140 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2141 << diag::TraitNotSatisfiedReason::DeletedDtr << 1

2142 << Dtr->getSourceRange();

2143 }

2144}

2145

2150 assert(B.getType()->getAsCXXRecordDecl() && "invalid base?");

2151 if (B.isVirtual())

2152 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2153 << diag::TraitNotSatisfiedReason::VBase << B.getType()

2154 << B.getSourceRange();

2156 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2157 << diag::TraitNotSatisfiedReason::NTRBase << B.getType()

2158 << B.getSourceRange();

2159 }

2161 if (!Field->getType()->isReferenceType() &&

2163 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2164 << diag::TraitNotSatisfiedReason::NTRField << Field

2165 << Field->getType() << Field->getSourceRange();

2166 }

2168 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2169 << diag::TraitNotSatisfiedReason::DeletedDtr << 0

2171

2172 if (D->hasAttr())

2173 return;

2175}

2176

2180 SemaRef.Diag(Loc, diag::note_unsatisfied_trait)

2181 << T << diag::TraitName::TriviallyRelocatable;

2182 if (T->isVariablyModifiedType())

2183 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2184 << diag::TraitNotSatisfiedReason::VLA;

2185

2186 if (T->isReferenceType())

2187 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2188 << diag::TraitNotSatisfiedReason::Ref;

2189 T = T.getNonReferenceType();

2190

2191 if (T.hasNonTrivialObjCLifetime())

2192 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2193 << diag::TraitNotSatisfiedReason::HasArcLifetime;

2194

2197 return;

2198

2201

2202 SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D;

2203}

2204

2208 assert(B.getType()->getAsCXXRecordDecl() && "invalid base?");

2210 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2211 << diag::TraitNotSatisfiedReason::NonReplaceableBase << B.getType()

2212 << B.getSourceRange();

2213 }

2216 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2217 << diag::TraitNotSatisfiedReason::NonReplaceableField << Field

2218 << Field->getType() << Field->getSourceRange();

2219 }

2221 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2222 << diag::TraitNotSatisfiedReason::DeletedDtr << 0

2224

2228 if (Decl && Decl->isDeleted())

2229 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2230 << diag::TraitNotSatisfiedReason::DeletedCtr

2232 }

2236 if (Decl && Decl->isDeleted())

2237 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2238 << diag::TraitNotSatisfiedReason::DeletedAssign

2240 }

2241

2242 if (D->hasAttr())

2243 return;

2245}

2246

2249 SemaRef.Diag(Loc, diag::note_unsatisfied_trait)

2250 << T << diag::TraitName::Replaceable;

2251

2252 if (T->isVariablyModifiedType())

2253 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2254 << diag::TraitNotSatisfiedReason::VLA;

2255

2256 if (T->isReferenceType())

2257 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2258 << diag::TraitNotSatisfiedReason::Ref;

2259 T = T.getNonReferenceType();

2260

2261 if (T.isConstQualified())

2262 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2263 << diag::TraitNotSatisfiedReason::Const;

2264

2265 if (T.isVolatileQualified())

2266 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2267 << diag::TraitNotSatisfiedReason::Volatile;

2268

2269 bool IsArray = T->isArrayType();

2271

2272 if (T->isScalarType())

2273 return;

2274

2276 if (!D) {

2277 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2278 << diag::TraitNotSatisfiedReason::NotScalarOrClass << IsArray;

2279 return;

2280 }

2281

2283 return;

2284

2287

2288 SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D;

2289}

2290

2295 assert(B.getType()->getAsCXXRecordDecl() && "invalid base?");

2296 if (B.isVirtual())

2297 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2298 << diag::TraitNotSatisfiedReason::VBase << B.getType()

2299 << B.getSourceRange();

2300 if (!B.getType().isTriviallyCopyableType(D->getASTContext())) {

2301 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2302 << diag::TraitNotSatisfiedReason::NTCBase << B.getType()

2303 << B.getSourceRange();

2304 }

2305 }

2307 if (!Field->getType().isTriviallyCopyableType(Field->getASTContext()))

2308 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2309 << diag::TraitNotSatisfiedReason::NTCField << Field

2310 << Field->getType() << Field->getSourceRange();

2311 }

2314 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2315 << diag::TraitNotSatisfiedReason::DeletedDtr

2317

2319 if (Method->isTrivial() || !Method->isUserProvided()) {

2320 continue;

2321 }

2322 auto SpecialMemberKind =

2324 switch (SpecialMemberKind) {

2329 bool IsAssignment =

2332 bool IsMove =

2335

2336 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2337 << (IsAssignment ? diag::TraitNotSatisfiedReason::UserProvidedAssign

2338 : diag::TraitNotSatisfiedReason::UserProvidedCtr)

2339 << IsMove << Method->getSourceRange();

2340 break;

2341 }

2342 default:

2343 break;

2344 }

2345 }

2346}

2347

2351 if (Ts.empty()) {

2352 return;

2353 }

2354

2355 bool ContainsVoid = false;

2356 for (const QualType &ArgTy : Ts) {

2357 ContainsVoid |= ArgTy->isVoidType();

2358 }

2359

2360 if (ContainsVoid)

2361 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2362 << diag::TraitNotSatisfiedReason::CVVoidType;

2363

2365 if (T->isFunctionType())

2366 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2367 << diag::TraitNotSatisfiedReason::FunctionType;

2368

2369 if (T->isIncompleteArrayType())

2370 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2371 << diag::TraitNotSatisfiedReason::IncompleteArrayType;

2372

2375 return;

2376

2377 llvm::BumpPtrAllocator OpaqueExprAllocator;

2379 ArgExprs.reserve(Ts.size() - 1);

2380 for (unsigned I = 1, N = Ts.size(); I != N; ++I) {

2384 ArgExprs.push_back(

2388 }

2389

2397

2398 Init.Diagnose(SemaRef, To, InitKind, ArgExprs);

2399 SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D;

2400}

2401

2404 SemaRef.Diag(Loc, diag::note_unsatisfied_trait)

2405 << T << diag::TraitName::TriviallyCopyable;

2406

2407 if (T->isReferenceType())

2408 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2409 << diag::TraitNotSatisfiedReason::Ref;

2410

2413 return;

2414

2417

2418 SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D;

2419}

2420

2424

2426 if (Ty->isObjectType() || Ty->isFunctionType())

2428 return {Loc, Ty.getNonLValueExprType(SemaRef.Context),

2430 };

2431

2432 auto LHS = createDeclValExpr(T);

2433 auto RHS = createDeclValExpr(U);

2434

2439 SemaRef.BuildBinOp(nullptr, Loc, BO_Assign, &LHS, &RHS);

2440

2442 return;

2443

2444 SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D;

2445}

2446

2449

2450 for (const auto *Field : D->fields()) {

2451 if (Field->isZeroLengthBitField())

2452 continue;

2453 if (Field->isBitField()) {

2454 S.Diag(Loc, diag::note_unsatisfied_trait_reason)

2455 << diag::TraitNotSatisfiedReason::NonZeroLengthField << Field

2456 << Field->getSourceRange();

2457 continue;

2458 }

2459 S.Diag(Loc, diag::note_unsatisfied_trait_reason)

2460 << diag::TraitNotSatisfiedReason::NonEmptyMember << Field

2461 << Field->getType() << Field->getSourceRange();

2462 }

2463

2464

2465 for (const auto *M : D->methods()) {

2466 if (M->isVirtual()) {

2467 S.Diag(Loc, diag::note_unsatisfied_trait_reason)

2468 << diag::TraitNotSatisfiedReason::VirtualFunction << M

2469 << M->getSourceRange();

2470 break;

2471 }

2472 }

2473

2474

2475 for (const auto &B : D->bases()) {

2476 const auto *BR = B.getType()->getAsCXXRecordDecl();

2477 if (!BR || BR->isInvalidDecl())

2478 continue;

2479 if (B.isVirtual()) {

2480 S.Diag(Loc, diag::note_unsatisfied_trait_reason)

2481 << diag::TraitNotSatisfiedReason::VBase << B.getType()

2482 << B.getSourceRange();

2483 }

2484 if (!BR->isEmpty()) {

2485 S.Diag(Loc, diag::note_unsatisfied_trait_reason)

2486 << diag::TraitNotSatisfiedReason::NonEmptyBase << B.getType()

2487 << B.getSourceRange();

2488 }

2489 }

2490}

2491

2493

2494 S.Diag(Loc, diag::note_unsatisfied_trait) << T << diag::TraitName::Empty;

2495

2496

2497

2498

2499 if (T->isReferenceType())

2500 S.Diag(Loc, diag::note_unsatisfied_trait_reason)

2501 << diag::TraitNotSatisfiedReason::Ref;

2502 T = T.getNonReferenceType();

2503

2505 T = AT->getElementType();

2506

2507 if (auto *D = T->getAsCXXRecordDecl()) {

2508 if (D->hasDefinition()) {

2510 S.Diag(D->getLocation(), diag::note_defined_here) << D;

2511 }

2512 }

2513}

2514

2518 return;

2519

2520

2522 S.Diag(Loc, diag::note_unsatisfied_trait_reason)

2523 << diag::TraitNotSatisfiedReason::NotMarkedFinal;

2525 return;

2526 }

2527}

2528

2530

2531 S.Diag(Loc, diag::note_unsatisfied_trait) << T << diag::TraitName::Final;

2532 if (T->isReferenceType()) {

2533 S.Diag(Loc, diag::note_unsatisfied_trait_reason)

2534 << diag::TraitNotSatisfiedReason::Ref;

2535 S.Diag(Loc, diag::note_unsatisfied_trait_reason)

2536 << diag::TraitNotSatisfiedReason::NotClassOrUnion;

2537 return;

2538 }

2539

2541 S.Diag(Loc, diag::note_unsatisfied_trait_reason)

2542 << diag::TraitNotSatisfiedReason::NotClassOrUnion;

2543 return;

2544 }

2545 if (T->isFunctionType()) {

2546 S.Diag(Loc, diag::note_unsatisfied_trait_reason)

2547 << diag::TraitNotSatisfiedReason::FunctionType;

2548 S.Diag(Loc, diag::note_unsatisfied_trait_reason)

2549 << diag::TraitNotSatisfiedReason::NotClassOrUnion;

2550 return;

2551 }

2552 if (T->isRecordType()) {

2553 S.Diag(Loc, diag::note_unsatisfied_trait_reason)

2554 << diag::TraitNotSatisfiedReason::NotClassOrUnion;

2555 return;

2556 }

2557 if (const auto *D = T->getAsCXXRecordDecl())

2559}

2560

2562 int NumBasesWithFields = 0;

2564 const CXXRecordDecl *BaseRD = Base.getType()->getAsCXXRecordDecl();

2566 continue;

2567

2569 if (!Field->isUnnamedBitField()) {

2570 if (++NumBasesWithFields > 1)

2571 return true;

2572 break;

2573 }

2574 }

2575 }

2576 return false;

2577}

2578

2582 assert(B.getType()->getAsCXXRecordDecl() && "invalid base?");

2583 if (B.isVirtual()) {

2584 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2585 << diag::TraitNotSatisfiedReason::VBase << B.getType()

2586 << B.getSourceRange();

2587 }

2588 if (!B.getType()->isStandardLayoutType()) {

2589 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2590 << diag::TraitNotSatisfiedReason::NonStandardLayoutBase << B.getType()

2591 << B.getSourceRange();

2592 }

2593 }

2594

2595 const FieldDecl *FirstField = nullptr;

2597

2599 if (Field->isUnnamedBitField())

2600 continue;

2601

2602

2603 if (!FirstField) {

2604 FirstField = Field;

2605 FirstAccess = Field->getAccess();

2606 continue;

2607 }

2608

2609

2610 if (Field->getAccess() != FirstAccess) {

2611

2612 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2613 << diag::TraitNotSatisfiedReason::MixedAccess;

2614

2615 SemaRef.Diag(FirstField->getLocation(), diag::note_defined_here)

2616 << FirstField;

2617

2618 SemaRef.Diag(Field->getLocation(), diag::note_unsatisfied_trait_reason)

2619 << diag::TraitNotSatisfiedReason::MixedAccessField << Field

2620 << FirstField;

2621

2622

2623 break;

2624 }

2625 }

2627 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2628 << diag::TraitNotSatisfiedReason::MultipleDataBase;

2629 }

2631

2633

2634 for (const auto *M : D->methods()) {

2635 if (M->isVirtual()) {

2636 VirtualMD = M;

2637 break;

2638 }

2639 }

2640 if (VirtualMD) {

2641 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2642 << diag::TraitNotSatisfiedReason::VirtualFunction << VirtualMD;

2643 SemaRef.Diag(VirtualMD->getLocation(), diag::note_defined_here)

2644 << VirtualMD;

2645 } else {

2646

2647 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2648 << diag::TraitNotSatisfiedReason::VirtualFunction << D;

2649 SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D;

2650 }

2651 }

2653 if (!Field->getType()->isStandardLayoutType()) {

2654 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2655 << diag::TraitNotSatisfiedReason::NonStandardLayoutMember << Field

2656 << Field->getType() << Field->getSourceRange();

2657 }

2658 }

2659

2664 Indirect = BaseDef;

2665 return false;

2666 }

2667 return true;

2668 });

2669 if (Indirect) {

2670 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2671 << diag::TraitNotSatisfiedReason::IndirectBaseWithFields << Indirect

2673 }

2674 }

2675}

2676

2679 SemaRef.Diag(Loc, diag::note_unsatisfied_trait)

2680 << T << diag::TraitName::StandardLayout;

2681

2682

2683 if (T->isVariablyModifiedType()) {

2684 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2685 << diag::TraitNotSatisfiedReason::VLA;

2686 return;

2687 }

2688

2689 if (T->isReferenceType()) {

2690 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2691 << diag::TraitNotSatisfiedReason::Ref;

2692 return;

2693 }

2694 T = T.getNonReferenceType();

2697 return;

2698

2701

2702 SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D;

2703}

2704

2708 if (Ctor->isUserProvided())

2709 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2710 << diag::TraitNotSatisfiedReason::UserDeclaredCtr;

2711 if (Ctor->isInheritingConstructor())

2712 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2713 << diag::TraitNotSatisfiedReason::InheritedCtr;

2714 }

2715

2716 if (llvm::any_of(D->decls(), [](auto const *Sub) {

2717 return isa(Sub);

2718 })) {

2719 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2720 << diag::TraitNotSatisfiedReason::InheritedCtr;

2721 }

2722

2724 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2725 << diag::TraitNotSatisfiedReason::PolymorphicType

2727

2729 if (B.isVirtual()) {

2730 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2731 << diag::TraitNotSatisfiedReason::VBase << B.getType()

2732 << B.getSourceRange();

2733 continue;

2734 }

2739 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2740 << diag::TraitNotSatisfiedReason::PrivateProtectedDirectBase

2742 break;

2743 default:

2744 break;

2745 }

2746 }

2747

2749 if (Method->isVirtual()) {

2750 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2751 << diag::TraitNotSatisfiedReason::VirtualFunction << Method

2752 << Method->getSourceRange();

2753 }

2754 }

2755

2761 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2762 << diag::TraitNotSatisfiedReason::PrivateProtectedDirectDataMember

2764 break;

2765 default:

2766 break;

2767 }

2768 }

2769

2770 SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D;

2771}

2772

2775 SemaRef.Diag(Loc, diag::note_unsatisfied_trait)

2776 << T << diag::TraitName::Aggregate;

2777

2778 if (T->isVoidType())

2779 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2780 << diag::TraitNotSatisfiedReason::CVVoidType;

2781

2782 T = T.getNonReferenceType();

2785 return;

2786

2789}

2790

2793

2794

2796 if (B.getType()->castAsCXXRecordDecl()->isAbstract()) {

2797 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2798 << diag::TraitNotSatisfiedReason::OverridesAllPureVirtual

2799 << B.getType() << B.getSourceRange();

2800 }

2801 }

2802}

2803

2806 SemaRef.Diag(Loc, diag::note_unsatisfied_trait)

2807 << T << diag::TraitName::Abstract;

2808

2809 if (T->isReferenceType()) {

2810 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2811 << diag::TraitNotSatisfiedReason::Ref;

2812 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2813 << diag::TraitNotSatisfiedReason::NotStructOrClass;

2814 return;

2815 }

2816

2817 if (T->isUnionType()) {

2818 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2819 << diag::TraitNotSatisfiedReason::UnionType;

2820 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2821 << diag::TraitNotSatisfiedReason::NotStructOrClass;

2822 return;

2823 }

2824

2826 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2827 << diag::TraitNotSatisfiedReason::ArrayType;

2828 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2829 << diag::TraitNotSatisfiedReason::NotStructOrClass;

2830 return;

2831 }

2832

2833 if (T->isFunctionType()) {

2834 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2835 << diag::TraitNotSatisfiedReason::FunctionType;

2836 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2837 << diag::TraitNotSatisfiedReason::NotStructOrClass;

2838 return;

2839 }

2840

2841 if (T->isPointerType()) {

2842 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2843 << diag::TraitNotSatisfiedReason::PointerType;

2844 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2845 << diag::TraitNotSatisfiedReason::NotStructOrClass;

2846 return;

2847 }

2848

2849 if (T->isStructureOrClassType()) {

2850 SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)

2851 << diag::TraitNotSatisfiedReason::NotStructOrClass;

2852 return;

2853 }

2854

2858}

2859

2863 return;

2864

2866 if (!TraitInfo)

2867 return;

2868

2869 const auto &[Trait, Args] = TraitInfo.value();

2870 switch (Trait) {

2871 case UTT_IsCppTriviallyRelocatable:

2873 break;

2874 case UTT_IsReplaceable:

2876 break;

2877 case UTT_IsTriviallyCopyable:

2879 break;

2880 case BTT_IsAssignable:

2882 break;

2883 case UTT_IsEmpty:

2885 break;

2886 case UTT_IsStandardLayout:

2888 break;

2889 case TT_IsConstructible:

2891 break;

2892 case UTT_IsAggregate:

2894 break;

2895 case UTT_IsFinal: {

2898 break;

2902 break;

2903 }

2904 case UTT_IsAbstract:

2906 break;

2907 default:

2908 break;

2909 }

2910}

static CanQualType GetReturnType(QualType RetTy)

Returns the "extra-canonicalized" return type, which discards qualifiers on the return type.

Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....

Defines the Diagnostic IDs-related interfaces.

TokenType getType() const

Returns the token's type, e.g.

This file declares semantic analysis for HLSL constructs.

static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, const TypeSourceInfo *Lhs, const TypeSourceInfo *Rhs, SourceLocation KeyLoc)

Definition SemaTypeTraits.cpp:1647

static bool HasNonDeletedDefaultedEqualityComparison(Sema &S, const CXXRecordDecl *Decl, SourceLocation KeyLoc)

Definition SemaTypeTraits.cpp:594

static void DiagnoseNonAbstractReason(Sema &SemaRef, SourceLocation Loc, const CXXRecordDecl *D)

Definition SemaTypeTraits.cpp:2791

static APValue EvaluateSizeTTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc, ArrayRef< TypeSourceInfo * > Args, SourceLocation RParenLoc, bool IsDependent)

Definition SemaTypeTraits.cpp:1285

static bool DiagnoseVLAInCXXTypeTrait(Sema &S, const TypeSourceInfo *T, clang::tok::TokenKind TypeTraitID)

Checks that type T is not a VLA.

Definition SemaTypeTraits.cpp:381

static bool HasNoThrowOperator(CXXRecordDecl *RD, OverloadedOperatorKind Op, Sema &Self, SourceLocation KeyLoc, ASTContext &C, bool(CXXRecordDecl::*HasTrivial)() const, bool(CXXRecordDecl::*HasNonTrivial)() const, bool(CXXMethodDecl::*IsDesiredOp)() const)

Definition SemaTypeTraits.cpp:561

static std::optional< TypeTrait > StdNameToTypeTrait(StringRef Name)

Definition SemaTypeTraits.cpp:2018

static void DiagnoseNonConstructibleReason(Sema &SemaRef, SourceLocation Loc, const llvm::SmallVector< clang::QualType, 1 > &Ts)

Definition SemaTypeTraits.cpp:2348

static bool IsEligibleForTrivialRelocation(Sema &SemaRef, const CXXRecordDecl *D)

Definition SemaTypeTraits.cpp:180

static CXXMethodDecl * LookupSpecialMemberFromXValue(Sema &SemaRef, const CXXRecordDecl *RD, bool Assign)

Definition SemaTypeTraits.cpp:31

static bool hasSuitableMoveAssignmentOperatorForRelocation(Sema &SemaRef, const CXXRecordDecl *D, bool AllowUserDefined)

Definition SemaTypeTraits.cpp:131

static bool DiagnoseAtomicInCXXTypeTrait(Sema &S, const TypeSourceInfo *T, clang::tok::TokenKind TypeTraitID)

Checks that type T is not an atomic type (_Atomic).

Definition SemaTypeTraits.cpp:395

static void DiagnoseNonStandardLayoutReason(Sema &SemaRef, SourceLocation Loc, const CXXRecordDecl *D)

Definition SemaTypeTraits.cpp:2579

static void DiagnoseIsFinalReason(Sema &S, SourceLocation Loc, const CXXRecordDecl *D)

Definition SemaTypeTraits.cpp:2515

static void DiagnoseIsEmptyReason(Sema &S, SourceLocation Loc, const CXXRecordDecl *D)

Definition SemaTypeTraits.cpp:2447

static bool hasMultipleDataBaseClassesWithFields(const CXXRecordDecl *D)

Definition SemaTypeTraits.cpp:2561

static bool IsEligibleForReplacement(Sema &SemaRef, const CXXRecordDecl *D)

Definition SemaTypeTraits.cpp:216

static bool EvaluateExpressionTrait(ExpressionTrait ET, Expr *E)

Definition SemaTypeTraits.cpp:1991

static ExtractedTypeTraitInfo ExtractTypeTraitFromExpression(const Expr *E)

Definition SemaTypeTraits.cpp:2041

std::optional< std::pair< TypeTrait, llvm::SmallVector< QualType, 1 > > > ExtractedTypeTraitInfo

Definition SemaTypeTraits.cpp:2034

static void DiagnoseNonTriviallyRelocatableReason(Sema &SemaRef, SourceLocation Loc, const CXXRecordDecl *D)

Definition SemaTypeTraits.cpp:2146

static void DiagnoseNonAssignableReason(Sema &SemaRef, SourceLocation Loc, QualType T, QualType U)

Definition SemaTypeTraits.cpp:2421

static bool IsTriviallyRelocatableType(Sema &SemaRef, QualType T)

Definition SemaTypeTraits.cpp:670

static void DiagnoseNonDefaultMovable(Sema &SemaRef, SourceLocation Loc, const CXXRecordDecl *D)

Definition SemaTypeTraits.cpp:2102

static bool IsDefaultMovable(Sema &SemaRef, const CXXRecordDecl *D)

Definition SemaTypeTraits.cpp:156

static bool hasSuitableConstructorForRelocation(Sema &SemaRef, const CXXRecordDecl *D, bool AllowUserDefined)

Definition SemaTypeTraits.cpp:117

static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, SourceLocation Loc, const CXXRecordDecl *D)

Definition SemaTypeTraits.cpp:2291

static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, SourceLocation KeyLoc, TypeSourceInfo *TInfo)

Definition SemaTypeTraits.cpp:704

static uint64_t EvaluateArrayTypeTrait(Sema &Self, ArrayTypeTrait ATT, QualType T, Expr *DimExpr, SourceLocation KeyLoc)

Definition SemaTypeTraits.cpp:1905

static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT, SourceLocation Loc, QualType ArgTy)

Check the completeness of a type in a unary type trait.

Definition SemaTypeTraits.cpp:411

static ExprResult CheckConvertibilityForTypeTraits(Sema &Self, const TypeSourceInfo *Lhs, const TypeSourceInfo *Rhs, SourceLocation KeyLoc, llvm::BumpPtrAllocator &OpaqueExprAllocator)

Definition SemaTypeTraits.cpp:1215

TypeTraitReturnType

Definition SemaTypeTraits.cpp:1529

@ SizeT

Definition SemaTypeTraits.cpp:1531

@ Bool

Definition SemaTypeTraits.cpp:1530

static void DiagnoseNonReplaceableReason(Sema &SemaRef, SourceLocation Loc, const CXXRecordDecl *D)

Definition SemaTypeTraits.cpp:2205

static void DiagnoseNonAggregateReason(Sema &SemaRef, SourceLocation Loc, const CXXRecordDecl *D)

Definition SemaTypeTraits.cpp:2705

static bool EvaluateBooleanTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc, ArrayRef< TypeSourceInfo * > Args, SourceLocation RParenLoc, bool IsDependent)

Definition SemaTypeTraits.cpp:1312

static bool IsCXXReplaceableType(Sema &S, const CXXRecordDecl *RD)

Definition SemaTypeTraits.cpp:349

static bool isTriviallyEqualityComparableType(Sema &S, QualType Type, SourceLocation KeyLoc)

Definition SemaTypeTraits.cpp:654

Defines various enumerations that describe declaration and type specifiers.

Defines enumerations for the type traits support.

C Language Family Type Representation.

APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...

Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...

TranslationUnitDecl * getTranslationUnitDecl() const

QualType getRValueReferenceType(QualType T) const

Return the uniqued reference to the type for an rvalue reference to the specified type.

DeclarationNameTable DeclarationNames

void setRelocationInfoForCXXRecord(const CXXRecordDecl *, CXXRecordDeclRelocationInfo)

QualType getPointerType(QualType T) const

Return the uniqued reference to the type for a pointer to the specified type.

bool containsAddressDiscriminatedPointerAuth(QualType T) const

Examines a given type, and returns whether the type itself is address discriminated,...

bool hasUniqueObjectRepresentations(QualType Ty, bool CheckIfTriviallyCopyable=true) const

Return true if the specified type has unique object representations according to (C++17 [meta....

QualType getBaseElementType(const ArrayType *VAT) const

Return the innermost element type of an array type.

const ArrayType * getAsArrayType(QualType T) const

Type Query functions.

TypeSourceInfo * CreateTypeSourceInfo(QualType T, unsigned Size=0) const

Allocate an uninitialized TypeSourceInfo.

llvm::APSInt MakeIntValue(uint64_t Value, QualType Type) const

Make an APSInt of the appropriate width and signedness for the given Value and integer Type.

QualType getSizeType() const

Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.

CanQualType getCanonicalTagType(const TagDecl *TD) const

std::optional< CXXRecordDeclRelocationInfo > getRelocationInfoForCXXRecord(const CXXRecordDecl *) const

static bool hasSameUnqualifiedType(QualType T1, QualType T2)

Determine whether the given types are equivalent after cvr-qualifiers have been removed.

An Embarcadero array type trait, as used in the implementation of __array_rank and __array_extent.

Represents an array type, per C99 6.7.5.2 - Array Declarators.

Represents a base class of a C++ class.

Represents a C++ constructor within a class.

Represents a C++ destructor within a class.

CXXDestructorDecl * getCanonicalDecl() override

Retrieves the "canonical" declaration of the given declaration.

Represents a static or instance method of a struct/union/class.

bool isMoveAssignmentOperator() const

Determine whether this is a move assignment operator.

bool isCopyAssignmentOperator() const

Determine whether this is a copy-assignment operator, regardless of whether it was declared implicitl...

Represents a C++ struct/union/class.

bool hasTrivialMoveAssignment() const

Determine whether this class has a trivial move assignment operator (C++11 [class....

bool hasNonTrivialCopyAssignment() const

Determine whether this class has a non-trivial copy assignment operator (C++ [class....

bool isEffectivelyFinal() const

Determine whether it's impossible for a class to be derived from this class.

bool hasSimpleMoveConstructor() const

true if we know for sure that this class has a single, accessible, unambiguous move constructor that ...

bool hasTrivialDefaultConstructor() const

Determine whether this class has a trivial default constructor (C++11 [class.ctor]p5).

bool hasTrivialDestructor() const

Determine whether this class has a trivial destructor (C++ [class.dtor]p3)

bool hasUserDeclaredDestructor() const

Determine whether this class has a user-declared destructor.

bool defaultedMoveConstructorIsDeleted() const

true if a defaulted move constructor for this class would be deleted.

bool hasUserDeclaredMoveAssignment() const

Determine whether this class has had a move assignment declared by the user.

bool hasDeletedDestructor() const

Returns the destructor decl for this class.

bool hasTrivialMoveConstructor() const

Determine whether this class has a trivial move constructor (C++11 [class.copy]p12)

bool needsImplicitDefaultConstructor() const

Determine if we need to declare a default constructor for this class.

bool needsImplicitMoveConstructor() const

Determine whether this class should get an implicit move constructor or if any existing special membe...

bool hasUserDeclaredCopyAssignment() const

Determine whether this class has a user-declared copy assignment operator.

method_range methods() const

CXXRecordDecl * getDefinition() const

bool hasTrivialCopyConstructor() const

Determine whether this class has a trivial copy constructor (C++ [class.copy]p6, C++11 [class....

bool isPolymorphic() const

Whether this class is polymorphic (C++ [class.virtual]), which means that the class contains or inher...

bool defaultedCopyConstructorIsDeleted() const

true if a defaulted copy constructor for this class would be deleted.

bool hasTrivialCopyAssignment() const

Determine whether this class has a trivial copy assignment operator (C++ [class.copy]p11,...

bool isAbstract() const

Determine whether this class has a pure virtual function.

bool needsImplicitCopyConstructor() const

Determine whether this class needs an implicit copy constructor to be lazily declared.

bool hasSimpleMoveAssignment() const

true if we know for sure that this class has a single, accessible, unambiguous move assignment operat...

bool hasNonTrivialMoveConstructor() const

Determine whether this class has a non-trivial move constructor (C++11 [class.copy]p12)

bool hasDirectFields() const

Determine whether this class has direct non-static data members.

bool hasUserDeclaredCopyConstructor() const

Determine whether this class has a user-declared copy constructor.

bool hasDefinition() const

bool hasSimpleCopyConstructor() const

true if we know for sure that this class has a single, accessible, unambiguous copy constructor that ...

bool isEmpty() const

Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).

CXXDestructorDecl * getDestructor() const

Returns the destructor decl for this class.

bool hasNonTrivialMoveAssignment() const

Determine whether this class has a non-trivial move assignment operator (C++11 [class....

bool hasUserDeclaredMoveOperation() const

Whether this class has a user-declared move constructor or assignment operator.

bool hasNonTrivialDefaultConstructor() const

Determine whether this class has a non-trivial default constructor (C++11 [class.ctor]p5).

bool hasUserDeclaredMoveConstructor() const

Determine whether this class has had a move constructor declared by the user.

bool forallBases(ForallBasesCallback BaseMatches) const

Determines if the given callback holds for all the direct or indirect base classes of this type.

bool hasNonTrivialCopyConstructor() const

Determine whether this class has a non-trivial copy constructor (C++ [class.copy]p6,...

bool hasSimpleCopyAssignment() const

true if we know for sure that this class has a single, accessible, unambiguous copy assignment operat...

CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).

FunctionDecl * getDirectCallee()

If the callee is a FunctionDecl, return it. Otherwise return null.

Represents the canonical version of C arrays with a specified constant size.

A POD class for pairing a NamedDecl* with an access specifier.

static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS)

DeclContextLookupResult lookup_result

lookup_result lookup(DeclarationName Name) const

lookup - Find the declarations (if any) with the given Name in this context.

decl_range decls() const

decls_begin/decls_end - Iterate over the declarations stored in this context.

Decl - This represents one declaration (or definition), e.g.

bool isInStdNamespace() const

ASTContext & getASTContext() const LLVM_READONLY

bool isInvalidDecl() const

SourceLocation getLocation() const

AccessSpecifier getAccess() const

virtual SourceRange getSourceRange() const LLVM_READONLY

Source range that this declaration covers.

The name of a declaration.

RAII object that enters a new expression evaluation context.

The return type of classify().

This represents one expression.

bool isTypeDependent() const

Determines whether the type of this expression depends on.

Expr * IgnoreParenImpCasts() LLVM_READONLY

Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...

bool containsErrors() const

Whether this expression contains subexpressions which had errors.

bool isLValue() const

isLValue - True if this expression is an "l-value" according to the rules of the current language.

Classification Classify(ASTContext &Ctx) const

Classify - Classify this expression according to the C++11 expression taxonomy.

bool hasPlaceholderType() const

Returns whether this expression has a placeholder type.

static ExprValueKind getValueKindForType(QualType T)

getValueKindForType - Given a formal return or parameter type, give its value kind.

An expression trait intrinsic.

Represents a member of a struct/union/class.

bool isTrivial() const

Whether this function is "trivial" in some specialized C++ senses.

bool isDeleted() const

Whether this function has been deleted.

bool isDefaulted() const

Whether this function is defaulted.

SourceRange getSourceRange() const override LLVM_READONLY

Source range that this declaration covers.

bool isUserProvided() const

True if this method is user-declared and was not deleted or defaulted on its first declaration.

Represents a prototype with parameter type info, e.g.

unsigned getNumParams() const

bool isNothrow(bool ResultIfDependent=false) const

Determine whether this function type has a non-throwing exception specification.

Declaration of a template function.

StringRef getName() const

Return the actual identifier string.

Describes the kind of initialization being performed, along with location information for tokens rela...

static InitializationKind CreateDirect(SourceLocation InitLoc, SourceLocation LParenLoc, SourceLocation RParenLoc)

Create a direct initialization.

static InitializationKind CreateCopy(SourceLocation InitLoc, SourceLocation EqualLoc, bool AllowExplicitConvs=false)

Create a copy initialization.

Describes the sequence of initializations required to initialize a given object or reference with a s...

Describes an entity that is being initialized.

static InitializedEntity InitializeTemporary(QualType Type)

Create the initialization entity for a temporary.

Represents the results of name lookup.

UnresolvedSetImpl::iterator iterator

void suppressDiagnostics()

Suppress the diagnostics that would normally fire because of this lookup.

This represents a decl that may have a name.

NamedDecl * getUnderlyingDecl()

Looks through UsingDecls and ObjCCompatibleAliasDecls for the underlying named decl.

IdentifierInfo * getIdentifier() const

Get the identifier that names this declaration, if there is one.

Represents a C++ nested name specifier, such as "\::std::vector::".

@ Type

A type, stored as a Type*.

Represents an ObjC class declaration.

bool isSuperClassOf(const ObjCInterfaceDecl *I) const

isSuperClassOf - Return true if this class is the specified class or is a super class of the specifie...

OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.

OverloadCandidateSet - A set of overload candidates, used in C++ overload resolution (C++ 13....

@ CSK_Normal

Normal lookup.

SmallVectorImpl< OverloadCandidate >::iterator iterator

OverloadingResult BestViableFunction(Sema &S, SourceLocation Loc, OverloadCandidateSet::iterator &Best)

Find the best viable function on this overload set, if it exists.

A (possibly-)qualified type.

bool isTriviallyCopyableType(const ASTContext &Context) const

Return true if this is a trivially copyable type (C++0x [basic.types]p9)

QualType getNonLValueExprType(const ASTContext &Context) const

Determine the type of a (typically non-lvalue) expression with the specified result type.

QualType getNonReferenceType() const

If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...

bool hasNonTrivialObjCLifetime() const

@ PCK_Trivial

The type does not fall into any of the following categories.

@ PCK_ARCStrong

The type is an Objective-C retainable pointer type that is qualified with the ARC __strong qualifier.

The collection of all-type qualifiers we support.

@ OCL_Strong

Assigning into this object requires the old value to be released and the new value to be retained.

@ OCL_ExplicitNone

This object can be modified without requiring retains or releases.

@ OCL_None

There is no lifetime qualification on this type.

@ OCL_Weak

Reading or writing from this object requires a barrier call.

@ OCL_Autoreleasing

Assigning into this object requires a lifetime extension.

bool canPassInRegisters() const

Determine whether this class can be passed in registers.

field_range fields() const

SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)

Emit a diagnostic.

CXXSpecialMemberKind asSpecialMember() const

RAII class used to determine whether SFINAE has trapped any errors that occur during template argumen...

bool hasErrorOccurred() const

Determine whether any SFINAE errors have been trapped.

Sema - This implements semantic analysis and AST building for C.

DefaultedFunctionKind getDefaultedFunctionKind(const FunctionDecl *FD)

Determine the kind of defaulting that would be done for a given function.

@ LookupOrdinaryName

Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....

ExprResult ActOnExpressionTrait(ExpressionTrait OET, SourceLocation KWLoc, Expr *Queried, SourceLocation RParen)

ActOnExpressionTrait - Parsed one of the unary type trait support pseudo-functions.

Definition SemaTypeTraits.cpp:1980

bool IsCXXTriviallyRelocatableType(QualType T)

Determines if a type is trivially relocatable according to the C++26 rules.

Definition SemaTypeTraits.cpp:325

bool BuiltinIsBaseOf(SourceLocation RhsTLoc, QualType LhsT, QualType RhsT)

Definition SemaTypeTraits.cpp:1595

void DiagnoseTypeTraitDetails(const Expr *E)

If E represents a built-in type trait, or a known standard type trait, try to print more information ...

Definition SemaTypeTraits.cpp:2860

ASTContext & getASTContext() const

ASTContext::CXXRecordDeclRelocationInfo CheckCXX2CRelocatableAndReplaceable(const clang::CXXRecordDecl *D)

Definition SemaTypeTraits.cpp:240

void LookupBinOp(Scope *S, SourceLocation OpLoc, BinaryOperatorKind Opc, UnresolvedSetImpl &Functions)

ExprResult CreateOverloadedBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc, const UnresolvedSetImpl &Fns, Expr *LHS, Expr *RHS, bool RequiresADL=true, bool AllowRewrittenCandidates=true, FunctionDecl *DefaultedFn=nullptr)

Create a binary operation that may resolve to an overloaded operator.

bool CheckTypeTraitArity(unsigned Arity, SourceLocation Loc, size_t N)

Definition SemaTypeTraits.cpp:1514

ExprResult ActOnArrayTypeTrait(ArrayTypeTrait ATT, SourceLocation KWLoc, ParsedType LhsTy, Expr *DimExpr, SourceLocation RParen)

ActOnArrayTypeTrait - Parsed one of the binary type trait support pseudo-functions.

Definition SemaTypeTraits.cpp:1894

void AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ObjectType, Expr::Classification ObjectClassification, ArrayRef< Expr * > Args, OverloadCandidateSet &CandidateSet, bool SuppressUserConversions=false, bool PartialOverloading=false, OverloadCandidateParamOrder PO={})

Add a C++ member function template as a candidate to the candidate set, using template argument deduc...

void AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef< Expr * > Args, OverloadCandidateSet &CandidateSet, bool SuppressUserConversions=false, bool PartialOverloading=false, bool AllowExplicit=true, ADLCallKind IsADLCandidate=ADLCallKind::NotADL, OverloadCandidateParamOrder PO={}, bool AggregateCandidateDeduction=false)

Add a C++ function template specialization as a candidate in the candidate set, using template argume...

const LangOptions & getLangOpts() const

void AddOverloadCandidate(FunctionDecl *Function, DeclAccessPair FoundDecl, ArrayRef< Expr * > Args, OverloadCandidateSet &CandidateSet, bool SuppressUserConversions=false, bool PartialOverloading=false, bool AllowExplicit=true, bool AllowExplicitConversion=false, ADLCallKind IsADLCandidate=ADLCallKind::NotADL, ConversionSequenceList EarlyConversions={}, OverloadCandidateParamOrder PO={}, bool AggregateCandidateDeduction=false, bool StrictPackMatch=false)

AddOverloadCandidate - Adds the given function to the set of candidate functions, using the given fun...

ExprResult BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc, ArrayRef< TypeSourceInfo * > Args, SourceLocation RParenLoc)

Definition SemaTypeTraits.cpp:1540

ExprResult BuildExpressionTrait(ExpressionTrait OET, SourceLocation KWLoc, Expr *Queried, SourceLocation RParen)

Definition SemaTypeTraits.cpp:2001

bool IsCXXReplaceableType(QualType T)

Determines if a type is replaceable according to the C++26 rules.

Definition SemaTypeTraits.cpp:359

ExprResult CheckPlaceholderExpr(Expr *E)

Check for operands with placeholder types and complain if found.

void AddMethodCandidate(DeclAccessPair FoundDecl, QualType ObjectType, Expr::Classification ObjectClassification, ArrayRef< Expr * > Args, OverloadCandidateSet &CandidateSet, bool SuppressUserConversion=false, OverloadCandidateParamOrder PO={})

AddMethodCandidate - Adds a named decl (which is some kind of method) as a method candidate to the gi...

CanThrowResult canThrow(const Stmt *E)

@ Unevaluated

The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7),...

bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)

Ensure that the type T is a complete type.

Scope * TUScope

Translation Unit Scope - useful to Objective-C actions that need to lookup file scope declarations in...

ExprResult BuildBinOp(Scope *S, SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr, bool ForFoldExpression=false)

ExprResult ActOnTypeTrait(TypeTrait Kind, SourceLocation KWLoc, ArrayRef< ParsedType > Args, SourceLocation RParenLoc)

Parsed one of the type trait support pseudo-functions.

Definition SemaTypeTraits.cpp:1577

ExprResult BuildArrayTypeTrait(ArrayTypeTrait ATT, SourceLocation KWLoc, TypeSourceInfo *TSInfo, Expr *DimExpr, SourceLocation RParen)

Definition SemaTypeTraits.cpp:1960

UnsignedOrNone GetDecompositionElementCount(QualType DecompType, SourceLocation Loc)

static QualType GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo=nullptr)

Encodes a location in the source.

A trivial tuple used to represent a source range.

SourceLocation getBegin() const

SourceRange getSourceRange() const LLVM_READONLY

SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...

SourceLocation getBeginLoc() const LLVM_READONLY

SourceRange getSourceRange() const override LLVM_READONLY

Source range that this declaration covers.

bool isDependentType() const

Whether this declaration declares a type that is dependent, i.e., a type that somehow depends on temp...

@ Pack

The template argument is actually a parameter pack.

@ Type

The template argument is a type.

The base class of all kinds of template declarations (e.g., class, function, etc.).

SourceLocation getBeginLoc() const

Get the begin source location.

A container of type source information.

TypeLoc getTypeLoc() const

Return the TypeLoc wrapper for the type source info.

QualType getType() const

Return the type wrapped by this type source info.

static TypeTraitExpr * Create(const ASTContext &C, QualType T, SourceLocation Loc, TypeTrait Kind, ArrayRef< TypeSourceInfo * > Args, SourceLocation RParenLoc, bool Value)

Create a new type trait expression.

The base class of the type hierarchy.

bool isIncompleteArrayType() const

bool isRValueReferenceType() const

CXXRecordDecl * getAsCXXRecordDecl() const

Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...

RecordDecl * getAsRecordDecl() const

Retrieves the RecordDecl this type refers to.

const T * castAs() const

Member-template castAs.

bool isEnumeralType() const

bool isScalarType() const

bool isVariableArrayType() const

bool isLValueReferenceType() const

bool isDependentType() const

Whether this type is a dependent type, meaning that its definition somehow depends on a template para...

bool isAggregateType() const

Determines whether the type is a C++ aggregate type or C aggregate or union type.

const Type * getBaseElementTypeUnsafe() const

Get the base element type of this type, potentially discarding type qualifiers.

bool isObjectType() const

Determine whether this type is an object type.

bool isIncompleteType(NamedDecl **Def=nullptr) const

Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...

bool isFunctionType() const

bool isStructureOrClassType() const

bool isVectorType() const

const T * getAsCanonical() const

If this type is canonically the specified type, return its canonical type cast to that specified type...

const T * getAs() const

Member-template getAs'.

A set of unresolved declarations.

Provides information about an attempted template argument deduction, whose success or failure was des...

TokenKind

Provides a simple uniform namespace for tokens from all C languages.

The JSON file list parser is used to communicate input to InstallAPI.

CanQual< Type > CanQualType

Represents a canonical, potentially-qualified type.

OverloadedOperatorKind

Enumeration specifying the different kinds of C++ overloaded operators.

bool isa(CodeGen::Address addr)

ArrayTypeTrait

Names for the array type traits.

unsigned getTypeTraitArity(TypeTrait T) LLVM_READONLY

Return the arity of the type trait T.

@ OR_Deleted

Succeeded, but refers to a deleted function.

@ OR_Success

Overload resolution succeeded.

@ Self

'self' clause, allowed on Compute and Combined Constructs, plus 'update'.

AccessSpecifier

A C++ access specifier (public, private, protected), plus the special value "none" which means differ...

@ Dependent

Parse the block as a dependent block, which may be used in some template instantiations but not other...

@ Result

The result type of a method or function.

const FunctionProtoType * T

CXXSpecialMemberKind

Kinds of C++ special members.

ExprValueKind

The categorization of expression values, currently following the C++11 scheme.

@ VK_PRValue

A pr-value expression (in the C++11 taxonomy) produces a temporary value.

@ VK_XValue

An x-value expression is a reference to an object with independent storage but which can be "moved",...

@ VK_LValue

An l-value expression is a reference to an object with independent storage.

const char * getTraitSpelling(ExpressionTrait T) LLVM_READONLY

Return the spelling of the type trait TT. Never null.

@ Success

Template argument deduction was successful.

U cast(CodeGen::Address addr)

ConstructorInfo getConstructorInfo(NamedDecl *ND)

OpaquePtr< QualType > ParsedType

An opaque type for threading parsed type information through the parser.

ActionResult< Expr * > ExprResult

TypeTrait

Names for traits that operate specifically on types.

DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...