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

217

219 return Info;

220

222

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

224 if (!Is.has_value())

229 return *Is;

230 };

231

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

233 if (!Is.has_value())

235 return *Is;

236 };

237

240 return false;

241

242

244 return false;

245

246

247 if (D->hasAttr())

248 return true;

249

250

251 if (IsUnion())

252 return true;

253

254

256 }();

257

258 return Info;

259}

260

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

263 getASTContext().getRelocationInfoForCXXRecord(&RD))

264 return Info->IsRelocatable;

268}

269

272

274 return false;

275

277 return false;

278

280 return false;

281

282 if (Context.containsNonRelocatablePointerAuth(Type))

283 return false;

284

286 return true;

287

290

291 return false;

292}

293

294

295

296

297

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

301 return false;

302

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

304 << 1 << TypeTraitID;

305 return true;

306}

307

308

309

310

311

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

315 return false;

316

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

318 << TypeTraitID;

319 return true;

320}

321

322

323

324

325

326

327

331

332

333

334

335

336

337

338

339

340 switch (UTT) {

341 default:

342 llvm_unreachable("not a UTT");

343

344 case UTT_IsCompleteType:

345

346

347

348

349

350

351 case UTT_IsVoid:

352 case UTT_IsIntegral:

353 case UTT_IsFloatingPoint:

354 case UTT_IsArray:

355 case UTT_IsBoundedArray:

356 case UTT_IsPointer:

357 case UTT_IsLvalueReference:

358 case UTT_IsRvalueReference:

359 case UTT_IsMemberFunctionPointer:

360 case UTT_IsMemberObjectPointer:

361 case UTT_IsEnum:

362 case UTT_IsScopedEnum:

363 case UTT_IsUnion:

364 case UTT_IsClass:

365 case UTT_IsFunction:

366 case UTT_IsReference:

367 case UTT_IsArithmetic:

368 case UTT_IsFundamental:

369 case UTT_IsObject:

370 case UTT_IsScalar:

371 case UTT_IsCompound:

372 case UTT_IsMemberPointer:

373 case UTT_IsTypedResourceElementCompatible:

374

375

376

377

378

379

380

381 case UTT_IsConst:

382 case UTT_IsVolatile:

383 case UTT_IsSigned:

384 case UTT_IsUnboundedArray:

385 case UTT_IsUnsigned:

386

387

388 case UTT_IsInterfaceClass:

389 return true;

390

391

392 case UTT_StructuredBindingSize:

393 return true;

394

395

396

397 case UTT_IsEmpty:

398 case UTT_IsPolymorphic:

399 case UTT_IsAbstract:

401 if (!RD->isUnion())

403 Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);

404 return true;

405

406

407

408 case UTT_IsFinal:

409 case UTT_IsSealed:

412 Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);

413 return true;

414

415

416 case UTT_IsAggregate:

417 case UTT_IsImplicitLifetime:

419 return true;

420

422 Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);

423

424

425

426 case UTT_HasUniqueObjectRepresentations:

429 return true;

431 Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);

432

433

434

435 case UTT_IsTrivial:

436 case UTT_IsTriviallyCopyable:

437 case UTT_IsStandardLayout:

438 case UTT_IsPOD:

439 case UTT_IsLiteral:

440 case UTT_IsBitwiseCloneable:

441

442

443 case UTT_IsTriviallyRelocatable:

444 case UTT_IsTriviallyEqualityComparable:

445 case UTT_IsCppTriviallyRelocatable:

446 case UTT_CanPassInRegs:

447

448

449

450 case UTT_HasNothrowAssign:

451 case UTT_HasNothrowMoveAssign:

452 case UTT_HasNothrowConstructor:

453 case UTT_HasNothrowCopy:

454 case UTT_HasTrivialAssign:

455 case UTT_HasTrivialMoveAssign:

456 case UTT_HasTrivialDefaultConstructor:

457 case UTT_HasTrivialMoveConstructor:

458 case UTT_HasTrivialCopy:

459 case UTT_HasTrivialDestructor:

460 case UTT_HasVirtualDestructor:

462 [[fallthrough]];

463

464

465 case UTT_IsDestructible:

466 case UTT_IsNothrowDestructible:

467 case UTT_IsTriviallyDestructible:

468 case UTT_IsIntangibleType:

470 return true;

471

473 Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);

474 }

475}

476

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

483 return true;

484

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

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

489 bool FoundOperator = false;

492 Op != OpEnd; ++Op) {

494 continue;

495

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

498 FoundOperator = true;

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

502 return false;

503 }

504 }

505 return FoundOperator;

506 }

507 return false;

508}

509

513 if (Decl->isUnion())

514 return false;

515 if (Decl->isLambda())

516 return Decl->isCapturelessLambda();

517

519 {

524

525

528

530

532 Functions, &Operand, &Operand);

534 return false;

535

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

538 return false;

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

541 if (!Callee->isDefaulted())

542 return false;

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

544 return false;

546 return false;

547 }

548

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

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

552 return HasNonDeletedDefaultedEqualityComparison(

553 S, RD, KeyLoc);

554 return true;

555 }) &&

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

557 auto Type = FD->getType();

558 if (Type->isArrayType())

559 Type = Type->getBaseElementTypeUnsafe()

560 ->getCanonicalTypeUnqualified();

561

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

563 return false;

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

565 return HasNonDeletedDefaultedEqualityComparison(S, RD, KeyLoc);

566 return true;

567 });

568}

569

572 QualType CanonicalType = Type.getCanonicalType();

575 return false;

576

579 return false;

580 }

581

583 CanonicalType, false);

584}

585

588

590 return false;

592 return false;

593

594

595

596

598 return false;

599

602 return true;

603

606

608 return true;

609

610 switch (T.isNonTrivialToPrimitiveDestructiveMove()) {

612 return T.isDestructedType();

614 return true;

615 default:

616 return false;

617 }

618}

619

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

625

627 switch (UTT) {

628 default:

629 llvm_unreachable("not a UTT");

630

631

632 case UTT_IsVoid:

633 return T->isVoidType();

634 case UTT_IsIntegral:

635 return T->isIntegralType(C);

636 case UTT_IsFloatingPoint:

637 return T->isFloatingType();

638 case UTT_IsArray:

639

640

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

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

643 return T->isArrayType();

644 case UTT_IsBoundedArray:

646 return false;

647

648

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

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

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

652 case UTT_IsUnboundedArray:

654 return false;

655 return T->isIncompleteArrayType();

656 case UTT_IsPointer:

657 return T->isAnyPointerType();

658 case UTT_IsLvalueReference:

659 return T->isLValueReferenceType();

660 case UTT_IsRvalueReference:

661 return T->isRValueReferenceType();

662 case UTT_IsMemberFunctionPointer:

663 return T->isMemberFunctionPointerType();

664 case UTT_IsMemberObjectPointer:

665 return T->isMemberDataPointerType();

666 case UTT_IsEnum:

667 return T->isEnumeralType();

668 case UTT_IsScopedEnum:

669 return T->isScopedEnumeralType();

670 case UTT_IsUnion:

671 return T->isUnionType();

672 case UTT_IsClass:

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

674 case UTT_IsFunction:

675 return T->isFunctionType();

676

677

678

679 case UTT_IsReference:

680 return T->isReferenceType();

681 case UTT_IsArithmetic:

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

683 case UTT_IsFundamental:

684 return T->isFundamentalType();

685 case UTT_IsObject:

686 return T->isObjectType();

687 case UTT_IsScalar:

688

689

690

691

692 if (T->isObjCLifetimeType()) {

693 switch (T.getObjCLifetime()) {

696 return true;

697

701 return false;

702 }

703 }

704

705 return T->isScalarType();

706 case UTT_IsCompound:

707 return T->isCompoundType();

708 case UTT_IsMemberPointer:

709 return T->isMemberPointerType();

710

711

712

713 case UTT_IsConst:

714 return T.isConstQualified();

715 case UTT_IsVolatile:

716 return T.isVolatileQualified();

717 case UTT_IsTrivial:

718 return T.isTrivialType(C);

719 case UTT_IsTriviallyCopyable:

720 return T.isTriviallyCopyableType(C);

721 case UTT_IsStandardLayout:

722 return T->isStandardLayoutType();

723 case UTT_IsPOD:

724 return T.isPODType(C);

725 case UTT_IsLiteral:

726 return T->isLiteralType(C);

727 case UTT_IsEmpty:

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

730 return false;

731 case UTT_IsPolymorphic:

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

734 return false;

735 case UTT_IsAbstract:

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

738 return false;

739 case UTT_IsAggregate:

740

741

742

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

744 T->isAnyComplexType();

745

746

747

748 case UTT_IsInterfaceClass:

749 return false;

750 case UTT_IsFinal:

751 case UTT_IsSealed:

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

753 return RD->hasAttr();

754 return false;

755 case UTT_IsSigned:

756

757

758 return T->isFloatingType() ||

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

760 case UTT_IsUnsigned:

761

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

763

764

765

766

767

768

769

770

771

772

773

774

775

776

777

778

779

780 case UTT_HasTrivialDefaultConstructor:

781

782

783

784

785 if (T.isPODType(C))

786 return true;

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

790 return false;

791 case UTT_HasTrivialMoveConstructor:

792

793

794

795 if (T.isPODType(C))

796 return true;

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

800 return false;

801 case UTT_HasTrivialCopy:

802

803

804

805

806

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

808 return true;

812 return false;

813 case UTT_HasTrivialMoveAssign:

814

815

816

817 if (T.isPODType(C))

818 return true;

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

822 return false;

823 case UTT_HasTrivialAssign:

824

825

826

827

828

829

830

831

832

833

834

835

836 if (T.isConstQualified())

837 return false;

838 if (T.isPODType(C))

839 return true;

843 return false;

844 case UTT_IsDestructible:

845 case UTT_IsTriviallyDestructible:

846 case UTT_IsNothrowDestructible:

847

848

849 if (T->isReferenceType())

850 return true;

851

852

853 if (T->isObjCLifetimeType() &&

855 return true;

856

857

858

859

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

861 return false;

862

863

864

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

866 return false;

867

868

869

870

871

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

875 return false;

876

877

878

880 return false;

882 return false;

883 if (UTT == UTT_IsNothrowDestructible) {

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

887 return false;

888 }

889 }

890 return true;

891

892 case UTT_HasTrivialDestructor:

893

894

895

896

897

898

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

900 return true;

901

902

903 if (T->isObjCLifetimeType() &&

905 return true;

906

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

909 return false;

910

911 case UTT_HasNothrowAssign:

912

913

914

915

916

917

918

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

920 return false;

921 if (T->isReferenceType())

922 return false;

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

924 return true;

925

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

931 return false;

932 case UTT_HasNothrowMoveAssign:

933

934

935

936 if (T.isPODType(C))

937 return true;

938

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

944 return false;

945 case UTT_HasNothrowCopy:

946

947

948

949

950

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

952 return true;

956 return true;

957

958 bool FoundConstructor = false;

959 unsigned FoundTQs;

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

961

962

963

965 continue;

966

968 continue;

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

971 FoundConstructor = true;

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

974 if (!CPT)

975 return false;

976

977

979 return false;

980 }

981 }

982

983 return FoundConstructor;

984 }

985 return false;

986 case UTT_HasNothrowConstructor:

987

988

989

990

991

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

993 return true;

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

996 return true;

997

998 bool FoundConstructor = false;

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

1000

1002 continue;

1003

1005 continue;

1007 if (Constructor->isDefaultConstructor()) {

1008 FoundConstructor = true;

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

1011 if (!CPT)

1012 return false;

1013

1014

1016 return false;

1017 }

1018 }

1019 return FoundConstructor;

1020 }

1021 return false;

1022 case UTT_HasVirtualDestructor:

1023

1024

1025

1029 return false;

1030

1031

1032

1033

1034 case UTT_IsCompleteType:

1035

1036

1037

1038 return T->isIncompleteType();

1039 case UTT_HasUniqueObjectRepresentations:

1040 return C.hasUniqueObjectRepresentations(T);

1041 case UTT_IsTriviallyRelocatable:

1043 case UTT_IsBitwiseCloneable:

1044 return T.isBitwiseCloneableType(C);

1045 case UTT_IsCppTriviallyRelocatable:

1046 return Self.IsCXXTriviallyRelocatableType(T);

1047 case UTT_CanPassInRegs:

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

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

1051 return false;

1052 case UTT_IsTriviallyEqualityComparable:

1054 case UTT_IsImplicitLifetime: {

1056 tok::kw___builtin_is_implicit_lifetime);

1058 tok::kw___builtin_is_implicit_lifetime);

1059

1060

1061

1062

1063

1064 QualType UnqualT = T->getCanonicalTypeUnqualified();

1066 return true;

1068 return true;

1070 if (!RD)

1071 return false;

1072

1073

1074

1075

1076

1077

1080 return true;

1081 bool HasTrivialNonDeletedDtr =

1083 if (!HasTrivialNonDeletedDtr)

1084 return false;

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

1087 continue;

1088 if (Ctr->isTrivial())

1089 return true;

1090 }

1094 return true;

1097 return true;

1100 return true;

1101 return false;

1102 }

1103 case UTT_IsIntangibleType:

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

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

1107 diag::err_incomplete_type))

1108 return false;

1110 tok::kw___builtin_hlsl_is_intangible))

1111 return false;

1112 return T->isHLSLIntangibleType();

1113

1114 case UTT_IsTypedResourceElementCompatible:

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

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

1117 if (T->isIncompleteType())

1118 return false;

1119

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

1121 }

1122}

1123

1128

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

1132

1135

1136

1137

1138

1139

1140

1141

1142

1143

1144

1145

1146

1147

1148

1149

1150

1151

1152

1153

1154

1155

1156

1157

1158

1159

1160

1161

1164

1165

1169

1170

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

1173

1174

1181

1182

1183

1189 if (Init.Failed())

1191

1195

1196 return Result;

1197}

1198

1203 bool IsDependent) {

1204 if (IsDependent)

1206

1207 switch (Kind) {

1208 case TypeTrait::UTT_StructuredBindingSize: {

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

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

1213 if (!Size) {

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

1216 }

1219 break;

1220 }

1221 default:

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

1223 }

1224}

1225

1230 bool IsDependent) {

1231 if (IsDependent)

1232 return false;

1233

1236

1237

1238

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

1240 Kind != BTT_ReferenceConstructsFromTemporary &&

1241 Kind != BTT_ReferenceConvertsFromTemporary)

1243

1244 switch (Kind) {

1245 case clang::BTT_ReferenceBindsToTemporary:

1246 case clang::BTT_ReferenceConstructsFromTemporary:

1247 case clang::BTT_ReferenceConvertsFromTemporary:

1248 case clang::TT_IsConstructible:

1249 case clang::TT_IsNothrowConstructible:

1250 case clang::TT_IsTriviallyConstructible: {

1251

1252

1253

1254

1255

1256

1257

1258

1259

1260

1261

1262

1263

1264 assert(!Args.empty());

1265

1266

1267

1268

1269 for (const auto *TSI : Args) {

1270 QualType ArgTy = TSI->getType();

1272 continue;

1273

1275 KWLoc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr))

1276 return false;

1277 }

1278

1279

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

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

1282 return false;

1283

1284

1287 return false;

1288

1289

1290

1291

1292 bool UseRawObjectType =

1293 Kind == clang::BTT_ReferenceBindsToTemporary ||

1294 Kind == clang::BTT_ReferenceConstructsFromTemporary ||

1295 Kind == clang::BTT_ReferenceConvertsFromTemporary;

1296

1297 llvm::BumpPtrAllocator OpaqueExprAllocator;

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

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

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

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

1305 ArgExprs.push_back(

1310 }

1311

1312

1313

1321 Kind == clang::BTT_ReferenceConvertsFromTemporary

1325 if (Init.Failed())

1326 return false;

1327

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

1330 return false;

1331

1332 if (Kind == clang::TT_IsConstructible)

1333 return true;

1334

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

1336 Kind == clang::BTT_ReferenceConstructsFromTemporary ||

1337 Kind == clang::BTT_ReferenceConvertsFromTemporary) {

1338 if (T->isReferenceType())

1339 return false;

1340

1341

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

1343 return false;

1344

1345 if (Init.isDirectReferenceBinding())

1346 return true;

1347

1348 if (Kind == clang::BTT_ReferenceBindsToTemporary)

1349 return false;

1350

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

1352 if (U->isReferenceType())

1353 return false;

1354

1360 OpaqueExprAllocator)

1362 }

1363

1364 if (Kind == clang::TT_IsNothrowConstructible)

1366

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

1368

1369

1370 if (T.getNonReferenceType().hasNonTrivialObjCLifetime())

1371 return false;

1372

1373

1374

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

1376 }

1377

1378 llvm_unreachable("unhandled type trait");

1379 return false;

1380 }

1381 default:

1382 llvm_unreachable("not a TT");

1383 }

1384

1385 return false;

1386}

1387

1388namespace {

1391 switch (Kind) {

1392 case UTT_HasNothrowAssign:

1393 case UTT_HasNothrowMoveAssign:

1394 Replacement = BTT_IsNothrowAssignable;

1395 break;

1396 case UTT_HasNothrowCopy:

1397 case UTT_HasNothrowConstructor:

1398 Replacement = TT_IsNothrowConstructible;

1399 break;

1400 case UTT_HasTrivialAssign:

1401 case UTT_HasTrivialMoveAssign:

1402 Replacement = BTT_IsTriviallyAssignable;

1403 break;

1404 case UTT_HasTrivialCopy:

1405 Replacement = UTT_IsTriviallyCopyable;

1406 break;

1407 case UTT_HasTrivialDefaultConstructor:

1408 case UTT_HasTrivialMoveConstructor:

1409 Replacement = TT_IsTriviallyConstructible;

1410 break;

1411 case UTT_HasTrivialDestructor:

1412 Replacement = UTT_IsTriviallyDestructible;

1413 break;

1414 case UTT_IsTriviallyRelocatable:

1415 Replacement = clang::UTT_IsCppTriviallyRelocatable;

1416 break;

1417 case BTT_ReferenceBindsToTemporary:

1418 Replacement = clang::BTT_ReferenceConstructsFromTemporary;

1419 break;

1420 default:

1421 return;

1422 }

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

1425}

1426}

1427

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

1430 Diag(Loc, diag::err_type_trait_arity)

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

1432 return false;

1433 }

1434

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

1436 Diag(Loc, diag::err_type_trait_arity)

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

1438 return false;

1439 }

1440 return true;

1441}

1442

1447

1449 if (Kind == TypeTrait::UTT_StructuredBindingSize)

1452}

1453

1459

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

1463

1464 DiagnoseBuiltinDeprecation(*this, Kind, KWLoc);

1465

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

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

1470 break;

1471 }

1472 }

1473

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

1480 }

1485 Args, RParenLoc, Result);

1486 }

1487 }

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

1489}

1490

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

1496

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

1500 if (!TInfo)

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

1502

1503 ConvertedArgs.push_back(TInfo);

1504 }

1505

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

1507}

1508

1511

1512

1513

1514

1515

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

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

1518 if (!rhsRecord || !lhsRecord) {

1521 if (!LHSObjTy || !RHSObjTy)

1522 return false;

1523

1526 if (!BaseInterface || !DerivedInterface)

1527 return false;

1528

1530 diag::err_incomplete_type_used_in_type_trait_expr))

1531 return false;

1532

1533 return BaseInterface->isSuperClassOf(DerivedInterface);

1534 }

1535

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

1537 (lhsRecord == rhsRecord));

1538

1539

1540

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

1542 return false;

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

1544 return false;

1545

1546 if (lhsRecord == rhsRecord)

1547 return true;

1548

1549

1550

1551

1552

1554 diag::err_incomplete_type_used_in_type_trait_expr))

1555 return false;

1556

1559}

1560

1567

1569 "Cannot evaluate traits of dependent types");

1570

1571 switch (BTT) {

1572 case BTT_IsBaseOf:

1574

1575 case BTT_IsVirtualBaseOf: {

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

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

1578

1579 if (!BaseRecord || !DerivedRecord) {

1581 tok::kw___builtin_is_virtual_base_of);

1583 tok::kw___builtin_is_virtual_base_of);

1584 return false;

1585 }

1586

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

1588 return false;

1589

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

1591 !DerivedRecord->isStructureOrClassType())

1592 return false;

1593

1595 diag::err_incomplete_type))

1596 return false;

1597

1600 }

1601 case BTT_IsSame:

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

1603 case BTT_TypeCompatible: {

1604

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

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

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

1609 }

1610 case BTT_IsConvertible:

1611 case BTT_IsConvertibleTo:

1612 case BTT_IsNothrowConvertible: {

1615 llvm::BumpPtrAllocator OpaqueExprAllocator;

1617 OpaqueExprAllocator);

1618 if (Result.isInvalid())

1619 return false;

1620

1621 if (BTT != BTT_IsNothrowConvertible)

1622 return true;

1623

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

1625 }

1626

1627 case BTT_IsAssignable:

1628 case BTT_IsNothrowAssignable:

1629 case BTT_IsTriviallyAssignable: {

1630

1631

1632

1633

1634

1635

1636

1637

1638

1639

1640

1642 Self.RequireCompleteType(

1644 diag::err_incomplete_type_used_in_type_trait_expr))

1645 return false;

1647 Self.RequireCompleteType(

1649 diag::err_incomplete_type_used_in_type_trait_expr))

1650 return false;

1651

1652

1654 return false;

1655

1656

1657

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

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

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

1663 };

1664

1665 auto Lhs = createDeclValExpr(LhsT);

1666 auto Rhs = createDeclValExpr(RhsT);

1667

1668

1669

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

1676 if (Result.isInvalid())

1677 return false;

1678

1679

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

1681

1683 return false;

1684

1685 if (BTT == BTT_IsAssignable)

1686 return true;

1687

1688 if (BTT == BTT_IsNothrowAssignable)

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

1690

1691 if (BTT == BTT_IsTriviallyAssignable) {

1692

1693

1695 return false;

1697 if (Context.containsAddressDiscriminatedPointerAuth(LhsT) ||

1698 Context.containsAddressDiscriminatedPointerAuth(RhsT))

1699 return false;

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

1701 }

1702

1703 llvm_unreachable("unhandled type trait");

1704 return false;

1705 }

1706 case BTT_IsLayoutCompatible: {

1709 diag::err_incomplete_type);

1712 diag::err_incomplete_type);

1713

1716

1717 return Self.IsLayoutCompatible(LhsT, RhsT);

1718 }

1719 case BTT_IsPointerInterconvertibleBaseOf: {

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

1723 diag::err_incomplete_type);

1724 }

1725

1727 tok::kw___is_pointer_interconvertible_base_of);

1729 tok::kw___is_pointer_interconvertible_base_of);

1730

1731 return Self.IsPointerInterconvertibleBaseOf(Lhs, Rhs);

1732 }

1733 case BTT_IsDeducible: {

1736 return Self.DeduceTemplateArgumentsFromType(

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

1739 }

1740 case BTT_IsScalarizedLayoutCompatible: {

1743 diag::err_incomplete_type))

1744 return true;

1747 diag::err_incomplete_type))

1748 return true;

1749

1751 Self, Lhs, tok::kw___builtin_hlsl_is_scalarized_layout_compatible);

1753 Self, Rhs, tok::kw___builtin_hlsl_is_scalarized_layout_compatible);

1754

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

1756 }

1757 case BTT_LtSynthesizesFromSpaceship:

1758 case BTT_LeSynthesizesFromSpaceship:

1759 case BTT_GtSynthesizesFromSpaceship:

1760 case BTT_GeSynthesizesFromSpaceship: {

1765

1776

1777 auto OpKind = [&] {

1778 switch (BTT) {

1779 case BTT_LtSynthesizesFromSpaceship:

1780 return BinaryOperatorKind::BO_LT;

1781 case BTT_LeSynthesizesFromSpaceship:

1782 return BinaryOperatorKind::BO_LE;

1783 case BTT_GtSynthesizesFromSpaceship:

1784 return BinaryOperatorKind::BO_GT;

1785 case BTT_GeSynthesizesFromSpaceship:

1786 return BinaryOperatorKind::BO_GE;

1787 default:

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

1789 }

1790 }();

1791

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

1794

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

1798 return false;

1799

1801 }

1802 default:

1803 llvm_unreachable("not a BTT");

1804 }

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

1806}

1807

1813 if (!TSInfo)

1814 TSInfo = Context.getTrivialTypeSourceInfo(T);

1815

1817}

1818

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

1823

1824 switch (ATT) {

1825 case ATT_ArrayRank:

1826 if (T->isArrayType()) {

1827 unsigned Dim = 0;

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

1830 T = AT->getElementType();

1831 }

1832 return Dim;

1833 }

1834 return 0;

1835

1836 case ATT_ArrayExtent: {

1837 llvm::APSInt Value;

1838 uint64_t Dim;

1839 if (Self.VerifyIntegerConstantExpression(

1840 DimExpr, &Value, diag::err_dimension_expr_not_constant_integer)

1841 .isInvalid())

1842 return 0;

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

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

1846 return 0;

1847 }

1848 Dim = Value.getLimitedValue();

1849

1850 if (T->isArrayType()) {

1851 unsigned D = 0;

1852 bool Matched = false;

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

1854 if (Dim == D) {

1855 Matched = true;

1856 break;

1857 }

1858 ++D;

1859 T = AT->getElementType();

1860 }

1861

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

1864 Self.Context.getAsConstantArrayType(T))

1865 return CAT->getLimitedSize();

1866 }

1867 }

1868 return 0;

1869 }

1870 }

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

1872}

1873

1878

1879

1880

1881 uint64_t Value = 0;

1882 if (T->isDependentType())

1884

1885

1886

1887

1888

1889

1891 RParen, Context.getSizeType());

1892}

1893

1896

1897 if (!Queried)

1899

1901

1903}

1904

1906 switch (ET) {

1907 case ET_IsLValueExpr:

1909 case ET_IsRValueExpr:

1911 }

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

1913}

1914

1918

1924 }

1925

1927

1930}

1931

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

1934 .Case("is_trivially_relocatable",

1935 TypeTrait::UTT_IsCppTriviallyRelocatable)

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

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

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

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

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

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

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

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

1944 .Default(std::nullopt);

1945}

1946

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

1949

1950

1951

1952

1953

1956 std::optional Trait;

1957

1958

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

1960 Trait = TraitExpr->getTrait();

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

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

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

1964 }

1965 const auto *Ref = dyn_cast(E);

1966 if (!Ref)

1967 return std::nullopt;

1968

1969

1970 if (const auto *VD =

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

1972 if (!VD->isInStdNamespace())

1973 return std::nullopt;

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

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

1976 return std::nullopt;

1978 if (!Trait)

1979 return std::nullopt;

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

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

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

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

1986 } else {

1987 llvm_unreachable("Unexpected kind");

1988 }

1989 }

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

1991 }

1992

1993

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

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

1998 return std::nullopt;

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

2000 if (!Ts)

2001 return std::nullopt;

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

2004 return std::nullopt;

2006 if (!Trait)

2007 return std::nullopt;

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

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

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

2011 }

2012 return std::nullopt;

2013}

2014

2019 if (Has)

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

2021 << diag::TraitNotSatisfiedReason::UnionWithUserDeclaredSMF << K;

2022 };

2031 return;

2032 }

2033

2035 const auto *Decl = cast_or_null(

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

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

2039 << diag::TraitNotSatisfiedReason::UserProvidedCtr

2041 }

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

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

2047 << diag::TraitNotSatisfiedReason::UserProvidedAssign

2049 }

2051 Dtr = Dtr->getCanonicalDecl();

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

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

2054 << diag::TraitNotSatisfiedReason::DeletedDtr << 1

2055 << Dtr->getSourceRange();

2056 }

2057}

2058

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

2064 if (B.isVirtual())

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

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

2067 << B.getSourceRange();

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

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

2071 << B.getSourceRange();

2072 }

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

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

2077 << diag::TraitNotSatisfiedReason::NTRField << Field

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

2079 }

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

2082 << diag::TraitNotSatisfiedReason::DeletedDtr << 0

2084

2085 if (D->hasAttr())

2086 return;

2088}

2089

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

2094 << T << diag::TraitName::TriviallyRelocatable;

2095 if (T->isVariablyModifiedType())

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

2097 << diag::TraitNotSatisfiedReason::VLA;

2098

2099 if (T->isReferenceType())

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

2101 << diag::TraitNotSatisfiedReason::Ref;

2102 T = T.getNonReferenceType();

2103

2104 if (T.hasNonTrivialObjCLifetime())

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

2106 << diag::TraitNotSatisfiedReason::HasArcLifetime;

2107

2110 return;

2111

2114

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

2116}

2117

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

2123 if (B.isVirtual())

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

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

2126 << B.getSourceRange();

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

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

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

2130 << B.getSourceRange();

2131 }

2132 }

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

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

2136 << diag::TraitNotSatisfiedReason::NTCField << Field

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

2138 }

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

2142 << diag::TraitNotSatisfiedReason::DeletedDtr

2144

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

2147 continue;

2148 }

2149 auto SpecialMemberKind =

2151 switch (SpecialMemberKind) {

2156 bool IsAssignment =

2159 bool IsMove =

2162

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

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

2165 : diag::TraitNotSatisfiedReason::UserProvidedCtr)

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

2167 break;

2168 }

2169 default:

2170 break;

2171 }

2172 }

2173}

2174

2178 if (Ts.empty()) {

2179 return;

2180 }

2181

2182 bool ContainsVoid = false;

2183 for (const QualType &ArgTy : Ts) {

2184 ContainsVoid |= ArgTy->isVoidType();

2185 }

2186

2187 if (ContainsVoid)

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

2189 << diag::TraitNotSatisfiedReason::CVVoidType;

2190

2192 if (T->isFunctionType())

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

2194 << diag::TraitNotSatisfiedReason::FunctionType;

2195

2196 if (T->isIncompleteArrayType())

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

2198 << diag::TraitNotSatisfiedReason::IncompleteArrayType;

2199

2202 return;

2203

2204 llvm::BumpPtrAllocator OpaqueExprAllocator;

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

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

2211 ArgExprs.push_back(

2215 }

2216

2224

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

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

2227}

2228

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

2232 << T << diag::TraitName::TriviallyCopyable;

2233

2234 if (T->isReferenceType())

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

2236 << diag::TraitNotSatisfiedReason::Ref;

2237

2240 return;

2241

2244

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

2246}

2247

2251

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

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

2257 };

2258

2259 auto LHS = createDeclValExpr(T);

2260 auto RHS = createDeclValExpr(U);

2261

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

2267

2269 return;

2270

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

2272}

2273

2276

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

2278 if (Field->isZeroLengthBitField())

2279 continue;

2280 if (Field->isBitField()) {

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

2282 << diag::TraitNotSatisfiedReason::NonZeroLengthField << Field

2283 << Field->getSourceRange();

2284 continue;

2285 }

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

2287 << diag::TraitNotSatisfiedReason::NonEmptyMember << Field

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

2289 }

2290

2291

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

2293 if (M->isVirtual()) {

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

2295 << diag::TraitNotSatisfiedReason::VirtualFunction << M

2296 << M->getSourceRange();

2297 break;

2298 }

2299 }

2300

2301

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

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

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

2305 continue;

2306 if (B.isVirtual()) {

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

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

2309 << B.getSourceRange();

2310 }

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

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

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

2314 << B.getSourceRange();

2315 }

2316 }

2317}

2318

2320

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

2322

2323

2324

2325

2326 if (T->isReferenceType())

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

2328 << diag::TraitNotSatisfiedReason::Ref;

2329 T = T.getNonReferenceType();

2330

2332 T = AT->getElementType();

2333

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

2335 if (D->hasDefinition()) {

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

2338 }

2339 }

2340}

2341

2345 return;

2346

2347

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

2350 << diag::TraitNotSatisfiedReason::NotMarkedFinal;

2352 return;

2353 }

2354}

2355

2357

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

2359 if (T->isReferenceType()) {

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

2361 << diag::TraitNotSatisfiedReason::Ref;

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

2363 << diag::TraitNotSatisfiedReason::NotClassOrUnion;

2364 return;

2365 }

2366

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

2369 << diag::TraitNotSatisfiedReason::NotClassOrUnion;

2370 return;

2371 }

2372 if (T->isFunctionType()) {

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

2374 << diag::TraitNotSatisfiedReason::FunctionType;

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

2376 << diag::TraitNotSatisfiedReason::NotClassOrUnion;

2377 return;

2378 }

2379 if (T->isRecordType()) {

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

2381 << diag::TraitNotSatisfiedReason::NotClassOrUnion;

2382 return;

2383 }

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

2386}

2387

2389 int NumBasesWithFields = 0;

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

2393 continue;

2394

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

2397 if (++NumBasesWithFields > 1)

2398 return true;

2399 break;

2400 }

2401 }

2402 }

2403 return false;

2404}

2405

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

2410 if (B.isVirtual()) {

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

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

2413 << B.getSourceRange();

2414 }

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

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

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

2418 << B.getSourceRange();

2419 }

2420 }

2421

2422 const FieldDecl *FirstField = nullptr;

2424

2426 if (Field->isUnnamedBitField())

2427 continue;

2428

2429

2430 if (!FirstField) {

2431 FirstField = Field;

2432 FirstAccess = Field->getAccess();

2433 continue;

2434 }

2435

2436

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

2438

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

2440 << diag::TraitNotSatisfiedReason::MixedAccess;

2441

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

2443 << FirstField;

2444

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

2446 << diag::TraitNotSatisfiedReason::MixedAccessField << Field

2447 << FirstField;

2448

2449

2450 break;

2451 }

2452 }

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

2455 << diag::TraitNotSatisfiedReason::MultipleDataBase;

2456 }

2458

2460

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

2462 if (M->isVirtual()) {

2463 VirtualMD = M;

2464 break;

2465 }

2466 }

2467 if (VirtualMD) {

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

2469 << diag::TraitNotSatisfiedReason::VirtualFunction << VirtualMD;

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

2471 << VirtualMD;

2472 } else {

2473

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

2475 << diag::TraitNotSatisfiedReason::VirtualFunction << D;

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

2477 }

2478 }

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

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

2482 << diag::TraitNotSatisfiedReason::NonStandardLayoutMember << Field

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

2484 }

2485 }

2486

2491 Indirect = BaseDef;

2492 return false;

2493 }

2494 return true;

2495 });

2496 if (Indirect) {

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

2498 << diag::TraitNotSatisfiedReason::IndirectBaseWithFields << Indirect

2500 }

2501 }

2502}

2503

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

2507 << T << diag::TraitName::StandardLayout;

2508

2509

2510 if (T->isVariablyModifiedType()) {

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

2512 << diag::TraitNotSatisfiedReason::VLA;

2513 return;

2514 }

2515

2516 if (T->isReferenceType()) {

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

2518 << diag::TraitNotSatisfiedReason::Ref;

2519 return;

2520 }

2521 T = T.getNonReferenceType();

2524 return;

2525

2528

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

2530}

2531

2535 if (Ctor->isUserProvided())

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

2537 << diag::TraitNotSatisfiedReason::UserDeclaredCtr;

2538 if (Ctor->isInheritingConstructor())

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

2540 << diag::TraitNotSatisfiedReason::InheritedCtr;

2541 }

2542

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

2544 return isa(Sub);

2545 })) {

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

2547 << diag::TraitNotSatisfiedReason::InheritedCtr;

2548 }

2549

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

2552 << diag::TraitNotSatisfiedReason::PolymorphicType

2554

2556 if (B.isVirtual()) {

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

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

2559 << B.getSourceRange();

2560 continue;

2561 }

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

2567 << diag::TraitNotSatisfiedReason::PrivateProtectedDirectBase

2569 break;

2570 default:

2571 break;

2572 }

2573 }

2574

2576 if (Method->isVirtual()) {

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

2578 << diag::TraitNotSatisfiedReason::VirtualFunction << Method

2579 << Method->getSourceRange();

2580 }

2581 }

2582

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

2589 << diag::TraitNotSatisfiedReason::PrivateProtectedDirectDataMember

2591 break;

2592 default:

2593 break;

2594 }

2595 }

2596

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

2598}

2599

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

2603 << T << diag::TraitName::Aggregate;

2604

2605 if (T->isVoidType())

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

2607 << diag::TraitNotSatisfiedReason::CVVoidType;

2608

2609 T = T.getNonReferenceType();

2612 return;

2613

2616}

2617

2620

2621

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

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

2625 << diag::TraitNotSatisfiedReason::OverridesAllPureVirtual

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

2627 }

2628 }

2629}

2630

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

2634 << T << diag::TraitName::Abstract;

2635

2636 if (T->isReferenceType()) {

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

2638 << diag::TraitNotSatisfiedReason::Ref;

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

2640 << diag::TraitNotSatisfiedReason::NotStructOrClass;

2641 return;

2642 }

2643

2644 if (T->isUnionType()) {

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

2646 << diag::TraitNotSatisfiedReason::UnionType;

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

2648 << diag::TraitNotSatisfiedReason::NotStructOrClass;

2649 return;

2650 }

2651

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

2654 << diag::TraitNotSatisfiedReason::ArrayType;

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

2656 << diag::TraitNotSatisfiedReason::NotStructOrClass;

2657 return;

2658 }

2659

2660 if (T->isFunctionType()) {

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

2662 << diag::TraitNotSatisfiedReason::FunctionType;

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

2664 << diag::TraitNotSatisfiedReason::NotStructOrClass;

2665 return;

2666 }

2667

2668 if (T->isPointerType()) {

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

2670 << diag::TraitNotSatisfiedReason::PointerType;

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

2672 << diag::TraitNotSatisfiedReason::NotStructOrClass;

2673 return;

2674 }

2675

2676 if (T->isStructureOrClassType()) {

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

2678 << diag::TraitNotSatisfiedReason::NotStructOrClass;

2679 return;

2680 }

2681

2685}

2686

2690 return;

2691

2693 if (!TraitInfo)

2694 return;

2695

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

2697 switch (Trait) {

2698 case UTT_IsCppTriviallyRelocatable:

2700 break;

2701 case UTT_IsTriviallyCopyable:

2703 break;

2704 case BTT_IsAssignable:

2706 break;

2707 case UTT_IsEmpty:

2709 break;

2710 case UTT_IsStandardLayout:

2712 break;

2713 case TT_IsConstructible:

2715 break;

2716 case UTT_IsAggregate:

2718 break;

2719 case UTT_IsFinal: {

2722 break;

2726 break;

2727 }

2728 case UTT_IsAbstract:

2730 break;

2731 default:

2732 break;

2733 }

2734}

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:1561

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

Definition SemaTypeTraits.cpp:510

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

Definition SemaTypeTraits.cpp:2618

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

Definition SemaTypeTraits.cpp:1199

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

Checks that type T is not a VLA.

Definition SemaTypeTraits.cpp:298

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:477

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

Definition SemaTypeTraits.cpp:1932

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

Definition SemaTypeTraits.cpp:2175

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:312

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

Definition SemaTypeTraits.cpp:2406

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

Definition SemaTypeTraits.cpp:2342

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

Definition SemaTypeTraits.cpp:2274

static bool hasMultipleDataBaseClassesWithFields(const CXXRecordDecl *D)

Definition SemaTypeTraits.cpp:2388

static bool EvaluateExpressionTrait(ExpressionTrait ET, Expr *E)

Definition SemaTypeTraits.cpp:1905

static ExtractedTypeTraitInfo ExtractTypeTraitFromExpression(const Expr *E)

Definition SemaTypeTraits.cpp:1954

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

Definition SemaTypeTraits.cpp:1947

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

Definition SemaTypeTraits.cpp:2059

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

Definition SemaTypeTraits.cpp:2248

static bool IsTriviallyRelocatableType(Sema &SemaRef, QualType T)

Definition SemaTypeTraits.cpp:586

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

Definition SemaTypeTraits.cpp:2015

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:2118

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

Definition SemaTypeTraits.cpp:620

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

Definition SemaTypeTraits.cpp:1819

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:328

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

Definition SemaTypeTraits.cpp:1129

TypeTraitReturnType

Definition SemaTypeTraits.cpp:1443

@ SizeT

Definition SemaTypeTraits.cpp:1445

@ Bool

Definition SemaTypeTraits.cpp:1444

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

Definition SemaTypeTraits.cpp:2532

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

Definition SemaTypeTraits.cpp:1226

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

Definition SemaTypeTraits.cpp:570

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

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:1894

bool IsCXXTriviallyRelocatableType(QualType T)

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

Definition SemaTypeTraits.cpp:270

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

Definition SemaTypeTraits.cpp:1509

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:2687

ASTContext & getASTContext() const

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:1428

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:1808

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:1454

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

Definition SemaTypeTraits.cpp:1915

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...

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

Definition SemaTypeTraits.cpp:215

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:1491

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

Definition SemaTypeTraits.cpp:1874

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...