clang: lib/CodeGen/CGClass.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

29#include "llvm/IR/Intrinsics.h"

30#include "llvm/IR/Metadata.h"

31#include "llvm/Support/SaveAndRestore.h"

32#include "llvm/Transforms/Utils/SanitizerStats.h"

33#include

34

35using namespace clang;

36using namespace CodeGen;

37

38

39

42 return CharUnits::One();

43

45

46

47

50

51

52 return layout.getNonVirtualAlignment();

53}

54

55

56

57

58

62

64

65

66

69

70

71 return std::max(layout.getNonVirtualSize(), CharUnits::One());

72}

73

74

75

79

80

81

84 CharUnits expectedVBaseAlign = baseLayout.getNonVirtualAlignment();

85

87 expectedVBaseAlign);

88}

89

94

95

97 return std::min(actualBaseAlign, expectedTargetAlign);

98

100 CharUnits expectedBaseAlign = baseLayout.getNonVirtualAlignment();

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120 if (actualBaseAlign >= expectedBaseAlign) {

121 return expectedTargetAlign;

122 }

123

124

125

126

127 return std::min(actualBaseAlign, expectedTargetAlign);

128}

129

131 assert(CurFuncDecl && "loading 'this' without a func declaration?");

132 auto *MD = cast(CurFuncDecl);

133

134

135 if (CXXThisAlignment.isZero()) {

136

137

138

140 }

141

143 LoadCXXThis(), MD->getFunctionObjectParameterType(), CXXThisAlignment,

145}

146

147

148

149

152 llvm::Value *memberPtr,

156

157 llvm::Value *ptr =

159 memberPtr, memberPtrType);

160

164 memberAlign =

167 memberAlign);

169 memberAlign);

170}

171

176

179

182 assert(Base->isVirtual() && "Should not see virtual bases here!");

183

184

186

187 const auto *BaseDecl =

189

190

192

193 RD = BaseDecl;

194 }

195

196 return Offset;

197}

198

199llvm::Constant *

203 assert(PathBegin != PathEnd && "Base path should not be empty!");

204

207 if (Offset.isZero())

208 return nullptr;

209

212

213 return llvm::ConstantInt::get(PtrDiffTy, Offset.getQuantity());

214}

215

216

217

218

219

220

225 bool BaseIsVirtual) {

226

227 assert(This.getElementType() == ConvertType(Derived));

228

229

232 if (BaseIsVirtual)

234 else

236

237

238

240 if (!Offset.isZero()) {

241 V = V.withElementType(Int8Ty);

243 }

245}

246

250 llvm::Value *virtualOffset,

253

254 assert(!nonVirtualOffset.isZero() || virtualOffset != nullptr);

255

256

257 llvm::Value *baseOffset;

258 if (!nonVirtualOffset.isZero()) {

259 llvm::Type *OffsetType =

264 baseOffset =

265 llvm::ConstantInt::get(OffsetType, nonVirtualOffset.getQuantity());

266 if (virtualOffset) {

267 baseOffset = CGF.Builder.CreateAdd(virtualOffset, baseOffset);

268 }

269 } else {

270 baseOffset = virtualOffset;

271 }

272

273

276

277

278

280 if (virtualOffset) {

281 assert(nearestVBase && "virtual offset without vbase?");

283 derivedClass, nearestVBase);

284 } else {

286 }

288

290}

291

297 assert(PathBegin != PathEnd && "Base path should not be empty!");

298

301

302

303

304

305

306 if ((*Start)->isVirtual()) {

307 VBase = cast(

309 ++Start;

310 }

311

312

313

314

316 VBase ? VBase : Derived, Start, PathEnd);

317

318

319

320

321 if (VBase && Derived->hasAttr()) {

324 NonVirtualOffset += vBaseOffset;

325 VBase = nullptr;

326 }

327

328

329 llvm::Type *BaseValueTy = ConvertType((PathEnd[-1])->getType());

330 llvm::Type *PtrTy = llvm::PointerType::get(

332

335

336

337

338 if (NonVirtualOffset.isZero() && !VBase) {

341 SkippedChecks.set(SanitizerKind::Null, !NullCheckValue);

343 DerivedAlign, SkippedChecks);

344 }

345 return Value.withElementType(BaseValueTy);

346 }

347

348 llvm::BasicBlock *origBB = nullptr;

349 llvm::BasicBlock *endBB = nullptr;

350

351

352

353 if (NullCheckValue) {

354 origBB = Builder.GetInsertBlock();

355 llvm::BasicBlock *notNullBB = createBasicBlock("cast.notnull");

357

359 Builder.CreateCondBr(isNull, endBB, notNullBB);

361 }

362

365 SkippedChecks.set(SanitizerKind::Null, true);

367 Value.emitRawPointer(*this), DerivedTy, DerivedAlign,

368 SkippedChecks);

369 }

370

371

372 llvm::Value *VirtualOffset = nullptr;

373 if (VBase) {

374 VirtualOffset =

376 }

377

378

380 VirtualOffset, Derived, VBase);

381

382

383 Value = Value.withElementType(BaseValueTy);

384

385

386 if (NullCheckValue) {

387 llvm::BasicBlock *notNullBB = Builder.GetInsertBlock();

390

391 llvm::PHINode *PHI = Builder.CreatePHI(PtrTy, 2, "cast.result");

392 PHI->addIncoming(Value.emitRawPointer(*this), notNullBB);

393 PHI->addIncoming(llvm::Constant::getNullValue(PtrTy), origBB);

395 }

396

398}

399

405 bool NullCheckValue) {

406 assert(PathBegin != PathEnd && "Base path should not be empty!");

407

410 llvm::Type *DerivedValueTy = ConvertType(DerivedTy);

411

412 llvm::Value *NonVirtualOffset =

414

415 if (!NonVirtualOffset) {

416

418 }

419

420 llvm::BasicBlock *CastNull = nullptr;

421 llvm::BasicBlock *CastNotNull = nullptr;

422 llvm::BasicBlock *CastEnd = nullptr;

423

424 if (NullCheckValue) {

428

430 Builder.CreateCondBr(IsNull, CastNull, CastNotNull);

432 }

433

434

437 Addr, Builder.CreateNeg(NonVirtualOffset), Int8Ty,

439

440

442

443

444 if (NullCheckValue) {

445 Builder.CreateBr(CastEnd);

447 Builder.CreateBr(CastEnd);

449

452 PHI->addIncoming(Value, CastNotNull);

453 PHI->addIncoming(llvm::Constant::getNullValue(Value->getType()), CastNull);

456 }

457

458 return Addr;

459}

460

462 bool ForVirtualBase,

465

466 return nullptr;

467 }

468

471

473

475

477 } else if (RD == Base) {

478

479

481 "doing no-op VTT offset in base dtor/ctor?");

482 assert(!ForVirtualBase && "Can't have same class as virtual base!");

483 SubVTTIndex = 0;

484 } else {

486 CharUnits BaseOffset = ForVirtualBase ?

489

490 SubVTTIndex =

492 assert(SubVTTIndex != 0 && "Sub-VTT index must be greater than zero!");

493 }

494

496

498 return Builder.CreateConstInBoundsGEP1_64(VoidPtrTy, VTT, SubVTTIndex);

499 } else {

500

502 return Builder.CreateConstInBoundsGEP2_64(

503 VTT->getValueType(), VTT, 0, SubVTTIndex);

504 }

505}

506

507namespace {

508

511 bool BaseIsVirtual;

513 : BaseClass(Base), BaseIsVirtual(BaseIsVirtual) {}

514

518

520

521

522 QualType ThisTy = D->getFunctionObjectParameterType();

525 DerivedClass, BaseClass,

526 BaseIsVirtual);

528 false, Addr, ThisTy);

529 }

530 };

531

532

533

536

537 bool UsesThis;

538

539 DynamicThisUseChecker(const ASTContext &C) : super(C), UsesThis(false) {}

540

541

542

543

544

545

546 void VisitCXXThisExpr(const CXXThisExpr *E) { UsesThis = true; }

547 };

548}

549

551 DynamicThisUseChecker Checker(C);

552 Checker.Visit(Init);

553 return Checker.UsesThis;

554}

555

560 "Must have base initializer!");

561

563

565 const auto *BaseClassDecl =

567

569

570

571

572

575

576

577

580 BaseClassDecl,

581 isBaseVirtual);

589

591

593 !BaseClassDecl->hasTrivialDestructor())

594 CGF.EHStack.pushCleanup(EHCleanup, BaseClassDecl,

595 isBaseVirtual);

596}

597

599 auto *CD = dyn_cast(D);

600 if (!(CD && CD->isCopyOrMoveConstructor()) &&

601 D->isCopyAssignmentOperator() && D->isMoveAssignmentOperator())

602 return false;

603

604

605 if (D->isTrivial() && D->getParent()->mayInsertExtraPadding())

606 return true;

607

608

609 if (D->getParent()->isUnion() && D->isDefaulted())

610 return true;

611

612 return false;

613}

614

620

622 for (const auto *I : IndirectField->chain())

624 } else {

626 }

627}

628

636 "Must have member initializer!");

637 assert(MemberInit->getInit() && "Must have initializer!");

638

639

641 QualType FieldType = Field->getType();

642

643 llvm::Value *ThisPtr = CGF.LoadCXXThis();

646

647

648

651 else

653

655

656

657

658

659

660

663 if (Array && Constructor->isDefaulted() &&

664 Constructor->isCopyOrMoveConstructor()) {

669 unsigned SrcArgIndex =

671 llvm::Value *SrcPtr

675

676

679

680

684 return;

685 }

686 }

687

689}

690

698 } else {

701 }

702 break;

705 break;

711

714 break;

715 }

716 }

717

718

719

723}

724

725

726

727

728

731

732

733

734

735

736

737

738

739

740

741

742

743

745

746

747

748

749

750

751

752

753

754

755

756

757

758

759 return false;

760 }

761

762

763

765 return false;

766

767

769 return false;

770

771 return true;

772}

773

774

775

776

783

784 struct SizeAndOffset {

787 };

788

789 unsigned PtrSize = CGM.getDataLayout().getPointerSizeInBits();

791

792

794 for (unsigned i = 0, e = Info.getFieldCount(); i != e; ++i)

795 SSV[i].Offset =

797

798 size_t NumFields = 0;

799 for (const auto *Field : ClassDecl->fields()) {

802 CharUnits FieldSize = FieldInfo.Width;

803 assert(NumFields < SSV.size());

804 SSV[NumFields].Size = D->isBitField() ? 0 : FieldSize.getQuantity();

805 NumFields++;

806 }

807 assert(NumFields == SSV.size());

808 if (SSV.size() <= 1) return;

809

810

811

813 llvm::FunctionType *FTy =

814 llvm::FunctionType::get(CGM.VoidTy, Args, false);

816 FTy, Prologue ? "__asan_poison_intra_object_redzone"

817 : "__asan_unpoison_intra_object_redzone");

818

822

823

824 for (size_t i = 0; i < SSV.size(); i++) {

826 uint64_t NextField = i == SSV.size() - 1 ? TypeSize : SSV[i + 1].Offset;

827 uint64_t PoisonSize = NextField - SSV[i].Offset - SSV[i].Size;

828 uint64_t EndOffset = SSV[i].Offset + SSV[i].Size;

829 if (PoisonSize < AsanAlignment || !SSV[i].Size ||

830 (NextField % AsanAlignment) != 0)

831 continue;

833 F, {Builder.CreateAdd(ThisPtr, Builder.getIntN(PtrSize, EndOffset)),

834 Builder.getIntN(PtrSize, PoisonSize)});

835 }

836}

837

838

843

846 "can only generate complete ctor for this ABI");

847

848

849

853 return;

854 }

855

858 assert(Definition == Ctor && "emitting wrong constructor body");

859

860

861

862 bool IsTryBody = isa_and_nonnull(Body);

863 if (IsTryBody)

865

868

869 RunCleanupsScope RunCleanups(*this);

870

871

872

873

874

875

877

878

879 if (IsTryBody)

880 EmitStmt(cast(Body)->getTryBlock());

881 else if (Body)

883

884

885

886

887

888 RunCleanups.ForceCleanup();

889

890 if (IsTryBody)

892}

893

894namespace {

895

896

897

898

899 class CopyingValueRepresentation {

900 public:

901 explicit CopyingValueRepresentation(CodeGenFunction &CGF)

902 : CGF(CGF), OldSanOpts(CGF.SanOpts) {

903 CGF.SanOpts.set(SanitizerKind::Bool, false);

904 CGF.SanOpts.set(SanitizerKind::Enum, false);

905 }

906 ~CopyingValueRepresentation() {

907 CGF.SanOpts = OldSanOpts;

908 }

909 private:

912 };

913}

914

915namespace {

916 class FieldMemcpyizer {

917 public:

920 : CGF(CGF), ClassDecl(ClassDecl), SrcRec(SrcRec),

921 RecLayout(CGF.getContext().getASTRecordLayout(ClassDecl)),

922 FirstField(nullptr), LastField(nullptr), FirstFieldOffset(0),

923 LastFieldOffset(0), LastAddedFieldIndex(0) {}

924

925 bool isMemcpyableField(FieldDecl *F) const {

926

928 return false;

931 return false;

932 return true;

933 }

934

935 void addMemcpyableField(FieldDecl *F) {

937 return;

938 if (!FirstField)

939 addInitialField(F);

940 else

941 addNextField(F);

942 }

943

944 CharUnits getMemcpySize(uint64_t FirstByteOffset) const {

946 unsigned LastFieldSize =

947 LastField->isBitField()

948 ? LastField->getBitWidthValue()

951 uint64_t MemcpySizeBits = LastFieldOffset + LastFieldSize -

954 return MemcpySize;

955 }

956

957 void emitMemcpy() {

958

959

960 if (!FirstField) {

961 return;

962 }

963

965 if (FirstField->isBitField()) {

969

970

972 } else {

973 FirstByteOffset = FirstFieldOffset;

974 }

975

976 CharUnits MemcpySize = getMemcpySize(FirstByteOffset);

984

985 emitMemcpyIR(

988 MemcpySize);

989 reset();

990 }

991

992 void reset() {

993 FirstField = nullptr;

994 }

995

996 protected:

999

1000 private:

1005 }

1006

1007 void addInitialField(FieldDecl *F) {

1008 FirstField = F;

1009 LastField = F;

1010 FirstFieldOffset = RecLayout.getFieldOffset(F->getFieldIndex());

1011 LastFieldOffset = FirstFieldOffset;

1013 }

1014

1015 void addNextField(FieldDecl *F) {

1016

1017

1018

1019

1020 assert(F->getFieldIndex() >= LastAddedFieldIndex + 1 &&

1021 "Cannot aggregate fields out of order.");

1023

1024

1025

1026

1028 if (FOffset < FirstFieldOffset) {

1029 FirstField = F;

1030 FirstFieldOffset = FOffset;

1031 } else if (FOffset >= LastFieldOffset) {

1032 LastField = F;

1033 LastFieldOffset = FOffset;

1034 }

1035 }

1036

1041 uint64_t FirstFieldOffset, LastFieldOffset;

1042 unsigned LastAddedFieldIndex;

1043 };

1044

1045 class ConstructorMemcpyizer : public FieldMemcpyizer {

1046 private:

1047

1048

1054 return nullptr;

1055 }

1056

1057

1058

1060 if (!MemcpyableCtor)

1061 return false;

1063 assert(Field && "No field for member init.");

1066

1067

1071 return false;

1072

1073

1074 if (!isMemcpyableField(Field))

1075 return false;

1076

1077

1078 return true;

1079 }

1080

1081 public:

1084 : FieldMemcpyizer(CGF, CD->getParent(), getTrivialCopySource(CGF, CD, Args)),

1085 ConstructorDecl(CD),

1086 MemcpyableCtor(CD->isDefaulted() &&

1087 CD->isCopyOrMoveConstructor() &&

1088 CGF.getLangOpts().getGC() == LangOptions::NonGC),

1089 Args(Args) { }

1090

1092 if (isMemberInitMemcpyable(MemberInit)) {

1093 AggregatedInits.push_back(MemberInit);

1094 addMemcpyableField(MemberInit->getMember());

1095 } else {

1096 emitAggregatedInits();

1098 ConstructorDecl, Args);

1099 }

1100 }

1101

1102 void emitAggregatedInits() {

1103 if (AggregatedInits.size() <= 1) {

1104

1105

1106 if (!AggregatedInits.empty()) {

1107 CopyingValueRepresentation CVR(CGF);

1109 AggregatedInits[0], ConstructorDecl, Args);

1110 AggregatedInits.clear();

1111 }

1112 reset();

1113 return;

1114 }

1115

1116 pushEHDestructors();

1117 emitMemcpy();

1118 AggregatedInits.clear();

1119 }

1120

1121 void pushEHDestructors() {

1125

1126 for (unsigned i = 0; i < AggregatedInits.size(); ++i) {

1131 continue;

1132 LValue FieldLHS = LHS;

1135 }

1136 }

1137

1138 void finish() {

1139 emitAggregatedInits();

1140 }

1141

1142 private:

1144 bool MemcpyableCtor;

1147 };

1148

1149 class AssignmentMemcpyizer : public FieldMemcpyizer {

1150 private:

1151

1152

1154 if (!AssignmentsMemcpyable)

1155 return nullptr;

1156 if (BinaryOperator *BO = dyn_cast(S)) {

1157

1158 if (BO->getOpcode() != BO_Assign)

1159 return nullptr;

1160 MemberExpr *ME = dyn_cast(BO->getLHS());

1161 if (!ME)

1162 return nullptr;

1164 if (!Field || !isMemcpyableField(Field))

1165 return nullptr;

1166 Stmt *RHS = BO->getRHS();

1168 RHS = EC->getSubExpr();

1169 if (!RHS)

1170 return nullptr;

1171 if (MemberExpr *ME2 = dyn_cast(RHS)) {

1172 if (ME2->getMemberDecl() == Field)

1174 }

1175 return nullptr;

1176 } else if (CXXMemberCallExpr *MCE = dyn_cast(S)) {

1177 CXXMethodDecl *MD = dyn_cast(MCE->getCalleeDecl());

1179 return nullptr;

1180 MemberExpr *IOA = dyn_cast(MCE->getImplicitObjectArgument());

1181 if (!IOA)

1182 return nullptr;

1184 if (!Field || !isMemcpyableField(Field))

1185 return nullptr;

1186 MemberExpr *Arg0 = dyn_cast(MCE->getArg(0));

1187 if (!Arg0 || Field != dyn_cast(Arg0->getMemberDecl()))

1188 return nullptr;

1190 } else if (CallExpr *CE = dyn_cast(S)) {

1191 FunctionDecl *FD = dyn_cast(CE->getCalleeDecl());

1192 if (!FD || FD->getBuiltinID() != Builtin::BI__builtin_memcpy)

1193 return nullptr;

1195 if (ImplicitCastExpr *DC = dyn_cast(DstPtr))

1196 DstPtr = DC->getSubExpr();

1197 UnaryOperator *DUO = dyn_cast(DstPtr);

1198 if (!DUO || DUO->getOpcode() != UO_AddrOf)

1199 return nullptr;

1201 if (!ME)

1202 return nullptr;

1204 if (!Field || !isMemcpyableField(Field))

1205 return nullptr;

1207 if (ImplicitCastExpr *SC = dyn_cast(SrcPtr))

1208 SrcPtr = SC->getSubExpr();

1209 UnaryOperator *SUO = dyn_cast(SrcPtr);

1210 if (!SUO || SUO->getOpcode() != UO_AddrOf)

1211 return nullptr;

1213 if (!ME2 || Field != dyn_cast(ME2->getMemberDecl()))

1214 return nullptr;

1216 }

1217

1218 return nullptr;

1219 }

1220

1221 bool AssignmentsMemcpyable;

1223

1224 public:

1227 : FieldMemcpyizer(CGF, AD->getParent(), Args[Args.size() - 1]),

1228 AssignmentsMemcpyable(CGF.getLangOpts().getGC() == LangOptions::NonGC) {

1229 assert(Args.size() == 2);

1230 }

1231

1232 void emitAssignment(Stmt *S) {

1233 FieldDecl *F = getMemcpyableField(S);

1234 if (F) {

1235 addMemcpyableField(F);

1236 AggregatedStmts.push_back(S);

1237 } else {

1238 emitAggregatedStmts();

1240 }

1241 }

1242

1243 void emitAggregatedStmts() {

1244 if (AggregatedStmts.size() <= 1) {

1245 if (!AggregatedStmts.empty()) {

1246 CopyingValueRepresentation CVR(CGF);

1247 CGF.EmitStmt(AggregatedStmts[0]);

1248 }

1249 reset();

1250 }

1251

1252 emitMemcpy();

1253 AggregatedStmts.clear();

1254 }

1255

1256 void finish() {

1257 emitAggregatedStmts();

1258 }

1259 };

1260}

1261

1264 const auto *BaseClassDecl =

1266 return BaseClassDecl->isDynamicClass();

1267}

1268

1269

1270

1276

1278

1281

1282

1283

1284

1285

1286

1287

1288

1289 bool ConstructVBases = CtorType != Ctor_Base &&

1292

1293

1294

1295

1296 llvm::BasicBlock *BaseCtorContinueBB = nullptr;

1297 if (ConstructVBases &&

1299 BaseCtorContinueBB =

1301 assert(BaseCtorContinueBB);

1302 }

1303

1304 for (; B != E && (*B)->isBaseInitializer() && (*B)->isBaseVirtual(); B++) {

1305 if (!ConstructVBases)

1306 continue;

1313 }

1314

1315 if (BaseCtorContinueBB) {

1316

1317 Builder.CreateBr(BaseCtorContinueBB);

1319 }

1320

1321

1322 for (; B != E && (*B)->isBaseInitializer(); B++) {

1323 assert(!(*B)->isBaseVirtual());

1330 }

1331

1333

1334

1336 ConstructorMemcpyizer CM(*this, CD, Args);

1337 for (; B != E; B++) {

1339 assert(Member->isBaseInitializer());

1340 assert(Member->isAnyMemberInitializer() &&

1341 "Delegating initializer on non-delegating constructor");

1342 CM.addMemberInitializer(Member);

1343 }

1344 CM.finish();

1345}

1346

1347static bool

1349

1350static bool

1354{

1355

1357 return true;

1358

1360 return false;

1361

1362

1363 for (const auto *Field : BaseClassDecl->fields())

1365 return false;

1366

1367

1368 for (const auto &I : BaseClassDecl->bases()) {

1369 if (I.isVirtual())

1370 continue;

1371

1373 cast(I.getType()->castAs<RecordType>()->getDecl());

1375 MostDerivedClassDecl))

1376 return false;

1377 }

1378

1379 if (BaseClassDecl == MostDerivedClassDecl) {

1380

1381 for (const auto &I : BaseClassDecl->vbases()) {

1383 cast(I.getType()->castAs<RecordType>()->getDecl());

1385 MostDerivedClassDecl))

1386 return false;

1387 }

1388 }

1389

1390 return true;

1391}

1392

1393static bool

1396{

1398

1400 if (!RT)

1401 return true;

1402

1404

1405

1407 return true;

1408

1410}

1411

1412

1413

1418 return true;

1419

1420

1421

1423 return true;

1424

1426 return false;

1427

1428

1429 for (const auto *Field : ClassDecl->fields())

1431 return false;

1432

1433 return true;

1434}

1435

1436

1440

1441

1442

1443

1444

1445

1447 llvm::CallInst *TrapCall = EmitTrapCall(llvm::Intrinsic::trap);

1448 TrapCall->setDoesNotReturn();

1449 TrapCall->setDoesNotThrow();

1450 Builder.CreateUnreachable();

1451 Builder.ClearInsertionPoint();

1452 return;

1453 }

1454

1456 if (Body) {

1459 }

1460

1461

1462

1463

1464

1466 RunCleanupsScope DtorEpilogue(*this);

1472 }

1473 return;

1474 }

1475

1476

1477

1478 bool isTryBody = isa_and_nonnull(Body);

1479 if (isTryBody)

1482

1483

1484 RunCleanupsScope DtorEpilogue(*this);

1485

1486

1487

1488

1489

1490

1491 switch (DtorType) {

1492 case Dtor_Comdat: llvm_unreachable("not expecting a COMDAT");

1493 case Dtor_Deleting: llvm_unreachable("already handled deleting case");

1494

1496 assert((Body || getTarget().getCXXABI().isMicrosoft()) &&

1497 "can't emit a dtor without a body for non-Microsoft ABIs");

1498

1499

1501

1502 if (!isTryBody) {

1506 break;

1507 }

1508

1509

1510 [[fallthrough]];

1511

1513 assert(Body);

1514

1515

1517

1518

1520

1521

1526 }

1527

1528 if (isTryBody)

1529 EmitStmt(cast(Body)->getTryBlock());

1530 else if (Body)

1532 else {

1533 assert(Dtor->isImplicit() && "bodyless dtor not implicit");

1534

1535 }

1536

1537

1539 CurFn->addFnAttr(llvm::Attribute::AlwaysInline);

1540

1541 break;

1542 }

1543

1544

1545 DtorEpilogue.ForceCleanup();

1546

1547

1548 if (isTryBody)

1550}

1551

1554 const Stmt *RootS = AssignOp->getBody();

1555 assert(isa(RootS) &&

1556 "Body of an implicit assignment operator should be compound stmt.");

1557 const CompoundStmt *RootCS = cast(RootS);

1558

1560

1563 AssignmentMemcpyizer AM(*this, AssignOp, Args);

1564 for (auto *I : RootCS->body())

1565 AM.emitAssignment(I);

1566 AM.finish();

1567}

1568

1569namespace {

1570 llvm::Value *LoadThisForDtorDelete(CodeGenFunction &CGF,

1575 }

1576

1577

1579 CallDtorDelete() {}

1580

1585 LoadThisForDtorDelete(CGF, Dtor),

1587 }

1588 };

1589

1590 void EmitConditionalDtorDeleteCall(CodeGenFunction &CGF,

1591 llvm::Value *ShouldDeleteCondition,

1592 bool ReturnAfterDelete) {

1593 llvm::BasicBlock *callDeleteBB = CGF.createBasicBlock("dtor.call_delete");

1594 llvm::BasicBlock *continueBB = CGF.createBasicBlock("dtor.continue");

1595 llvm::Value *ShouldCallDelete

1597 CGF.Builder.CreateCondBr(ShouldCallDelete, continueBB, callDeleteBB);

1598

1603 LoadThisForDtorDelete(CGF, Dtor),

1606 ReturnAfterDelete &&

1607 "unexpected value for ReturnAfterDelete");

1608 if (ReturnAfterDelete)

1610 else

1611 CGF.Builder.CreateBr(continueBB);

1612

1614 }

1615

1617 llvm::Value *ShouldDeleteCondition;

1618

1619 public:

1620 CallDtorDeleteConditional(llvm::Value *ShouldDeleteCondition)

1621 : ShouldDeleteCondition(ShouldDeleteCondition) {

1622 assert(ShouldDeleteCondition != nullptr);

1623 }

1624

1626 EmitConditionalDtorDeleteCall(CGF, ShouldDeleteCondition,

1627 false);

1628 }

1629 };

1630

1633 CodeGenFunction::Destroyer *destroyer;

1634 bool useEHCleanupForArray;

1635

1636 public:

1637 DestroyField(const FieldDecl *field, CodeGenFunction::Destroyer *destroyer,

1638 bool useEHCleanupForArray)

1639 : field(field), destroyer(destroyer),

1640 useEHCleanupForArray(useEHCleanupForArray) {}

1641

1643

1649

1651 flags.isForNormalCleanup() && useEHCleanupForArray);

1652 }

1653 };

1654

1655 class DeclAsInlineDebugLocation {

1657 llvm::MDNode *InlinedAt;

1658 std::optional Location;

1659

1660 public:

1662 : DI(CGF.getDebugInfo()) {

1663 if (!DI)

1664 return;

1668 }

1669

1670 ~DeclAsInlineDebugLocation() {

1671 if (!DI)

1672 return;

1673 Location.reset();

1675 }

1676 };

1677

1678 static void EmitSanitizerDtorCallback(

1680 std::optionalCharUnits::QuantityType PoisonSize = {}) {

1681 CodeGenFunction::SanitizerScope SanScope(&CGF);

1682

1683

1686

1687 if (PoisonSize.has_value()) {

1688 Args.emplace_back(llvm::ConstantInt::get(CGF.SizeTy, *PoisonSize));

1689 ArgTypes.emplace_back(CGF.SizeTy);

1690 }

1691

1692 llvm::FunctionType *FnType =

1693 llvm::FunctionType::get(CGF.VoidTy, ArgTypes, false);

1695

1697 }

1698

1699 static void

1700 EmitSanitizerDtorFieldsCallback(CodeGenFunction &CGF, llvm::Value *Ptr,

1702 EmitSanitizerDtorCallback(CGF, "__sanitizer_dtor_callback_fields", Ptr,

1703 PoisonSize);

1704 }

1705

1706

1709 bool BaseIsVirtual;

1710 SanitizeDtorTrivialBase(const CXXRecordDecl *Base, bool BaseIsVirtual)

1711 : BaseClass(Base), BaseIsVirtual(BaseIsVirtual) {}

1712

1716

1719

1723

1725 return;

1726

1727

1728

1729 DeclAsInlineDebugLocation InlineHere(CGF, *BaseClass);

1730 EmitSanitizerDtorFieldsCallback(CGF, Addr.emitRawPointer(CGF),

1732

1733

1734 CGF.CurFn->addFnAttr("disable-tail-calls", "true");

1735 }

1736 };

1737

1740 unsigned StartIndex;

1741 unsigned EndIndex;

1742

1743 public:

1744 SanitizeDtorFieldRange(const CXXDestructorDecl *Dtor, unsigned StartIndex,

1745 unsigned EndIndex)

1746 : Dtor(Dtor), StartIndex(StartIndex), EndIndex(EndIndex) {}

1747

1748

1749

1750

1755

1756

1757

1760 llvm::ConstantInt *OffsetSizePtr =

1762

1763 llvm::Value *OffsetPtr =

1765

1769 } else {

1770 PoisonEnd =

1772 }

1773 CharUnits PoisonSize = PoisonEnd - PoisonStart;

1775 return;

1776

1777

1778 DeclAsInlineDebugLocation InlineHere(

1779 CGF, **std::next(Dtor->getParent()->field_begin(), StartIndex));

1780 EmitSanitizerDtorFieldsCallback(CGF, OffsetPtr, PoisonSize.getQuantity());

1781

1782

1783 CGF.CurFn->addFnAttr("disable-tail-calls", "true");

1784 }

1785 };

1786

1789

1790 public:

1791 SanitizeDtorVTable(const CXXDestructorDecl *Dtor) : Dtor(Dtor) {}

1792

1793

1795 assert(Dtor->getParent()->isDynamicClass());

1796 (void)Dtor;

1797

1798 llvm::Value *VTablePtr = CGF.LoadCXXThis();

1799

1800

1801

1802 EmitSanitizerDtorCallback(CGF, "__sanitizer_dtor_callback_vptr",

1803 VTablePtr);

1804 }

1805 };

1806

1807 class SanitizeDtorCleanupBuilder {

1811 std::optional StartIndex;

1812

1813 public:

1816 : Context(Context), EHStack(EHStack), DD(DD), StartIndex(std::nullopt) {}

1817 void PushCleanupForField(const FieldDecl *Field) {

1819 return;

1820 unsigned FieldIndex = Field->getFieldIndex();

1822 if (!StartIndex)

1823 StartIndex = FieldIndex;

1824 } else if (StartIndex) {

1826 *StartIndex, FieldIndex);

1827 StartIndex = std::nullopt;

1828 }

1829 }

1830 void End() {

1831 if (StartIndex)

1833 *StartIndex, -1);

1834 }

1835 };

1836}

1837

1838

1839

1840

1841

1842

1843

1846 assert((!DD->isTrivial() || DD->hasAttr()) &&

1847 "Should not emit dtor epilogue for non-exported trivial dtor!");

1848

1849

1850

1853 "operator delete missing - EnterDtorCleanups");

1854 if (CXXStructorImplicitParamValue) {

1855

1856

1858 EmitConditionalDtorDeleteCall(*this, CXXStructorImplicitParamValue,

1859 true);

1860 else

1861 EHStack.pushCleanup(

1863 } else {

1867 LoadThisForDtorDelete(*this, DD),

1868 getContext().getTagDeclType(ClassDecl));

1870 } else {

1872 }

1873 }

1874 return;

1875 }

1876

1878

1879

1880 if (ClassDecl->isUnion())

1881 return;

1882

1883

1885

1886

1891

1892

1893

1894 for (const auto &Base : ClassDecl->vbases()) {

1895 auto *BaseClassDecl =

1897

1898 if (BaseClassDecl->hasTrivialDestructor()) {

1899

1900

1901

1903 SanOpts.has(SanitizerKind::Memory) && !BaseClassDecl->isEmpty())

1905 BaseClassDecl,

1906 true);

1907 } else {

1909 true);

1910 }

1911 }

1912

1913 return;

1914 }

1915

1917

1918

1923

1924

1925 for (const auto &Base : ClassDecl->bases()) {

1926

1927 if (Base.isVirtual())

1928 continue;

1929

1930 CXXRecordDecl *BaseClassDecl = Base.getType()->getAsCXXRecordDecl();

1931

1934 SanOpts.has(SanitizerKind::Memory) && !BaseClassDecl->isEmpty())

1936 BaseClassDecl,

1937 false);

1938 } else {

1940 false);

1941 }

1942 }

1943

1944

1945

1946 bool SanitizeFields = CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor &&

1948 SanitizeDtorCleanupBuilder SanitizeBuilder(getContext(), EHStack, DD);

1949

1950

1951 for (const auto *Field : ClassDecl->fields()) {

1952 if (SanitizeFields)

1953 SanitizeBuilder.PushCleanupForField(Field);

1954

1957 if (!dtorKind)

1958 continue;

1959

1960

1963 continue;

1964

1966 EHStack.pushCleanup(

1968 }

1969

1970 if (SanitizeFields)

1971 SanitizeBuilder.End();

1972}

1973

1974

1975

1976

1977

1978

1979

1980

1981

1985 bool zeroInitialize) {

1987 llvm::Value *numElements =

1989

1991 NewPointerIsChecked, zeroInitialize);

1992}

1993

1994

1995

1996

1997

1998

1999

2000

2001

2002

2004 llvm::Value *numElements,

2007 bool NewPointerIsChecked,

2008 bool zeroInitialize) {

2009

2010

2011

2012

2013

2014 llvm::BranchInst *zeroCheckBranch = nullptr;

2015

2016

2017 llvm::ConstantInt *constantCount

2018 = dyn_castllvm::ConstantInt(numElements);

2019 if (constantCount) {

2020

2021 if (constantCount->isZero()) return;

2022

2023

2024 } else {

2025 llvm::BasicBlock *loopBB = createBasicBlock("new.ctorloop");

2027 zeroCheckBranch = Builder.CreateCondBr(iszero, loopBB, loopBB);

2029 }

2030

2031

2032 llvm::Type *elementType = arrayBase.getElementType();

2033 llvm::Value *arrayBegin = arrayBase.emitRawPointer(*this);

2035 elementType, arrayBegin, numElements, "arrayctor.end");

2036

2037

2038 llvm::BasicBlock *entryBB = Builder.GetInsertBlock();

2039 llvm::BasicBlock *loopBB = createBasicBlock("arrayctor.loop");

2041 llvm::PHINode *cur = Builder.CreatePHI(arrayBegin->getType(), 2,

2042 "arrayctor.cur");

2043 cur->addIncoming(arrayBegin, entryBB);

2044

2045

2046

2047

2048

2049

2050

2051

2052

2057 Address curAddr = Address(cur, elementType, eltAlignment);

2058

2059

2060 if (zeroInitialize)

2062

2063

2064

2065

2066

2067

2068

2069

2070

2071 {

2072 RunCleanupsScope Scope(*this);

2073

2074

2075

2080 *destroyer);

2081 }

2089 false, currAVS, E);

2090 }

2091

2092

2094 elementType, cur, llvm::ConstantInt::get(SizeTy, 1), "arrayctor.next");

2095 cur->addIncoming(next, Builder.GetInsertBlock());

2096

2097

2098 llvm::Value *done = Builder.CreateICmpEQ(next, arrayEnd, "arrayctor.done");

2099 llvm::BasicBlock *contBB = createBasicBlock("arrayctor.cont");

2100 Builder.CreateCondBr(done, contBB, loopBB);

2101

2102

2103 if (zeroCheckBranch) zeroCheckBranch->setSuccessor(0, contBB);

2104

2106}

2107

2116 false, addr, type);

2117}

2118

2121 bool ForVirtualBase,

2128 LangAS ThisAS = D->getFunctionObjectParameterType().getAddressSpace();

2129 llvm::Value *ThisPtr =

2131

2132 if (SlotAS != ThisAS) {

2134 llvm::Type *NewType =

2135 llvm::PointerType::get(getLLVMContext(), TargetThisAS);

2137 SlotAS, NewType);

2138 }

2139

2140

2142

2143

2144

2145

2147 assert(E->getNumArgs() == 1 && "unexpected argcount for trivial ctor");

2148

2149 const Expr *Arg = E->getArg(0);

2154 return;

2155 }

2156

2157

2162 EmitCallArgs(Args, FPT, E->arguments(), E->getConstructor(),

2163 0, Order);

2164

2168}

2169

2173

2175 return false;

2176

2178

2180 if (P->needsDestruction(CGF.getContext()))

2181 return false;

2182

2183

2187 return false;

2188 }

2189

2190

2191 return true;

2192}

2193

2198 bool NewPointerIsChecked, llvm::CallBase **CallOrInvoke) {

2200

2201 if (!NewPointerIsChecked)

2204

2205 if (D->isTrivial() && D->isDefaultConstructor()) {

2206 assert(Args.size() == 1 && "trivial default ctor with args");

2207 return;

2208 }

2209

2210

2211

2212

2214 assert(Args.size() == 2 && "unexpected argcount for trivial ctor");

2215 QualType SrcTy = D->getParamDecl(0)->getType().getNonReferenceType();

2217 Args[1].getRValue(*this).getScalarVal(), SrcTy);

2222 return;

2223 }

2224

2225 bool PassPrototypeArgs = true;

2226

2227 if (auto Inherited = D->getInheritedConstructor()) {

2232 return;

2233 }

2234 }

2235

2236

2240

2241

2244 Args, D, Type, ExtraArgs.Prefix, ExtraArgs.Suffix, PassPrototypeArgs);

2247

2248

2249

2250

2251

2252

2253

2254

2255

2256

2257

2258

2264}

2265

2271 This, D->getThisType()->getPointeeType())),

2272 D->getThisType());

2273

2274

2275 if (InheritedFromVBase &&

2277

2278

2279

2280

2281 Args.push_back(ThisArg);

2282 } else if (!CXXInheritedCtorInitExprArgs.empty()) {

2283

2284 assert(CXXInheritedCtorInitExprArgs.size() >= D->getNumParams() &&

2285 "wrong number of parameters for inherited constructor call");

2286 Args = CXXInheritedCtorInitExprArgs;

2287 Args[0] = ThisArg;

2288 } else {

2289

2290 Args.push_back(ThisArg);

2291 const auto *OuterCtor = cast(CurCodeDecl);

2292 assert(OuterCtor->getNumParams() == D->getNumParams());

2293 assert(!OuterCtor->isVariadic() && "should have been inlined");

2294

2295 for (const auto *Param : OuterCtor->parameters()) {

2296 assert(getContext().hasSameUnqualifiedType(

2297 OuterCtor->getParamDecl(Param->getFunctionScopeIndex())->getType(),

2298 Param->getType()));

2300

2301

2302 if (Param->hasAttr()) {

2303 auto *POSParam = SizeArguments[Param];

2304 assert(POSParam && "missing pass_object_size value for forwarding");

2306 }

2307 }

2308 }

2309

2312 E->getLocation(), true);

2313}

2314

2319 InlinedInheritingConstructorScope Scope(*this, GD);

2321 RunCleanupsScope RunCleanups(*this);

2322

2323

2324 CXXInheritedCtorInitExprArgs = Args;

2325

2329

2330

2333

2334

2335 assert(Args.size() >= Params.size() && "too few arguments for call");

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

2337 if (I < Params.size() && isa(Params[I])) {

2338 const RValue &RV = Args[I].getRValue(*this);

2339 assert(!RV.isComplex() && "complex indirect params not supported");

2340 ParamValue Val = RV.isScalar()

2342 : ParamValue::forIndirect(RV.getAggregateAddress());

2344 }

2345 }

2346

2347

2348

2349

2352

2354 CXXThisValue = CXXABIThisValue;

2355

2356

2358}

2359

2361 llvm::Value *VTableGlobal =

2363 if (!VTableGlobal)

2364 return;

2365

2366

2367 CharUnits NonVirtualOffset = Vptr.Base.getBaseOffset();

2368

2369 if (!NonVirtualOffset.isZero())

2372 Vptr.VTableClass, Vptr.NearestVBase);

2373

2374 llvm::Value *VPtrValue =

2375 GetVTablePtr(This, VTableGlobal->getType(), Vptr.VTableClass);

2376 llvm::Value *Cmp =

2377 Builder.CreateICmpEQ(VPtrValue, VTableGlobal, "cmp.vtables");

2378 Builder.CreateAssumption(Cmp);

2379}

2380

2386}

2387

2388void

2393

2395

2396

2398 D->getThisType());

2399

2400

2404 llvm::Value *SrcVal = Builder.CreateBitCast(Val, t);

2406

2407

2408 EmitCallArgs(Args, FPT, drop_begin(E->arguments(), 1), E->getConstructor(),

2409 1);

2410

2412 false, This, Args,

2414 false);

2415}

2416

2417void

2423

2424 FunctionArgList::const_iterator I = Args.begin(), E = Args.end();

2425 assert(I != E && "no parameters to constructor");

2426

2427

2430 This, (*I)->getType()->getPointeeType())),

2431 (*I)->getType());

2432 ++I;

2433

2434

2435

2437 assert(I != E && "cannot skip vtt parameter, already done with args");

2438 assert((*I)->getType()->isPointerType() &&

2439 "skipping parameter not of vtt type");

2440 ++I;

2441 }

2442

2443

2444 for (; I != E; ++I) {

2445 const VarDecl *param = *I;

2446

2448 }

2449

2451 true, This, DelegateArgs,

2453 true);

2454}

2455

2456namespace {

2461

2464 : Dtor(D), Addr(Addr), Type(Type) {}

2465

2467

2468

2469 QualType ThisTy = Dtor->getFunctionObjectParameterType();

2471 true, Addr, ThisTy);

2472 }

2473 };

2474}

2475

2476void

2480

2482

2490

2492

2494

2499

2502 ThisPtr, Type);

2503 }

2504}

2505

2508 bool ForVirtualBase,

2513}

2514

2515namespace {

2520

2522 : Dtor(D), Addr(Addr), Ty(Ty) {}

2523

2526 false,

2527 false, Addr, Ty);

2528 }

2529 };

2530}

2531

2535}

2536

2539 if (!ClassDecl) return;

2541

2543 assert(D && D->isUsed() && "destructor not marked as used!");

2545}

2546

2548

2549 llvm::Value *VTableAddressPoint =

2551 *this, Vptr.VTableClass, Vptr.Base, Vptr.NearestVBase);

2552

2553 if (!VTableAddressPoint)

2554 return;

2555

2556

2557 llvm::Value *VirtualOffset = nullptr;

2559

2561

2562

2563

2566 NonVirtualOffset = Vptr.OffsetFromNearestVBase;

2567 } else {

2568

2569 NonVirtualOffset = Vptr.Base.getBaseOffset();

2570 }

2571

2572

2574 if (!NonVirtualOffset.isZero() || VirtualOffset)

2576 *this, VTableField, NonVirtualOffset, VirtualOffset, Vptr.VTableClass,

2577 Vptr.NearestVBase);

2578

2579

2580

2581 unsigned GlobalsAS = CGM.getDataLayout().getDefaultGlobalsAddressSpace();

2582 llvm::Type *PtrTy = llvm::PointerType::get(CGM.getLLVMContext(), GlobalsAS);

2583

2584

2586

2588 this, Vptr.Base.getBase(), VTableField.emitRawPointer(*this)))

2589 VTableAddressPoint =

2591

2598}

2599

2605 nullptr,

2607 false, VTableClass, VBases,

2608 VPtrsResult);

2609 return VPtrsResult;

2610}

2611

2614 CharUnits OffsetFromNearestVBase,

2615 bool BaseIsNonVirtualPrimaryBase,

2617 VisitedVirtualBasesSetTy &VBases,

2618 VPtrsVector &Vptrs) {

2619

2620

2621 if (!BaseIsNonVirtualPrimaryBase) {

2622

2623 VPtr Vptr = {Base, NearestVBase, OffsetFromNearestVBase, VTableClass};

2624 Vptrs.push_back(Vptr);

2625 }

2626

2628

2629

2630 for (const auto &I : RD->bases()) {

2631 auto *BaseDecl =

2632 cast(I.getType()->castAs<RecordType>()->getDecl());

2633

2634

2635 if (!BaseDecl->isDynamicClass())

2636 continue;

2637

2639 CharUnits BaseOffsetFromNearestVBase;

2640 bool BaseDeclIsNonVirtualPrimaryBase;

2641

2642 if (I.isVirtual()) {

2643

2644 if (!VBases.insert(BaseDecl).second)

2645 continue;

2646

2649

2652 BaseDeclIsNonVirtualPrimaryBase = false;

2653 } else {

2655

2657 BaseOffsetFromNearestVBase =

2659 BaseDeclIsNonVirtualPrimaryBase = Layout.getPrimaryBase() == BaseDecl;

2660 }

2661

2664 I.isVirtual() ? BaseDecl : NearestVBase, BaseOffsetFromNearestVBase,

2665 BaseDeclIsNonVirtualPrimaryBase, VTableClass, VBases, Vptrs);

2666 }

2667}

2668

2670

2672 return;

2673

2674

2678

2681}

2682

2684 llvm::Type *VTableTy,

2686 VTableAuthMode AuthMode) {

2687 Address VTablePtrSrc = This.withElementType(VTableTy);

2688 llvm::Instruction *VTable = Builder.CreateLoad(VTablePtrSrc, "vtable");

2691

2692 if (auto AuthenticationInfo =

2695 VTable = castllvm::Instruction(

2698

2699

2700

2701 VTable =

2702 castllvm::Instruction(Builder.CreateBitCast(VTable, Int8PtrTy));

2704 true);

2705 }

2706 } else {

2709 nullptr),

2710 VTable));

2711 }

2712 }

2713

2717

2718 return VTable;

2719}

2720

2721

2722

2723

2724

2725

2726

2727

2728

2729

2733 return RD;

2734

2736 return RD;

2737

2739 return RD;

2740

2743

2744

2745

2746 if (isa(MD) && MD->isImplicit())

2747 continue;

2748 return RD;

2749 }

2750 }

2751

2754}

2755

2757 llvm::Value *VTable,

2759 if (SanOpts.has(SanitizerKind::CFIVCall))

2762

2763

2767 llvm::Value *TypeId =

2769

2770

2771

2772

2773

2775 ? llvm::Intrinsic::type_test

2776 : llvm::Intrinsic::public_type_test;

2777 llvm::Value *TypeTest =

2780 }

2781}

2782

2784 llvm::Value *VTable,

2785 CFITypeCheckKind TCK,

2787 if (SanOpts.has(SanitizerKind::CFICastStrict))

2789

2791}

2792

2794 bool MayBeNull,

2795 CFITypeCheckKind TCK,

2798 return;

2799

2801 if (!ClassTy)

2802 return;

2803

2804 const CXXRecordDecl *ClassDecl = cast(ClassTy->getDecl());

2805

2807 return;

2808

2809 if (SanOpts.has(SanitizerKind::CFICastStrict))

2811

2812 llvm::BasicBlock *ContBlock = nullptr;

2813

2814 if (MayBeNull) {

2815 llvm::Value *DerivedNotNull =

2817

2818 llvm::BasicBlock *CheckBlock = createBasicBlock("cast.check");

2820

2821 Builder.CreateCondBr(DerivedNotNull, CheckBlock, ContBlock);

2822

2824 }

2825

2826 llvm::Value *VTable;

2827 std::tie(VTable, ClassDecl) =

2829

2831

2832 if (MayBeNull) {

2833 Builder.CreateBr(ContBlock);

2835 }

2836}

2837

2839 llvm::Value *VTable,

2840 CFITypeCheckKind TCK,

2844 return;

2845

2847 llvm::SanitizerStatKind SSK;

2848 switch (TCK) {

2850 M = SanitizerKind::SO_CFIVCall;

2851 SSK = llvm::SanStat_CFI_VCall;

2852 break;

2854 M = SanitizerKind::SO_CFINVCall;

2855 SSK = llvm::SanStat_CFI_NVCall;

2856 break;

2858 M = SanitizerKind::SO_CFIDerivedCast;

2859 SSK = llvm::SanStat_CFI_DerivedCast;

2860 break;

2862 M = SanitizerKind::SO_CFIUnrelatedCast;

2863 SSK = llvm::SanStat_CFI_UnrelatedCast;

2864 break;

2868 llvm_unreachable("unexpected sanitizer kind");

2869 }

2870

2872 if (getContext().getNoSanitizeList().containsType(

2874 return;

2875

2876 SanitizerScope SanScope(this);

2878

2879 llvm::Metadata *MD =

2881 llvm::Value *TypeId = llvm::MetadataAsValue::get(getLLVMContext(), MD);

2882

2883 llvm::Value *TypeTest = Builder.CreateCall(

2884 CGM.getIntrinsic(llvm::Intrinsic::type_test), {VTable, TypeId});

2885

2886 llvm::Constant *StaticData[] = {

2887 llvm::ConstantInt::get(Int8Ty, TCK),

2890 };

2891

2893 if (CGM.getCodeGenOpts().SanitizeCfiCrossDso && CrossDsoTypeId) {

2895 return;

2896 }

2897

2899 EmitTrapCheck(TypeTest, SanitizerHandler::CFICheckFail);

2900 return;

2901 }

2902

2903 llvm::Value *AllVtables = llvm::MetadataAsValue::get(

2906 llvm::Value *ValidVtable = Builder.CreateCall(

2907 CGM.getIntrinsic(llvm::Intrinsic::type_test), {VTable, AllVtables});

2908 EmitCheck(std::make_pair(TypeTest, M), SanitizerHandler::CFICheckFail,

2909 StaticData, {VTable, ValidVtable});

2910}

2911

2915 return false;

2916

2918 return true;

2919

2920 if (SanOpts.has(SanitizerKind::CFIVCall) ||

2922 return false;

2923

2926 TypeName);

2927}

2928

2930 const CXXRecordDecl *RD, llvm::Value *VTable, llvm::Type *VTableTy,

2931 uint64_t VTableByteOffset) {

2932 SanitizerScope SanScope(this);

2933

2935

2936 llvm::Metadata *MD =

2938 llvm::Value *TypeId = llvm::MetadataAsValue::get(CGM.getLLVMContext(), MD);

2939

2940 llvm::Value *CheckedLoad = Builder.CreateCall(

2942 {VTable, llvm::ConstantInt::get(Int32Ty, VTableByteOffset), TypeId});

2943 llvm::Value *CheckResult = Builder.CreateExtractValue(CheckedLoad, 1);

2944

2946 if (SanOpts.has(SanitizerKind::CFIVCall) &&

2947 getContext().getNoSanitizeList().containsType(SanitizerKind::CFIVCall,

2948 TypeName)) {

2949 EmitCheck(std::make_pair(CheckResult, SanitizerKind::SO_CFIVCall),

2950 SanitizerHandler::CFICheckFail, {}, {});

2951 }

2952

2953 return Builder.CreateBitCast(Builder.CreateExtractValue(CheckedLoad, 0),

2954 VTableTy);

2955}

2956

2959 const CGFunctionInfo *calleeFnInfo, llvm::Constant *calleePtr) {

2960

2961 if (!calleeFnInfo)

2963

2964 if (!calleePtr)

2965 calleePtr =

2968

2969

2974 if (!resultType->isVoidType() &&

2977 returnSlot =

2979 false, true);

2980

2981

2982

2983

2984

2985

2987 RValue RV = EmitCall(*calleeFnInfo, callee, returnSlot, callArgs);

2988

2989

2990 if (!resultType->isVoidType() && returnSlot.isNull()) {

2991 if (getLangOpts().ObjCAutoRefCount && resultType->isObjCRetainableType()) {

2993 }

2994 EmitReturnOfRValue(RV, resultType);

2995 } else

2997}

2998

3004

3006

3007

3008

3010 return;

3011 }

3012

3013

3015

3019

3020

3021 for (auto *param : BD->parameters())

3023

3025 "generic lambda interconversion to block not implemented");

3027}

3028

3031

3032

3033

3035 return;

3036 }

3037

3039

3040

3042

3047

3049}

3050

3053

3054 for (auto *Param : MD->parameters())

3056

3059

3060

3065 void *InsertPos = nullptr;

3066 FunctionDecl *CorrespondingCallOpSpecialization =

3068 assert(CorrespondingCallOpSpecialization);

3069 CallOp = cast(CorrespondingCallOpSpecialization);

3070 }

3071

3072

3073 if (hasInAllocaArg(MD)) {

3075 llvm::Function *ImplFn = nullptr;

3077

3079 return;

3080 }

3081

3083}

3084

3087

3088

3090 return;

3091 }

3092

3093

3097 llvm::Value *ThisArg = CurFn->getArg(0);

3099

3101}

3102

3105 llvm::Function **ImplFn) {

3108 llvm::Function *CallOpFn =

3110

3111

3112

3114 for (auto I = FnInfo.arg_begin(); I != FnInfo.arg_end(); ++I)

3115 ArgTypes.push_back(I->type);

3119

3120

3121

3122

3123

3124

3125 StringRef CallOpName = CallOpFn->getName();

3126 std::string ImplName;

3127 if (size_t Pos = CallOpName.find_first_of("<lambda"))

3128 ImplName = ("?__impl@" + CallOpName.drop_front(Pos)).str();

3129 else

3130 ImplName = ("__impl" + CallOpName).str();

3131

3132 llvm::Function *Fn = CallOpFn->getParent()->getFunction(ImplName);

3133 if (!Fn) {

3135 llvm::GlobalValue::InternalLinkage, ImplName,

3138

3140 const auto *D = cast(GD.getDecl());

3143 }

3144 *ImplFn = Fn;

3145}

static Address ApplyNonVirtualAndVirtualOffset(CodeGenFunction &CGF, Address addr, CharUnits nonVirtualOffset, llvm::Value *virtualOffset, const CXXRecordDecl *derivedClass, const CXXRecordDecl *nearestVBase)

static bool canEmitDelegateCallArgs(CodeGenFunction &CGF, const CXXConstructorDecl *Ctor, CXXCtorType Type, CallArgList &Args)

static bool CanSkipVTablePointerInitialization(CodeGenFunction &CGF, const CXXDestructorDecl *Dtor)

CanSkipVTablePointerInitialization - Check whether we need to initialize any vtable pointers before c...

static bool isInitializerOfDynamicClass(const CXXCtorInitializer *BaseInit)

static const CXXRecordDecl * LeastDerivedClassWithSameLayout(const CXXRecordDecl *RD)

static void EmitBaseInitializer(CodeGenFunction &CGF, const CXXRecordDecl *ClassDecl, CXXCtorInitializer *BaseInit)

static bool isMemcpyEquivalentSpecialMember(const CXXMethodDecl *D)

static bool BaseInitializerUsesThis(ASTContext &C, const Expr *Init)

static bool FieldHasTrivialDestructorBody(ASTContext &Context, const FieldDecl *Field)

static bool HasTrivialDestructorBody(ASTContext &Context, const CXXRecordDecl *BaseClassDecl, const CXXRecordDecl *MostDerivedClassDecl)

static void EmitMemberInitializer(CodeGenFunction &CGF, const CXXRecordDecl *ClassDecl, CXXCtorInitializer *MemberInit, const CXXConstructorDecl *Constructor, FunctionArgList &Args)

static void EmitLValueForAnyFieldInitialization(CodeGenFunction &CGF, CXXCtorInitializer *MemberInit, LValue &LHS)

Defines the C++ template declaration subclasses.

static const RecordType * getRecordType(QualType QT)

Checks that the passed in QualType either is of RecordType or points to RecordType.

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

const ConstantArrayType * getAsConstantArrayType(QualType T) const

QualType getTagDeclType(const TagDecl *Decl) const

Return the unique reference to the type for the specified TagDecl (struct/union/class/enum) decl.

QualType getRecordType(const RecordDecl *Decl) const

const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const

Get or compute information about the layout of the specified record (struct/union/class) D,...

CanQualType getCanonicalType(QualType T) const

Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...

QualType getPointerType(QualType T) const

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

QualType getTypeDeclType(const TypeDecl *Decl, const TypeDecl *PrevDecl=nullptr) const

Return the unique reference to the type for the specified type declaration.

const LangOptions & getLangOpts() const

QualType getBaseElementType(const ArrayType *VAT) const

Return the innermost element type of an array type.

const NoSanitizeList & getNoSanitizeList() const

TypeInfoChars getTypeInfoDataSizeInChars(QualType T) const

TypeInfoChars getTypeInfoInChars(const Type *T) const

int64_t toBits(CharUnits CharSize) const

Convert a size in characters to a size in bits.

CharUnits toCharUnitsFromBits(int64_t BitSize) const

Convert a size in bits to a size in characters.

unsigned getTargetAddressSpace(LangAS AS) const

uint64_t getCharWidth() const

Return the size of the character type, in bits.

ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...

CharUnits getAlignment() const

getAlignment - Get the record alignment in characters.

CharUnits getSize() const

getSize - Get the record size in characters.

unsigned getFieldCount() const

getFieldCount - Get the number of fields in the layout.

uint64_t getFieldOffset(unsigned FieldNo) const

getFieldOffset - Get the offset of the given field index, in bits.

CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const

getBaseClassOffset - Get the offset, in chars, for the given base class.

CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const

getVBaseClassOffset - Get the offset, in chars, for the given base class.

const CXXRecordDecl * getPrimaryBase() const

getPrimaryBase - Get the primary base for this record.

CharUnits getNonVirtualSize() const

getNonVirtualSize - Get the non-virtual size (in chars) of an object, which is the size of the object...

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

A builtin binary operation expression such as "x + y" or "x <= y".

Represents a block literal declaration, which is like an unnamed FunctionDecl.

capture_const_iterator capture_begin() const

ArrayRef< ParmVarDecl * > parameters() const

Represents a base class of a C++ class.

QualType getType() const

Retrieves the type of the base class.

Represents a call to a C++ constructor.

Expr * getArg(unsigned Arg)

Return the specified argument.

CXXConstructorDecl * getConstructor() const

Get the constructor that this expression will (ultimately) call.

Represents a C++ constructor within a class.

init_iterator init_end()

Retrieve an iterator past the last initializer.

init_iterator init_begin()

Retrieve an iterator to the first initializer.

bool isDelegatingConstructor() const

Determine whether this constructor is a delegating constructor.

bool isCopyOrMoveConstructor(unsigned &TypeQuals) const

Determine whether this is a copy or move constructor.

CXXCtorInitializer *const * init_const_iterator

Iterates through the member/base initializer list.

Represents a C++ base or member initializer.

FieldDecl * getMember() const

If this is a member initializer, returns the declaration of the non-static data member being initiali...

Expr * getInit() const

Get the initializer.

SourceLocation getSourceLocation() const

Determine the source location of the initializer.

bool isAnyMemberInitializer() const

bool isBaseInitializer() const

Determine whether this initializer is initializing a base class.

bool isIndirectMemberInitializer() const

const Type * getBaseClass() const

If this is a base class initializer, returns the type of the base class.

FieldDecl * getAnyMember() const

IndirectFieldDecl * getIndirectMember() const

bool isBaseVirtual() const

Returns whether the base is virtual or not.

Represents a C++ destructor within a class.

const FunctionDecl * getOperatorDelete() const

Expr * getOperatorDeleteThisArg() const

Represents a call to an inherited base class constructor from an inheriting constructor.

Represents a call to a member function that may be written either with member call syntax (e....

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

const CXXRecordDecl * getParent() const

Return the parent of this method declaration, which is the class in which this method is defined.

QualType getFunctionObjectParameterType() const

Represents a C++ struct/union/class.

bool isEffectivelyFinal() const

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

bool isGenericLambda() const

Determine whether this class describes a generic lambda function object (i.e.

bool hasTrivialDestructor() const

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

method_range methods() const

bool isPolymorphic() const

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

unsigned getNumBases() const

Retrieves the number of base classes of this class.

base_class_iterator bases_begin()

base_class_range vbases()

bool isAbstract() const

Determine whether this class has a pure virtual function.

bool isDynamicClass() const

bool hasDefinition() const

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.

CXXMethodDecl * getLambdaCallOperator() const

Retrieve the lambda call operator of the closure type if this is a closure type.

unsigned getNumVBases() const

Retrieves the number of virtual base classes of this class.

Represents the this expression in C++.

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

const CXXBaseSpecifier *const * path_const_iterator

CharUnits - This is an opaque type for sizes expressed in character units.

CharUnits alignmentAtOffset(CharUnits offset) const

Given that this is a non-zero alignment value, what is the alignment at the given offset?

bool isPositive() const

isPositive - Test whether the quantity is greater than zero.

bool isZero() const

isZero - Test whether the quantity equals zero.

QuantityType getQuantity() const

getQuantity - Get the raw integer representation of this quantity.

static CharUnits One()

One - Construct a CharUnits quantity of one.

CharUnits alignmentOfArrayElement(CharUnits elementSize) const

Given that this is the alignment of the first element of an array, return the minimum alignment of an...

static CharUnits Zero()

Zero - Construct a CharUnits quantity of zero.

SanitizerSet SanitizeTrap

Set of sanitizer checks that trap rather than diagnose.

@ Indirect

Indirect - Pass the argument indirectly via a hidden pointer with the specified alignment (0 indicate...

Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...

llvm::Value * emitRawPointer(CodeGenFunction &CGF) const

Return the pointer contained in this class after authenticating it and adding offset to it if necessa...

CharUnits getAlignment() const

llvm::Type * getElementType() const

Return the type of the values stored in this address.

Address withElementType(llvm::Type *ElemTy) const

Return address with different element type, but same pointer and alignment.

llvm::PointerType * getType() const

Return the type of the pointer value.

bool isSanitizerChecked() const

Address getAddress() const

Qualifiers getQualifiers() const

static AggValueSlot forLValue(const LValue &LV, IsDestructed_t isDestructed, NeedsGCBarriers_t needsGC, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed, IsSanitizerChecked_t isChecked=IsNotSanitizerChecked)

static AggValueSlot forAddr(Address addr, Qualifiers quals, IsDestructed_t isDestructed, NeedsGCBarriers_t needsGC, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed, IsSanitizerChecked_t isChecked=IsNotSanitizerChecked)

forAddr - Make a slot for an aggregate value.

Overlap_t mayOverlap() const

A scoped helper to set the current debug location to the specified location or preferred location of ...

A scoped helper to set the current debug location to an inlined location.

const BlockDecl * getBlockDecl() const

llvm::StoreInst * CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile=false)

Address CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset, const llvm::Twine &Name="")

Given a pointer to i8, adjust it by a given constant offset.

llvm::Value * CreateIsNull(Address Addr, const Twine &Name="")

Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index, const llvm::Twine &Name="")

llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")

Address CreateLaunderInvariantGroup(Address Addr)

llvm::CallInst * CreateMemCpy(Address Dest, Address Src, llvm::Value *Size, bool IsVolatile=false)

Address CreateInBoundsGEP(Address Addr, ArrayRef< llvm::Value * > IdxList, llvm::Type *ElementType, CharUnits Align, const Twine &Name="")

virtual llvm::Value * getVTableAddressPointInStructor(CodeGenFunction &CGF, const CXXRecordDecl *RD, BaseSubobject Base, const CXXRecordDecl *NearestVBase)=0

Get the address point of the vtable for the given base subobject while building a constructor or a de...

virtual void initializeHiddenVirtualInheritanceMembers(CodeGenFunction &CGF, const CXXRecordDecl *RD)

Emit the code to initialize hidden members required to handle virtual inheritance,...

virtual size_t getSrcArgforCopyCtor(const CXXConstructorDecl *, FunctionArgList &Args) const =0

virtual bool isVirtualOffsetNeededForVTableField(CodeGenFunction &CGF, CodeGenFunction::VPtr Vptr)=0

Checks if ABI requires extra virtual offset for vtable field.

virtual void EmitInstanceFunctionProlog(CodeGenFunction &CGF)=0

Emit the ABI-specific prolog for the function.

virtual bool NeedsVTTParameter(GlobalDecl GD)

Return whether the given global decl needs a VTT parameter.

virtual bool canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const =0

Determine whether it's possible to emit a vtable for RD, even though we do not know that the vtable h...

virtual llvm::Constant * getVTableAddressPoint(BaseSubobject Base, const CXXRecordDecl *VTableClass)=0

Get the address point of the vtable for the given base subobject.

virtual llvm::Value * EmitMemberDataPointerAddress(CodeGenFunction &CGF, const Expr *E, Address Base, llvm::Value *MemPtr, const MemberPointerType *MPT)

Calculate an l-value from an object and a data member pointer.

virtual std::pair< llvm::Value *, const CXXRecordDecl * > LoadVTablePtr(CodeGenFunction &CGF, Address This, const CXXRecordDecl *RD)=0

Load a vtable from This, an object of polymorphic type RD, or from one of its virtual bases if it doe...

virtual llvm::BasicBlock * EmitCtorCompleteObjectHandler(CodeGenFunction &CGF, const CXXRecordDecl *RD)

virtual bool doStructorsInitializeVPtrs(const CXXRecordDecl *VTableClass)=0

Checks if ABI requires to initialize vptrs for given dynamic class.

virtual llvm::Value * GetVirtualBaseClassOffset(CodeGenFunction &CGF, Address This, const CXXRecordDecl *ClassDecl, const CXXRecordDecl *BaseClassDecl)=0

virtual void EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD, CXXDtorType Type, bool ForVirtualBase, bool Delegating, Address This, QualType ThisTy)=0

Emit the destructor call.

AddedStructorArgCounts addImplicitConstructorArgs(CodeGenFunction &CGF, const CXXConstructorDecl *D, CXXCtorType Type, bool ForVirtualBase, bool Delegating, CallArgList &Args)

Add any ABI-specific implicit arguments needed to call a constructor.

All available information about a concrete callee.

static CGCallee forDirect(llvm::Constant *functionPtr, const CGCalleeInfo &abstractInfo=CGCalleeInfo())

This class gathers all debug information during compilation and is responsible for emitting to llvm g...

llvm::MDNode * getInlinedAt() const

void setInlinedAt(llvm::MDNode *InlinedAt)

Update the current inline scope.

CGFunctionInfo - Class to encapsulate the information about a function definition.

bool usesInAlloca() const

Return true if this function uses inalloca arguments.

FunctionType::ExtInfo getExtInfo() const

ABIArgInfo & getReturnInfo()

const_arg_iterator arg_begin() const

CanQualType getReturnType() const

const_arg_iterator arg_end() const

RequiredArgs getRequiredArgs() const

CGRecordLayout - This class handles struct and union layout info while lowering AST types to LLVM typ...

const CGBitFieldInfo & getBitFieldInfo(const FieldDecl *FD) const

Return the BitFieldInfo that corresponds to the field FD.

CallArgList - Type for representing both the value and type of arguments in a call.

void add(RValue rvalue, QualType type)

static ParamValue forDirect(llvm::Value *value)

CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...

llvm::Value * EmitPointerAuthAuth(const CGPointerAuthInfo &Info, llvm::Value *Pointer)

void EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D, Address This, Address Src, const CXXConstructExpr *E)

void EmitDestructorBody(FunctionArgList &Args)

void EmitNullInitialization(Address DestPtr, QualType Ty)

EmitNullInitialization - Generate code to set a value of the given type to null, If the type contains...

GlobalDecl CurGD

CurGD - The GlobalDecl for the current function being compiled.

llvm::Value * GetVTablePtr(Address This, llvm::Type *VTableTy, const CXXRecordDecl *VTableClass, VTableAuthMode AuthMode=VTableAuthMode::Authenticate)

GetVTablePtr - Return the Value of the vtable pointer member pointed to by This.

Address EmitCXXMemberDataPointerAddress(const Expr *E, Address base, llvm::Value *memberPtr, const MemberPointerType *memberPtrType, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr)

void EmitAsanPrologueOrEpilogue(bool Prologue)

static TypeEvaluationKind getEvaluationKind(QualType T)

getEvaluationKind - Return the TypeEvaluationKind of QualType T.

void EmitLambdaInAllocaImplFn(const CXXMethodDecl *CallOp, const CGFunctionInfo **ImplFnInfo, llvm::Function **ImplFn)

llvm::CallInst * EmitTrapCall(llvm::Intrinsic::ID IntrID)

Emit a call to trap or debugtrap and attach function attribute "trap-func-name" if specified.

bool sanitizePerformTypeCheck() const

Whether any type-checking sanitizers are enabled.

void EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor, CXXCtorType CtorType, const FunctionArgList &Args, SourceLocation Loc)

void EmitSanitizerStatReport(llvm::SanitizerStatKind SSK)

void EmitDelegatingCXXConstructorCall(const CXXConstructorDecl *Ctor, const FunctionArgList &Args)

SanitizerSet SanOpts

Sanitizers enabled for this function.

void EmitForwardingCallToLambda(const CXXMethodDecl *LambdaCallOperator, CallArgList &CallArgs, const CGFunctionInfo *CallOpFnInfo=nullptr, llvm::Constant *CallOpFn=nullptr)

void EmitVTableAssumptionLoad(const VPtr &vptr, Address This)

Emit assumption that vptr load == global vtable.

void EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD)

void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit=false)

EmitStoreThroughLValue - Store the specified rvalue into the specified lvalue, where both are guarant...

static bool hasScalarEvaluationKind(QualType T)

void EmitVTablePtrCheckForCall(const CXXRecordDecl *RD, llvm::Value *VTable, CFITypeCheckKind TCK, SourceLocation Loc)

EmitVTablePtrCheckForCall - Virtual method MD is being called via VTable.

void EmitCallArgs(CallArgList &Args, PrototypeWrapper Prototype, llvm::iterator_range< CallExpr::const_arg_iterator > ArgRange, AbstractCallee AC=AbstractCallee(), unsigned ParamsToSkip=0, EvaluationOrder Order=EvaluationOrder::Default)

void EmitTrapCheck(llvm::Value *Checked, SanitizerHandler CheckHandlerID, bool NoMerge=false)

Create a basic block that will call the trap intrinsic, and emit a conditional branch to it,...

llvm::Value * EmitARCRetainAutoreleasedReturnValue(llvm::Value *value)

llvm::Value * emitArrayLength(const ArrayType *arrayType, QualType &baseType, Address &addr)

emitArrayLength - Compute the length of an array, even if it's a VLA, and drill down to the base elem...

void EmitCXXAggrConstructorCall(const CXXConstructorDecl *D, const ArrayType *ArrayTy, Address ArrayPtr, const CXXConstructExpr *E, bool NewPointerIsChecked, bool ZeroInitialization=false)

AggValueSlot::Overlap_t getOverlapForBaseInit(const CXXRecordDecl *RD, const CXXRecordDecl *BaseRD, bool IsVirtual)

Determine whether a base class initialization may overlap some other object.

void EmitCXXDestructorCall(const CXXDestructorDecl *D, CXXDtorType Type, bool ForVirtualBase, bool Delegating, Address This, QualType ThisTy)

LValue EmitLValue(const Expr *E, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)

EmitLValue - Emit code to compute a designator that specifies the location of the expression.

void EmitVTablePtrCheckForCast(QualType T, Address Derived, bool MayBeNull, CFITypeCheckKind TCK, SourceLocation Loc)

Derived is the presumed address of an object of type T after a cast.

llvm::Value * getAsNaturalPointerTo(Address Addr, QualType PointeeType)

void EmitDeleteCall(const FunctionDecl *DeleteFD, llvm::Value *Ptr, QualType DeleteTy, llvm::Value *NumElements=nullptr, CharUnits CookieSize=CharUnits())

llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)

createBasicBlock - Create an LLVM basic block.

const LangOptions & getLangOpts() const

llvm::Constant * EmitCheckTypeDescriptor(QualType T)

Emit a description of a type in a format suitable for passing to a runtime sanitizer handler.

void pushEHDestroy(QualType::DestructionKind dtorKind, Address addr, QualType type)

LValue EmitLValueForFieldInitialization(LValue Base, const FieldDecl *Field)

EmitLValueForFieldInitialization - Like EmitLValueForField, except that if the Field is a reference,...

void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)

EmitBlock - Emit the given block.

const CodeGen::CGBlockInfo * BlockInfo

void EmitAggregateCopyCtor(LValue Dest, LValue Src, AggValueSlot::Overlap_t MayOverlap)

llvm::Value * EmitVTableTypeCheckedLoad(const CXXRecordDecl *RD, llvm::Value *VTable, llvm::Type *VTableTy, uint64_t VTableByteOffset)

Emit a type checked load from the given vtable.

Address makeNaturalAddressForPointer(llvm::Value *Ptr, QualType T, CharUnits Alignment=CharUnits::Zero(), bool ForPointeeType=false, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)

Construct an address with the natural alignment of T.

void EmitExprAsInit(const Expr *init, const ValueDecl *D, LValue lvalue, bool capturedByInit)

EmitExprAsInit - Emits the code necessary to initialize a location in memory with the given initializ...

llvm::Value * GetVTTParameter(GlobalDecl GD, bool ForVirtualBase, bool Delegating)

GetVTTParameter - Return the VTT parameter that should be passed to a base constructor/destructor wit...

void EmitInheritedCXXConstructorCall(const CXXConstructorDecl *D, bool ForVirtualBase, Address This, bool InheritedFromVBase, const CXXInheritedCtorInitExpr *E)

Emit a call to a constructor inherited from a base class, passing the current constructor's arguments...

@ TCK_ConstructorCall

Checking the 'this' pointer for a constructor call.

@ TCK_UpcastToVirtualBase

Checking the operand of a cast to a virtual base object.

@ TCK_Upcast

Checking the operand of a cast to a base object.

VPtrsVector getVTablePointers(const CXXRecordDecl *VTableClass)

llvm::Type * ConvertTypeForMem(QualType T)

const Decl * CurCodeDecl

CurCodeDecl - This is the inner-most code context, which includes blocks.

JumpDest ReturnBlock

ReturnBlock - Unified return block.

LValue EmitLValueForField(LValue Base, const FieldDecl *Field)

RawAddress CreateMemTemp(QualType T, const Twine &Name="tmp", RawAddress *Alloca=nullptr)

CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen and cas...

static Destroyer destroyCXXObject

@ ForceLeftToRight

! Language semantics require left-to-right evaluation.

@ Default

! No language constraints on evaluation order.

void EmitLambdaBlockInvokeBody()

Destroyer * getDestroyer(QualType::DestructionKind destructionKind)

llvm::SmallPtrSet< const CXXRecordDecl *, 4 > VisitedVirtualBasesSetTy

llvm::Value * EmitPointerAuthSign(const CGPointerAuthInfo &Info, llvm::Value *Pointer)

const TargetInfo & getTarget() const

void emitDestroy(Address addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray)

void EmitInitializerForField(FieldDecl *Field, LValue LHS, Expr *Init)

void EmitComplexExprIntoLValue(const Expr *E, LValue dest, bool isInit)

EmitComplexExprIntoLValue - Emit the given expression of complex type and place its result into the s...

void EmitVTablePtrCheck(const CXXRecordDecl *RD, llvm::Value *VTable, CFITypeCheckKind TCK, SourceLocation Loc)

EmitVTablePtrCheck - Emit a check that VTable is a valid virtual table for RD using llvm....

bool ShouldEmitVTableTypeCheckedLoad(const CXXRecordDecl *RD)

Returns whether we should perform a type checked load when loading a virtual function for virtual cal...

void EmitCheck(ArrayRef< std::pair< llvm::Value *, SanitizerKind::SanitizerOrdinal > > Checked, SanitizerHandler Check, ArrayRef< llvm::Constant * > StaticArgs, ArrayRef< llvm::Value * > DynamicArgs)

Create a basic block that will either trap or call a handler function in the UBSan runtime with the p...

void PushDestructorCleanup(QualType T, Address Addr)

PushDestructorCleanup - Push a cleanup to call the complete-object destructor of an object of the giv...

void EmitCXXConstructorCall(const CXXConstructorDecl *D, CXXCtorType Type, bool ForVirtualBase, bool Delegating, AggValueSlot ThisAVS, const CXXConstructExpr *E)

void EmitDelegateCallArg(CallArgList &args, const VarDecl *param, SourceLocation loc)

EmitDelegateCallArg - We are performing a delegate call; that is, the current function is delegating ...

bool HaveInsertPoint() const

HaveInsertPoint - True if an insertion point is defined.

llvm::Constant * EmitCheckSourceLocation(SourceLocation Loc)

Emit a description of a source location in a format suitable for passing to a runtime sanitizer handl...

AggValueSlot::Overlap_t getOverlapForFieldInit(const FieldDecl *FD)

Determine whether a field initialization may overlap some other object.

void EmitAggregateCopy(LValue Dest, LValue Src, QualType EltTy, AggValueSlot::Overlap_t MayOverlap, bool isVolatile=false)

EmitAggregateCopy - Emit an aggregate copy.

void maybeCreateMCDCCondBitmap()

Allocate a temp value on the stack that MCDC can use to track condition results.

const TargetCodeGenInfo & getTargetHooks() const

void EmitInlinedInheritingCXXConstructorCall(const CXXConstructorDecl *Ctor, CXXCtorType CtorType, bool ForVirtualBase, bool Delegating, CallArgList &Args)

Emit a call to an inheriting constructor (that is, one that invokes a constructor inherited from a ba...

void EmitAggExpr(const Expr *E, AggValueSlot AS)

EmitAggExpr - Emit the computation of the specified expression of aggregate type.

Address GetAddressOfDerivedClass(Address Value, const CXXRecordDecl *Derived, CastExpr::path_const_iterator PathBegin, CastExpr::path_const_iterator PathEnd, bool NullCheckValue)

void EnterCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock=false)

static bool IsConstructorDelegationValid(const CXXConstructorDecl *Ctor)

RValue EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee, ReturnValueSlot ReturnValue, const CallArgList &Args, llvm::CallBase **CallOrInvoke, bool IsMustTail, SourceLocation Loc, bool IsVirtualFunctionPointerThunk=false)

EmitCall - Generate a call of the given function, expecting the given result type,...

void EmitCfiSlowPathCheck(SanitizerKind::SanitizerOrdinal Ordinal, llvm::Value *Cond, llvm::ConstantInt *TypeId, llvm::Value *Ptr, ArrayRef< llvm::Constant * > StaticArgs)

Emit a slow path cross-DSO CFI check which calls __cfi_slowpath if Cond if false.

void EmitConstructorBody(FunctionArgList &Args)

llvm::CallInst * EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")

ASTContext & getContext() const

void EmitVTableAssumptionLoads(const CXXRecordDecl *ClassDecl, Address This)

Emit assumption load for all bases.

void Destroyer(CodeGenFunction &CGF, Address addr, QualType ty)

const Decl * CurFuncDecl

CurFuncDecl - Holds the Decl for the current outermost non-closure context.

void EmitLambdaInAllocaCallOpBody(const CXXMethodDecl *MD)

llvm::Value * LoadCXXVTT()

LoadCXXVTT - Load the VTT parameter to base constructors/destructors have virtual bases.

Address GetAddressOfBaseClass(Address Value, const CXXRecordDecl *Derived, CastExpr::path_const_iterator PathBegin, CastExpr::path_const_iterator PathEnd, bool NullCheckValue, SourceLocation Loc)

GetAddressOfBaseClass - This function will add the necessary delta to the load of 'this' and returns ...

void EmitBranchThroughCleanup(JumpDest Dest)

EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...

Address GetAddressOfDirectBaseInCompleteClass(Address Value, const CXXRecordDecl *Derived, const CXXRecordDecl *Base, bool BaseIsVirtual)

GetAddressOfBaseOfCompleteClass - Convert the given pointer to a complete class to the given direct b...

void EmitStmt(const Stmt *S, ArrayRef< const Attr * > Attrs={})

EmitStmt - Emit the code for the statement.

bool needsEHCleanup(QualType::DestructionKind kind)

Determines whether an EH cleanup is required to destroy a type with the given destruction kind.

void EmitTypeMetadataCodeForVCall(const CXXRecordDecl *RD, llvm::Value *VTable, SourceLocation Loc)

If whole-program virtual table optimization is enabled, emit an assumption that VTable is a member of...

CleanupKind getCleanupKind(QualType::DestructionKind kind)

llvm::Type * ConvertType(QualType T)

Address GetAddrOfBlockDecl(const VarDecl *var)

CodeGenTypes & getTypes() const

void EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc, LValue LV, QualType Type, SanitizerSet SkippedChecks=SanitizerSet(), llvm::Value *ArraySize=nullptr)

QualType BuildFunctionArgList(GlobalDecl GD, FunctionArgList &Args)

void EmitCtorPrologue(const CXXConstructorDecl *CD, CXXCtorType Type, FunctionArgList &Args)

Address LoadCXXThisAddress()

void EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD, CallArgList &CallArgs)

RawAddress CreateIRTemp(QualType T, const Twine &Name="tmp")

CreateIRTemp - Create a temporary IR object of the given type, with appropriate alignment.

void emitImplicitAssignmentOperatorBody(FunctionArgList &Args)

LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)

llvm::Value * LoadCXXThis()

LoadCXXThis - Load the value of 'this'.

LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)

Address GetAddrOfLocalVar(const VarDecl *VD)

GetAddrOfLocalVar - Return the address of a local variable.

void EmitParmDecl(const VarDecl &D, ParamValue Arg, unsigned ArgNo)

EmitParmDecl - Emit a ParmVarDecl or an ImplicitParamDecl.

void EnterDtorCleanups(const CXXDestructorDecl *Dtor, CXXDtorType Type)

EnterDtorCleanups - Enter the cleanups necessary to complete the given phase of destruction for a des...

Address ReturnValue

ReturnValue - The temporary alloca to hold the return value.

void ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock=false)

LValue MakeNaturalAlignPointeeAddrLValue(llvm::Value *V, QualType T)

Given a value of type T* that may not be to a complete object, construct an l-value with the natural ...

llvm::LLVMContext & getLLVMContext()

llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)

EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...

void incrementProfileCounter(const Stmt *S, llvm::Value *StepV=nullptr)

Increment the profiler's counter for the given statement by StepV.

llvm::SmallVector< VPtr, 4 > VPtrsVector

void InitializeVTablePointers(const CXXRecordDecl *ClassDecl)

void InitializeVTablePointer(const VPtr &vptr)

Initialize the vtable pointer of the given subobject.

void pushRegularPartialArrayCleanup(llvm::Value *arrayBegin, llvm::Value *arrayEnd, QualType elementType, CharUnits elementAlignment, Destroyer *destroyer)

void GenerateCode(GlobalDecl GD, llvm::Function *Fn, const CGFunctionInfo &FnInfo)

void SetInternalFunctionAttributes(GlobalDecl GD, llvm::Function *F, const CGFunctionInfo &FI)

Set the attributes on the LLVM function for the given decl and function info.

llvm::Module & getModule() const

llvm::FunctionCallee CreateRuntimeFunction(llvm::FunctionType *Ty, StringRef Name, llvm::AttributeList ExtraAttrs=llvm::AttributeList(), bool Local=false, bool AssumeConvergent=false)

Create or return a runtime function declaration with the specified type and name.

CodeGenVTables & getVTables()

llvm::ConstantInt * CreateCrossDsoCfiTypeId(llvm::Metadata *MD)

Generate a cross-DSO type identifier for MD.

CharUnits getMinimumClassObjectSize(const CXXRecordDecl *CD)

Returns the minimum object size for an object of the given class type (or a class derived from it).

llvm::Constant * GetAddrOfFunction(GlobalDecl GD, llvm::Type *Ty=nullptr, bool ForVTable=false, bool DontDefer=false, ForDefinition_t IsForDefinition=NotForDefinition)

Return the address of the given function.

void DecorateInstructionWithInvariantGroup(llvm::Instruction *I, const CXXRecordDecl *RD)

Adds !invariant.barrier !tag to instruction.

llvm::Constant * getAddrOfCXXStructor(GlobalDecl GD, const CGFunctionInfo *FnInfo=nullptr, llvm::FunctionType *FnType=nullptr, bool DontDefer=false, ForDefinition_t IsForDefinition=NotForDefinition)

Return the address of the constructor/destructor of the given type.

void ErrorUnsupported(const Stmt *S, const char *Type)

Print out an error that codegen doesn't support the specified stmt yet.

const LangOptions & getLangOpts() const

CharUnits getNaturalTypeAlignment(QualType T, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr, bool forPointeeType=false)

CodeGenTypes & getTypes()

const TargetInfo & getTarget() const

llvm::Metadata * CreateMetadataIdentifierForType(QualType T)

Create a metadata identifier for the given type.

llvm::Constant * GetNonVirtualBaseClassOffset(const CXXRecordDecl *ClassDecl, CastExpr::path_const_iterator PathBegin, CastExpr::path_const_iterator PathEnd)

Returns the offset from a derived class to a class.

bool HasHiddenLTOVisibility(const CXXRecordDecl *RD)

Returns whether the given record has hidden LTO visibility and therefore may participate in (single-m...

const llvm::DataLayout & getDataLayout() const

CharUnits computeNonVirtualBaseClassOffset(const CXXRecordDecl *DerivedClass, CastExpr::path_const_iterator Start, CastExpr::path_const_iterator End)

TBAAAccessInfo getTBAAVTablePtrAccessInfo(llvm::Type *VTablePtrType)

getTBAAVTablePtrAccessInfo - Get the TBAA information that describes an access to a virtual table poi...

CGCXXABI & getCXXABI() const

CharUnits getVBaseAlignment(CharUnits DerivedAlign, const CXXRecordDecl *Derived, const CXXRecordDecl *VBase)

Returns the assumed alignment of a virtual base of a class.

CharUnits getClassPointerAlignment(const CXXRecordDecl *CD)

Returns the assumed alignment of an opaque pointer to the given class.

bool AlwaysHasLTOVisibilityPublic(const CXXRecordDecl *RD)

Returns whether the given record has public LTO visibility (regardless of -lto-whole-program-visibili...

void DecorateInstructionWithTBAA(llvm::Instruction *Inst, TBAAAccessInfo TBAAInfo)

DecorateInstructionWithTBAA - Decorate the instruction with a TBAA tag.

CharUnits getDynamicOffsetAlignment(CharUnits ActualAlign, const CXXRecordDecl *Class, CharUnits ExpectedTargetAlign)

Given a class pointer with an actual known alignment, and the expected alignment of an object at a dy...

ItaniumVTableContext & getItaniumVTableContext()

ASTContext & getContext() const

const CodeGenOptions & getCodeGenOpts() const

llvm::LLVMContext & getLLVMContext()

llvm::Function * getIntrinsic(unsigned IID, ArrayRef< llvm::Type * > Tys={})

std::optional< CGPointerAuthInfo > getVTablePointerAuthInfo(CodeGenFunction *Context, const CXXRecordDecl *Record, llvm::Value *StorageAddress)

void SetLLVMFunctionAttributesForDefinition(const Decl *D, llvm::Function *F)

Set the LLVM function attributes which only apply to a function definition.

llvm::Type * ConvertType(QualType T)

ConvertType - Convert type T into a llvm::Type.

const CGFunctionInfo & arrangeCXXMethodDeclaration(const CXXMethodDecl *MD)

C++ methods have some special rules and also have implicit parameters.

const CGFunctionInfo & arrangeLLVMFunctionInfo(CanQualType returnType, FnInfoOpts opts, ArrayRef< CanQualType > argTypes, FunctionType::ExtInfo info, ArrayRef< FunctionProtoType::ExtParameterInfo > paramInfos, RequiredArgs args)

"Arrange" the LLVM information for a call or type with the given signature.

llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)

GetFunctionType - Get the LLVM function type for.

bool inheritingCtorHasParams(const InheritedConstructor &Inherited, CXXCtorType Type)

Determine if a C++ inheriting constructor should have parameters matching those of its inherited cons...

const CGRecordLayout & getCGRecordLayout(const RecordDecl *)

getCGRecordLayout - Return record layout info for the given record decl.

const CGFunctionInfo & arrangeCXXConstructorCall(const CallArgList &Args, const CXXConstructorDecl *D, CXXCtorType CtorKind, unsigned ExtraPrefixArgs, unsigned ExtraSuffixArgs, bool PassProtoArgs=true)

Arrange a call to a C++ method, passing the given arguments.

llvm::GlobalVariable * GetAddrOfVTT(const CXXRecordDecl *RD)

GetAddrOfVTT - Get the address of the VTT for the given record decl.

uint64_t getSubVTTIndex(const CXXRecordDecl *RD, BaseSubobject Base)

getSubVTTIndex - Return the index of the sub-VTT for the base class of the given record decl.

Information for lazily generating a cleanup.

A stack of scopes which respond to exceptions, including cleanups and catch blocks.

FunctionArgList - Type for representing both the decl and type of parameters to a function.

LValue - This represents an lvalue references.

bool isVolatileQualified() const

Address getAddress() const

Address getBitFieldAddress() const

RValue - This trivial value class is used to represent the result of an expression that is evaluated.

static RValue get(llvm::Value *V)

llvm::Value * getScalarVal() const

getScalarVal() - Return the Value* of this scalar value.

An abstract representation of an aligned address.

ReturnValueSlot - Contains the address where the return value of a function can be stored,...

Address performAddrSpaceCast(CodeGen::CodeGenFunction &CGF, Address Addr, LangAS SrcAddr, LangAS DestAddr, llvm::Type *DestTy, bool IsNonNull=false) const

CompoundStmt - This represents a group of statements like { stmt stmt }.

ConstEvaluatedExprVisitor - This class visits 'const Expr *'s.

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

DeclContext * getParent()

getParent - Returns the containing DeclContext.

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

SourceLocation getEndLoc() const LLVM_READONLY

bool isImplicit() const

isImplicit - Indicates whether the declaration was implicitly generated by the implementation.

SourceLocation getLocation() const

bool isUsed(bool CheckUsedAttr=true) const

Whether any (re-)declaration of the entity was used, meaning that a definition is required.

This represents one expression.

SourceLocation getExprLoc() const LLVM_READONLY

getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...

Represents a member of a struct/union/class.

unsigned getFieldIndex() const

Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...

Represents a function declaration or definition.

Stmt * getBody(const FunctionDecl *&Definition) const

Retrieve the body (definition) of the function.

bool hasTrivialBody() const

Returns whether the function has a trivial body that does not require any specific codegen.

bool isFunctionTemplateSpecialization() const

Determine whether this function is a function template specialization.

FunctionTemplateDecl * getDescribedFunctionTemplate() const

Retrieves the function template that is described by this function declaration.

bool isDestroyingOperatorDelete() const

Determine whether this is a destroying operator delete.

unsigned getBuiltinID(bool ConsiderWrapperFunctions=false) const

Returns a value indicating whether this function corresponds to a builtin function.

ArrayRef< ParmVarDecl * > parameters() const

bool isTrivial() const

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

bool isVariadic() const

Whether this function is variadic.

const TemplateArgumentList * getTemplateSpecializationArgs() const

Retrieve the template arguments used to produce this function template specialization from the primar...

bool isDefaulted() const

Whether this function is defaulted.

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

param_type_iterator param_type_begin() const

bool isVariadic() const

Whether this function prototype is variadic.

Declaration of a template function.

FunctionDecl * findSpecialization(ArrayRef< TemplateArgument > Args, void *&InsertPos)

Return the specialization with the provided arguments if it exists, otherwise return the insertion po...

QualType getReturnType() const

GlobalDecl - represents a global declaration.

CXXCtorType getCtorType() const

CXXDtorType getDtorType() const

const Decl * getDecl() const

ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...

Represents a field injected from an anonymous union/struct into the parent scope.

ArrayRef< NamedDecl * > chain() const

bool isRelativeLayout() const

Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...

MemberExpr - [C99 6.5.2.3] Structure and Union Members.

ValueDecl * getMemberDecl() const

Retrieve the member declaration to which this expression refers.

A pointer to member type per C++ 8.3.3 - Pointers to members.

QualType getPointeeType() const

const Type * getClass() const

This represents a decl that may have a name.

std::string getQualifiedNameAsString() const

bool containsType(SanitizerMask Mask, StringRef MangledTypeName, StringRef Category=StringRef()) const

A (possibly-)qualified type.

bool isTriviallyCopyableType(const ASTContext &Context) const

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

Qualifiers getQualifiers() const

Retrieve the set of qualifiers applied to this type.

DestructionKind isDestructedType() const

Returns a nonzero value if objects of this type require non-trivial work to clean up after.

bool isPODType(const ASTContext &Context) const

Determine whether this is a Plain Old Data (POD) type (C++ 3.9p10).

The collection of all-type qualifiers we support.

bool hasObjCLifetime() const

LangAS getAddressSpace() const

field_range fields() const

bool mayInsertExtraPadding(bool EmitRemark=false) const

Whether we are allowed to insert extra padding between fields.

bool isAnonymousStructOrUnion() const

Whether this is an anonymous struct or union.

A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...

RecordDecl * getDecl() const

static constexpr SanitizerMask bitPosToMask(const unsigned Pos)

Create a mask with a bit enabled at position Pos.

Scope - A scope is a transient data structure that is used while parsing the program.

Encodes a location in the source.

Stmt - This represents one statement.

SourceRange getSourceRange() const LLVM_READONLY

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

bool isCompleteDefinition() const

Return true if this decl has its body fully specified.

bool hasConstructorVariants() const

Does this ABI have different entrypoints for complete-object and base-subobject constructors?

bool areArgsDestroyedLeftToRightInCallee() const

Are arguments to a call destroyed left to right in the callee? This is a fundamental language change,...

bool isItaniumFamily() const

Does this ABI generally fall into the Itanium family of ABIs?

TargetCXXABI getCXXABI() const

Get the C++ ABI currently in use.

A template argument list.

ArrayRef< TemplateArgument > asArray() const

Produce this as an array ref.

const Type * getTypeForDecl() const

The base class of the type hierarchy.

CXXRecordDecl * getAsCXXRecordDecl() const

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

const T * castAs() const

Member-template castAs.

bool isReferenceType() const

const T * getAs() const

Member-template getAs'.

UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...

Expr * getSubExpr() const

Represents a variable declaration or definition.

@ Type

The l-value was considered opaque, so the alignment was determined from a type.

bool isEmptyFieldForLayout(const ASTContext &Context, const FieldDecl *FD)

isEmptyFieldForLayout - Return true iff the field is "empty", that is, either a zero-width bit-field ...

@ EHCleanup

Denotes a cleanup that should run when a scope is exited using exceptional control flow (a throw stat...

const internal::VariadicAllOfMatcher< Type > type

Matches Types in the clang AST.

const AstTypeMatcher< ArrayType > arrayType

Matches all kinds of arrays.

const void * Store

Store - This opaque type encapsulates an immutable mapping from locations to values.

bool This(InterpState &S, CodePtr OpPC)

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

CXXCtorType

C++ constructor types.

@ Ctor_Base

Base object ctor.

@ Ctor_Complete

Complete object ctor.

CXXDtorType

C++ destructor types.

@ Dtor_Comdat

The COMDAT used for dtors.

@ Dtor_Base

Base object dtor.

@ Dtor_Complete

Complete object dtor.

@ Dtor_Deleting

Deleting dtor.

LangAS

Defines the address space values used by the address space qualifier of QualType.

const FunctionProtoType * T

Structure with information about how a bitfield should be accessed.

CharUnits StorageOffset

The offset of the bitfield storage from the start of the struct.

Similar to AddedStructorArgs, but only notes the number of additional arguments.

llvm::PointerType * VoidPtrTy

llvm::IntegerType * Int8Ty

i8, i16, i32, and i64

llvm::IntegerType * SizeTy

llvm::IntegerType * Int32Ty

llvm::IntegerType * IntPtrTy

llvm::PointerType * Int8PtrTy

llvm::IntegerType * PtrDiffTy

CharUnits getPointerAlign() const

void set(SanitizerMask K, bool Value)

Enable or disable a certain (single) sanitizer.

bool has(SanitizerMask K) const

Check if a certain (single) sanitizer is enabled.