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

1

2

3

4

5

6

7

8

9

10

11

12

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

23

24using namespace clang;

26

27namespace {

28struct MemberCallInfo {

29 RequiredArgs ReqArgs;

30

31 unsigned PrefixSize;

32};

33}

34

35static MemberCallInfo

37 llvm::Value *This, llvm::Value *ImplicitParam,

41

44 assert(MD->isImplicitObjectMemberFunction() &&

45 "Trying to emit a member or operator call expr on a static method!");

46

47

51

52

53 if (ImplicitParam) {

54 Args.add(RValue::get(ImplicitParam), ImplicitParamTy);

55 }

56

59 unsigned PrefixSize = Args.size() - 1;

60

61

62 if (RtlArgs) {

63

64

65

67 } else if (CE) {

68

69 unsigned ArgsToSkip = 0;

70 if (const auto *Op = dyn_cast(CE)) {

71 if (const auto *M = dyn_cast(Op->getCalleeDecl()))

72 ArgsToSkip =

73 static_cast<unsigned>(!M->isExplicitObjectMemberFunction());

74 }

77 } else {

78 assert(

80 "No CallExpr specified for function with non-zero number of arguments");

81 }

82 return {required, PrefixSize};

83}

84

89 llvm::CallBase **CallOrInvoke) {

93 *this, MD, This, ImplicitParam, ImplicitParamTy, CE, Args, RtlArgs);

94 auto &FnInfo = CGM.getTypes().arrangeCXXMethodCall(

95 Args, FPT, CallInfo.ReqArgs, CallInfo.PrefixSize);

99}

100

103 llvm::Value *ImplicitParam, QualType ImplicitParamTy, const CallExpr *CE,

104 llvm::CallBase **CallOrInvoke) {

106

107 assert(!ThisTy.isNull());

109 "Pointer/Object mixup");

110

113 if (SrcAS != DstAS) {

115 llvm::Type *NewType = CGM.getTypes().ConvertType(DstTy);

117 }

118

121 ImplicitParamTy, CE, Args, nullptr);

122 return EmitCall(CGM.getTypes().arrangeCXXStructorDeclaration(Dtor), Callee,

126}

127

132

133

134

138

139

143 BaseQuals = PTy->getPointeeType().getQualifiers();

144 } else {

149 }

150

155 break;

156

161 break;

162

165 break;

166 }

167 } else {

168

169

170

171

172

174 }

175

177}

178

182 T = PTy->getPointeeType();

183 return T->castAsCXXRecordDecl();

184}

185

186

187

190 llvm::CallBase **CallOrInvoke) {

192

195

198

200

204 ReturnValue, nullptr, CallOrInvoke);

205 }

206

209 bool IsArrow = ME->isArrow();

211

213 HasQualifier, Qualifier, IsArrow,

214 Base, CallOrInvoke);

215}

216

220 const Expr *Base, llvm::CallBase **CallOrInvoke) {

222

223

224 bool CanUseVirtualCall = MD->isVirtual() && !HasQualifier;

225

226 const CXXMethodDecl *DevirtualizedMethod = nullptr;

227 if (CanUseVirtualCall &&

229 const CXXRecordDecl *BestDynamicDecl = Base->getBestDynamicClassType();

231 assert(DevirtualizedMethod);

233 const Expr *Inner = Base->IgnoreParenBaseCasts();

236

237

238

239

240

241 DevirtualizedMethod = nullptr;

242 else if (getCXXRecord(Inner) == DevirtualizedClass)

243

244

245 Base = Inner;

247

248

249

250

251 DevirtualizedMethod = nullptr;

252 }

253 }

254

255 bool TrivialForCodegen =

257 bool TrivialAssignment =

258 TrivialForCodegen &&

261

262

263

266 LValue TrivialAssignmentRHS;

267 if (auto *OCE = dyn_cast(CE)) {

268 if (OCE->isAssignmentOp()) {

269 if (TrivialAssignment) {

271 } else {

272 RtlArgs = &RtlArgStorage;

276 }

277 }

278 }

279

281 if (IsArrow) {

286 BaseInfo, TBAAInfo);

287 } else {

289 }

290

291 if (const CXXConstructorDecl *Ctor = dyn_cast(MD)) {

292

293

294 assert(!RtlArgs);

295 assert(ReturnValue.isNull() && "Constructor shouldn't have return value");

299 nullptr,

300 QualType(), CE, Args, nullptr);

301

303 false, This.getAddress(), Args,

305 false, CallOrInvoke);

307 }

308

309 if (TrivialForCodegen) {

312

313 if (TrivialAssignment) {

314

315

316

317

318

320 ? TrivialAssignmentRHS

324 }

325

327 "unknown trivial member function");

328 }

329

330

332 DevirtualizedMethod ? DevirtualizedMethod : MD;

334 if (const auto *Dtor = dyn_cast(CalleeDecl))

335 FInfo = &CGM.getTypes().arrangeCXXStructorDeclaration(

337 else

338 FInfo = &CGM.getTypes().arrangeCXXMethodDeclaration(CalleeDecl);

339

340 llvm::FunctionType *Ty = CGM.getTypes().GetFunctionType(*FInfo);

341

342

343

344

347 if (CE)

349

351 if (const auto *CMCE = dyn_cast(CE)) {

352 auto *IOA = CMCE->getImplicitObjectArgument();

354 if (IsImplicitObjectCXXThis)

355 SkippedChecks.set(SanitizerKind::Alignment, true);

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

358 }

359

362 This.emitRawPointer(*this),

363 C.getCanonicalTagType(CalleeDecl->getParent()),

365

366

367

368

369

370

371

372 bool UseVirtualCall = CanUseVirtualCall && !DevirtualizedMethod;

373

374 if (const CXXDestructorDecl *Dtor = dyn_cast(CalleeDecl)) {

375 assert(CE->arguments().empty() &&

376 "Destructor shouldn't have explicit parameters");

377 assert(ReturnValue.isNull() && "Destructor shouldn't have return value");

378 if (UseVirtualCall) {

379 CGM.getCXXABI().EmitVirtualDestructorCall(

382 } else {

385 if (getLangOpts().AppleKext && Dtor->isVirtual() && HasQualifier)

387 else if (!DevirtualizedMethod)

388 Callee =

390 else {

392 }

393

395 IsArrow ? Base->getType()->getPointeeType() : Base->getType();

397 nullptr,

398 QualType(), CE, CallOrInvoke);

399 }

401 }

402

403

404

405

407 if (UseVirtualCall) {

409 } else {

410 if (SanOpts.has(SanitizerKind::CFINVCall) &&

412 llvm::Value *VTable;

414 std::tie(VTable, RD) = CGM.getCXXABI().LoadVTablePtr(

415 *this, This.getAddress(), CalleeDecl->getParent());

417 }

418

421 else if (!DevirtualizedMethod)

422 Callee =

424 else {

425 Callee =

428 }

429 }

430

433 CGM.getCXXABI().adjustThisArgumentForVirtualFunctionCall(

434 *this, CalleeDecl, This.getAddress(), UseVirtualCall);

435 This.setAddress(NewThisAddr);

436 }

437

440 nullptr, QualType(), CE, RtlArgs, CallOrInvoke);

441}

442

446 llvm::CallBase **CallOrInvoke) {

450 const Expr *MemFnExpr = BO->getRHS();

451

454 const auto *RD = MPT->getMostRecentCXXRecordDecl();

455

456

458 if (BO->getOpcode() == BO_PtrMemI)

460 else

462

463 CanQualType ClassType = CGM.getContext().getCanonicalTagType(RD);

465 ClassType);

466

467

469

470

471 llvm::Value *ThisPtrForCall = nullptr;

473 CGM.getCXXABI().EmitLoadOfMemberFunctionPointer(*this, BO, This,

474 ThisPtrForCall, MemFnPtr, MPT);

475

477

479

480

482

484

485

487 return EmitCall(CGM.getTypes().arrangeCXXMethodCall(Args, FPT, required,

488 0),

491}

492

497 "Trying to emit a member call expr on a static method!");

499 E, MD, ReturnValue, false, std::nullopt,

500 false, E->getArg(0), CallOrInvoke);

501}

502

505 llvm::CallBase **CallOrInvoke) {

506

508 return CGM.getCUDARuntime().EmitCUDADeviceKernelCallExpr(

510 return CGM.getCUDARuntime().EmitCUDAKernelCallExpr(*this, E, ReturnValue,

511 CallOrInvoke);

512}

513

517 if (Base->isEmpty())

518 return;

519

521

524

525

526

527

530

531

533 std::vector VBPtrOffsets =

535 for (CharUnits VBPtrOffset : VBPtrOffsets) {

536

537 if (VBPtrOffset >= NVSize)

538 break;

539 std::pair<CharUnits, CharUnits> LastStore = Stores.pop_back_val();

540 CharUnits LastStoreOffset = LastStore.first;

541 CharUnits LastStoreSize = LastStore.second;

542

543 CharUnits SplitBeforeOffset = LastStoreOffset;

544 CharUnits SplitBeforeSize = VBPtrOffset - SplitBeforeOffset;

545 assert(!SplitBeforeSize.isNegative() && "negative store size!");

546 if (!SplitBeforeSize.isZero())

547 Stores.emplace_back(SplitBeforeOffset, SplitBeforeSize);

548

549 CharUnits SplitAfterOffset = VBPtrOffset + VBPtrWidth;

550 CharUnits SplitAfterSize = LastStoreSize - SplitAfterOffset;

551 assert(!SplitAfterSize.isNegative() && "negative store size!");

552 if (!SplitAfterSize.isZero())

553 Stores.emplace_back(SplitAfterOffset, SplitAfterSize);

554 }

555

556

557

558

559

560

561

563 if (!NullConstantForBase->isNullValue()) {

564 llvm::GlobalVariable *NullVariable = new llvm::GlobalVariable(

565 CGF.CGM.getModule(), NullConstantForBase->getType(),

566 true, llvm::GlobalVariable::PrivateLinkage,

567 NullConstantForBase, Twine());

568

571 NullVariable->setAlignment(Align.getAsAlign());

572

574

575

576 for (std::pair<CharUnits, CharUnits> Store : Stores) {

577 CharUnits StoreOffset = Store.first;

578 CharUnits StoreSize = Store.second;

579 llvm::Value *StoreSizeVal = CGF.CGM.getSize(StoreSize);

583 StoreSizeVal);

584 }

585

586

587

588

589 } else {

590 for (std::pair<CharUnits, CharUnits> Store : Stores) {

591 CharUnits StoreOffset = Store.first;

592 CharUnits StoreSize = Store.second;

593 llvm::Value *StoreSizeVal = CGF.CGM.getSize(StoreSize);

596 CGF.Builder.getInt8(0), StoreSizeVal);

597 }

598 }

599}

600

601void

604 assert(!Dest.isIgnored() && "Must have a destination!");

606

607

608

609

610

616 break;

621 break;

622 }

623 }

624

625

627 return;

628

629

631

632

633

634

635

638 assert(

641 return;

642 }

643

648 } else {

650 bool ForVirtualBase = false;

652

655

658 break;

659

662 break;

663

665 ForVirtualBase = true;

666 [[fallthrough]];

667

670 }

671

672

674 }

675}

676

678 const Expr *Exp) {

679 if (const ExprWithCleanups *E = dyn_cast(Exp))

680 Exp = E->getSubExpr();

682 "EmitSynthesizedCXXCopyCtor - unknown copy ctor expr");

686

687

688

689

690

693

695 && "EmitSynthesizedCXXCopyCtor - Copied-in Array");

697}

698

711

714 unsigned minElements,

715 llvm::Value *&numElements,

716 llvm::Value *&sizeWithoutCookie) {

718

721 sizeWithoutCookie

723 return sizeWithoutCookie;

724 }

725

726

727 unsigned sizeWidth = CGF.SizeTy->getBitWidth();

728

729

730 llvm::APInt cookieSize(sizeWidth,

732

733

734

735

738 if (!numElements)

741

742

743

744

745

746

747

748 bool isSigned

749 = (*e->getArraySize())->getType()->isSignedIntegerOrEnumerationType();

750 llvm::IntegerType *numElementsType

752 unsigned numElementsWidth = numElementsType->getBitWidth();

753

754

755 llvm::APInt arraySizeMultiplier(sizeWidth, 1);

758 type = CAT->getElementType();

759 arraySizeMultiplier *= CAT->getSize();

760 }

761

763 llvm::APInt typeSizeMultiplier(sizeWidth, typeSize.getQuantity());

764 typeSizeMultiplier *= arraySizeMultiplier;

765

766

767 llvm::Value *size;

768

769

770

771 if (llvm::ConstantInt *numElementsC =

772 dyn_castllvm::ConstantInt(numElements)) {

773 const llvm::APInt &count = numElementsC->getValue();

774

775 bool hasAnyOverflow = false;

776

777

778 if (isSigned && count.isNegative())

779 hasAnyOverflow = true;

780

781

782

783

784 else if (numElementsWidth > sizeWidth &&

785 numElementsWidth - sizeWidth > count.countl_zero())

786 hasAnyOverflow = true;

787

788

789 llvm::APInt adjustedCount = count.zextOrTrunc(sizeWidth);

790

791

792

793 if (adjustedCount.ult(minElements))

794 hasAnyOverflow = true;

795

796

797

798

799 numElements = llvm::ConstantInt::get(CGF.SizeTy,

800 adjustedCount * arraySizeMultiplier);

801

802

803 bool overflow;

804 llvm::APInt allocationSize

805 = adjustedCount.umul_ov(typeSizeMultiplier, overflow);

806 hasAnyOverflow |= overflow;

807

808

809 if (cookieSize != 0) {

810

811

812 sizeWithoutCookie = llvm::ConstantInt::get(CGF.SizeTy, allocationSize);

813

814 allocationSize = allocationSize.uadd_ov(cookieSize, overflow);

815 hasAnyOverflow |= overflow;

816 }

817

818

819 if (hasAnyOverflow) {

820 size = llvm::Constant::getAllOnesValue(CGF.SizeTy);

821 } else {

822 size = llvm::ConstantInt::get(CGF.SizeTy, allocationSize);

823 }

824

825

826 } else {

827

828

829

830

831

832

833

834

835

836

837

838

839

840 llvm::Value *hasOverflow = nullptr;

841

842

843

844

845 if (numElementsWidth > sizeWidth) {

846 llvm::APInt threshold =

847 llvm::APInt::getOneBitSet(numElementsWidth, sizeWidth);

848

849 llvm::Value *thresholdV

850 = llvm::ConstantInt::get(numElementsType, threshold);

851

852 hasOverflow = CGF.Builder.CreateICmpUGE(numElements, thresholdV);

853 numElements = CGF.Builder.CreateTrunc(numElements, CGF.SizeTy);

854

855

856 } else if (isSigned) {

857 if (numElementsWidth < sizeWidth)

858 numElements = CGF.Builder.CreateSExt(numElements, CGF.SizeTy);

859

860

861

862

863

864

865 if (typeSizeMultiplier == 1)

866 hasOverflow = CGF.Builder.CreateICmpSLT(numElements,

867 llvm::ConstantInt::get(CGF.SizeTy, minElements));

868

869

870 } else if (numElementsWidth < sizeWidth) {

871 numElements = CGF.Builder.CreateZExt(numElements, CGF.SizeTy);

872 }

873

874 assert(numElements->getType() == CGF.SizeTy);

875

876 if (minElements) {

877

878 if (!hasOverflow) {

879 hasOverflow = CGF.Builder.CreateICmpULT(numElements,

880 llvm::ConstantInt::get(CGF.SizeTy, minElements));

881 } else if (numElementsWidth > sizeWidth) {

882

883

884

885 hasOverflow = CGF.Builder.CreateOr(hasOverflow,

886 CGF.Builder.CreateICmpULT(numElements,

887 llvm::ConstantInt::get(CGF.SizeTy, minElements)));

888 }

889 }

890

891 size = numElements;

892

893

894

895

896

897

898

899

900 if (typeSizeMultiplier != 1) {

901 llvm::Function *umul_with_overflow

903

904 llvm::Value *tsmV =

905 llvm::ConstantInt::get(CGF.SizeTy, typeSizeMultiplier);

906 llvm::Value *result =

907 CGF.Builder.CreateCall(umul_with_overflow, {size, tsmV});

908

909 llvm::Value *overflowed = CGF.Builder.CreateExtractValue(result, 1);

910 if (hasOverflow)

911 hasOverflow = CGF.Builder.CreateOr(hasOverflow, overflowed);

912 else

913 hasOverflow = overflowed;

914

915 size = CGF.Builder.CreateExtractValue(result, 0);

916

917

918 if (arraySizeMultiplier != 1) {

919

920

921 if (typeSize.isOne()) {

922 assert(arraySizeMultiplier == typeSizeMultiplier);

923 numElements = size;

924

925

926 } else {

927 llvm::Value *asmV =

928 llvm::ConstantInt::get(CGF.SizeTy, arraySizeMultiplier);

929 numElements = CGF.Builder.CreateMul(numElements, asmV);

930 }

931 }

932 } else {

933

934 assert(arraySizeMultiplier == 1);

935 }

936

937

938 if (cookieSize != 0) {

939 sizeWithoutCookie = size;

940

941 llvm::Function *uadd_with_overflow

943

944 llvm::Value *cookieSizeV = llvm::ConstantInt::get(CGF.SizeTy, cookieSize);

945 llvm::Value *result =

946 CGF.Builder.CreateCall(uadd_with_overflow, {size, cookieSizeV});

947

948 llvm::Value *overflowed = CGF.Builder.CreateExtractValue(result, 1);

949 if (hasOverflow)

950 hasOverflow = CGF.Builder.CreateOr(hasOverflow, overflowed);

951 else

952 hasOverflow = overflowed;

953

954 size = CGF.Builder.CreateExtractValue(result, 0);

955 }

956

957

958

959

960 if (hasOverflow)

961 size = CGF.Builder.CreateSelect(hasOverflow,

962 llvm::Constant::getAllOnesValue(CGF.SizeTy),

963 size);

964 }

965

966 if (cookieSize == 0)

967 sizeWithoutCookie = size;

968 else

969 assert(sizeWithoutCookie && "didn't set sizeWithoutCookie?");

970

971 return size;

972}

973

977

982 return;

985 true);

986 return;

996 return;

997 }

998 }

999 llvm_unreachable("bad evaluation kind");

1000}

1001

1004 Address BeginPtr, llvm::Value *NumElements,

1005 llvm::Value *AllocSizeWithoutCookie) {

1006

1007

1009 return;

1010

1011 Address CurPtr = BeginPtr;

1012

1013 unsigned InitListElements = 0;

1014

1019 bool pushedCleanup = false;

1020

1024

1025

1026 auto TryMemsetInitialization = [&]() -> bool {

1027

1028

1029 if (CGM.getTypes().isZeroInitializable(ElementType))

1030 return false;

1031

1032

1033

1034

1035

1036 auto *RemainingSize = AllocSizeWithoutCookie;

1037 if (InitListElements) {

1038

1039 auto *InitializedSize = llvm::ConstantInt::get(

1040 RemainingSize->getType(),

1041 getContext().getTypeSizeInChars(ElementType).getQuantity() *

1042 InitListElements);

1043 RemainingSize = Builder.CreateSub(RemainingSize, InitializedSize);

1044 }

1045

1046

1047 Builder.CreateMemSet(CurPtr, Builder.getInt8(0), RemainingSize, false);

1048 return true;

1049 };

1050

1055 const Expr *IgnoreParen = nullptr;

1056 if (!ILE) {

1057 IgnoreParen = Init->IgnoreParenImpCasts();

1058 CPLIE = dyn_cast(IgnoreParen);

1059 SL = dyn_cast(IgnoreParen);

1060 OCEE = dyn_cast(IgnoreParen);

1061 }

1062

1063

1064 if (ILE || CPLIE || SL || OCEE) {

1065

1066

1068 if (!ILE)

1069 Init = IgnoreParen;

1070

1071

1072

1082

1083

1084 InitListElements =

1086 ->getZExtSize();

1087 CurPtr = Builder.CreateConstInBoundsGEP(

1088 CurPtr, InitListElements, "string.init.end");

1089

1090

1091 llvm::ConstantInt *ConstNum = dyn_castllvm::ConstantInt(NumElements);

1092 if (!ConstNum || !ConstNum->equalsInt(InitListElements)) {

1093 bool OK = TryMemsetInitialization();

1094 (void)OK;

1095 assert(OK && "couldn't memset character type?");

1096 }

1097 return;

1098 }

1099

1102 InitListElements = InitExprs.size();

1103

1104

1105

1107 if (const ConstantArrayType *CAT = dyn_cast_or_null(

1112 }

1113

1114

1115 if (DtorKind) {

1117

1118

1119

1120

1121 llvm::Instruction *DominatingIP =

1122 Builder.CreateFlagLoad(llvm::ConstantInt::getNullValue(Int8PtrTy));

1124 "array.init.end");

1126 EndOfInit, ElementType, ElementAlign,

1129 .AddAuxAllocas(AllocaTracker.Take());

1131 {EHStack.stable_begin(), DominatingIP});

1132 pushedCleanup = true;

1133 }

1134

1136 unsigned i = 0;

1137 for (const Expr *IE : InitExprs) {

1138

1139

1140

1141 if (EndOfInit.isValid()) {

1143 }

1144

1145

1146

1152 "array.exp.next"),

1155 }

1156

1157

1159

1160

1161

1162

1163 while (Init && Init->getType()->isConstantArrayType()) {

1164 auto *SubILE = dyn_cast(Init);

1165 if (!SubILE)

1166 break;

1167 assert(SubILE->getNumInits() == 0 && "explicit inits in array filler?");

1168 Init = SubILE->getArrayFiller();

1169 }

1170

1171

1173 }

1174

1175

1176

1177 llvm::ConstantInt *ConstNum = dyn_castllvm::ConstantInt(NumElements);

1178 if (ConstNum && ConstNum->getZExtValue() <= InitListElements) {

1179 return;

1180 }

1181

1182 assert(Init && "have trailing elements to initialize but no initializer");

1183

1184

1185

1189

1190

1191 if (!CCE->requiresZeroInitialization() || Ctor->getParent()->isEmpty())

1192 return;

1193

1194 if (TryMemsetInitialization())

1195 return;

1196 }

1197

1198

1199

1200

1201

1202 if (EndOfInit.isValid())

1204

1205

1206 if (InitListElements)

1207 NumElements = Builder.CreateSub(

1208 NumElements,

1209 llvm::ConstantInt::get(NumElements->getType(), InitListElements));

1211 true,

1212 CCE->requiresZeroInitialization());

1213 return;

1214 }

1215

1216

1219 if (TryMemsetInitialization())

1220 return;

1221

1222

1223

1224

1225 Init = &IVIE;

1226 }

1227

1228

1229

1230 assert(getContext().hasSameUnqualifiedType(ElementType, Init->getType()) &&

1231 "got wrong type of element to initialize");

1232

1233

1234 if (auto *ILE = dyn_cast(Init))

1235 if (ILE->getNumInits() == 0 && TryMemsetInitialization())

1236 return;

1237

1238

1239

1240 if (auto *ILE = dyn_cast(Init)) {

1241 if (const RecordType *RType =

1243 if (RType->getDecl()->isStruct()) {

1245 unsigned NumElements = 0;

1246 if (auto *CXXRD = dyn_cast(RD))

1247 NumElements = CXXRD->getNumBases();

1248 for (auto *Field : RD->fields())

1249 if (!Field->isUnnamedBitField())

1250 ++NumElements;

1251

1253 for (unsigned i = 0, e = ILE->getNumInits(); i != e; ++i)

1255 --NumElements;

1256 if (ILE->getNumInits() == NumElements && TryMemsetInitialization())

1257 return;

1258 }

1259 }

1260 }

1261

1262

1263 llvm::BasicBlock *EntryBB = Builder.GetInsertBlock();

1265 llvm::BasicBlock *ContBB = createBasicBlock("new.loop.end");

1266

1267

1268 llvm::Value *EndPtr = Builder.CreateInBoundsGEP(

1270 "array.end");

1271

1272

1273

1274 if (!ConstNum) {

1276 EndPtr, "array.isempty");

1277 Builder.CreateCondBr(IsEmpty, ContBB, LoopBB);

1278 }

1279

1280

1282

1283

1284 llvm::PHINode *CurPtrPhi =

1285 Builder.CreatePHI(CurPtr.getType(), 2, "array.cur");

1286 CurPtrPhi->addIncoming(CurPtr.emitRawPointer(*this), EntryBB);

1287

1289

1290

1291 if (EndOfInit.isValid())

1293

1294

1296 llvm::Instruction *DominatingIP =

1297 Builder.CreateFlagLoad(llvm::ConstantInt::getNullValue(Int8PtrTy));

1302 {EHStack.stable_begin(), DominatingIP});

1303 }

1304

1305

1308

1309

1311

1312

1313 llvm::Value *NextPtr = Builder.CreateConstInBoundsGEP1_32(

1314 ElementTy, CurPtr.emitRawPointer(*this), 1, "array.next");

1315

1316

1317

1318 llvm::Value *IsEnd = Builder.CreateICmpEQ(NextPtr, EndPtr, "array.atend");

1319 Builder.CreateCondBr(IsEnd, ContBB, LoopBB);

1320 CurPtrPhi->addIncoming(NextPtr, Builder.GetInsertBlock());

1321

1323}

1324

1326 QualType ElementType, llvm::Type *ElementTy,

1327 Address NewPtr, llvm::Value *NumElements,

1328 llvm::Value *AllocSizeWithoutCookie) {

1332 AllocSizeWithoutCookie);

1336}

1337

1338

1339

1344 llvm::CallBase *CallOrInvoke;

1349 Args, CalleeType, false),

1351

1352

1353

1354

1355

1356

1357 llvm::Function *Fn = dyn_castllvm::Function(CalleePtr);

1359 Fn && Fn->hasFnAttribute(llvm::Attribute::NoBuiltin)) {

1360 CallOrInvoke->addFnAttr(llvm::Attribute::Builtin);

1361 }

1362

1363 return RV;

1364}

1365

1368 bool IsDelete) {

1371

1375

1377 if (auto *FD = dyn_cast(Decl))

1380 if (auto *CB = dyn_cast_if_presentllvm::CallBase(RV.getScalarVal())) {

1381 if (SanOpts.has(SanitizerKind::AllocToken)) {

1382

1384 }

1385 }

1386 return RV;

1387 }

1388 llvm_unreachable("predeclared global operator new/delete is missing");

1389}

1390

1391namespace {

1392

1393

1394

1395 template

1396 class CallDeleteDuringNew final : public EHScopeStack::Cleanup {

1397

1398 typedef typename Traits::ValueTy ValueTy;

1399

1400 typedef typename Traits::RValueTy RValueTy;

1401 struct PlacementArg {

1402 RValueTy ArgValue;

1404 };

1405

1406 unsigned NumPlacementArgs : 30;

1408 unsigned PassAlignmentToPlacementDelete : 1;

1410 RValueTy TypeIdentity;

1411 ValueTy Ptr;

1412 ValueTy AllocSize;

1414

1415 PlacementArg *getPlacementArgs() {

1416 return reinterpret_cast<PlacementArg *>(this + 1);

1417 }

1418

1419 public:

1420 static size_t getExtraSize(size_t NumPlacementArgs) {

1421 return NumPlacementArgs * sizeof(PlacementArg);

1422 }

1423

1424 CallDeleteDuringNew(size_t NumPlacementArgs,

1425 const FunctionDecl *OperatorDelete,

1426 RValueTy TypeIdentity, ValueTy Ptr, ValueTy AllocSize,

1427 const ImplicitAllocationParameters &IAP,

1428 CharUnits AllocAlign)

1429 : NumPlacementArgs(NumPlacementArgs),

1430 PassAlignmentToPlacementDelete(

1432 OperatorDelete(OperatorDelete), TypeIdentity(TypeIdentity), Ptr(Ptr),

1433 AllocSize(AllocSize), AllocAlign(AllocAlign) {}

1434

1435 void setPlacementArg(unsigned I, RValueTy Arg, QualType Type) {

1436 assert(I < NumPlacementArgs && "index out of range");

1437 getPlacementArgs()[I] = {Arg, Type};

1438 }

1439

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

1441 const auto *FPT = OperatorDelete->getType()->castAs();

1442 CallArgList DeleteArgs;

1443 unsigned FirstNonTypeArg = 0;

1445 TypeAwareAllocationMode::No;

1446 if (OperatorDelete->isTypeAwareOperatorNewOrDelete()) {

1447 TypeAwareDeallocation = TypeAwareAllocationMode::Yes;

1448 QualType SpecializedTypeIdentity = FPT->getParamType(0);

1449 ++FirstNonTypeArg;

1450 DeleteArgs.add(Traits::get(CGF, TypeIdentity), SpecializedTypeIdentity);

1451 }

1452

1453

1454 DeleteArgs.add(Traits::get(CGF, Ptr), FPT->getParamType(FirstNonTypeArg));

1455

1456

1457 UsualDeleteParams Params;

1458 if (NumPlacementArgs) {

1459

1460

1465 } else {

1466

1467

1468 Params = OperatorDelete->getUsualDeleteParams();

1469 }

1470

1472 "should not call destroying delete in a new-expression");

1473

1474

1475 if (Params.Size)

1476 DeleteArgs.add(Traits::get(CGF, AllocSize),

1478

1479

1480

1481

1482

1484 DeleteArgs.add(RValue::get(llvm::ConstantInt::get(

1487

1488

1489 for (unsigned I = 0; I != NumPlacementArgs; ++I) {

1490 auto Arg = getPlacementArgs()[I];

1491 DeleteArgs.add(Traits::get(CGF, Arg.ArgValue), Arg.ArgType);

1492 }

1493

1494

1496 }

1497 };

1498}

1499

1500

1501

1504 llvm::Value *AllocSize, CharUnits AllocAlign,

1507

1508

1509

1511 struct DirectCleanupTraits {

1512 typedef llvm::Value *ValueTy;

1513 typedef RValue RValueTy;

1516 };

1517

1518 typedef CallDeleteDuringNew DirectCleanup;

1519

1522 TypeIdentity, NewPtr.emitRawPointer(CGF), AllocSize,

1525 auto &Arg = NewArgs[I + NumNonPlacementArgs];

1526 Cleanup->setPlacementArg(I, Arg.getRValue(CGF), Arg.Ty);

1527 }

1528

1529 return;

1530 }

1531

1532

1539 struct ConditionalCleanupTraits {

1543 return V.restore(CGF);

1544 }

1545 };

1546 typedef CallDeleteDuringNew ConditionalCleanup;

1547

1548 ConditionalCleanup *Cleanup =

1551 SavedTypeIdentity, SavedNewPtr, SavedAllocSize,

1554 auto &Arg = NewArgs[I + NumNonPlacementArgs];

1555 Cleanup->setPlacementArg(

1557 }

1558

1560}

1561

1563

1565

1566

1568

1569

1570

1571 unsigned minElements = 0;

1572 unsigned IndexOfAlignArg = 1;

1577 const Expr *IgnoreParen = Init->IgnoreParenImpCasts();

1580 minElements =

1582 ->getZExtSize();

1583 } else if (ILE || CPLIE) {

1585 }

1586 }

1587

1588 llvm::Value *numElements = nullptr;

1589 llvm::Value *allocSizeWithoutCookie = nullptr;

1590 llvm::Value *allocSize =

1592 allocSizeWithoutCookie);

1594

1595

1596

1599 RValue TypeIdentityArg;

1600 if (allocator->isReservedGlobalPlacementOperator()) {

1603

1606

1607

1608

1609

1612

1613

1614

1618 allocatorArgs.add(RValue::get(allocation, *this), arg->getType());

1619 }

1620

1621 } else {

1625 unsigned ParamsToSkip = 0;

1631 allocatorArgs.add(TypeIdentityArg, SpecializedTypeIdentity);

1632 ++ParamsToSkip;

1633 ++IndexOfAlignArg;

1634 }

1635

1637 allocatorArgs.add(RValue::get(allocSize), sizeType);

1638 ++ParamsToSkip;

1639

1640 if (allocSize != allocSizeWithoutCookie) {

1642 allocAlign = std::max(allocAlign, cookieAlign);

1643 }

1644

1645

1647 QualType AlignValT = sizeType;

1648 if (allocatorType->getNumParams() > IndexOfAlignArg) {

1649 AlignValT = allocatorType->getParamType(IndexOfAlignArg);

1650 assert(getContext().hasSameUnqualifiedType(

1652 "wrong type for alignment parameter");

1653 ++ParamsToSkip;

1654 } else {

1655

1656 assert(allocator->isVariadic() && "can't pass alignment to allocator");

1657 }

1658 allocatorArgs.add(

1660 AlignValT);

1661 }

1662

1663

1665 AbstractCallee(), ParamsToSkip);

1666

1668 EmitNewDeleteCall(*this, allocator, allocatorType, allocatorArgs);

1669

1670 if (auto *newCall = dyn_castllvm::CallBase(RV.getScalarVal())) {

1672

1673 CGDI->addHeapAllocSiteMetadata(newCall, allocType, E->getExprLoc());

1674 }

1675 if (SanOpts.has(SanitizerKind::AllocToken)) {

1676

1678 }

1679 }

1680

1681

1682

1683

1684

1685 CharUnits allocationAlign = allocAlign;

1687 allocator->isReplaceableGlobalAllocationFunction()) {

1688 unsigned AllocatorAlign = llvm::bit_floor(std::min<uint64_t>(

1690 allocationAlign = std::max(

1691 allocationAlign, getContext().toCharUnitsFromBits(AllocatorAlign));

1692 }

1693

1695 }

1696

1697

1698

1699

1700

1704

1705 llvm::BasicBlock *nullCheckBB = nullptr;

1706 llvm::BasicBlock *contBB = nullptr;

1707

1708

1709

1711

1712 if (nullCheck) {

1713 conditional.begin(*this);

1714

1715 nullCheckBB = Builder.GetInsertBlock();

1716 llvm::BasicBlock *notNullBB = createBasicBlock("new.notnull");

1718

1719 llvm::Value *isNull = Builder.CreateIsNull(allocation, "new.isnull");

1720 Builder.CreateCondBr(isNull, contBB, notNullBB);

1722 }

1723

1724

1725

1727 llvm::Instruction *cleanupDominator = nullptr;

1731 allocAlign, allocatorArgs);

1732 operatorDeleteCleanup = EHStack.stable_begin();

1733 cleanupDominator = Builder.CreateUnreachable();

1734 }

1735

1736 assert((allocSize == allocSizeWithoutCookie) ==

1738 if (allocSize != allocSizeWithoutCookie) {

1740 allocation = CGM.getCXXABI().InitializeArrayCookie(*this, allocation,

1741 numElements,

1742 E, allocType);

1743 }

1744

1747

1748

1749

1750

1751

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

1753 allocator->isReservedGlobalPlacementOperator())

1754 result = Builder.CreateLaunderInvariantGroup(result);

1755

1756

1757

1758

1759

1760

1762 SkippedChecks.set(SanitizerKind::Null, nullCheck);

1765 result, allocType, result.getAlignment(), SkippedChecks,

1766 numElements);

1767

1768 EmitNewInitializer(*this, E, allocType, elementTy, result, numElements,

1769 allocSizeWithoutCookie);

1770 llvm::Value *resultPtr = result.emitRawPointer(*this);

1771

1772

1773

1774 if (operatorDeleteCleanup.isValid()) {

1776 cleanupDominator->eraseFromParent();

1777 }

1778

1779 if (nullCheck) {

1780 conditional.end(*this);

1781

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

1784

1785 llvm::PHINode *PHI = Builder.CreatePHI(resultPtr->getType(), 2);

1786 PHI->addIncoming(resultPtr, notNullBB);

1787 PHI->addIncoming(llvm::Constant::getNullValue(resultPtr->getType()),

1788 nullCheckBB);

1789

1790 resultPtr = PHI;

1791 }

1792

1793 return resultPtr;

1794}

1795

1797 llvm::Value *DeletePtr, QualType DeleteTy,

1798 llvm::Value *NumElements,

1800 assert((!NumElements && CookieSize.isZero()) ||

1802

1805

1807 auto ParamTypeIt = DeleteFTy->param_type_begin();

1808

1809 std::optional<llvm::AllocaInst *> TagAlloca;

1810 auto EmitTag = [&](QualType TagType, const char *TagName) {

1811 assert(!TagAlloca);

1813 CharUnits Align = CGM.getNaturalTypeAlignment(TagType);

1814 llvm::AllocaInst *TagAllocation = CreateTempAlloca(Ty, TagName);

1815 TagAllocation->setAlignment(Align.getAsAlign());

1817 TagType);

1818 TagAlloca = TagAllocation;

1819 };

1820

1821

1823 EmitTag(*ParamTypeIt++, "typeaware.delete.tag");

1824

1825

1826 QualType ArgTy = *ParamTypeIt++;

1827 DeleteArgs.add(RValue::get(DeletePtr), ArgTy);

1828

1829

1831 EmitTag(*ParamTypeIt++, "destroying.delete.tag");

1832

1833

1834 if (Params.Size) {

1835 QualType SizeType = *ParamTypeIt++;

1837 llvm::Value *Size = llvm::ConstantInt::get(ConvertType(SizeType),

1839

1840

1841 if (NumElements)

1842 Size = Builder.CreateMul(Size, NumElements);

1843

1844

1845 if (!CookieSize.isZero())

1846 Size = Builder.CreateAdd(

1847 Size, llvm::ConstantInt::get(SizeTy, CookieSize.getQuantity()));

1848

1849 DeleteArgs.add(RValue::get(Size), SizeType);

1850 }

1851

1852

1854 QualType AlignValType = *ParamTypeIt++;

1857 DeleteTy, true ));

1858 llvm::Value *Align = llvm::ConstantInt::get(ConvertType(AlignValType),

1860 DeleteArgs.add(RValue::get(Align), AlignValType);

1861 }

1862

1863 assert(ParamTypeIt == DeleteFTy->param_type_end() &&

1864 "unknown parameter to usual delete function");

1865

1866

1868

1869

1870

1871 if (TagAlloca && (*TagAlloca)->use_empty())

1872 (*TagAlloca)->eraseFromParent();

1873}

1874namespace {

1875

1876 struct CallObjectDelete final : EHScopeStack::Cleanup {

1877 llvm::Value *Ptr;

1880

1881 CallObjectDelete(llvm::Value *Ptr,

1884 : Ptr(Ptr), OperatorDelete(OperatorDelete), ElementType(ElementType) {}

1885

1887 CGF.EmitDeleteCall(OperatorDelete, Ptr, ElementType);

1888 }

1889 };

1890}

1891

1892void

1894 llvm::Value *CompletePtr,

1897 OperatorDelete, ElementType);

1898}

1899

1900

1901

1902

1903

1908 if (Dtor && Dtor->isVirtual())

1910 Dtor);

1911 else

1913 ElementType);

1914}

1915

1916

1917

1918

1921 llvm::BasicBlock *UnconditionalDeleteBlock) {

1922

1923

1924

1925

1926

1928 ElementType);

1929

1931 assert(!OperatorDelete->isDestroyingOperatorDelete());

1932

1933

1934

1937 if (RD->hasDefinition() && !RD->hasTrivialDestructor()) {

1938 Dtor = RD->getDestructor();

1939

1941 bool UseVirtualCall = true;

1943 if (auto *DevirtualizedDtor =

1944 dyn_cast_or_null(

1947 UseVirtualCall = false;

1951

1952

1953 Dtor = DevirtualizedDtor;

1954 } else {

1955

1956

1957

1958

1959

1960 UseVirtualCall = true;

1961 }

1962 }

1963 if (UseVirtualCall) {

1965 Dtor);

1966 return false;

1967 }

1968 }

1969 }

1970 }

1971

1972

1973

1974

1975 CGF.EHStack.pushCleanup(

1977

1978 if (Dtor)

1980 false,

1981 false,

1982 Ptr, ElementType);

1983 else if (auto Lifetime = ElementType.getObjCLifetime()) {

1984 switch (Lifetime) {

1988 break;

1989

1992 break;

1993

1996 break;

1997 }

1998 }

1999

2000

2002 CGF.EmitBlock(UnconditionalDeleteBlock);

2004 return true;

2005 }

2006

2008 return false;

2009}

2010

2011namespace {

2012

2013 struct CallArrayDelete final : EHScopeStack::Cleanup {

2014 llvm::Value *Ptr;

2015 const FunctionDecl *OperatorDelete;

2016 llvm::Value *NumElements;

2017 QualType ElementType;

2018 CharUnits CookieSize;

2019

2020 CallArrayDelete(llvm::Value *Ptr,

2021 const FunctionDecl *OperatorDelete,

2022 llvm::Value *NumElements,

2023 QualType ElementType,

2024 CharUnits CookieSize)

2025 : Ptr(Ptr), OperatorDelete(OperatorDelete), NumElements(NumElements),

2026 ElementType(ElementType), CookieSize(CookieSize) {}

2027

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

2029 CGF.EmitDeleteCall(OperatorDelete, Ptr, ElementType, NumElements,

2030 CookieSize);

2031 }

2032 };

2033}

2034

2035

2040 llvm::Value *numElements = nullptr;

2041 llvm::Value *allocatedPtr = nullptr;

2044 numElements, allocatedPtr, cookieSize);

2045

2046 assert(allocatedPtr && "ReadArrayCookie didn't set allocated pointer");

2047

2048

2051 allocatedPtr, operatorDelete,

2052 numElements, elementType,

2053 cookieSize);

2054

2055

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

2058

2062

2063 llvm::Value *arrayBegin = deletedPtr.emitRawPointer(CGF);

2065 deletedPtr.getElementType(), arrayBegin, numElements, "delete.end");

2066

2067

2068

2069

2070 CGF.emitArrayDestroy(arrayBegin, arrayEnd, elementType, elementAlign,

2072 true,

2074 }

2075

2076

2078}

2079

2083

2084

2085

2086

2087

2088

2089

2090

2091 llvm::BasicBlock *DeleteNotNull = createBasicBlock("delete.notnull");

2092 llvm::BasicBlock *DeleteEnd = createBasicBlock("delete.end");

2093

2094 llvm::Value *IsNull = Builder.CreateIsNull(Ptr, "isnull");

2095

2096 Builder.CreateCondBr(IsNull, DeleteEnd, DeleteNotNull);

2099

2101

2102

2103

2107 return;

2108 }

2109

2110

2113

2115 CGM.getContext().getTargetInfo().emitVectorDeletingDtors(

2116 CGM.getContext().getLangOpts())) {

2118 auto *Dtor = RD->getDestructor();

2119 if (Dtor && Dtor->isVirtual()) {

2120 llvm::Value *NumElements = nullptr;

2121 llvm::Value *AllocatedPtr = nullptr;

2124 llvm::BasicBlock *DoneBB = createBasicBlock("vdtor.nocall");

2125

2126

2127 CGM.getCXXABI().ReadArrayCookie(*this, Ptr, E, DeleteTy, NumElements,

2128 AllocatedPtr, CookieSize);

2129

2131 llvm::Value *IsEmpty = Builder.CreateICmpEQ(

2132 NumElements, llvm::ConstantInt::get(CondTy, 0));

2133 Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);

2134

2135

2138 EmitDeleteCall(OperatorDelete, AllocatedPtr, DeleteTy, NumElements,

2139 CookieSize);

2141

2145 return;

2146 }

2147 }

2148 }

2149

2153 } else {

2156 }

2157}

2158

2160 llvm::Type *StdTypeInfoPtrTy,

2161 bool HasNullCheck) {

2162

2164

2166

2167

2168

2169

2170

2172 ThisPtr, SrcRecordTy);

2173

2174

2175

2176

2177 if (HasNullCheck &&

2179 llvm::BasicBlock *BadTypeidBlock =

2181 llvm::BasicBlock *EndBlock = CGF.createBasicBlock("typeid.end");

2182

2184 CGF.Builder.CreateCondBr(IsNull, BadTypeidBlock, EndBlock);

2185

2189 }

2190

2192 StdTypeInfoPtrTy);

2193}

2194

2196

2197

2198

2199

2200

2202 LangAS GlobAS = CGM.GetGlobalVarAddressSpace(nullptr);

2203

2204 auto MaybeASCast = [=](auto &&TypeInfo) {

2208 };

2209

2213 return MaybeASCast(TypeInfo);

2214 }

2215

2216

2217

2218

2219

2220

2221

2225

2227 return MaybeASCast(CGM.GetAddrOfRTTIDescriptor(OperandTy));

2228}

2229

2232 llvm::Type *DestLTy = CGF.ConvertType(DestTy);

2234 return llvm::Constant::getNullValue(DestLTy);

2235

2236

2237

2239 return nullptr;

2240

2241 CGF.Builder.ClearInsertionPoint();

2242 return llvm::PoisonValue::get(DestLTy);

2243}

2244

2247 CGM.EmitExplicitCastExprType(DCE, this);

2249

2251

2252

2253

2254

2258 if (IsDynamicCastToVoid) {

2260

2264 } else {

2265 SrcRecordTy = SrcTy;

2267 }

2268

2269

2270

2271

2272

2273

2275

2278

2279 if (Builder.GetInsertBlock())

2281 return T;

2282 }

2283 }

2284

2285 assert(SrcRecordTy->isRecordType() && "source type must be a record type!");

2286

2287

2288

2289 bool IsExact = !IsDynamicCastToVoid &&

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

2292 CGM.getCXXABI().shouldEmitExactDynamicCast(DestRecordTy);

2293

2294 std::optionalCGCXXABI::ExactDynamicCastInfo ExactCastInfo;

2295 if (IsExact) {

2296 ExactCastInfo = CGM.getCXXABI().getExactDynamicCastInfo(SrcRecordTy, DestTy,

2297 DestRecordTy);

2298 if (!ExactCastInfo) {

2300 if (Builder.GetInsertBlock())

2302 return NullValue;

2303 }

2304 }

2305

2306

2307

2308

2309 bool ShouldNullCheckSrcValue =

2310 IsExact || CGM.getCXXABI().shouldDynamicCastCallBeNullChecked(

2312

2313 llvm::BasicBlock *CastNull = nullptr;

2314 llvm::BasicBlock *CastNotNull = nullptr;

2315 llvm::BasicBlock *CastEnd = createBasicBlock("dynamic_cast.end");

2316

2317 if (ShouldNullCheckSrcValue) {

2320

2321 llvm::Value *IsNull = Builder.CreateIsNull(ThisAddr);

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

2324 }

2325

2326 llvm::Value *Value;

2327 if (IsDynamicCastToVoid) {

2328 Value = CGM.getCXXABI().emitDynamicCastToVoid(*this, ThisAddr, SrcRecordTy);

2329 } else if (IsExact) {

2330

2331

2332 Value = CGM.getCXXABI().emitExactDynamicCast(

2333 *this, ThisAddr, SrcRecordTy, DestTy, DestRecordTy, *ExactCastInfo,

2334 CastEnd, CastNull);

2335 } else {

2337 "destination type must be a record type!");

2338 Value = CGM.getCXXABI().emitDynamicCastCall(*this, ThisAddr, SrcRecordTy,

2339 DestTy, DestRecordTy, CastEnd);

2340 }

2341 CastNotNull = Builder.GetInsertBlock();

2342

2343 llvm::Value *NullValue = nullptr;

2344 if (ShouldNullCheckSrcValue) {

2346

2349 CastNull = Builder.GetInsertBlock();

2350

2352 }

2353

2355

2356 if (CastNull) {

2358 PHI->addIncoming(Value, CastNotNull);

2359 PHI->addIncoming(NullValue, CastNull);

2360

2362 }

2363

2365}

static MemberCallInfo commonEmitCXXMemberOrOperatorCall(CodeGenFunction &CGF, GlobalDecl GD, llvm::Value *This, llvm::Value *ImplicitParam, QualType ImplicitParamTy, const CallExpr *CE, CallArgList &Args, CallArgList *RtlArgs)

Definition CGExprCXX.cpp:36

static llvm::Value * EmitTypeidFromVTable(CodeGenFunction &CGF, const Expr *E, llvm::Type *StdTypeInfoPtrTy, bool HasNullCheck)

Definition CGExprCXX.cpp:2159

static llvm::Value * EmitDynamicCastToNull(CodeGenFunction &CGF, QualType DestTy)

Definition CGExprCXX.cpp:2230

static RValue EmitNewDeleteCall(CodeGenFunction &CGF, const FunctionDecl *CalleeDecl, const FunctionProtoType *CalleeType, const CallArgList &Args)

Emit a call to an operator new or operator delete function, as implicitly created by new-expressions ...

Definition CGExprCXX.cpp:1340

static void EmitDestroyingObjectDelete(CodeGenFunction &CGF, const CXXDeleteExpr *DE, Address Ptr, QualType ElementType)

Emit the code for deleting a single object with a destroying operator delete.

Definition CGExprCXX.cpp:1904

static void EmitNullBaseClassInitialization(CodeGenFunction &CGF, Address DestPtr, const CXXRecordDecl *Base)

Definition CGExprCXX.cpp:514

static bool EmitObjectDelete(CodeGenFunction &CGF, const CXXDeleteExpr *DE, Address Ptr, QualType ElementType, llvm::BasicBlock *UnconditionalDeleteBlock)

Emit the code for deleting a single object.

Definition CGExprCXX.cpp:1919

static CXXRecordDecl * getCXXRecord(const Expr *E)

Definition CGExprCXX.cpp:179

static void EnterNewDeleteCleanup(CodeGenFunction &CGF, const CXXNewExpr *E, RValue TypeIdentity, Address NewPtr, llvm::Value *AllocSize, CharUnits AllocAlign, const CallArgList &NewArgs)

Enter a cleanup to call 'operator delete' if the initializer in a new-expression throws.

Definition CGExprCXX.cpp:1502

static CharUnits CalculateCookiePadding(CodeGenFunction &CGF, const CXXNewExpr *E)

Definition CGExprCXX.cpp:699

static void EmitArrayDelete(CodeGenFunction &CGF, const CXXDeleteExpr *E, Address deletedPtr, QualType elementType)

Emit the code for deleting an array of objects.

Definition CGExprCXX.cpp:2036

static void StoreAnyExprIntoOneUnit(CodeGenFunction &CGF, const Expr *Init, QualType AllocType, Address NewPtr, AggValueSlot::Overlap_t MayOverlap)

Definition CGExprCXX.cpp:974

static void EmitNewInitializer(CodeGenFunction &CGF, const CXXNewExpr *E, QualType ElementType, llvm::Type *ElementTy, Address NewPtr, llvm::Value *NumElements, llvm::Value *AllocSizeWithoutCookie)

Definition CGExprCXX.cpp:1325

static llvm::Value * EmitCXXNewAllocSize(CodeGenFunction &CGF, const CXXNewExpr *e, unsigned minElements, llvm::Value *&numElements, llvm::Value *&sizeWithoutCookie)

Definition CGExprCXX.cpp:712

static QualType getPointeeType(const MemRegion *R)

a trap message and trap category.

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

TranslationUnitDecl * getTranslationUnitDecl() const

const ConstantArrayType * getAsConstantArrayType(QualType T) const

CharUnits getTypeAlignInChars(QualType T) const

Return the ABI-specified alignment of a (complete) type T, in characters.

DeclarationNameTable DeclarationNames

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.

QualType getBaseElementType(const ArrayType *VAT) const

Return the innermost element type of an array type.

CharUnits getTypeSizeInChars(QualType T) const

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

static bool hasSameType(QualType T1, QualType T2)

Determine whether the given types T1 and T2 are equivalent.

QualType getSizeType() const

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

CharUnits toCharUnitsFromBits(int64_t BitSize) const

Convert a size in bits to a size in characters.

uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const

Return number of constant array elements.

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

CharUnits getNonVirtualAlignment() const

getNonVirtualAlignment - Get the non-virtual alignment (in chars) of an object, which is the alignmen...

CharUnits getNonVirtualSize() const

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

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

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

Represents a call to a CUDA kernel function.

Represents a call to a C++ constructor.

bool isElidable() const

Whether this construction is elidable.

Expr * getArg(unsigned Arg)

Return the specified argument.

bool requiresZeroInitialization() const

Whether this construction first requires zero-initialization before the initializer is called.

CXXConstructorDecl * getConstructor() const

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

CXXConstructionKind getConstructionKind() const

Determine whether this constructor is actually constructing a base class (rather than a complete obje...

Represents a C++ constructor within a class.

bool isDefaultConstructor() const

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

Represents a delete expression for memory deallocation and destructor calls, e.g.

FunctionDecl * getOperatorDelete() const

QualType getDestroyedType() const

Retrieve the type being destroyed.

Represents a C++ destructor within a class.

A C++ dynamic_cast expression (C++ [expr.dynamic.cast]).

bool isAlwaysNull() const

isAlwaysNull - Return whether the result of the dynamic_cast is proven to always be null.

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

SourceLocation getExprLoc() const LLVM_READONLY

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

bool isImplicitObjectMemberFunction() const

[C++2b][dcl.fct]/p7 An implicit object member function is a non-static member function without an exp...

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.

Qualifiers getMethodQualifiers() const

CXXMethodDecl * getDevirtualizedMethod(const Expr *Base, bool IsAppleKext)

If it's possible to devirtualize a call to this method, return the called function.

CXXMethodDecl * getCorrespondingMethodInClass(const CXXRecordDecl *RD, bool MayBeBase=false)

Find the method in RD that corresponds to this one.

bool isCopyAssignmentOperator() const

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

Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)".

llvm::iterator_range< arg_iterator > placement_arguments()

QualType getAllocatedType() const

unsigned getNumImplicitArgs() const

std::optional< Expr * > getArraySize()

This might return std::nullopt even if isArray() returns true, since there might not be an array size...

ImplicitAllocationParameters implicitAllocationParameters() const

Provides the full set of information about expected implicit parameters in this call.

bool hasInitializer() const

Whether this new-expression has any initializer at all.

bool shouldNullCheckAllocation() const

True if the allocation result needs to be null-checked.

bool passAlignment() const

Indicates whether the required alignment should be implicitly passed to the allocation function.

FunctionDecl * getOperatorDelete() const

unsigned getNumPlacementArgs() const

TypeSourceInfo * getAllocatedTypeSourceInfo() const

FunctionDecl * getOperatorNew() const

Expr * getInitializer()

The initializer of this new-expression.

A call to an overloaded operator written using operator syntax.

Represents a list-initialization with parenthesis.

MutableArrayRef< Expr * > getInitExprs()

Represents a C++ pseudo-destructor (C++ [expr.pseudo]).

bool isArrow() const

Determine whether this pseudo-destructor expression was written using an '->' (otherwise,...

QualType getDestroyedType() const

Retrieve the type being destroyed.

Represents a C++ struct/union/class.

bool isEffectivelyFinal() const

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

bool isDynamicClass() 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.

An expression "T()" which creates an rvalue of a non-class type T.

A C++ typeid expression (C++ [expr.typeid]), which gets the type_info that corresponds to the supplie...

bool isTypeOperand() const

QualType getTypeOperand(const ASTContext &Context) const

Retrieves the type operand of this typeid() expression after various required adjustments (removing r...

Expr * getExprOperand() const

bool isMostDerived(const ASTContext &Context) const

Best-effort check if the expression operand refers to a most derived object.

bool isPotentiallyEvaluated() const

Determine whether this typeid has a type operand which is potentially evaluated, per C++11 [expr....

bool hasNullCheck() const

Whether this is of a form like "typeid(*ptr)" that can throw a std::bad_typeid if a pointer is a null...

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

Expr * getArg(unsigned Arg)

getArg - Return the specified argument.

SourceLocation getBeginLoc() const

FunctionDecl * getDirectCallee()

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

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

isNegative - Test whether the quantity is less than zero.

bool isZero() const

isZero - Test whether the quantity equals zero.

llvm::Align getAsAlign() const

getAsAlign - Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit b...

QuantityType getQuantity() const

getQuantity - Get the raw integer representation of this quantity.

CharUnits alignmentOfArrayElement(CharUnits elementSize) const

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

bool isOne() const

isOne - Test whether the quantity equals one.

static CharUnits Zero()

Zero - Construct a CharUnits quantity of zero.

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.

Address setKnownNonNull()

void setAlignment(CharUnits Value)

llvm::PointerType * getType() const

Return the type of the pointer value.

bool isSanitizerChecked() const

Address getAddress() const

IsZeroed_t isZeroed() const

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.

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

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

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

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

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

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 std::vector< CharUnits > getVBPtrOffsets(const CXXRecordDecl *RD)

Gets the offsets of all the virtual base pointers in a given class.

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.

virtual bool shouldTypeidBeNullChecked(QualType SrcRecordTy)=0

virtual void emitVirtualObjectDelete(CodeGenFunction &CGF, const CXXDeleteExpr *DE, Address Ptr, QualType ElementType, const CXXDestructorDecl *Dtor)=0

virtual const CXXRecordDecl * getThisArgumentTypeForMethod(GlobalDecl GD)

Get the type of the implicit "this" parameter used by a method.

virtual bool EmitBadCastCall(CodeGenFunction &CGF)=0

virtual llvm::Value * EmitTypeid(CodeGenFunction &CGF, QualType SrcRecordTy, Address ThisPtr, llvm::Type *StdTypeInfoPtrTy)=0

virtual CharUnits GetArrayCookieSize(const CXXNewExpr *expr)

Returns the extra size required in order to store the array cookie for the given new-expression.

virtual void EmitBadTypeidCall(CodeGenFunction &CGF)=0

All available information about a concrete callee.

static CGCallee forVirtual(const CallExpr *CE, GlobalDecl MD, Address Addr, llvm::FunctionType *FTy)

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

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

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

void add(RValue rvalue, QualType type)

void addFrom(const CallArgList &other)

Add all the arguments from another CallArgList to this one.

An abstract representation of regular/ObjC call/message targets.

An object to manage conditionally-evaluated expressions.

void begin(CodeGenFunction &CGF)

void end(CodeGenFunction &CGF)

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

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.

GlobalDecl CurGD

CurGD - The GlobalDecl for the current function being compiled.

void EmitCXXConstructExpr(const CXXConstructExpr *E, AggValueSlot Dest)

Definition CGExprCXX.cpp:602

SanitizerSet SanOpts

Sanitizers enabled for this function.

void EmitNullInitialization(Address DestPtr, QualType Ty)

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

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

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

llvm::Type * ConvertType(QualType T)

RValue EmitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr *E)

Definition CGExprCXX.cpp:128

RValue EmitCXXMemberOrOperatorMemberCallExpr(const CallExpr *CE, const CXXMethodDecl *MD, ReturnValueSlot ReturnValue, bool HasQualifier, NestedNameSpecifier Qualifier, bool IsArrow, const Expr *Base, llvm::CallBase **CallOrInvoke)

Definition CGExprCXX.cpp:217

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

EmitVTablePtrCheckForCall - Virtual method MD is being called via VTable.

void EmitARCDestroyWeak(Address addr)

void @objc_destroyWeak(i8** addr) Essentially objc_storeWeak(addr, nil).

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

void EmitSynthesizedCXXCopyCtor(Address Dest, Address Src, const Expr *Exp)

Definition CGExprCXX.cpp:677

llvm::SmallVector< DeferredDeactivateCleanup > DeferredDeactivationCleanupStack

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

createBasicBlock - Create an LLVM basic block.

void EmitCXXDeleteExpr(const CXXDeleteExpr *E)

Definition CGExprCXX.cpp:2080

const LangOptions & getLangOpts() const

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

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

@ TCK_ConstructorCall

Checking the 'this' pointer for a constructor call.

@ TCK_MemberCall

Checking the 'this' pointer for a call to a non-static member function.

@ TCK_DynamicOperation

Checking the operand of a dynamic_cast or a typeid expression.

llvm::Value * EmitCXXNewExpr(const CXXNewExpr *E)

Definition CGExprCXX.cpp:1562

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

void pushIrregularPartialArrayCleanup(llvm::Value *arrayBegin, Address arrayEndPointer, QualType elementType, CharUnits elementAlignment, Destroyer *destroyer)

pushIrregularPartialArrayCleanup - Push a NormalAndEHCleanup to destroy already-constructed elements ...

Destroyer * getDestroyer(QualType::DestructionKind destructionKind)

void EmitAggregateAssign(LValue Dest, LValue Src, QualType EltTy)

Emit an aggregate assignment.

void EmitARCRelease(llvm::Value *value, ARCPreciseLifetime_t precise)

Release the given object.

void pushCallObjectDeleteCleanup(const FunctionDecl *OperatorDelete, llvm::Value *CompletePtr, QualType ElementType)

Definition CGExprCXX.cpp:1893

RValue EmitCXXMemberOrOperatorCall(const CXXMethodDecl *Method, const CGCallee &Callee, ReturnValueSlot ReturnValue, llvm::Value *This, llvm::Value *ImplicitParam, QualType ImplicitParamTy, const CallExpr *E, CallArgList *RtlArgs, llvm::CallBase **CallOrInvoke)

Definition CGExprCXX.cpp:85

@ ForceRightToLeft

! Language semantics require right-to-left evaluation.

RValue EmitCUDAKernelCallExpr(const CUDAKernelCallExpr *E, ReturnValueSlot ReturnValue, llvm::CallBase **CallOrInvoke)

Definition CGExprCXX.cpp:503

void initFullExprCleanup()

Set up the last cleanup that was pushed as a conditional full-expression cleanup.

bool isInConditionalBranch() const

isInConditionalBranch - Return true if we're currently emitting one branch or the other of a conditio...

void EmitIgnoredExpr(const Expr *E)

EmitIgnoredExpr - Emit an expression in a context which ignores the result.

void EmitARCDestroyStrong(Address addr, ARCPreciseLifetime_t precise)

Destroy a __strong variable.

void DeactivateCleanupBlock(EHScopeStack::stable_iterator Cleanup, llvm::Instruction *DominatingIP)

DeactivateCleanupBlock - Deactivates the given cleanup block.

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

CGDebugInfo * getDebugInfo()

llvm::Value * getTypeSize(QualType Ty)

Returns calculated size of the specified type.

RValue EmitCXXMemberCallExpr(const CXXMemberCallExpr *E, ReturnValueSlot ReturnValue, llvm::CallBase **CallOrInvoke=nullptr)

Definition CGExprCXX.cpp:188

llvm::AllocaInst * CreateTempAlloca(llvm::Type *Ty, const Twine &Name="tmp", llvm::Value *ArraySize=nullptr)

CreateTempAlloca - This creates an alloca and inserts it into the entry block if ArraySize is nullptr...

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

RValue EmitAnyExprToTemp(const Expr *E)

EmitAnyExprToTemp - Similarly to EmitAnyExpr(), however, the result will always be accessible even if...

ASTContext & getContext() const

void EmitAllocToken(llvm::CallBase *CB, QualType AllocType)

Emit and set additional metadata used by the AllocToken instrumentation.

bool needsEHCleanup(QualType::DestructionKind kind)

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

RValue EmitBuiltinNewDeleteCall(const FunctionProtoType *Type, const CallExpr *TheCallExpr, bool IsDelete)

Definition CGExprCXX.cpp:1366

llvm::Type * ConvertTypeForMem(QualType T)

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

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

Definition CGExprCXX.cpp:1796

CodeGenTypes & getTypes() const

static TypeEvaluationKind getEvaluationKind(QualType T)

getEvaluationKind - Return the TypeEvaluationKind of QualType T.

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

const TargetInfo & Target

Address EmitPointerWithAlignment(const Expr *Addr, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)

EmitPointerWithAlignment - Given an expression with a pointer type, emit the value and compute our be...

void EmitBranch(llvm::BasicBlock *Block)

EmitBranch - Emit a branch to the specified basic block from the current insert block,...

CGCallee BuildAppleKextVirtualCall(const CXXMethodDecl *MD, NestedNameSpecifier Qual, llvm::Type *Ty)

BuildAppleKextVirtualCall - This routine is to support gcc's kext ABI making indirect call to virtual...

RValue EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E, ReturnValueSlot ReturnValue, llvm::CallBase **CallOrInvoke)

Definition CGExprCXX.cpp:444

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 * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)

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

static bool IsWrappedCXXThis(const Expr *E)

Check if E is a C++ "this" pointer wrapped in value-preserving casts.

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.

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

const CallExpr * MustTailCall

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.

void EmitNewArrayInitializer(const CXXNewExpr *E, QualType elementType, llvm::Type *ElementTy, Address NewPtr, llvm::Value *NumElements, llvm::Value *AllocSizeWithoutCookie)

Definition CGExprCXX.cpp:1002

RValue EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E, const CXXMethodDecl *MD, ReturnValueSlot ReturnValue, llvm::CallBase **CallOrInvoke)

Definition CGExprCXX.cpp:493

void PopCleanupBlock(bool FallThroughIsBranchThrough=false, bool ForDeactivation=false)

PopCleanupBlock - Will pop the cleanup entry on the stack and process all branch fixups.

llvm::Value * EmitDynamicCast(Address V, const CXXDynamicCastExpr *DCE)

Definition CGExprCXX.cpp:2245

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

EmitBlock - Emit the given block.

llvm::Value * EmitCXXTypeidExpr(const CXXTypeidExpr *E)

Definition CGExprCXX.cpp:2195

llvm::Module & getModule() const

llvm::Constant * EmitNullConstantForBase(const CXXRecordDecl *Record)

Return a null constant appropriate for zero-initializing a base class with the given type.

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

Return the address of the given function.

const LangOptions & getLangOpts() const

CodeGenTypes & getTypes()

CGCXXABI & getCXXABI() const

const CodeGenOptions & getCodeGenOpts() const

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

llvm::ConstantInt * getSize(CharUnits numChars)

Emit the given number of characters as a value of type size_t.

llvm::Type * ConvertType(QualType T)

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

CanQualType DeriveThisType(const CXXRecordDecl *RD, const CXXMethodDecl *MD)

Derives the 'this' type for codegen purposes, i.e.

const CGFunctionInfo & arrangeFreeFunctionCall(const CallArgList &Args, const FunctionType *Ty, bool ChainCall)

Figure out the rules for calling a function with the given formal type using the given arguments.

llvm::Constant * tryEmitAbstract(const Expr *E, QualType T)

Try to emit the result of the given expression as an abstract constant.

A saved depth on the scope stack.

T * pushCleanupWithExtra(CleanupKind Kind, size_t N, As... A)

Push a cleanup with non-constant storage requirements on the stack.

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)

static RValue getAggregate(Address addr, bool isVolatile=false)

Convert an Address to an RValue.

llvm::Value * getScalarVal() const

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

A class for recording the number of arguments that a function signature requires.

static RequiredArgs forPrototypePlus(const FunctionProtoType *prototype, unsigned additional)

Compute the arguments required by the given formal prototype, given that there may be some additional...

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

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

DeclContext * getParent()

getParent - Returns the containing DeclContext.

lookup_result lookup(DeclarationName Name) const

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

The name of a declaration.

QualType getIntegerType() const

Return the integer type this enum decl corresponds to.

QualType getTypeAsWritten() const

getTypeAsWritten - Returns the type that this expression is casting to, as written in the source code...

Represents an expression – generally a full-expression – that introduces cleanups to be run at the en...

This represents one expression.

Expr * IgnoreParens() LLVM_READONLY

Skip past any parentheses which might surround this expression until reaching a fixed point.

bool isTemporaryObject(ASTContext &Ctx, const CXXRecordDecl *TempTy) const

Determine whether the result of this expression is a temporary object of the given class type.

SourceLocation getExprLoc() const LLVM_READONLY

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

Represents a function declaration or definition.

bool isDestroyingOperatorDelete() const

Determine whether this is a destroying operator delete.

QualType getReturnType() const

bool isTrivial() const

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

bool isReplaceableGlobalAllocationFunction(UnsignedOrNone *AlignmentParam=nullptr, bool *IsNothrow=nullptr) const

Determines whether this function is one of the replaceable global allocation functions: void *operato...

UsualDeleteParams getUsualDeleteParams() const

bool isReservedGlobalPlacementOperator() const

Determines whether this operator new or delete is one of the reserved global placement operators: voi...

bool isDefaulted() const

Whether this function is defaulted.

OverloadedOperatorKind getOverloadedOperator() const

getOverloadedOperator - Which C++ overloaded operator this function represents, if any.

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

unsigned getNumParams() const

QualType getParamType(unsigned i) const

GlobalDecl - represents a global declaration.

const Decl * getDecl() const

Represents an implicitly-generated value initialization of an object of a given type.

Describes an C or C++ initializer list.

bool isStringLiteralInit() const

Is this an initializer for an array of characters, initialized by a string literal or an @encode?

unsigned getNumInits() const

Expr * getArrayFiller()

If this initializer list initializes an array with more elements than there are initializers in the l...

const Expr * getInit(unsigned Init) const

ArrayRef< Expr * > inits()

MemberExpr - [C99 6.5.2.3] Structure and Union Members.

NestedNameSpecifier getQualifier() const

If the member name was qualified, retrieves the nested-name-specifier that precedes the member name.

ValueDecl * getMemberDecl() const

Retrieve the member declaration to which this expression refers.

bool hasQualifier() const

Determines whether this member expression actually had a C++ nested-name-specifier prior to the name ...

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

QualType getPointeeType() const

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

ObjCEncodeExpr, used for @encode in Objective-C.

PointerType - C99 6.7.5.1 - Pointer Declarators.

A (possibly-)qualified type.

bool isVolatileQualified() const

Determine whether this type is volatile-qualified.

bool isNull() const

Return true if this QualType doesn't point to a type yet.

LangAS getAddressSpace() const

Return the address space of this type.

Qualifiers getQualifiers() const

Retrieve the set of qualifiers applied to this type.

Qualifiers::ObjCLifetime getObjCLifetime() const

Returns lifetime attribute of this type.

QualType getCanonicalType() 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).

bool hasStrongOrWeakObjCLifetime() const

The collection of all-type qualifiers we support.

@ OCL_Strong

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

@ OCL_ExplicitNone

This object can be modified without requiring retains or releases.

@ OCL_None

There is no lifetime qualification on this type.

@ OCL_Weak

Reading or writing from this object requires a barrier call.

@ OCL_Autoreleasing

Assigning into this object requires a lifetime extension.

LangAS getAddressSpace() const

Represents a struct/union/class.

field_range fields() const

bool mayInsertExtraPadding(bool EmitRemark=false) const

Whether we are allowed to insert extra padding between fields.

RecordDecl * getDefinitionOrSelf() const

Base for LValueReferenceType and RValueReferenceType.

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

Encodes a location in the source.

StringLiteral - This represents a string literal expression, e.g.

SourceLocation getBeginLoc() const

Get the begin source location.

TypeLoc getTypeLoc() const

Return the TypeLoc wrapper for the type source info.

CXXRecordDecl * getAsCXXRecordDecl() const

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

bool isVoidPointerType() const

bool isPointerType() const

const T * castAs() const

Member-template castAs.

QualType getPointeeType() const

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

EnumDecl * castAsEnumDecl() const

const ArrayType * getAsArrayTypeUnsafe() const

A variant of getAs<> for array types which silently discards qualifiers from the outermost type.

const T * getAsCanonical() const

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

const T * getAs() const

Member-template getAs'.

bool isRecordType() const

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

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

AlignedAllocationMode alignedAllocationModeFromBool(bool IsAligned)

bool isAlignedAllocation(AlignedAllocationMode Mode)

const FunctionProtoType * T

@ Dtor_Complete

Complete object dtor.

@ Type

The name was classified as a type.

bool isTypeAwareAllocation(TypeAwareAllocationMode Mode)

LangAS

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

bool declaresSameEntity(const Decl *D1, const Decl *D2)

Determine whether two declarations declare the same entity.

U cast(CodeGen::Address addr)

llvm::IntegerType * Int8Ty

i8, i16, i32, and i64

CharUnits getPointerSize() const

llvm::IntegerType * SizeTy

CharUnits getSizeAlign() const

llvm::PointerType * Int8PtrTy

CharUnits getPointerAlign() const

A metaprogramming class for ensuring that a value will dominate an arbitrary position in a function.

static saved_type save(CodeGenFunction &CGF, type value)

void set(SanitizerMask K, bool Value)

Enable or disable a certain (single) sanitizer.

TypeAwareAllocationMode TypeAwareDelete

AlignedAllocationMode Alignment