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;

25using namespace CodeGen;

26

27namespace {

28struct MemberCallInfo {

30

31 unsigned PrefixSize;

32};

33}

34

35static MemberCallInfo

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

40 auto *MD = cast(GD.getDecl());

41

42 assert(CE == nullptr || isa(CE) ||

43 isa(CE));

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

85RValue CodeGenFunction::EmitCXXMemberOrOperatorCall(

87 ReturnValueSlot ReturnValue, llvm::Value *This, llvm::Value *ImplicitParam,

89 llvm::CallBase **CallOrInvoke) {

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

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

117 NewType);

118 }

119

122 ImplicitParamTy, CE, Args, nullptr);

127}

128

131 QualType DestroyedType = E->getDestroyedType();

133

134

135

136 Expr *BaseExpr = E->getBase();

139

140

141 if (E->isArrow()) {

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

145 } else {

150 }

151

156 break;

157

162 break;

163

166 break;

167 }

168 } else {

169

170

171

172

173

175 }

176

178}

179

185 return cast(Ty->getDecl());

186}

187

188

189

192 llvm::CallBase **CallOrInvoke) {

194

195 if (isa(callee))

197

198 const MemberExpr *ME = cast(callee);

200

202

206 ReturnValue, nullptr, CallOrInvoke);

207 }

208

211 bool IsArrow = ME->isArrow();

213

215 HasQualifier, Qualifier, IsArrow,

216 Base, CallOrInvoke);

217}

218

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

223 assert(isa(CE) || isa(CE));

224

225

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

227

228 const CXXMethodDecl *DevirtualizedMethod = nullptr;

229 if (CanUseVirtualCall &&

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

233 assert(DevirtualizedMethod);

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

238

239

240

241

242

243 DevirtualizedMethod = nullptr;

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

245

246

247 Base = Inner;

249

250

251

252

253 DevirtualizedMethod = nullptr;

254 }

255 }

256

257 bool TrivialForCodegen =

259 bool TrivialAssignment =

260 TrivialForCodegen &&

263

264

265

268 LValue TrivialAssignmentRHS;

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

270 if (OCE->isAssignmentOp()) {

271 if (TrivialAssignment) {

273 } else {

274 RtlArgs = &RtlArgStorage;

278 }

279 }

280 }

281

283 if (IsArrow) {

288 BaseInfo, TBAAInfo);

289 } else {

291 }

292

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

294

295

296 assert(!RtlArgs);

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

301 nullptr,

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

303

305 false, This.getAddress(), Args,

307 false, CallOrInvoke);

309 }

310

311 if (TrivialForCodegen) {

312 if (isa(MD))

314

315 if (TrivialAssignment) {

316

317

318

319

320

321 LValue RHS = isa(CE)

322 ? TrivialAssignmentRHS

326 }

327

329 "unknown trivial member function");

330 }

331

332

334 DevirtualizedMethod ? DevirtualizedMethod : MD;

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

339 else

341

343

344

345

346

349 if (CE)

351

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

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

356 if (IsImplicitObjectCXXThis)

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

358 if (IsImplicitObjectCXXThis || isa(IOA))

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

360 }

361

364 This.emitRawPointer(*this),

365 C.getRecordType(CalleeDecl->getParent()),

367

368

369

370

371

372

373

374 bool UseVirtualCall = CanUseVirtualCall && !DevirtualizedMethod;

375

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

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

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

380 if (UseVirtualCall) {

383 cast(CE), CallOrInvoke);

384 } else {

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

389 else if (!DevirtualizedMethod)

392 else {

394 }

395

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

399 nullptr,

400 QualType(), CE, CallOrInvoke);

401 }

403 }

404

405

406

407

409 if (UseVirtualCall) {

411 } else {

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

414 llvm::Value *VTable;

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

419 }

420

423 else if (!DevirtualizedMethod)

426 else {

430 }

431 }

432

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

437 This.setAddress(NewThisAddr);

438 }

439

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

443}

444

448 llvm::CallBase **CallOrInvoke) {

450 cast(E->getCallee()->IgnoreParens());

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

453

456 const auto *RD =

457 cast(MPT->getClass()->castAs<RecordType>()->getDecl());

458

459

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

463 else

465

467 QualType(MPT->getClass(), 0));

468

469

471

472

473 llvm::Value *ThisPtrForCall = nullptr;

476 ThisPtrForCall, MemFnPtr, MPT);

477

479

482

483

485

487

488

491 0),

494}

495

498 ReturnValueSlot ReturnValue, llvm::CallBase **CallOrInvoke) {

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

502 E, MD, ReturnValue, false, nullptr,

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

504}

505

508 llvm::CallBase **CallOrInvoke) {

510 CallOrInvoke);

511}

512

516 if (Base->isEmpty())

517 return;

518

520

523

524

525

526

529

530

532 std::vector VBPtrOffsets =

534 for (CharUnits VBPtrOffset : VBPtrOffsets) {

535

536 if (VBPtrOffset >= NVSize)

537 break;

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

539 CharUnits LastStoreOffset = LastStore.first;

540 CharUnits LastStoreSize = LastStore.second;

541

542 CharUnits SplitBeforeOffset = LastStoreOffset;

543 CharUnits SplitBeforeSize = VBPtrOffset - SplitBeforeOffset;

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

545 if (!SplitBeforeSize.isZero())

546 Stores.emplace_back(SplitBeforeOffset, SplitBeforeSize);

547

548 CharUnits SplitAfterOffset = VBPtrOffset + VBPtrWidth;

549 CharUnits SplitAfterSize = LastStoreSize - SplitAfterOffset;

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

551 if (!SplitAfterSize.isZero())

552 Stores.emplace_back(SplitAfterOffset, SplitAfterSize);

553 }

554

555

556

557

558

559

560

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

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

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

565 true, llvm::GlobalVariable::PrivateLinkage,

566 NullConstantForBase, Twine());

567

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

571

573

574

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

576 CharUnits StoreOffset = Store.first;

577 CharUnits StoreSize = Store.second;

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

582 StoreSizeVal);

583 }

584

585

586

587

588 } else {

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

590 CharUnits StoreOffset = Store.first;

591 CharUnits StoreSize = Store.second;

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

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

596 }

597 }

598}

599

600void

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

605

606

607

608

609

610 if (E->requiresZeroInitialization() && !Dest.isZeroed()) {

611 switch (E->getConstructionKind()) {

615 break;

620 break;

621 }

622 }

623

624

626 return;

627

628

629 if (getLangOpts().ElideConstructors && E->isElidable()) {

630

631

632

633

634

635 const Expr *SrcObj = E->getArg(0);

637 assert(

640 return;

641 }

642

647 } else {

649 bool ForVirtualBase = false;

651

652 switch (E->getConstructionKind()) {

654

657 break;

658

661 break;

662

664 ForVirtualBase = true;

665 [[fallthrough]];

666

669 }

670

671

673 }

674}

675

677 const Expr *Exp) {

679 Exp = E->getSubExpr();

680 assert(isa(Exp) &&

681 "EmitSynthesizedCXXCopyCtor - unknown copy ctor expr");

684 RunCleanupsScope Scope(*this);

685

686

687

688

689

690 if (E->requiresZeroInitialization())

692

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

696}

697

700 if (E->isArray())

702

703

704

705 if (E->getOperatorNew()->isReservedGlobalPlacementOperator())

707

709}

710

713 unsigned minElements,

714 llvm::Value *&numElements,

715 llvm::Value *&sizeWithoutCookie) {

717

720 sizeWithoutCookie

722 return sizeWithoutCookie;

723 }

724

725

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

727

728

729 llvm::APInt cookieSize(sizeWidth,

731

732

733

734

735 numElements =

737 if (!numElements)

739 assert(isallvm::IntegerType(numElements->getType()));

740

741

742

743

744

745

746

747 bool isSigned

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

749 llvm::IntegerType *numElementsType

750 = castllvm::IntegerType(numElements->getType());

751 unsigned numElementsWidth = numElementsType->getBitWidth();

752

753

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

757 type = CAT->getElementType();

758 arraySizeMultiplier *= CAT->getSize();

759 }

760

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

763 typeSizeMultiplier *= arraySizeMultiplier;

764

765

766 llvm::Value *size;

767

768

769

770 if (llvm::ConstantInt *numElementsC =

771 dyn_castllvm::ConstantInt(numElements)) {

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

773

774 bool hasAnyOverflow = false;

775

776

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

778 hasAnyOverflow = true;

779

780

781

782

783 else if (numElementsWidth > sizeWidth &&

784 numElementsWidth - sizeWidth > count.countl_zero())

785 hasAnyOverflow = true;

786

787

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

789

790

791

792 if (adjustedCount.ult(minElements))

793 hasAnyOverflow = true;

794

795

796

797

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

799 adjustedCount * arraySizeMultiplier);

800

801

802 bool overflow;

803 llvm::APInt allocationSize

804 = adjustedCount.umul_ov(typeSizeMultiplier, overflow);

805 hasAnyOverflow |= overflow;

806

807

808 if (cookieSize != 0) {

809

810

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

812

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

814 hasAnyOverflow |= overflow;

815 }

816

817

818 if (hasAnyOverflow) {

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

820 } else {

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

822 }

823

824

825 } else {

826

827

828

829

830

831

832

833

834

835

836

837

838

839 llvm::Value *hasOverflow = nullptr;

840

841

842

843

844 if (numElementsWidth > sizeWidth) {

845 llvm::APInt threshold =

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

847

848 llvm::Value *thresholdV

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

850

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

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

853

854

855 } else if (isSigned) {

856 if (numElementsWidth < sizeWidth)

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

858

859

860

861

862

863

864 if (typeSizeMultiplier == 1)

865 hasOverflow = CGF.Builder.CreateICmpSLT(numElements,

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

867

868

869 } else if (numElementsWidth < sizeWidth) {

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

871 }

872

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

874

875 if (minElements) {

876

877 if (!hasOverflow) {

878 hasOverflow = CGF.Builder.CreateICmpULT(numElements,

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

880 } else if (numElementsWidth > sizeWidth) {

881

882

883

884 hasOverflow = CGF.Builder.CreateOr(hasOverflow,

885 CGF.Builder.CreateICmpULT(numElements,

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

887 }

888 }

889

890 size = numElements;

891

892

893

894

895

896

897

898

899 if (typeSizeMultiplier != 1) {

900 llvm::Function *umul_with_overflow

902

903 llvm::Value *tsmV =

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

905 llvm::Value *result =

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

907

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

909 if (hasOverflow)

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

911 else

912 hasOverflow = overflowed;

913

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

915

916

917 if (arraySizeMultiplier != 1) {

918

919

920 if (typeSize.isOne()) {

921 assert(arraySizeMultiplier == typeSizeMultiplier);

922 numElements = size;

923

924

925 } else {

926 llvm::Value *asmV =

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

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

929 }

930 }

931 } else {

932

933 assert(arraySizeMultiplier == 1);

934 }

935

936

937 if (cookieSize != 0) {

938 sizeWithoutCookie = size;

939

940 llvm::Function *uadd_with_overflow

942

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

944 llvm::Value *result =

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

946

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

948 if (hasOverflow)

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

950 else

951 hasOverflow = overflowed;

952

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

954 }

955

956

957

958

959 if (hasOverflow)

960 size = CGF.Builder.CreateSelect(hasOverflow,

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

962 size);

963 }

964

965 if (cookieSize == 0)

966 sizeWithoutCookie = size;

967 else

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

969

970 return size;

971}

972

976

981 return;

984 true);

985 return;

995 return;

996 }

997 }

998 llvm_unreachable("bad evaluation kind");

999}

1000

1003 Address BeginPtr, llvm::Value *NumElements,

1004 llvm::Value *AllocSizeWithoutCookie) {

1005

1006

1007 if (E->hasInitializer())

1008 return;

1009

1010 Address CurPtr = BeginPtr;

1011

1012 unsigned InitListElements = 0;

1013

1014 const Expr *Init = E->getInitializer();

1017 CleanupDeactivationScope deactivation(*this);

1018 bool pushedCleanup = false;

1019

1023

1024

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

1026

1027

1029 return false;

1030

1031

1032

1033

1034

1035 auto *RemainingSize = AllocSizeWithoutCookie;

1036 if (InitListElements) {

1037

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

1039 RemainingSize->getType(),

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

1041 InitListElements);

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

1043 }

1044

1045

1047 return true;

1048 };

1049

1054 const Expr *IgnoreParen = nullptr;

1055 if (!ILE) {

1056 IgnoreParen = Init->IgnoreParenImpCasts();

1057 CPLIE = dyn_cast(IgnoreParen);

1058 SL = dyn_cast(IgnoreParen);

1059 OCEE = dyn_cast(IgnoreParen);

1060 }

1061

1062

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

1064

1065

1067 if (!ILE)

1068 Init = IgnoreParen;

1069

1070

1071

1081

1082

1083 InitListElements =

1084 cast(Init->getType()->getAsArrayTypeUnsafe())

1085 ->getZExtSize();

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

1088

1089

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

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

1092 bool OK = TryMemsetInitialization();

1093 (void)OK;

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

1095 }

1096 return;

1097 }

1098

1101 InitListElements = InitExprs.size();

1102

1103

1104

1105 QualType AllocType = E->getAllocatedType();

1106 if (const ConstantArrayType *CAT = dyn_cast_or_null(

1111 }

1112

1113

1114 if (DtorKind) {

1115 AllocaTrackerRAII AllocaTracker(*this);

1116

1117

1118

1119

1120 llvm::Instruction *DominatingIP =

1123 "array.init.end");

1125 EndOfInit, ElementType, ElementAlign,

1128 .AddAuxAllocas(AllocaTracker.Take());

1131 pushedCleanup = true;

1132 }

1133

1135 unsigned i = 0;

1136 for (const Expr *IE : InitExprs) {

1137

1138

1139

1140 if (EndOfInit.isValid()) {

1142 }

1143

1144

1145

1151 "array.exp.next"),

1154 }

1155

1156

1158

1159

1160

1161

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

1163 auto *SubILE = dyn_cast(Init);

1164 if (!SubILE)

1165 break;

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

1167 Init = SubILE->getArrayFiller();

1168 }

1169

1170

1172 }

1173

1174

1175

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

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

1178 return;

1179 }

1180

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

1182

1183

1184

1188

1189

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

1191 return;

1192

1193 if (TryMemsetInitialization())

1194 return;

1195 }

1196

1197

1198

1199

1200

1201 if (EndOfInit.isValid())

1203

1204

1205 if (InitListElements)

1206 NumElements = Builder.CreateSub(

1207 NumElements,

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

1210 true,

1211 CCE->requiresZeroInitialization());

1212 return;

1213 }

1214

1215

1217 if (isa(Init)) {

1218 if (TryMemsetInitialization())

1219 return;

1220

1221

1222

1223

1224 Init = &IVIE;

1225 }

1226

1227

1228

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

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

1231

1232

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

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

1235 return;

1236

1237

1238

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

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

1242 unsigned NumElements = 0;

1243 if (auto *CXXRD = dyn_cast(RType->getDecl()))

1244 NumElements = CXXRD->getNumBases();

1245 for (auto *Field : RType->getDecl()->fields())

1246 if (Field->isUnnamedBitField())

1247 ++NumElements;

1248

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

1251 if (!isa(ILE->getInit(i)))

1252 --NumElements;

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

1254 return;

1255 }

1256 }

1257 }

1258

1259

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

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

1263

1264

1267 "array.end");

1268

1269

1270

1271 if (!ConstNum) {

1273 EndPtr, "array.isempty");

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

1275 }

1276

1277

1279

1280

1281 llvm::PHINode *CurPtrPhi =

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

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

1284

1286

1287

1288 if (EndOfInit.isValid())

1290

1291

1293 llvm::Instruction *DominatingIP =

1300 }

1301

1302

1305

1306

1307 deactivation.ForceDeactivate();

1308

1309

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

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

1312

1313

1314

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

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

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

1318

1320}

1321

1323 QualType ElementType, llvm::Type *ElementTy,

1324 Address NewPtr, llvm::Value *NumElements,

1325 llvm::Value *AllocSizeWithoutCookie) {

1327 if (E->isArray())

1329 AllocSizeWithoutCookie);

1330 else if (const Expr *Init = E->getInitializer())

1333}

1334

1335

1336

1341 llvm::CallBase *CallOrInvoke;

1346 Args, CalleeType, false),

1348

1349

1350

1351

1352

1353

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

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

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

1358 }

1359

1360 return RV;

1361}

1362

1365 bool IsDelete) {

1368

1372

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

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

1378}

1379

1380namespace {

1381

1382struct UsualDeleteParams {

1383 bool DestroyingDelete = false;

1384 bool Size = false;

1385 bool Alignment = false;

1386};

1387}

1388

1390 UsualDeleteParams Params;

1391

1394

1395

1396 ++AI;

1397

1398

1400 Params.DestroyingDelete = true;

1401 assert(AI != AE);

1402 ++AI;

1403 }

1404

1405

1407 Params.Size = true;

1408 ++AI;

1409 }

1410

1412 Params.Alignment = true;

1413 ++AI;

1414 }

1415

1416 assert(AI == AE && "unexpected usual deallocation function parameter");

1417 return Params;

1418}

1419

1420namespace {

1421

1422

1423

1424 template

1426

1427 typedef typename Traits::ValueTy ValueTy;

1428

1429 typedef typename Traits::RValueTy RValueTy;

1430 struct PlacementArg {

1431 RValueTy ArgValue;

1433 };

1434

1435 unsigned NumPlacementArgs : 31;

1436 LLVM_PREFERRED_TYPE(bool)

1437 unsigned PassAlignmentToPlacementDelete : 1;

1439 ValueTy Ptr;

1440 ValueTy AllocSize;

1442

1443 PlacementArg *getPlacementArgs() {

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

1445 }

1446

1447 public:

1448 static size_t getExtraSize(size_t NumPlacementArgs) {

1449 return NumPlacementArgs * sizeof(PlacementArg);

1450 }

1451

1452 CallDeleteDuringNew(size_t NumPlacementArgs,

1453 const FunctionDecl *OperatorDelete, ValueTy Ptr,

1454 ValueTy AllocSize, bool PassAlignmentToPlacementDelete,

1456 : NumPlacementArgs(NumPlacementArgs),

1457 PassAlignmentToPlacementDelete(PassAlignmentToPlacementDelete),

1458 OperatorDelete(OperatorDelete), Ptr(Ptr), AllocSize(AllocSize),

1459 AllocAlign(AllocAlign) {}

1460

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

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

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

1464 }

1465

1467 const auto *FPT = OperatorDelete->getType()->castAs<FunctionProtoType>();

1469

1470

1471

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

1473

1474

1475 UsualDeleteParams Params;

1476 if (NumPlacementArgs) {

1477

1478

1479 Params.Alignment = PassAlignmentToPlacementDelete;

1480 } else {

1481

1482

1484 }

1485

1486 assert(!Params.DestroyingDelete &&

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

1488

1489

1490 if (Params.Size)

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

1493

1494

1495

1496

1497

1498 if (Params.Alignment)

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

1502

1503

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

1505 auto Arg = getPlacementArgs()[I];

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

1507 }

1508

1509

1511 }

1512 };

1513}

1514

1515

1516

1520 llvm::Value *AllocSize,

1523 unsigned NumNonPlacementArgs = E->passAlignment() ? 2 : 1;

1524

1525

1526

1528 struct DirectCleanupTraits {

1529 typedef llvm::Value *ValueTy;

1530 typedef RValue RValueTy;

1533 };

1534

1535 typedef CallDeleteDuringNew DirectCleanup;

1536

1538 EHCleanup, E->getNumPlacementArgs(), E->getOperatorDelete(),

1539 NewPtr.emitRawPointer(CGF), AllocSize, E->passAlignment(), AllocAlign);

1540 for (unsigned I = 0, N = E->getNumPlacementArgs(); I != N; ++I) {

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

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

1543 }

1544

1545 return;

1546 }

1547

1548

1553

1554 struct ConditionalCleanupTraits {

1558 return V.restore(CGF);

1559 }

1560 };

1561 typedef CallDeleteDuringNew ConditionalCleanup;

1562

1563 ConditionalCleanup *Cleanup = CGF.EHStack

1565 E->getNumPlacementArgs(),

1566 E->getOperatorDelete(),

1567 SavedNewPtr,

1568 SavedAllocSize,

1569 E->passAlignment(),

1570 AllocAlign);

1571 for (unsigned I = 0, N = E->getNumPlacementArgs(); I != N; ++I) {

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

1573 Cleanup->setPlacementArg(

1575 }

1576

1578}

1579

1581

1583

1584

1586

1587

1588

1589 unsigned minElements = 0;

1590 if (E->isArray() && E->hasInitializer()) {

1591 const Expr *Init = E->getInitializer();

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

1596 isa(IgnoreParen) || isa(IgnoreParen)) {

1597 minElements =

1598 cast(Init->getType()->getAsArrayTypeUnsafe())

1599 ->getZExtSize();

1600 } else if (ILE || CPLIE) {

1602 }

1603 }

1604

1605 llvm::Value *numElements = nullptr;

1606 llvm::Value *allocSizeWithoutCookie = nullptr;

1607 llvm::Value *allocSize =

1609 allocSizeWithoutCookie);

1611

1612

1613

1617 assert(E->getNumPlacementArgs() == 1);

1618 const Expr *arg = *E->placement_arguments().begin();

1619

1622

1623

1624

1625

1628

1629

1630

1631 if (E->getOperatorDelete() &&

1632 E->getOperatorDelete()->isReservedGlobalPlacementOperator()) {

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

1635 }

1636

1637 } else {

1640 unsigned ParamsToSkip = 0;

1641

1642

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

1645 ++ParamsToSkip;

1646

1647 if (allocSize != allocSizeWithoutCookie) {

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

1650 }

1651

1652

1653 if (E->passAlignment()) {

1654 QualType AlignValT = sizeType;

1657 assert(getContext().hasSameUnqualifiedType(

1659 sizeType) &&

1660 "wrong type for alignment parameter");

1661 ++ParamsToSkip;

1662 } else {

1663

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

1665 }

1666 allocatorArgs.add(

1668 AlignValT);

1669 }

1670

1671

1672 EmitCallArgs(allocatorArgs, allocatorType, E->placement_arguments(),

1673 AbstractCallee(), ParamsToSkip);

1674

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

1677

1678

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

1683

1684

1685

1686

1687

1688 CharUnits allocationAlign = allocAlign;

1689 if (E->passAlignment() &&

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

1693 allocationAlign = std::max(

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

1695 }

1696

1698 }

1699

1700

1701

1702

1703

1704 bool nullCheck = E->shouldNullCheckAllocation() &&

1707

1708 llvm::BasicBlock *nullCheckBB = nullptr;

1709 llvm::BasicBlock *contBB = nullptr;

1710

1711

1712

1713 ConditionalEvaluation conditional(*this);

1714

1715 if (nullCheck) {

1716 conditional.begin(*this);

1717

1718 nullCheckBB = Builder.GetInsertBlock();

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

1721

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

1725 }

1726

1727

1728

1730 llvm::Instruction *cleanupDominator = nullptr;

1731 if (E->getOperatorDelete() &&

1732 E->getOperatorDelete()->isReservedGlobalPlacementOperator()) {

1734 allocatorArgs);

1736 cleanupDominator = Builder.CreateUnreachable();

1737 }

1738

1739 assert((allocSize == allocSizeWithoutCookie) ==

1741 if (allocSize != allocSizeWithoutCookie) {

1742 assert(E->isArray());

1744 numElements,

1745 E, allocType);

1746 }

1747

1750

1751

1752

1753

1754

1758

1759

1760

1761

1762

1763

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

1767 E->getAllocatedTypeSourceInfo()->getTypeLoc().getBeginLoc(),

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

1769 numElements);

1770

1772 allocSizeWithoutCookie);

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

1774

1775

1776

1777 if (operatorDeleteCleanup.isValid()) {

1779 cleanupDominator->eraseFromParent();

1780 }

1781

1782 if (nullCheck) {

1783 conditional.end(*this);

1784

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

1787

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

1789 PHI->addIncoming(resultPtr, notNullBB);

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

1791 nullCheckBB);

1792

1793 resultPtr = PHI;

1794 }

1795

1796 return resultPtr;

1797}

1798

1800 llvm::Value *DeletePtr, QualType DeleteTy,

1801 llvm::Value *NumElements,

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

1805

1808

1810 auto ParamTypeIt = DeleteFTy->param_type_begin();

1811

1812

1813 QualType ArgTy = *ParamTypeIt++;

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

1815

1816

1817 llvm::AllocaInst *DestroyingDeleteTag = nullptr;

1818 if (Params.DestroyingDelete) {

1819 QualType DDTag = *ParamTypeIt++;

1822 DestroyingDeleteTag = CreateTempAlloca(Ty, "destroying.delete.tag");

1823 DestroyingDeleteTag->setAlignment(Align.getAsAlign());

1824 DeleteArgs.add(

1826 }

1827

1828

1829 if (Params.Size) {

1830 QualType SizeType = *ParamTypeIt++;

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

1834

1835

1836 if (NumElements)

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

1838

1839

1840 if (!CookieSize.isZero())

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

1843

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

1845 }

1846

1847

1848 if (Params.Alignment) {

1849 QualType AlignValType = *ParamTypeIt++;

1852 DeleteTy, true ));

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

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

1856 }

1857

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

1859 "unknown parameter to usual delete function");

1860

1861

1863

1864

1865

1866 if (DestroyingDeleteTag && DestroyingDeleteTag->use_empty())

1867 DestroyingDeleteTag->eraseFromParent();

1868}

1869

1870namespace {

1871

1873 llvm::Value *Ptr;

1876

1877 CallObjectDelete(llvm::Value *Ptr,

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

1881

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

1884 }

1885 };

1886}

1887

1888void

1890 llvm::Value *CompletePtr,

1893 OperatorDelete, ElementType);

1894}

1895

1896

1897

1898

1899

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

1906 Dtor);

1907 else

1909 ElementType);

1910}

1911

1912

1913

1914

1919 llvm::BasicBlock *UnconditionalDeleteBlock) {

1920

1921

1922

1923

1924

1926 ElementType);

1927

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

1930

1931

1932

1935 CXXRecordDecl *RD = cast(RT->getDecl());

1938

1940 bool UseVirtualCall = true;

1942 if (auto *DevirtualizedDtor =

1943 dyn_cast_or_null(

1946 UseVirtualCall = false;

1950

1951

1952 Dtor = DevirtualizedDtor;

1953 } else {

1954

1955

1956

1957

1958

1959 UseVirtualCall = true;

1960 }

1961 }

1962 if (UseVirtualCall) {

1964 Dtor);

1965 return false;

1966 }

1967 }

1968 }

1969 }

1970

1971

1972

1973

1974 CGF.EHStack.pushCleanup(

1976

1977 if (Dtor)

1979 false,

1980 false,

1981 Ptr, ElementType);

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

1983 switch (Lifetime) {

1987 break;

1988

1991 break;

1992

1995 break;

1996 }

1997 }

1998

1999

2001 CGF.EmitBlock(UnconditionalDeleteBlock);

2003 return true;

2004 }

2005

2007 return false;

2008}

2009

2010namespace {

2011

2013 llvm::Value *Ptr;

2015 llvm::Value *NumElements;

2018

2019 CallArrayDelete(llvm::Value *Ptr,

2021 llvm::Value *NumElements,

2024 : Ptr(Ptr), OperatorDelete(OperatorDelete), NumElements(NumElements),

2025 ElementType(ElementType), CookieSize(CookieSize) {}

2026

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

2029 CookieSize);

2030 }

2031 };

2032}

2033

2034

2039 llvm::Value *numElements = nullptr;

2040 llvm::Value *allocatedPtr = nullptr;

2043 numElements, allocatedPtr, cookieSize);

2044

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

2046

2047

2048 const FunctionDecl *operatorDelete = E->getOperatorDelete();

2050 allocatedPtr, operatorDelete,

2051 numElements, elementType,

2052 cookieSize);

2053

2054

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

2057

2061

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

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

2065

2066

2067

2068

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

2071 true,

2073 }

2074

2075

2077}

2078

2080 const Expr *Arg = E->getArgument();

2082

2083

2084

2085

2086

2087

2088

2089

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

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

2092

2094

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

2098

2099 QualType DeleteTy = E->getDestroyedType();

2100

2101

2102

2103 if (E->getOperatorDelete()->isDestroyingOperatorDelete()) {

2106 return;

2107 }

2108

2109

2110

2111

2113 llvm::Value *Zero = Builder.getInt32(0);

2115

2116 GEP.push_back(Zero);

2117

2118

2120 = getContext().getAsConstantArrayType(DeleteTy)) {

2121

2122 DeleteTy = Arr->getElementType();

2123

2124

2125 GEP.push_back(Zero);

2126 }

2127

2130 }

2131

2133

2134 if (E->isArrayForm()) {

2137 } else {

2140 }

2141}

2142

2144 llvm::Type *StdTypeInfoPtrTy,

2145 bool HasNullCheck) {

2146

2148

2150

2151

2152

2153

2154

2156 ThisPtr, SrcRecordTy);

2157

2158

2159

2160

2161 if (HasNullCheck &&

2163 llvm::BasicBlock *BadTypeidBlock =

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

2166

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

2169

2173 }

2174

2176 StdTypeInfoPtrTy);

2177}

2178

2180

2181

2182

2183

2184

2187

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

2193 };

2194

2195 if (E->isTypeOperand()) {

2198 return MaybeASCast(TypeInfo);

2199 }

2200

2201

2202

2203

2204

2205

2206

2207 if (E->isPotentiallyEvaluated() && E->isMostDerived(getContext()))

2209 E->hasNullCheck());

2210

2213}

2214

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

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

2220

2221

2222

2224 return nullptr;

2225

2226 CGF.Builder.ClearInsertionPoint();

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

2228}

2229

2234

2236

2237

2238

2239

2243 if (IsDynamicCastToVoid) {

2245

2249 } else {

2250 SrcRecordTy = SrcTy;

2252 }

2253

2254

2255

2256

2257

2258

2260

2263

2264 if (Builder.GetInsertBlock())

2266 return T;

2267 }

2268 }

2269

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

2271

2272

2273

2274 bool IsExact = !IsDynamicCastToVoid &&

2278

2279

2280

2281

2282 bool ShouldNullCheckSrcValue =

2285

2286 llvm::BasicBlock *CastNull = nullptr;

2287 llvm::BasicBlock *CastNotNull = nullptr;

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

2289

2290 if (ShouldNullCheckSrcValue) {

2293

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

2297 }

2298

2299 llvm::Value *Value;

2300 if (IsDynamicCastToVoid) {

2302 } else if (IsExact) {

2303

2304

2306 *this, ThisAddr, SrcRecordTy, DestTy, DestRecordTy, CastEnd, CastNull);

2307 } else {

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

2311 DestTy, DestRecordTy, CastEnd);

2312 }

2313 CastNotNull = Builder.GetInsertBlock();

2314

2315 llvm::Value *NullValue = nullptr;

2316 if (ShouldNullCheckSrcValue) {

2318

2321 CastNull = Builder.GetInsertBlock();

2322

2324 }

2325

2327

2328 if (CastNull) {

2330 PHI->addIncoming(Value, CastNotNull);

2331 PHI->addIncoming(NullValue, CastNull);

2332

2334 }

2335

2337}

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

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

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

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

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.

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

static void EnterNewDeleteCleanup(CodeGenFunction &CGF, const CXXNewExpr *E, 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.

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

Emit the code for deleting a single object.

static UsualDeleteParams getUsualDeleteParams(const FunctionDecl *FD)

static CXXRecordDecl * getCXXRecord(const Expr *E)

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

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

Emit the code for deleting an array of objects.

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

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

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

llvm::MachO::Target Target

static QualType getPointeeType(const MemRegion *R)

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

bool hasSameType(QualType T1, QualType T2) const

Determine whether the given types T1 and T2 are equivalent.

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.

CanQualType getSizeType() const

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

CharUnits getTypeSizeInChars(QualType T) const

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

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.

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

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

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

QualType getAllocatedType() const

std::optional< Expr * > getArraySize()

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

A call to an overloaded operator written using operator syntax.

Represents a list-initialization with parenthesis.

ArrayRef< Expr * > getInitExprs()

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

Represents a C++ struct/union/class.

bool isEffectivelyFinal() const

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

bool hasTrivialDestructor() const

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

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.

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

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 LLVM_READONLY

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

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

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

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

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

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

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

llvm::LoadInst * CreateFlagLoad(llvm::Value *Addr, const llvm::Twine &Name="")

Emit a load from an i1 flag variable.

Address CreateLaunderInvariantGroup(Address Addr)

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

llvm::ConstantInt * getSize(CharUnits N)

Address CreateConstInBoundsGEP(Address Addr, uint64_t Index, const llvm::Twine &Name="")

Given addr = T* ... produce name = getelementptr inbounds addr, i64 index where i64 is actually the t...

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

virtual RValue EmitCUDAKernelCallExpr(CodeGenFunction &CGF, const CUDAKernelCallExpr *E, ReturnValueSlot ReturnValue, llvm::CallBase **CallOrInvoke=nullptr)

virtual bool shouldEmitExactDynamicCast(QualType DestRecordTy)=0

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 std::pair< llvm::Value *, const CXXRecordDecl * > LoadVTablePtr(CodeGenFunction &CGF, Address This, const CXXRecordDecl *RD)=0

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

virtual Address adjustThisArgumentForVirtualFunctionCall(CodeGenFunction &CGF, GlobalDecl GD, Address This, bool VirtualCall)

Perform ABI-specific "this" argument adjustment required prior to a call of a virtual function.

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

virtual llvm::Value * emitExactDynamicCast(CodeGenFunction &CGF, Address Value, QualType SrcRecordTy, QualType DestTy, QualType DestRecordTy, llvm::BasicBlock *CastSuccess, llvm::BasicBlock *CastFail)=0

Emit a dynamic_cast from SrcRecordTy to DestRecordTy.

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 CGCallee EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, const Expr *E, Address This, llvm::Value *&ThisPtrForCall, llvm::Value *MemPtr, const MemberPointerType *MPT)

Load a member function from an object and a member function pointer.

virtual llvm::Value * EmitVirtualDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, CXXDtorType DtorType, Address This, DeleteOrMemberCallExpr E, llvm::CallBase **CallOrInvoke)=0

Emit the ABI-specific virtual destructor call.

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

virtual llvm::Value * emitDynamicCastToVoid(CodeGenFunction &CGF, Address Value, QualType SrcRecordTy)=0

virtual llvm::Value * emitDynamicCastCall(CodeGenFunction &CGF, Address Value, QualType SrcRecordTy, QualType DestTy, QualType DestRecordTy, llvm::BasicBlock *CastEnd)=0

virtual Address InitializeArrayCookie(CodeGenFunction &CGF, Address NewPtr, llvm::Value *NumElements, const CXXNewExpr *expr, QualType ElementType)

Initialize the array cookie for the given allocation.

virtual bool shouldDynamicCastCallBeNullChecked(bool SrcIsPtr, QualType SrcRecordTy)=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())

void addHeapAllocSiteMetadata(llvm::CallBase *CallSite, QualType AllocatedTy, SourceLocation Loc)

Add heapallocsite metadata for MSAllocator calls.

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.

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

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

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

void EmitARCDestroyWeak(Address addr)

void EmitNullInitialization(Address DestPtr, QualType Ty)

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

GlobalDecl CurGD

CurGD - The GlobalDecl for the current function being compiled.

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

DeactivateCleanupBlock - Deactivates the given cleanup block.

static TypeEvaluationKind getEvaluationKind(QualType T)

getEvaluationKind - Return the TypeEvaluationKind of QualType T.

bool sanitizePerformTypeCheck() const

Whether any type-checking sanitizers are enabled.

SanitizerSet SanOpts

Sanitizers enabled for this function.

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

EmitVTablePtrCheckForCall - Virtual method MD is being called via VTable.

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

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

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)

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

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

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

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

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

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

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

llvm::SmallVector< DeferredDeactivateCleanup > DeferredDeactivationCleanupStack

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

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

createBasicBlock - Create an LLVM basic block.

RValue EmitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr *E)

const LangOptions & getLangOpts() const

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

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

EmitBlock - Emit the given block.

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

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

void EmitIgnoredExpr(const Expr *E)

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

llvm::Type * ConvertTypeForMem(QualType T)

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

Emit an aggregate assignment.

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

@ ForceRightToLeft

! Language semantics require right-to-left evaluation.

Destroyer * getDestroyer(QualType::DestructionKind destructionKind)

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

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

llvm::Value * getTypeSize(QualType Ty)

Returns calculated size of the specified type.

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 EmitARCRelease(llvm::Value *value, ARCPreciseLifetime_t precise)

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

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

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

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

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

CGDebugInfo * getDebugInfo()

void EmitBranch(llvm::BasicBlock *Block)

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

void EmitCXXDeleteExpr(const CXXDeleteExpr *E)

const TargetCodeGenInfo & getTargetHooks() const

void EmitAggExpr(const Expr *E, AggValueSlot AS)

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

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

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

ASTContext & getContext() const

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

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

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

bool needsEHCleanup(QualType::DestructionKind kind)

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

void EmitCXXConstructExpr(const CXXConstructExpr *E, AggValueSlot Dest)

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

llvm::Type * ConvertType(QualType T)

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

CodeGenTypes & getTypes() const

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

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

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

const CallExpr * MustTailCall

Address ReturnValue

ReturnValue - The temporary alloca to hold the return value.

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

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

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

void EmitARCDestroyStrong(Address addr, ARCPreciseLifetime_t precise)

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

static bool IsWrappedCXXThis(const Expr *E)

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

void EmitExplicitCastExprType(const ExplicitCastExpr *E, CodeGenFunction *CGF=nullptr)

Emit type info if type of an expression is a variably modified type.

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 * GetAddrOfRTTIDescriptor(QualType Ty, bool ForEH=false)

Get the address of the RTTI descriptor for 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.

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

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

const LangOptions & getLangOpts() const

CGCUDARuntime & getCUDARuntime()

Return a reference to the configured CUDA runtime.

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

CodeGenTypes & getTypes()

CGCXXABI & getCXXABI() const

const CodeGenOptions & getCodeGenOpts() const

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

LangAS GetGlobalVarAddressSpace(const VarDecl *D)

Return the AST address space of the underlying global variable for D, as determined by its declaratio...

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.

const CGFunctionInfo & arrangeCXXMethodDeclaration(const CXXMethodDecl *MD)

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

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

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

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

GetFunctionType - Get the LLVM function type for.

const CGFunctionInfo & arrangeCXXMethodCall(const CallArgList &args, const FunctionProtoType *type, RequiredArgs required, unsigned numPrefixArgs)

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

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.

bool isZeroInitializable(QualType T)

IsZeroInitializable - Return whether a type can be zero-initialized (in the C++ sense) with an LLVM z...

const CGFunctionInfo & arrangeCXXStructorDeclaration(GlobalDecl GD)

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

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

Information for lazily generating a cleanup.

A saved depth on the scope stack.

stable_iterator stable_begin() const

Create a stable reference to the top of the EH stack.

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

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

iterator find(stable_iterator save) const

Turn a stable reference to a scope depth into a unstable pointer to the EH stack.

AlignmentSource getAlignmentSource() const

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

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

The name of a declaration.

QualType getIntegerType() const

Return the integer type this enum decl corresponds to.

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

EnumDecl * getDecl() const

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

Whether this function is variadic.

bool isReservedGlobalPlacementOperator() const

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

bool isReplaceableGlobalAllocationFunction(std::optional< unsigned > *AlignmentParam=nullptr, bool *IsNothrow=nullptr) const

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

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.

param_type_iterator param_type_begin() const

unsigned getNumParams() const

QualType getParamType(unsigned i) const

param_type_iterator param_type_end() const

GlobalDecl - represents a global declaration.

CXXCtorType getCtorType() const

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.

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

NestedNameSpecifier * getQualifier() const

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

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

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

bool mayInsertExtraPadding(bool EmitRemark=false) const

Whether we are allowed to insert extra padding between fields.

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

RecordDecl * getDecl() 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.

SourceLocation getBeginLoc() const LLVM_READONLY

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

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

bool isConstantArrayType() const

bool isVoidPointerType() const

bool isPointerType() const

bool isIntegerType() const

isIntegerType() does not include complex integers (a GCC extension).

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.

const ArrayType * getAsArrayTypeUnsafe() const

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

const T * getAs() const

Member-template getAs'.

bool isRecordType() const

@ 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

Matches all kinds of arrays.

bool This(InterpState &S, CodePtr OpPC)

bool Zero(InterpState &S, CodePtr OpPC)

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

CXXCtorType

C++ constructor types.

@ Ctor_Base

Base object ctor.

@ Ctor_Complete

Complete object ctor.

@ Dtor_Complete

Complete object dtor.

LangAS

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

const FunctionProtoType * T

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

Determine whether two declarations declare the same entity.

__DEVICE__ _Tp arg(const std::complex< _Tp > &__c)

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.

bool has(SanitizerMask K) const

Check if a certain (single) sanitizer is enabled.