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;

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?");

133

134

135 if (CXXThisAlignment.isZero()) {

136

137

138

139 CXXThisAlignment = CGM.getClassPointerAlignment(MD->getParent());

140 }

141

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

145}

146

147

148

149

151 const Expr *E, Address base, llvm::Value *memberPtr,

154

155 llvm::Value *ptr = CGM.getCXXABI().EmitMemberDataPointerAddress(

156 *this, E, base, memberPtr, memberPtrType, IsInBounds);

157

160 CGM.getNaturalTypeAlignment(memberType, BaseInfo, TBAAInfo);

161 memberAlign = CGM.getDynamicOffsetAlignment(

163 memberAlign);

165 memberAlign);

166}

167

172

175

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

179

180

181 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);

182

183 const auto *BaseDecl = Base->getType()->castAsCXXRecordDecl();

184

186

187 RD = BaseDecl;

188 }

189

190 return Offset;

191}

192

193llvm::Constant *

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

198

201 if (Offset.isZero())

202 return nullptr;

203

206

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

208}

209

210

211

212

213

214

219 bool BaseIsVirtual) {

220

222

223

226 if (BaseIsVirtual)

228 else

230

231

232

234 if (!Offset.isZero()) {

235 V = V.withElementType(Int8Ty);

236 V = Builder.CreateConstInBoundsByteGEP(V, Offset);

237 }

239}

240

244 llvm::Value *virtualOffset,

247

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

249

250

251 llvm::Value *baseOffset;

252 if (!nonVirtualOffset.isZero()) {

253 llvm::Type *OffsetType =

254 (CGF.CGM.getTarget().getCXXABI().isItaniumFamily() &&

258 baseOffset =

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

260 if (virtualOffset) {

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

262 }

263 } else {

264 baseOffset = virtualOffset;

265 }

266

267

270

271

272

274 if (virtualOffset) {

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

277 derivedClass, nearestVBase);

278 } else {

280 }

282

284}

285

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

292

295

296

297

298

299

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

301 VBase = (*Start)->getType()->castAsCXXRecordDecl();

302 ++Start;

303 }

304

305

306

307

308 CharUnits NonVirtualOffset = CGM.computeNonVirtualBaseClassOffset(

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

310

311

312

313

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

317 NonVirtualOffset += vBaseOffset;

318 VBase = nullptr;

319 }

320

321

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

324 CGM.getLLVMContext(), Value.getType()->getPointerAddressSpace());

325

327 CharUnits DerivedAlign = CGM.getClassPointerAlignment(Derived);

328

329

330

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

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

336 DerivedAlign, SkippedChecks);

337 }

338 return Value.withElementType(BaseValueTy);

339 }

340

341 llvm::BasicBlock *origBB = nullptr;

342 llvm::BasicBlock *endBB = nullptr;

343

344

345

346 if (NullCheckValue) {

347 origBB = Builder.GetInsertBlock();

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

350

351 llvm::Value *isNull = Builder.CreateIsNull(Value);

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

354 }

355

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

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

361 SkippedChecks);

362 }

363

364

365 llvm::Value *VirtualOffset = nullptr;

366 if (VBase) {

367 VirtualOffset =

368 CGM.getCXXABI().GetVirtualBaseClassOffset(*this, Value, Derived, VBase);

369 }

370

371

373 VirtualOffset, Derived, VBase);

374

375

376 Value = Value.withElementType(BaseValueTy);

377

378

379 if (NullCheckValue) {

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

383

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

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

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

388 }

389

391}

392

398 bool NullCheckValue) {

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

400

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

403

404 llvm::Value *NonVirtualOffset =

405 CGM.GetNonVirtualBaseClassOffset(Derived, PathBegin, PathEnd);

406

407 if (!NonVirtualOffset) {

408

410 }

411

412 llvm::BasicBlock *CastNull = nullptr;

413 llvm::BasicBlock *CastNotNull = nullptr;

414 llvm::BasicBlock *CastEnd = nullptr;

415

416 if (NullCheckValue) {

420

421 llvm::Value *IsNull = Builder.CreateIsNull(BaseAddr);

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

424 }

425

426

430 CGM.getClassPointerAlignment(Derived), "sub.ptr");

431

432

433 Addr = Addr.withElementType(DerivedValueTy);

434

435

436 if (NullCheckValue) {

437 Builder.CreateBr(CastEnd);

439 Builder.CreateBr(CastEnd);

441

442 llvm::Value *Value = Addr.emitRawPointer(*this);

444 PHI->addIncoming(Value, CastNotNull);

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

446 return Address(PHI, Addr.getElementType(),

447 CGM.getClassPointerAlignment(Derived));

448 }

449

451}

452

454 bool ForVirtualBase,

456 if (CGM.getCXXABI().NeedsVTTParameter(GD)) {

457

458 return nullptr;

459 }

460

463

464 uint64_t SubVTTIndex;

465

467

469 } else if (RD == Base) {

470

471

472 assert(CGM.getCXXABI().NeedsVTTParameter(CurGD) &&

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

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

475 SubVTTIndex = 0;

476 } else {

478 CharUnits BaseOffset = ForVirtualBase ?

481

482 SubVTTIndex =

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

485 }

486

487 if (CGM.getCXXABI().NeedsVTTParameter(CurGD)) {

488

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

491 } else {

492

493 llvm::GlobalValue *VTT = CGM.getVTables().GetAddrOfVTT(RD);

494 return Builder.CreateConstInBoundsGEP2_64(

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

496 }

497}

498

499namespace {

500

501 struct CallBaseDtor final : EHScopeStack::Cleanup {

503 bool BaseIsVirtual;

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

506

510

512

513

517 DerivedClass, BaseClass,

518 BaseIsVirtual);

520 false, Addr, ThisTy);

521 }

522 };

523

524

525

526 struct DynamicThisUseChecker : ConstEvaluatedExprVisitor {

527 typedef ConstEvaluatedExprVisitor super;

528

529 bool UsesThis;

530

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

532

533

534

535

536

537

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

539 };

540}

541

543 DynamicThisUseChecker Checker(C);

544 Checker.Visit(Init);

545 return Checker.UsesThis;

546}

547

552 "Must have base initializer!");

553

555

557

559

560

561

562

565

566

567

570 BaseClassDecl,

571 isBaseVirtual);

579

581

583 !BaseClassDecl->hasTrivialDestructor())

584 CGF.EHStack.pushCleanup(EHCleanup, BaseClassDecl,

585 isBaseVirtual);

586}

587

589 auto *CD = dyn_cast(D);

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

592 return false;

593

594

596 return true;

597

598

600 return true;

601

602 return false;

603}

604

607 LValue &LHS) {

610

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

614 } else {

616 }

617}

618

627 "Must have member initializer!");

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

629

630

632 QualType FieldType = Field->getType();

633

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

636 LValue LHS;

637

638

639

642 else

644

646

647

648

649

650

651

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

655 Constructor->isCopyOrMoveConstructor()) {

660 unsigned SrcArgIndex =

662 llvm::Value *SrcPtr

666

667

669 LHS.isVolatileQualified());

670

671

674 CGF.pushEHDestroy(dtorKind, LHS.getAddress(), FieldType);

675 return;

676 }

677 }

678

680}

681

684 QualType FieldType = Field->getType();

689 } else {

692 }

693 break;

696 break;

702

705 break;

706 }

707 }

708

709

710

714}

715

716

717

718

719

722

723

724

725

726

727

728

729

730

731

732

733

734

736

737

738

739

740

741

742

743

744

745

746

747

748

749

750 return false;

751 }

752

753

754

756 return false;

757

758

760 return false;

761

762 return true;

763}

764

765

766

767

774

775 struct SizeAndOffset {

776 uint64_t Size;

777 uint64_t Offset;

778 };

779

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

781 const ASTRecordLayout &Info = Context.getASTRecordLayout(ClassDecl);

782

783

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

786 SSV[i].Offset =

787 Context.toCharUnitsFromBits(Info.getFieldOffset(i)).getQuantity();

788

789 size_t NumFields = 0;

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

792 auto FieldInfo = Context.getTypeInfoInChars(D->getType());

793 CharUnits FieldSize = FieldInfo.Width;

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

796 NumFields++;

797 }

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

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

800

801

802

804 llvm::FunctionType *FTy =

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

806 llvm::FunctionCallee F = CGM.CreateRuntimeFunction(

807 FTy, Prologue ? "__asan_poison_intra_object_redzone"

808 : "__asan_unpoison_intra_object_redzone");

809

813

814

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

816 uint64_t AsanAlignment = 8;

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

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

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

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

821 (NextField % AsanAlignment) != 0)

822 continue;

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

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

826 }

827}

828

829

834

835 assert((CGM.getTarget().getCXXABI().hasConstructorVariants() ||

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

838

839

840

842 CGM.getTarget().getCXXABI().hasConstructorVariants()) {

844 return;

845 }

846

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

850

851

852

853 bool IsTryBody = isa_and_nonnull(Body);

854 if (IsTryBody)

856

859

861

862

863

864

865

866

868

869

870 if (IsTryBody)

872 else if (Body)

874

875

876

877

878

880

881 if (IsTryBody)

883}

884

885namespace {

886

887

888

889

890 class CopyingValueRepresentation {

891 public:

892 explicit CopyingValueRepresentation(CodeGenFunction &CGF)

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

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

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

896 }

897 ~CopyingValueRepresentation() {

898 CGF.SanOpts = OldSanOpts;

899 }

900 private:

903 };

904}

905

906namespace {

907 class FieldMemcpyizer {

908 public:

909 FieldMemcpyizer(CodeGenFunction &CGF, const CXXRecordDecl *ClassDecl,

910 const VarDecl *SrcRec)

911 : CGF(CGF), ClassDecl(ClassDecl), SrcRec(SrcRec),

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

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

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

915

916 bool isMemcpyableField(FieldDecl *F) const {

917

919 return false;

922 return false;

925 return false;

926 return true;

927 }

928

929 void addMemcpyableField(FieldDecl *F) {

931 return;

932 if (!FirstField)

933 addInitialField(F);

934 else

935 addNextField(F);

936 }

937

938 CharUnits getMemcpySize(uint64_t FirstByteOffset) const {

940 unsigned LastFieldSize =

941 LastField->isBitField()

942 ? LastField->getBitWidthValue()

945 uint64_t MemcpySizeBits = LastFieldOffset + LastFieldSize -

948 return MemcpySize;

949 }

950

951 void emitMemcpy() {

952

953

954 if (!FirstField) {

955 return;

956 }

957

959 if (FirstField->isBitField()) {

960 const CGRecordLayout &RL =

962 const CGBitFieldInfo &BFInfo = RL.getBitFieldInfo(FirstField);

963

964

966 } else {

967 FirstByteOffset = FirstFieldOffset;

968 }

969

970 CharUnits MemcpySize = getMemcpySize(FirstByteOffset);

973 LValue DestLV = CGF.MakeAddrLValue(ThisPtr, RecordTy);

978

979 emitMemcpyIR(

980 Dest.isBitField() ? Dest.getBitFieldAddress() : Dest.getAddress(),

981 Src.isBitField() ? Src.getBitFieldAddress() : Src.getAddress(),

982 MemcpySize);

983 reset();

984 }

985

986 void reset() {

987 FirstField = nullptr;

988 }

989

990 protected:

991 CodeGenFunction &CGF;

992 const CXXRecordDecl *ClassDecl;

993

994 private:

995 void emitMemcpyIR(Address DestPtr, Address SrcPtr, CharUnits Size) {

1000 }

1001

1002 void addInitialField(FieldDecl *F) {

1003 FirstField = F;

1004 LastField = F;

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

1006 LastFieldOffset = FirstFieldOffset;

1008 }

1009

1010 void addNextField(FieldDecl *F) {

1011

1012

1013

1014

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

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

1018

1019

1020

1021

1023 if (FOffset < FirstFieldOffset) {

1024 FirstField = F;

1025 FirstFieldOffset = FOffset;

1026 } else if (FOffset >= LastFieldOffset) {

1027 LastField = F;

1028 LastFieldOffset = FOffset;

1029 }

1030 }

1031

1032 const VarDecl *SrcRec;

1033 const ASTRecordLayout &RecLayout;

1034 FieldDecl *FirstField;

1035 FieldDecl *LastField;

1036 uint64_t FirstFieldOffset, LastFieldOffset;

1037 unsigned LastAddedFieldIndex;

1038 };

1039

1040 class ConstructorMemcpyizer : public FieldMemcpyizer {

1041 private:

1042

1043

1044 static const VarDecl *getTrivialCopySource(CodeGenFunction &CGF,

1045 const CXXConstructorDecl *CD,

1046 FunctionArgList &Args) {

1049 return nullptr;

1050 }

1051

1052

1053

1054 bool isMemberInitMemcpyable(CXXCtorInitializer *MemberInit) const {

1055 if (!MemcpyableCtor)

1056 return false;

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

1059 QualType FieldType = Field->getType();

1060 CXXConstructExpr *CE = dyn_cast(MemberInit->getInit());

1061

1062

1066 return false;

1067

1068

1069 if (!isMemcpyableField(Field))

1070 return false;

1071

1072

1073 return true;

1074 }

1075

1076 public:

1077 ConstructorMemcpyizer(CodeGenFunction &CGF, const CXXConstructorDecl *CD,

1078 FunctionArgList &Args)

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

1080 ConstructorDecl(CD),

1081 MemcpyableCtor(CD->isDefaulted() &&

1082 CD->isCopyOrMoveConstructor() &&

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

1084 Args(Args) { }

1085

1086 void addMemberInitializer(CXXCtorInitializer *MemberInit) {

1087 if (isMemberInitMemcpyable(MemberInit)) {

1088 AggregatedInits.push_back(MemberInit);

1089 addMemcpyableField(MemberInit->getMember());

1090 } else {

1091 emitAggregatedInits();

1093 ConstructorDecl, Args);

1094 }

1095 }

1096

1097 void emitAggregatedInits() {

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

1099

1100

1101 if (!AggregatedInits.empty()) {

1102 CopyingValueRepresentation CVR(CGF);

1104 AggregatedInits[0], ConstructorDecl, Args);

1105 AggregatedInits.clear();

1106 }

1107 reset();

1108 return;

1109 }

1110

1111 pushEHDestructors();

1113 emitMemcpy();

1114 AggregatedInits.clear();

1115 }

1116

1117 void pushEHDestructors() {

1121

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

1123 CXXCtorInitializer *MemberInit = AggregatedInits[i];

1127 continue;

1128 LValue FieldLHS = LHS;

1130 CGF.pushEHDestroy(dtorKind, FieldLHS.getAddress(), FieldType);

1131 }

1132 }

1133

1134 void finish() {

1135 emitAggregatedInits();

1136 }

1137

1138 private:

1139 const CXXConstructorDecl *ConstructorDecl;

1140 bool MemcpyableCtor;

1141 FunctionArgList &Args;

1142 SmallVector<CXXCtorInitializer*, 16> AggregatedInits;

1143 };

1144

1145 class AssignmentMemcpyizer : public FieldMemcpyizer {

1146 private:

1147

1148

1149 FieldDecl *getMemcpyableField(Stmt *S) {

1150 if (!AssignmentsMemcpyable)

1151 return nullptr;

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

1153

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

1155 return nullptr;

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

1157 if (!ME)

1158 return nullptr;

1160 if (!Field || !isMemcpyableField(Field))

1161 return nullptr;

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

1163 if (ImplicitCastExpr *EC = dyn_cast(RHS))

1164 RHS = EC->getSubExpr();

1165 if (!RHS)

1166 return nullptr;

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

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

1170 }

1171 return nullptr;

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

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

1175 return nullptr;

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

1177 if (!IOA)

1178 return nullptr;

1180 if (!Field || !isMemcpyableField(Field))

1181 return nullptr;

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

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

1184 return nullptr;

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

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

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

1189 return nullptr;

1190 Expr *DstPtr = CE->getArg(0);

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

1192 DstPtr = DC->getSubExpr();

1193 UnaryOperator *DUO = dyn_cast(DstPtr);

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

1195 return nullptr;

1196 MemberExpr *ME = dyn_cast(DUO->getSubExpr());

1197 if (!ME)

1198 return nullptr;

1200 if (!Field || !isMemcpyableField(Field))

1201 return nullptr;

1202 Expr *SrcPtr = CE->getArg(1);

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

1204 SrcPtr = SC->getSubExpr();

1205 UnaryOperator *SUO = dyn_cast(SrcPtr);

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

1207 return nullptr;

1208 MemberExpr *ME2 = dyn_cast(SUO->getSubExpr());

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

1210 return nullptr;

1212 }

1213

1214 return nullptr;

1215 }

1216

1217 bool AssignmentsMemcpyable;

1218 SmallVector<Stmt*, 16> AggregatedStmts;

1219

1220 public:

1221 AssignmentMemcpyizer(CodeGenFunction &CGF, const CXXMethodDecl *AD,

1222 FunctionArgList &Args)

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

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

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

1226 }

1227

1228 void emitAssignment(Stmt *S) {

1229 FieldDecl *F = getMemcpyableField(S);

1230 if (F) {

1231 addMemcpyableField(F);

1232 AggregatedStmts.push_back(S);

1233 } else {

1234 emitAggregatedStmts();

1236 }

1237 }

1238

1239 void emitAggregatedStmts() {

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

1241 if (!AggregatedStmts.empty()) {

1242 CopyingValueRepresentation CVR(CGF);

1243 CGF.EmitStmt(AggregatedStmts[0]);

1244 }

1245 reset();

1246 }

1247

1249 emitMemcpy();

1250 AggregatedStmts.clear();

1251 }

1252

1253 void finish() {

1254 emitAggregatedStmts();

1255 }

1256 };

1257}

1258

1263

1264

1265

1271

1273

1274

1275

1276

1277

1278

1279

1280

1281 bool ConstructVBases = CtorType != Ctor_Base &&

1284

1285

1286

1287

1288 llvm::BasicBlock *BaseCtorContinueBB = nullptr;

1289 if (ConstructVBases &&

1290 CGM.getTarget().getCXXABI().hasConstructorVariants()) {

1291 BaseCtorContinueBB =

1292 CGM.getCXXABI().EmitCtorCompleteObjectHandler(*this, ClassDecl);

1293 assert(BaseCtorContinueBB);

1294 }

1295

1296

1297 auto AllInits = CD->inits();

1298

1299

1300 auto VirtualBaseEnd = std::find_if(

1302 return !(Init->isBaseInitializer() && Init->isBaseVirtual());

1303 });

1304

1305 auto NonVirtualBaseEnd = std::find_if(VirtualBaseEnd, AllInits.end(),

1307 return !Init->isBaseInitializer();

1308 });

1309

1310

1311 auto VirtualBaseInits = llvm::make_range(AllInits.begin(), VirtualBaseEnd);

1312 auto NonVirtualBaseInits =

1313 llvm::make_range(VirtualBaseEnd, NonVirtualBaseEnd);

1314 auto MemberInits = llvm::make_range(NonVirtualBaseEnd, AllInits.end());

1315

1316

1317 if (ConstructVBases) {

1320 if (CGM.getCodeGenOpts().StrictVTablePointers &&

1321 CGM.getCodeGenOpts().OptimizationLevel > 0 &&

1325 }

1326 }

1327

1328 if (BaseCtorContinueBB) {

1329

1330 Builder.CreateBr(BaseCtorContinueBB);

1332 }

1333

1334

1338 if (CGM.getCodeGenOpts().StrictVTablePointers &&

1339 CGM.getCodeGenOpts().OptimizationLevel > 0 &&

1343 }

1344

1346

1347

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

1351 assert(Member->isBaseInitializer());

1352 assert(Member->isAnyMemberInitializer() &&

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

1354 CM.addMemberInitializer(Member);

1355 }

1356

1357 CM.finish();

1358}

1359

1360static bool

1362

1363static bool

1367{

1368

1370 return true;

1371

1373 return false;

1374

1375

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

1378 return false;

1379

1380

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

1382 if (I.isVirtual())

1383 continue;

1384

1385 const auto *NonVirtualBase = I.getType()->castAsCXXRecordDecl();

1387 MostDerivedClassDecl))

1388 return false;

1389 }

1390

1391 if (BaseClassDecl == MostDerivedClassDecl) {

1392

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

1394 const auto *VirtualBase = I.getType()->castAsCXXRecordDecl();

1396 MostDerivedClassDecl))

1397 return false;

1398 }

1399 }

1400

1401 return true;

1402}

1403

1404static bool

1407{

1408 QualType FieldBaseElementType = Context.getBaseElementType(Field->getType());

1409

1411 if (!FieldClassDecl)

1412 return true;

1413

1414

1415 if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())

1416 return true;

1417

1419}

1420

1421

1422

1427 return true;

1428

1429

1430

1432 return true;

1433

1435 return false;

1436

1437

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

1440 return false;

1441

1442 return true;

1443}

1444

1447 llvm::Value *ShouldDeleteCondition) {

1449 llvm::BasicBlock *ScalarBB = CGF.createBasicBlock("dtor.scalar");

1450 llvm::BasicBlock *callDeleteBB =

1451 CGF.createBasicBlock("dtor.call_delete_after_array_destroy");

1452 llvm::BasicBlock *VectorBB = CGF.createBasicBlock("dtor.vector");

1454 llvm::Value *CheckTheBitForArrayDestroy = CGF.Builder.CreateAnd(

1455 ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 2));

1456 llvm::Value *ShouldDestroyArray =

1458 CGF.Builder.CreateCondBr(ShouldDestroyArray, ScalarBB, VectorBB);

1459

1461

1462 llvm::Value *numElements = nullptr;

1463 llvm::Value *allocatedPtr = nullptr;

1467 allocatedPtr, cookieSize);

1468

1469

1471

1472 assert(dtorKind);

1473 assert(numElements && "no element count for a type with a destructor!");

1474

1478

1479 llvm::Value *arrayBegin = ThisPtr.emitRawPointer(CGF);

1481 ThisPtr.getElementType(), arrayBegin, numElements, "delete.end");

1482

1483

1484

1485 CGF.emitArrayDestroy(arrayBegin, arrayEnd, EltTy, elementAlign,

1487 false, CGF.needsEHCleanup(dtorKind));

1488

1489 llvm::BasicBlock *VectorBBCont = CGF.createBasicBlock("dtor.vector.cont");

1491

1492 llvm::Value *CheckTheBitForDeleteCall = CGF.Builder.CreateAnd(

1493 ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 1));

1494

1495 llvm::Value *ShouldCallDelete =

1498 callDeleteBB);

1506 } else {

1507

1508

1509

1510 llvm::Value *CheckTheBitForGlobDeleteCall = CGF.Builder.CreateAnd(

1511 ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 4));

1512

1513 llvm::Value *ShouldCallGlobDelete =

1515 llvm::BasicBlock *GlobDelete =

1516 CGF.createBasicBlock("dtor.call_glob_delete_after_array_destroy");

1517 llvm::BasicBlock *ClassDelete =

1518 CGF.createBasicBlock("dtor.call_class_delete_after_array_destroy");

1519 CGF.Builder.CreateCondBr(ShouldCallGlobDelete, ClassDelete, GlobDelete);

1524

1528 }

1529 } else {

1530

1531 llvm::CallInst *TrapCall = CGF.EmitTrapCall(llvm::Intrinsic::trap);

1532 TrapCall->setDoesNotReturn();

1533 TrapCall->setDoesNotThrow();

1534 CGF.Builder.CreateUnreachable();

1535 CGF.Builder.ClearInsertionPoint();

1536 }

1537

1540}

1541

1542

1546

1547

1548

1549

1550

1551

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

1554 TrapCall->setDoesNotReturn();

1555 TrapCall->setDoesNotThrow();

1556 Builder.CreateUnreachable();

1557 Builder.ClearInsertionPoint();

1558 return;

1559 }

1560

1562 if (Body) {

1565 }

1566

1567

1568

1569

1570

1580 }

1581 return;

1582 }

1583

1584

1585

1586 bool isTryBody = isa_and_nonnull(Body);

1587 if (isTryBody)

1590

1591

1593

1594

1595

1596

1597

1598

1599 switch (DtorType) {

1601 llvm_unreachable("not expecting a unified dtor");

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

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

1605 llvm_unreachable("already handled vector deleting case");

1606

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

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

1610

1611

1613

1614 if (!isTryBody) {

1618 break;

1619 }

1620

1621

1622 [[fallthrough]];

1623

1625 assert(Body);

1626

1627

1629

1630

1632

1633

1634 if (CGM.getCodeGenOpts().StrictVTablePointers &&

1635 CGM.getCodeGenOpts().OptimizationLevel > 0)

1638 }

1639

1640 if (isTryBody)

1642 else if (Body)

1644 else {

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

1646

1647 }

1648

1649

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

1652

1653 break;

1654 }

1655

1656

1658

1659

1660 if (isTryBody)

1662}

1663

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

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

1670

1672

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

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

1677 AM.emitAssignment(I);

1678

1679 AM.finish();

1680}

1681

1682namespace {

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

1688 }

1689

1690

1691 struct CallDtorDelete final : EHScopeStack::Cleanup {

1692 CallDtorDelete() {}

1693

1698 LoadThisForDtorDelete(CGF, Dtor),

1700 }

1701 };

1702

1703

1704

1705

1706

1707

1708 void EmitConditionalDtorDeleteCall(CodeGenFunction &CGF,

1709 llvm::Value *ShouldDeleteCondition,

1710 bool ReturnAfterDelete) {

1712 const CXXRecordDecl *ClassDecl = Dtor->getParent();

1715 "unexpected value for ReturnAfterDelete");

1717

1718

1719

1720 ASTContext &Context = CGF.getContext();

1721 bool CallGlobDelete =

1725 llvm::BasicBlock *CallDtor = CGF.createBasicBlock("dtor.call_dtor");

1726 llvm::BasicBlock *DontCallDtor = CGF.createBasicBlock("dtor.entry_cont");

1727

1728

1729

1730

1731 llvm::Value *Check3rdBit = CGF.Builder.CreateAnd(

1732 ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 4));

1734 CGF.Builder.CreateCondBr(ShouldCallDtor, DontCallDtor, CallDtor);

1739 ThisTy);

1740 CGF.Builder.CreateBr(DontCallDtor);

1742 }

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

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

1745

1746 llvm::Value *Check1stBit = CGF.Builder.CreateAnd(

1747 ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 1));

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

1750

1752 auto EmitDeleteAndGoToEnd = [&](const FunctionDecl *DeleteOp) {

1753 CGF.EmitDeleteCall(DeleteOp, LoadThisForDtorDelete(CGF, Dtor),

1755 if (ReturnAfterDelete)

1757 else

1758 CGF.Builder.CreateBr(continueBB);

1759 };

1760

1761

1762

1765

1766

1767 llvm::Value *CheckTheBitForGlobDeleteCall = CGF.Builder.CreateAnd(

1768 ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 4));

1769 llvm::Value *ShouldCallGlobDelete =

1771 llvm::BasicBlock *GlobDelete =

1773 llvm::BasicBlock *ClassDelete =

1775 CGF.Builder.CreateCondBr(ShouldCallGlobDelete, ClassDelete, GlobDelete);

1777

1778 EmitDeleteAndGoToEnd(GlobOD);

1780 }

1781 EmitDeleteAndGoToEnd(OD);

1783 }

1784

1785 struct CallDtorDeleteConditional final : EHScopeStack::Cleanup {

1786 llvm::Value *ShouldDeleteCondition;

1787

1788 public:

1789 CallDtorDeleteConditional(llvm::Value *ShouldDeleteCondition)

1790 : ShouldDeleteCondition(ShouldDeleteCondition) {

1791 assert(ShouldDeleteCondition != nullptr);

1792 }

1793

1794 void Emit(CodeGenFunction &CGF, Flags flags) override {

1795 EmitConditionalDtorDeleteCall(CGF, ShouldDeleteCondition,

1796 false);

1797 }

1798 };

1799

1800 class DestroyField final : public EHScopeStack::Cleanup {

1801 const FieldDecl *field;

1803 bool useEHCleanupForArray;

1804

1805 public:

1807 bool useEHCleanupForArray)

1808 : field(field), destroyer(destroyer),

1809 useEHCleanupForArray(useEHCleanupForArray) {}

1810

1811 void Emit(CodeGenFunction &CGF, Flags flags) override {

1812

1816 LValue ThisLV = CGF.MakeAddrLValue(thisValue, RecordTy);

1818 assert(LV.isSimple());

1819

1820 CGF.emitDestroy(LV.getAddress(), field->getType(), destroyer,

1821 flags.isForNormalCleanup() && useEHCleanupForArray);

1822 }

1823 };

1824

1825 class DeclAsInlineDebugLocation {

1826 CGDebugInfo *DI;

1827 llvm::MDNode *InlinedAt;

1828 std::optional Location;

1829

1830 public:

1831 DeclAsInlineDebugLocation(CodeGenFunction &CGF, const NamedDecl &Decl)

1832 : DI(CGF.getDebugInfo()) {

1833 if (!DI)

1834 return;

1837 Location.emplace(CGF, Decl.getLocation());

1838 }

1839

1840 ~DeclAsInlineDebugLocation() {

1841 if (!DI)

1842 return;

1843 Location.reset();

1845 }

1846 };

1847

1848 static void EmitSanitizerDtorCallback(

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

1852

1853

1854 SmallVector<llvm::Value *, 2> Args = {Ptr};

1855 SmallVector<llvm::Type *, 2> ArgTypes = {CGF.VoidPtrTy};

1856

1857 if (PoisonSize.has_value()) {

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

1859 ArgTypes.emplace_back(CGF.SizeTy);

1860 }

1861

1862 llvm::FunctionType *FnType =

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

1865

1867 }

1868

1869 static void

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

1872 EmitSanitizerDtorCallback(CGF, "__sanitizer_dtor_callback_fields", Ptr,

1873 PoisonSize);

1874 }

1875

1876

1877 struct SanitizeDtorTrivialBase final : EHScopeStack::Cleanup {

1878 const CXXRecordDecl *BaseClass;

1879 bool BaseIsVirtual;

1880 SanitizeDtorTrivialBase(const CXXRecordDecl *Base, bool BaseIsVirtual)

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

1882

1883 void Emit(CodeGenFunction &CGF, Flags flags) override {

1884 const CXXRecordDecl *DerivedClass =

1886

1889

1890 const ASTRecordLayout &BaseLayout =

1892 CharUnits BaseSize = BaseLayout.getSize();

1893

1895 return;

1896

1897

1898

1899 DeclAsInlineDebugLocation InlineHere(CGF, *BaseClass);

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

1902

1903

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

1905 }

1906 };

1907

1908 class SanitizeDtorFieldRange final : public EHScopeStack::Cleanup {

1909 const CXXDestructorDecl *Dtor;

1910 unsigned StartIndex;

1911 unsigned EndIndex;

1912

1913 public:

1914 SanitizeDtorFieldRange(const CXXDestructorDecl *Dtor, unsigned StartIndex,

1915 unsigned EndIndex)

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

1917

1918

1919

1920

1921 void Emit(CodeGenFunction &CGF, Flags flags) override {

1922 const ASTContext &Context = CGF.getContext();

1923 const ASTRecordLayout &Layout =

1925

1926

1927

1930 llvm::ConstantInt *OffsetSizePtr =

1932

1933 llvm::Value *OffsetPtr =

1935

1936 CharUnits PoisonEnd;

1939 } else {

1940 PoisonEnd =

1942 }

1943 CharUnits PoisonSize = PoisonEnd - PoisonStart;

1945 return;

1946

1947

1948 DeclAsInlineDebugLocation InlineHere(

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

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

1951

1952

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

1954 }

1955 };

1956

1957 class SanitizeDtorVTable final : public EHScopeStack::Cleanup {

1958 const CXXDestructorDecl *Dtor;

1959

1960 public:

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

1962

1963

1964 void Emit(CodeGenFunction &CGF, Flags flags) override {

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

1966 (void)Dtor;

1967

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

1969

1970

1971

1972 EmitSanitizerDtorCallback(CGF, "__sanitizer_dtor_callback_vptr",

1973 VTablePtr);

1974 }

1975 };

1976

1977 class SanitizeDtorCleanupBuilder {

1978 ASTContext &Context;

1979 EHScopeStack &EHStack;

1980 const CXXDestructorDecl *DD;

1981 std::optional StartIndex;

1982

1983 public:

1984 SanitizeDtorCleanupBuilder(ASTContext &Context, EHScopeStack &EHStack,

1985 const CXXDestructorDecl *DD)

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

1987 void PushCleanupForField(const FieldDecl *Field) {

1989 return;

1990 unsigned FieldIndex = Field->getFieldIndex();

1992 if (!StartIndex)

1993 StartIndex = FieldIndex;

1994 } else if (StartIndex) {

1996 *StartIndex, FieldIndex);

1997 StartIndex = std::nullopt;

1998 }

1999 }

2000 void End() {

2001 if (StartIndex)

2003 *StartIndex, -1);

2004 }

2005 };

2006}

2007

2008

2009

2010

2011

2012

2013

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

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

2018

2019

2020

2023 "operator delete missing - EnterDtorCleanups");

2024 if (CXXStructorImplicitParamValue) {

2025

2026

2028 EmitConditionalDtorDeleteCall(*this, CXXStructorImplicitParamValue,

2029 true);

2030 else

2031 EHStack.pushCleanup(

2033 } else {

2037 LoadThisForDtorDelete(*this, DD),

2038 getContext().getCanonicalTagType(ClassDecl));

2040 } else {

2042 }

2043 }

2044 return;

2045 }

2046

2048

2049

2050 if (ClassDecl->isUnion())

2051 return;

2052

2053

2055

2056

2057 if (CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor &&

2061

2062

2063

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

2065 auto *BaseClassDecl = Base.getType()->castAsCXXRecordDecl();

2066 if (BaseClassDecl->hasTrivialDestructor()) {

2067

2068

2069

2070 if (CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor &&

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

2073 BaseClassDecl,

2074 true);

2075 } else {

2077 true);

2078 }

2079 }

2080

2081 return;

2082 }

2083

2085

2086

2087 if (CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor &&

2091

2092

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

2094

2095 if (Base.isVirtual())

2096 continue;

2097

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

2099

2101 if (CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor &&

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

2104 BaseClassDecl,

2105 false);

2106 } else {

2108 false);

2109 }

2110 }

2111

2112

2113

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

2115 SanOpts.has(SanitizerKind::Memory);

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

2117

2118

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

2120 if (SanitizeFields)

2121 SanitizeBuilder.PushCleanupForField(Field);

2122

2125 if (!dtorKind)

2126 continue;

2127

2128

2129 const RecordType *RT = type->getAsUnionType();

2130 if (RT && RT->getDecl()->isAnonymousStructOrUnion())

2131 continue;

2132

2134 EHStack.pushCleanup(

2136 }

2137

2138 if (SanitizeFields)

2139 SanitizeBuilder.End();

2140}

2141

2142

2143

2144

2145

2146

2147

2148

2149

2153 bool zeroInitialize) {

2155 llvm::Value *numElements =

2157

2159 NewPointerIsChecked, zeroInitialize);

2160}

2161

2162

2163

2164

2165

2166

2167

2168

2169

2170

2172 llvm::Value *numElements,

2175 bool NewPointerIsChecked,

2176 bool zeroInitialize) {

2177

2178

2179

2180

2181

2182 llvm::BranchInst *zeroCheckBranch = nullptr;

2183

2184

2185 llvm::ConstantInt *constantCount

2186 = dyn_castllvm::ConstantInt(numElements);

2187 if (constantCount) {

2188

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

2190

2191

2192 } else {

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

2194 llvm::Value *iszero = Builder.CreateIsNull(numElements, "isempty");

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

2197 }

2198

2199

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

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

2202 llvm::Value *arrayEnd = Builder.CreateInBoundsGEP(

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

2204

2205

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

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

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

2210 "arrayctor.cur");

2211 cur->addIncoming(arrayBegin, entryBB);

2212

2213

2214 if (CGM.shouldEmitConvergenceTokens())

2216

2217

2218

2219

2220

2221

2222

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

2228

2229

2230 if (zeroInitialize)

2232

2233

2234

2235

2236

2237

2238

2239

2240

2241 {

2243

2244

2245

2250 *destroyer);

2251 }

2259 false, currAVS, E);

2260 }

2261

2262

2263 llvm::Value *next = Builder.CreateInBoundsGEP(

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

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

2266

2267

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

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

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

2271

2272

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

2274

2275 if (CGM.shouldEmitConvergenceTokens())

2277

2279}

2280

2287 false, addr, type);

2288}

2289

2292 bool ForVirtualBase,

2300 llvm::Value *ThisPtr =

2302

2303 if (SlotAS != ThisAS) {

2305 llvm::Type *NewType =

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

2307 ThisPtr =

2309 }

2310

2311

2313

2314

2315

2316

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

2319

2325 return;

2326 }

2327

2328

2334 0, Order);

2335

2339}

2340

2344

2346 return false;

2347

2349

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

2352 return false;

2353

2354

2358 return false;

2359 }

2360

2361

2362 return true;

2363}

2364

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

2371

2372 if (!NewPointerIsChecked)

2374 getContext().getCanonicalTagType(ClassDecl),

2376

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

2379 return;

2380 }

2381

2382

2383

2384

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

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

2394 return;

2395 }

2396

2397 bool PassPrototypeArgs = true;

2398

2404 return;

2405 }

2406 }

2407

2408

2410 CGM.getCXXABI().addImplicitConstructorArgs(*this, D, Type, ForVirtualBase,

2412

2413

2414 llvm::Constant *CalleePtr = CGM.getAddrOfCXXStructor(GlobalDecl(D, Type));

2415 const CGFunctionInfo &Info = CGM.getTypes().arrangeCXXConstructorCall(

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

2419

2420

2421

2422

2423

2424

2425

2426

2427

2428

2429

2430

2431 if (CGM.getCodeGenOpts().OptimizationLevel > 0 &&

2433 CGM.getCXXABI().canSpeculativelyEmitVTable(ClassDecl) &&

2434 CGM.getCodeGenOpts().StrictVTablePointers)

2436}

2437

2445

2446

2447 if (InheritedFromVBase &&

2448 CGM.getTarget().getCXXABI().hasConstructorVariants()) {

2449

2450

2451

2452

2453 Args.push_back(ThisArg);

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

2455

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

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

2458 Args = CXXInheritedCtorInitExprArgs;

2459 Args[0] = ThisArg;

2460 } else {

2461

2462 Args.push_back(ThisArg);

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

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

2466

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

2468 assert(getContext().hasSameUnqualifiedType(

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

2470 Param->getType()));

2472

2473

2474 if (Param->hasAttr()) {

2475 auto *POSParam = SizeArguments[Param];

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

2478 }

2479 }

2480 }

2481

2484 E->getLocation(), true);

2485}

2486

2494

2495

2496 CXXInheritedCtorInitExprArgs = Args;

2497

2501

2502

2503 CGM.getCXXABI().addImplicitConstructorArgs(*this, Ctor, CtorType,

2505

2506

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

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

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

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

2516 }

2517 }

2518

2519

2520

2521

2524

2525 CGM.getCXXABI().EmitInstanceFunctionProlog(*this);

2526 CXXThisValue = CXXABIThisValue;

2527

2528

2530}

2531

2533 llvm::Value *VTableGlobal =

2535 if (!VTableGlobal)

2536 return;

2537

2538

2540

2541 if (!NonVirtualOffset.isZero())

2545

2546 llvm::Value *VPtrValue =

2548 llvm::Value *Cmp =

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

2550 Builder.CreateAssumption(Cmp);

2551}

2552

2555 if (CGM.getCXXABI().doStructorsInitializeVPtrs(ClassDecl))

2558}

2559

2560void

2565

2567

2568

2571

2572

2574 llvm::Type *t = CGM.getTypes().ConvertType(QT);

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

2578

2579

2581 1);

2582

2584 false, This, Args,

2586 false);

2587}

2588

2589void

2595

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

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

2598

2599

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

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

2604 ++I;

2605

2606

2607

2608 if (CGM.getCXXABI().NeedsVTTParameter(CurGD)) {

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

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

2611 "skipping parameter not of vtt type");

2612 ++I;

2613 }

2614

2615

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

2617 const VarDecl *param = *I;

2618

2620 }

2621

2623 true, This, DelegateArgs,

2625 true);

2626}

2627

2628namespace {

2629 struct CallDelegatingCtorDtor final : EHScopeStack::Cleanup {

2633

2637

2639

2640

2641 QualType ThisTy = Dtor->getFunctionObjectParameterType();

2643 true, Addr, ThisTy);

2644 }

2645 };

2646}

2647

2648void

2652

2654

2662

2664

2666

2671

2674 ThisPtr, Type);

2675 }

2676}

2677

2680 bool ForVirtualBase,

2683 CGM.getCXXABI().EmitDestructorCall(*this, DD, Type, ForVirtualBase,

2685}

2686

2687namespace {

2688 struct CallLocalDtor final : EHScopeStack::Cleanup {

2692

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

2695

2698 false,

2699 false, Addr, Ty);

2700 }

2701 };

2702}

2703

2708

2711 if (!ClassDecl) return;

2713

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

2717}

2718

2720

2721 llvm::Value *VTableAddressPoint =

2722 CGM.getCXXABI().getVTableAddressPointInStructor(

2724

2725 if (!VTableAddressPoint)

2726 return;

2727

2728

2729 llvm::Value *VirtualOffset = nullptr;

2731

2732 if (CGM.getCXXABI().isVirtualOffsetNeededForVTableField(*this, Vptr)) {

2733

2734

2735

2736 VirtualOffset = CGM.getCXXABI().GetVirtualBaseClassOffset(

2739 } else {

2740

2742 }

2743

2744

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

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

2750

2751

2752

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

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

2755

2756

2758

2759 if (auto AuthenticationInfo = CGM.getVTablePointerAuthInfo(

2761 VTableAddressPoint =

2763

2764 llvm::StoreInst *Store = Builder.CreateStore(VTableAddressPoint, VTableField);

2765 TBAAAccessInfo TBAAInfo = CGM.getTBAAVTablePtrAccessInfo(PtrTy);

2766 CGM.DecorateInstructionWithTBAA(Store, TBAAInfo);

2767 if (CGM.getCodeGenOpts().OptimizationLevel > 0 &&

2768 CGM.getCodeGenOpts().StrictVTablePointers)

2769 CGM.DecorateInstructionWithInvariantGroup(Store, Vptr.VTableClass);

2770}

2771

2777 nullptr,

2779 false, VTableClass, VBases,

2780 VPtrsResult);

2781 return VPtrsResult;

2782}

2783

2786 CharUnits OffsetFromNearestVBase,

2787 bool BaseIsNonVirtualPrimaryBase,

2791

2792

2793 if (!BaseIsNonVirtualPrimaryBase) {

2794

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

2796 Vptrs.push_back(Vptr);

2797 }

2798

2800

2801

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

2803 auto *BaseDecl = I.getType()->castAsCXXRecordDecl();

2804

2805 if (!BaseDecl->isDynamicClass())

2806 continue;

2807

2809 CharUnits BaseOffsetFromNearestVBase;

2810 bool BaseDeclIsNonVirtualPrimaryBase;

2811

2812 if (I.isVirtual()) {

2813

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

2815 continue;

2816

2819

2822 BaseDeclIsNonVirtualPrimaryBase = false;

2823 } else {

2825

2827 BaseOffsetFromNearestVBase =

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

2830 }

2831

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

2835 BaseDeclIsNonVirtualPrimaryBase, VTableClass, VBases, Vptrs);

2836 }

2837}

2838

2840

2842 return;

2843

2844

2845 if (CGM.getCXXABI().doStructorsInitializeVPtrs(RD))

2848

2850 CGM.getCXXABI().initializeHiddenVirtualInheritanceMembers(*this, RD);

2851}

2852

2854 llvm::Type *VTableTy,

2857 Address VTablePtrSrc = This.withElementType(VTableTy);

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

2859 TBAAAccessInfo TBAAInfo = CGM.getTBAAVTablePtrAccessInfo(VTableTy);

2860 CGM.DecorateInstructionWithTBAA(VTable, TBAAInfo);

2861

2862 if (auto AuthenticationInfo =

2863 CGM.getVTablePointerAuthInfo(this, RD, This.emitRawPointer(*this))) {

2868

2869

2870

2871 VTable =

2874 true);

2875 }

2876 } else {

2879 nullptr),

2880 VTable));

2881 }

2882 }

2883

2884 if (CGM.getCodeGenOpts().OptimizationLevel > 0 &&

2885 CGM.getCodeGenOpts().StrictVTablePointers)

2886 CGM.DecorateInstructionWithInvariantGroup(VTable, RD);

2887

2888 return VTable;

2889}

2890

2891

2892

2893

2894

2895

2896

2897

2898

2899

2903 return RD;

2904

2906 return RD;

2907

2909 return RD;

2910

2913

2914

2915

2917 continue;

2918 return RD;

2919 }

2920 }

2921

2924}

2925

2927 llvm::Value *VTable,

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

2931

2932

2933

2934

2935

2936

2937 else if ((CGM.getCodeGenOpts().WholeProgramVTables &&

2938 CGM.AlwaysHasLTOVisibilityPublic(RD)) ||

2939 CGM.getCodeGenOpts().DevirtualizeSpeculatively) {

2940 CanQualType Ty = CGM.getContext().getCanonicalTagType(RD);

2941 llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(Ty);

2942 llvm::Value *TypeId =

2943 llvm::MetadataAsValue::get(CGM.getLLVMContext(), MD);

2944

2945

2946

2947

2948

2949 llvm::Intrinsic::ID IID = CGM.HasHiddenLTOVisibility(RD)

2950 ? llvm::Intrinsic::type_test

2951 : llvm::Intrinsic::public_type_test;

2952 llvm::Value *TypeTest =

2953 Builder.CreateCall(CGM.getIntrinsic(IID), {VTable, TypeId});

2954 Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::assume), TypeTest);

2955 }

2956}

2957

2958

2959

2960static std::pair<SanitizerKind::SanitizerOrdinal, llvm::SanitizerStatKind>

2962 switch (TCK) {

2964 return std::make_pair(SanitizerKind::SO_CFIVCall, llvm::SanStat_CFI_VCall);

2966 return std::make_pair(SanitizerKind::SO_CFINVCall,

2967 llvm::SanStat_CFI_NVCall);

2969 return std::make_pair(SanitizerKind::SO_CFIDerivedCast,

2970 llvm::SanStat_CFI_DerivedCast);

2972 return std::make_pair(SanitizerKind::SO_CFIUnrelatedCast,

2973 llvm::SanStat_CFI_UnrelatedCast);

2977 llvm_unreachable("unexpected sanitizer kind");

2978 }

2979 llvm_unreachable("Unknown CFITypeCheckKind enum");

2980}

2981

2983 llvm::Value *VTable,

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

2988

2991 SanitizerHandler::CFICheckFail);

2992

2994}

2995

2997 bool MayBeNull,

3001 return;

3002

3003 const auto *ClassDecl = T->getAsCXXRecordDecl();

3004 if (!ClassDecl)

3005 return;

3006

3008 return;

3009

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

3012

3015 SanitizerHandler::CFICheckFail);

3016

3017 llvm::BasicBlock *ContBlock = nullptr;

3018

3019 if (MayBeNull) {

3020 llvm::Value *DerivedNotNull =

3022

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

3025

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

3027

3029 }

3030

3031 llvm::Value *VTable;

3032 std::tie(VTable, ClassDecl) =

3033 CGM.getCXXABI().LoadVTablePtr(*this, Derived, ClassDecl);

3034

3036

3037 if (MayBeNull) {

3038 Builder.CreateBr(ContBlock);

3040 }

3041}

3042

3044 llvm::Value *VTable,

3048

3049 if (CGM.getCodeGenOpts().SanitizeCfiCrossDso &&

3050 CGM.HasHiddenLTOVisibility(RD))

3051 return;

3052

3054

3056 if (getContext().getNoSanitizeList().containsType(

3058 return;

3059

3061

3062 CanQualType T = CGM.getContext().getCanonicalTagType(RD);

3063 llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(T);

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

3065

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

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

3068

3069 llvm::Constant *StaticData[] = {

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

3073 };

3074

3075 auto CrossDsoTypeId = CGM.CreateCrossDsoCfiTypeId(MD);

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

3078 return;

3079 }

3080

3081 if (CGM.getCodeGenOpts().SanitizeTrap.has(M)) {

3082 bool NoMerge = CGM.getCodeGenOpts().SanitizeMergeHandlers.has(M);

3083 EmitTrapCheck(TypeTest, SanitizerHandler::CFICheckFail, NoMerge);

3084 return;

3085 }

3086

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

3088 CGM.getLLVMContext(),

3089 llvm::MDString::get(CGM.getLLVMContext(), "all-vtables"));

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

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

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

3093 StaticData, {VTable, ValidVtable});

3094}

3095

3097 if ((CGM.getCodeGenOpts().WholeProgramVTables ||

3098 CGM.HasHiddenLTOVisibility(RD)) &&

3099 CGM.getCodeGenOpts().DevirtualizeSpeculatively)

3100 return false;

3101

3102 if (CGM.getCodeGenOpts().VirtualFunctionElimination)

3103 return true;

3104

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

3106 CGM.getCodeGenOpts().SanitizeTrap.has(SanitizerKind::CFIVCall))

3107 return false;

3108

3112}

3113

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

3116 uint64_t VTableByteOffset) {

3117 auto CheckOrdinal = SanitizerKind::SO_CFIVCall;

3118 auto CheckHandler = SanitizerHandler::CFICheckFail;

3120

3122

3123 CanQualType T = CGM.getContext().getCanonicalTagType(RD);

3124 llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(T);

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

3126

3127 auto CheckedLoadIntrinsic = CGM.getVTables().useRelativeLayout()

3128 ? llvm::Intrinsic::type_checked_load_relative

3129 : llvm::Intrinsic::type_checked_load;

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

3131 CGM.getIntrinsic(CheckedLoadIntrinsic),

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

3133

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

3135

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

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

3140 EmitCheck(std::make_pair(CheckResult, CheckOrdinal), CheckHandler, {}, {});

3141 }

3142

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

3144 VTableTy);

3145}

3146

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

3150

3151 if (!calleeFnInfo)

3152 calleeFnInfo = &CGM.getTypes().arrangeCXXMethodDeclaration(callOperator);

3153

3154 if (!calleePtr)

3155 calleePtr =

3157 CGM.getTypes().GetFunctionType(*calleeFnInfo));

3158

3159

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

3167 returnSlot =

3169 false, true);

3170

3171

3172

3173

3174

3175

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

3178

3179

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

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

3183 }

3184 EmitReturnOfRValue(RV, resultType);

3185 } else

3187}

3188

3194

3195 if (CallOp->isVariadic()) {

3196

3197

3198

3199 CGM.ErrorUnsupported(CurCodeDecl, "lambda conversion to variadic function");

3200 return;

3201 }

3202

3203

3205

3210

3211

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

3214

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

3218}

3219

3222

3223

3224

3225 CGM.ErrorUnsupported(MD, "lambda conversion to variadic function");

3226 return;

3227 }

3228

3230

3231

3233

3238

3240}

3241

3244

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

3247

3250

3251

3255 FunctionTemplateDecl *CallOpTemplate = CallOp->getDescribedFunctionTemplate();

3256 void *InsertPos = nullptr;

3257 FunctionDecl *CorrespondingCallOpSpecialization =

3259 assert(CorrespondingCallOpSpecialization);

3261 }

3262

3263

3264 if (hasInAllocaArg(MD)) {

3266 llvm::Function *ImplFn = nullptr;

3268

3270 return;

3271 }

3272

3274}

3275

3278

3279

3280 CGM.ErrorUnsupported(MD, "lambda conversion to variadic function");

3281 return;

3282 }

3283

3284

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

3290

3292}

3293

3296 llvm::Function **ImplFn) {

3298 CGM.getTypes().arrangeCXXMethodDeclaration(CallOp);

3299 llvm::Function *CallOpFn =

3301

3302

3303

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

3306 ArgTypes.push_back(I->type);

3307 *ImplFnInfo = &CGM.getTypes().arrangeLLVMFunctionInfo(

3310

3311

3312

3313

3314

3315

3316 StringRef CallOpName = CallOpFn->getName();

3317 std::string ImplName;

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

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

3320 else

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

3322

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

3324 if (!Fn) {

3325 Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(**ImplFnInfo),

3326 llvm::GlobalValue::InternalLinkage, ImplName,

3327 CGM.getModule());

3328 CGM.SetInternalFunctionAttributes(CallOp, Fn, **ImplFnInfo);

3329

3332 CodeGenFunction(CGM).GenerateCode(GD, Fn, **ImplFnInfo);

3333 CGM.SetLLVMFunctionAttributesForDefinition(D, Fn);

3334 }

3335 *ImplFn = Fn;

3336}

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

Definition CGClass.cpp:242

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

Definition CGClass.cpp:2341

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

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

Definition CGClass.cpp:1423

static const CXXRecordDecl * LeastDerivedClassWithSameLayout(const CXXRecordDecl *RD)

Definition CGClass.cpp:2901

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

Definition CGClass.cpp:548

static bool isMemcpyEquivalentSpecialMember(const CXXMethodDecl *D)

Definition CGClass.cpp:588

static std::pair< SanitizerKind::SanitizerOrdinal, llvm::SanitizerStatKind > SanitizerInfoFromCFICheckKind(CodeGenFunction::CFITypeCheckKind TCK)

Converts the CFITypeCheckKind into SanitizerKind::SanitizerOrdinal and llvm::SanitizerStatKind.

Definition CGClass.cpp:2961

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

Definition CGClass.cpp:542

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

Definition CGClass.cpp:1405

static void EmitConditionalArrayDtorCall(const CXXDestructorDecl *DD, CodeGenFunction &CGF, llvm::Value *ShouldDeleteCondition)

Definition CGClass.cpp:1445

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

Definition CGClass.cpp:1364

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

Definition CGClass.cpp:619

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

Definition CGClass.cpp:605

static bool isInitializerOfDynamicClass(const CXXCtorInitializer *baseInit)

Defines the C++ template declaration subclasses.

TokenType getType() const

Returns the token's type, e.g.

a trap message and trap category.

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

const ConstantArrayType * getAsConstantArrayType(QualType T) const

const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const

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

QualType getPointerType(QualType T) const

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

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

int64_t toBits(CharUnits CharSize) const

Convert a size in characters to a size in bits.

CharUnits getTypeSizeInChars(QualType T) const

Return the size of the specified (complete) type T, in characters.

const TargetInfo & getTargetInfo() const

CharUnits toCharUnitsFromBits(int64_t BitSize) const

Convert a size in bits to a size in characters.

CanQualType getCanonicalTagType(const TagDecl *TD) const

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.

const CXXRecordDecl * getBase() const

getBase - Returns the base class declaration.

CharUnits getBaseOffset() const

getBaseOffset - Returns the base class offset.

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.

bool isListInitialization() const

Whether this constructor call was written as list-initialization.

unsigned getNumArgs() const

Return the number of arguments to the constructor call.

Represents a C++ constructor within a class.

init_iterator init_begin()

Retrieve an iterator to the first initializer.

bool isDefaultConstructor() const

Whether this constructor is a default constructor (C++ [class.ctor]p5), which can be used to default-...

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.

InheritedConstructor getInheritedConstructor() const

Get the constructor that this inheriting constructor is based on.

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 * getOperatorGlobalDelete() const

const FunctionDecl * getGlobalArrayOperatorDelete() const

const FunctionDecl * getOperatorDelete() const

Expr * getOperatorDeleteThisArg() const

const FunctionDecl * getArrayOperatorDelete() const

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

SourceLocation getLocation() const LLVM_READONLY

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 getThisType() const

Return the type of the this pointer.

bool isMoveAssignmentOperator() const

Determine whether this is a move assignment operator.

QualType getFunctionObjectParameterType() const

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

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.

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

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 source atom group for CGDebugInfo::addInstToCurrentSourceAtom.

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.

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="")

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 size_t getSrcArgforCopyCtor(const CXXConstructorDecl *, FunctionArgList &Args) const =0

virtual void ReadArrayCookie(CodeGenFunction &CGF, Address Ptr, const CXXDeleteExpr *expr, QualType ElementType, llvm::Value *&NumElements, llvm::Value *&AllocPtr, CharUnits &CookieSize)

Reads the array cookie associated with the given pointer, if it has one.

All available information about a concrete callee.

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

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

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)

A scope within which we are constructing the fields of an object which might use a CXXDefaultInitExpr...

static ParamValue forIndirect(Address addr)

static ParamValue forDirect(llvm::Value *value)

Enters a new scope for capturing cleanups, all of which will be executed once the scope is exited.

void ForceCleanup(std::initializer_list< llvm::Value ** > ValuesToReload={})

Force the emission of cleanups now, instead of waiting until this object is destroyed.

RAII object to set/unset CodeGenFunction::IsSanitizerScope.

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

void emitArrayDestroy(llvm::Value *begin, llvm::Value *end, QualType elementType, CharUnits elementAlign, Destroyer *destroyer, bool checkZeroLength, bool useEHCleanup)

emitArrayDestroy - Destroys all the elements of the given array, beginning from last to first.

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.

Definition CGClass.cpp:2853

GlobalDecl CurGD

CurGD - The GlobalDecl for the current function being compiled.

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

Definition CGClass.cpp:2649

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

emitDestroy - Immediately perform the destruction of the given object.

AggValueSlot::Overlap_t getOverlapForFieldInit(const FieldDecl *FD)

Determine whether a field initialization may overlap some other object.

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

Definition CGClass.cpp:2590

SanitizerSet SanOpts

Sanitizers enabled for this function.

void EmitAsanPrologueOrEpilogue(bool Prologue)

Definition CGClass.cpp:768

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

Definition CGClass.cpp:2487

void EmitNullInitialization(Address DestPtr, QualType Ty)

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

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

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

Address LoadCXXThisAddress()

Definition CGClass.cpp:130

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

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

static bool hasScalarEvaluationKind(QualType T)

llvm::Type * ConvertType(QualType T)

void EmitSanitizerStatReport(llvm::SanitizerStatKind SSK)

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

pushEHDestroy - Push the standard destructor for the given type as an EH-only cleanup.

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

EmitVTablePtrCheckForCall - Virtual method MD is being called via VTable.

Definition CGClass.cpp:2982

void EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD)

Definition CGClass.cpp:3220

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

Definition CGClass.cpp:3242

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

Definition CGClass.cpp:286

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

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

pushRegularPartialArrayCleanup - Push an EH cleanup to destroy already-constructed elements of the gi...

SmallVector< llvm::ConvergenceControlInst *, 4 > ConvergenceTokenStack

Stack to track the controlled convergence tokens.

llvm::Constant * EmitCheckSourceLocation(SourceLocation Loc)

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

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

Definition CGClass.cpp:3147

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

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

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

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

createBasicBlock - Create an LLVM basic block.

void addInstToCurrentSourceAtom(llvm::Instruction *KeyInstruction, llvm::Value *Backup)

See CGDebugInfo::addInstToCurrentSourceAtom.

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

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

const LangOptions & getLangOpts() const

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

Retain the given object which is the result of a function call.

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

static bool IsConstructorDelegationValid(const CXXConstructorDecl *Ctor)

Checks whether the given constructor is a valid subject for the complete-to-base constructor delegati...

Definition CGClass.cpp:720

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

Definition CGClass.cpp:394

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

Definition CGClass.cpp:3043

void EmitConstructorBody(FunctionArgList &Args)

EmitConstructorBody - Emits the body of the current constructor.

Definition CGClass.cpp:830

const CodeGen::CGBlockInfo * BlockInfo

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

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.

static Destroyer destroyCXXObject

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

Definition CGClass.cpp:3294

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

EmitCXXAggrConstructorCall - Emit a loop to call a particular constructor for each of several members...

Definition CGClass.cpp:2150

VPtrsVector getVTablePointers(const CXXRecordDecl *VTableClass)

Definition CGClass.cpp:2773

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.

Definition CGClass.cpp:2996

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

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

Definition CGClass.cpp:2678

void EmitBranchThroughCleanup(JumpDest Dest)

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

const Decl * CurCodeDecl

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

Destroyer * getDestroyer(QualType::DestructionKind destructionKind)

void PushDestructorCleanup(QualType T, Address Addr)

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

Definition CGClass.cpp:2709

JumpDest ReturnBlock

ReturnBlock - Unified return block.

llvm::Constant * EmitCheckTypeDescriptor(QualType T)

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

@ ForceLeftToRight

! Language semantics require left-to-right evaluation.

@ Default

! No language constraints on evaluation order.

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

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

EmitAggregateCopy - Emit an aggregate copy.

LValue EmitLValueForField(LValue Base, const FieldDecl *Field, bool IsInBounds=true)

const TargetInfo & getTarget() const

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

Emit the address of a field using a member data pointer.

Definition CGClass.cpp:150

void maybeCreateMCDCCondBitmap()

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

Address GetAddrOfBlockDecl(const VarDecl *var)

void EnterDtorCleanups(const CXXDestructorDecl *Dtor, CXXDtorType Type)

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

Definition CGClass.cpp:2014

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

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

Definition CGClass.cpp:2290

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

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

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

bool HaveInsertPoint() const

HaveInsertPoint - True if an insertion point is defined.

void EmitVTableAssumptionLoads(const CXXRecordDecl *ClassDecl, Address This)

Emit assumption load for all bases.

Definition CGClass.cpp:2553

CGDebugInfo * getDebugInfo()

void EmitDestructorBody(FunctionArgList &Args)

EmitDestructorBody - Emits the body of the current destructor.

Definition CGClass.cpp:1543

LValue EmitLValueForFieldInitialization(LValue Base, const FieldDecl *Field)

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

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

Definition CGClass.cpp:216

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

const TargetCodeGenInfo & getTargetHooks() const

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

EmitCtorPrologue - This routine generates necessary code to initialize base classes and non-static da...

Definition CGClass.cpp:1266

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

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

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

Definition CGClass.cpp:2926

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

ASTContext & getContext() const

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

const Decl * CurFuncDecl

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

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

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

llvm::Value * LoadCXXVTT()

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

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

EmitParmDecl - Emit a ParmVarDecl or an ImplicitParamDecl.

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

Definition CGClass.cpp:682

void EmitLambdaInAllocaCallOpBody(const CXXMethodDecl *MD)

Definition CGClass.cpp:3276

bool needsEHCleanup(QualType::DestructionKind kind)

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

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

EmitStmt - Emit the code for the statement.

CleanupKind getCleanupKind(QualType::DestructionKind kind)

llvm::Type * ConvertTypeForMem(QualType T)

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

Definition CGClass.cpp:2561

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

CodeGenTypes & getTypes() const

static TypeEvaluationKind getEvaluationKind(QualType T)

getEvaluationKind - Return the TypeEvaluationKind of QualType T.

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

bool IsSanitizerScope

True if CodeGen currently emits code implementing sanitizer checks.

void emitImplicitAssignmentOperatorBody(FunctionArgList &Args)

Definition CGClass.cpp:1664

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

void EmitLambdaBlockInvokeBody()

Definition CGClass.cpp:3189

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

Definition CGClass.cpp:2438

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

bool sanitizePerformTypeCheck() const

Whether any type-checking sanitizers are enabled.

void EmitAggExpr(const Expr *E, AggValueSlot AS)

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

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

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

Definition CGClass.cpp:453

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

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

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

EmitCallArgs - Emit call arguments for a function.

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

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

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

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

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

llvm::Value * LoadCXXThis()

LoadCXXThis - Load the value of 'this'.

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

Address GetAddrOfLocalVar(const VarDecl *VD)

GetAddrOfLocalVar - Return the address of a local variable.

void InitializeVTablePointer(const VPtr &vptr)

Initialize the vtable pointer of the given subobject.

Definition CGClass.cpp:2719

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

Emit a type checked load from the given vtable.

Definition CGClass.cpp:3114

Address ReturnValue

ReturnValue - The temporary alloca to hold the return value.

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

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

bool ShouldEmitVTableTypeCheckedLoad(const CXXRecordDecl *RD)

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

Definition CGClass.cpp:3096

llvm::LLVMContext & getLLVMContext()

llvm::SmallVector< VPtr, 4 > VPtrsVector

void InitializeVTablePointers(const CXXRecordDecl *ClassDecl)

Definition CGClass.cpp:2839

void EmitVTableAssumptionLoad(const VPtr &vptr, Address This)

Emit assumption that vptr load == global vtable.

Definition CGClass.cpp:2532

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

EmitBlock - Emit the given block.

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

QualType BuildFunctionArgList(GlobalDecl GD, FunctionArgList &Args)

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

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.

CharUnits getMinimumClassObjectSize(const CXXRecordDecl *CD)

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

Definition CGClass.cpp:59

const LangOptions & getLangOpts() const

CodeGenTypes & getTypes()

const TargetInfo & getTarget() const

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.

Definition CGClass.cpp:194

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

Definition CGClass.cpp:168

CGCXXABI & getCXXABI() const

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

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

Definition CGClass.cpp:76

CharUnits getClassPointerAlignment(const CXXRecordDecl *CD)

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

Definition CGClass.cpp:40

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

Definition CGClass.cpp:91

ItaniumVTableContext & getItaniumVTableContext()

ASTContext & getContext() const

llvm::Type * ConvertType(QualType T)

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

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.

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

LValue - This represents an lvalue references.

Address getAddress() const

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

static RValue get(llvm::Value *V)

Address getAggregateAddress() const

getAggregateAddr() - Return the Value* of the address of the aggregate.

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, llvm::Type *DestTy, bool IsNonNull=false) const

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

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

SourceLocation getEndLoc() const LLVM_READONLY

bool isImplicit() const

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

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.

bool isBitField() const

Determines whether this field is a bitfield.

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.

const ParmVarDecl * getParamDecl(unsigned i) const

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.

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.

unsigned getNumParams() const

Return the number of parameters this function must have based on its FunctionType.

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

const Decl * getDecl() const

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

ArrayRef< NamedDecl * > chain() const

bool isRelativeLayout() const

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.

CXXRecordDecl * getMostRecentCXXRecordDecl() const

Note: this can trigger extra deserialization when external AST sources are used.

QualType getPointeeType() const

std::string getQualifiedNameAsString() const

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

bool isAddressDiscriminated() 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)

PointerAuthQualifier getPointerAuth() const

LangAS getAddressSpace() const

Return the address space of this type.

Qualifiers getQualifiers() const

Retrieve the set of qualifiers applied to this type.

QualType getNonReferenceType() const

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

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.

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 areArgsDestroyedLeftToRightInCallee() const

Are arguments to a call destroyed left to right in the callee?

TargetCXXABI getCXXABI() const

Get the C++ ABI currently in use.

virtual bool callGlobalDeleteInDeletingDtor(const LangOptions &) const

Controls whether global operator delete is called by the deleting destructor or at the point where de...

A template argument list.

ArrayRef< TemplateArgument > asArray() const

Produce this as an array ref.

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

CXXRecordDecl * castAsCXXRecordDecl() const

const T * castAs() const

Member-template castAs.

bool isReferenceType() const

QualType getPointeeType() const

If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.

Expr * getSubExpr() const

Represents a variable declaration or definition.

@ Type

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

@ Decl

The l-value was an access to a declared entity or something equivalently strong, like the address of ...

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

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

CanQual< Type > CanQualType

Represents a canonical, potentially-qualified type.

CXXCtorType

C++ constructor types.

@ Ctor_Base

Base object ctor.

@ Ctor_Complete

Complete object ctor.

bool isa(CodeGen::Address addr)

nullptr

This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...

const FunctionProtoType * T

CXXDtorType

C++ destructor types.

@ Dtor_VectorDeleting

Vector deleting dtor.

@ Dtor_Comdat

The COMDAT used for dtors.

@ Dtor_Unified

GCC-style unified dtor.

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

U cast(CodeGen::Address addr)

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::BasicBlock * getBlock() const

Struct with all information about dynamic [sub]class needed to set vptr.

const CXXRecordDecl * NearestVBase

const CXXRecordDecl * VTableClass

CharUnits OffsetFromNearestVBase

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

void set(SanitizerMask K, bool Value)

Enable or disable a certain (single) sanitizer.