29#include "llvm/IR/Intrinsics.h"
30#include "llvm/IR/Metadata.h"
31#include "llvm/Support/SaveAndRestore.h"
32#include "llvm/Transforms/Utils/ModuleUtils.h"
33#include "llvm/Transforms/Utils/SanitizerStats.h"
53 return layout.getNonVirtualAlignment();
85 CharUnits expectedVBaseAlign = baseLayout.getNonVirtualAlignment();
98 return std::min(actualBaseAlign, expectedTargetAlign);
101 CharUnits expectedBaseAlign = baseLayout.getNonVirtualAlignment();
121 if (actualBaseAlign >= expectedBaseAlign) {
122 return expectedTargetAlign;
128 return std::min(actualBaseAlign, expectedTargetAlign);
132 assert(
CurFuncDecl &&
"loading 'this' without a func declaration?");
136 if (CXXThisAlignment.isZero()) {
140 CXXThisAlignment =
CGM.getClassPointerAlignment(MD->getParent());
144 LoadCXXThis(), MD->getFunctionObjectParameterType(), CXXThisAlignment,
152 const Expr *E,
Address base, llvm::Value *memberPtr,
156 llvm::Value *ptr =
CGM.getCXXABI().EmitMemberDataPointerAddress(
157 *
this, E, base, memberPtr, memberPtrType, IsInBounds);
161 CGM.getNaturalTypeAlignment(memberType, BaseInfo, TBAAInfo);
162 memberAlign =
CGM.getDynamicOffsetAlignment(
179 assert(!
Base->isVirtual() &&
"Should not see virtual bases here!");
184 const auto *BaseDecl =
Base->getType()->castAsCXXRecordDecl();
197 assert(PathBegin != PathEnd &&
"Base path should not be empty!");
207 return llvm::ConstantInt::get(
PtrDiffTy, Offset.getQuantity());
217 bool BaseIsVirtual) {
232 if (!Offset.isZero()) {
234 V =
Builder.CreateConstInBoundsByteGEP(
V, Offset);
241 llvm::Value *virtualOffset,
const CXXRecordDecl *derivedClass,
244 assert(!nonVirtualOffset.
isZero() || virtualOffset !=
nullptr);
247 llvm::Value *baseOffset;
248 if (!nonVirtualOffset.
isZero()) {
249 llvm::Type *OffsetType =
255 llvm::ConstantInt::get(OffsetType, nonVirtualOffset.
getQuantity());
257 baseOffset = CGF.
Builder.CreateAdd(virtualOffset, baseOffset);
260 baseOffset = virtualOffset;
271 assert(nearestVBase &&
"virtual offset without vbase?");
287 assert(PathBegin != PathEnd &&
"Base path should not be empty!");
296 if ((*Start)->isVirtual()) {
297 VBase = (*Start)->getType()->castAsCXXRecordDecl();
304 CharUnits NonVirtualOffset =
CGM.computeNonVirtualBaseClassOffset(
305 VBase ? VBase : Derived, Start, PathEnd);
310 if (VBase && Derived->
hasAttr<FinalAttr>()) {
313 NonVirtualOffset += vBaseOffset;
319 llvm::Type *PtrTy = llvm::PointerType::get(
323 CharUnits DerivedAlign =
CGM.getClassPointerAlignment(Derived);
327 if (NonVirtualOffset.
isZero() && !VBase) {
330 SkippedChecks.
set(SanitizerKind::Null, !NullCheckValue);
332 DerivedAlign, SkippedChecks);
334 return Value.withElementType(BaseValueTy);
337 llvm::BasicBlock *origBB =
nullptr;
338 llvm::BasicBlock *endBB =
nullptr;
342 if (NullCheckValue) {
343 origBB =
Builder.GetInsertBlock();
348 Builder.CreateCondBr(isNull, endBB, notNullBB);
354 SkippedChecks.
set(SanitizerKind::Null,
true);
356 Value.emitRawPointer(*
this), DerivedTy, DerivedAlign,
361 llvm::Value *VirtualOffset =
nullptr;
364 CGM.getCXXABI().GetVirtualBaseClassOffset(*
this,
Value, Derived, VBase);
369 VirtualOffset, Derived, VBase);
375 if (NullCheckValue) {
376 llvm::BasicBlock *notNullBB =
Builder.GetInsertBlock();
380 llvm::PHINode *PHI =
Builder.CreatePHI(PtrTy, 2,
"cast.result");
381 PHI->addIncoming(
Value.emitRawPointer(*
this), notNullBB);
382 PHI->addIncoming(llvm::Constant::getNullValue(PtrTy), origBB);
393 assert(PathBegin != PathEnd &&
"Base path should not be empty!");
396 llvm::Type *DerivedValueTy =
ConvertType(DerivedTy);
398 llvm::Value *NonVirtualOffset =
399 CGM.GetNonVirtualBaseClassOffset(Derived, PathBegin, PathEnd);
401 if (!NonVirtualOffset) {
406 llvm::BasicBlock *CastNull =
nullptr;
407 llvm::BasicBlock *CastNotNull =
nullptr;
408 llvm::BasicBlock *CastEnd =
nullptr;
410 if (NullCheckValue) {
424 CGM.getClassPointerAlignment(Derived),
"sub.ptr");
427 Addr =
Addr.withElementType(DerivedValueTy);
430 if (NullCheckValue) {
436 llvm::Value *
Value =
Addr.emitRawPointer(*
this);
438 PHI->addIncoming(
Value, CastNotNull);
439 PHI->addIncoming(llvm::Constant::getNullValue(
Value->
getType()), CastNull);
441 CGM.getClassPointerAlignment(Derived));
450 if (!
CGM.getCXXABI().NeedsVTTParameter(GD)) {
458 uint64_t SubVTTIndex;
463 }
else if (RD ==
Base) {
466 assert(!
CGM.getCXXABI().NeedsVTTParameter(
CurGD) &&
467 "doing no-op VTT offset in base dtor/ctor?");
468 assert(!ForVirtualBase &&
"Can't have same class as virtual base!");
477 assert(SubVTTIndex != 0 &&
"Sub-VTT index must be greater than zero!");
481 if (
CGM.getCXXABI().NeedsVTTParameter(
CurGD)) {
486 VTT =
CGM.getVTables().GetAddrOfVTT(RD);
488 return Builder.CreateConstInBoundsGEP1_64(
CGM.GlobalsInt8PtrTy, VTT,
494struct CallBaseDtor final : EHScopeStack::Cleanup {
498 : BaseClass(
Base), BaseIsVirtual(BaseIsVirtual) {}
511 false,
Addr, ThisTy);
517struct DynamicThisUseChecker
518 : ConstEvaluatedExprVisitor<DynamicThisUseChecker> {
519 typedef ConstEvaluatedExprVisitor<DynamicThisUseChecker> super;
523 DynamicThisUseChecker(
const ASTContext &
C) : super(
C), UsesThis(
false) {}
530 void VisitCXXThisExpr(
const CXXThisExpr *E) { UsesThis =
true; }
535 DynamicThisUseChecker Checker(
C);
537 return Checker.UsesThis;
560 ThisPtr, ClassDecl, BaseClassDecl, isBaseVirtual);
569 !BaseClassDecl->hasTrivialDestructor())
581 for (
const auto *I : IndirectField->
chain())
596 "Must have member initializer!");
597 assert(MemberInit->
getInit() &&
"Must have initializer!");
601 QualType FieldType = Field->getType();
630 unsigned SrcArgIndex =
632 llvm::Value *SrcPtr =
640 LHS.isVolatileQualified());
655 QualType FieldType = Field->getType();
747 struct SizeAndOffset {
752 unsigned PtrSize =
CGM.getDataLayout().getPointerSizeInBits();
759 Context.toCharUnitsFromBits(Info.
getFieldOffset(i)).getQuantity();
761 size_t NumFields = 0;
762 for (
const auto *Field : ClassDecl->
fields()) {
764 auto FieldInfo = Context.getTypeInfoInChars(D->
getType());
766 assert(NumFields < SSV.size());
770 assert(NumFields == SSV.size());
777 llvm::FunctionType *FTy = llvm::FunctionType::get(
CGM.VoidTy, Args,
false);
778 llvm::FunctionCallee F =
CGM.CreateRuntimeFunction(
779 FTy, Prologue ?
"__asan_poison_intra_object_redzone"
780 :
"__asan_unpoison_intra_object_redzone");
787 for (
size_t i = 0; i < SSV.size(); i++) {
788 uint64_t AsanAlignment = 8;
789 uint64_t NextField = i == SSV.size() - 1 ? TypeSize : SSV[i + 1].Offset;
790 uint64_t PoisonSize = NextField - SSV[i].Offset - SSV[i].Size;
791 uint64_t EndOffset = SSV[i].Offset + SSV[i].Size;
792 if (PoisonSize < AsanAlignment || !SSV[i].Size ||
793 (NextField % AsanAlignment) != 0)
796 F, {
Builder.CreateAdd(ThisPtr,
Builder.getIntN(PtrSize, EndOffset)),
797 Builder.getIntN(PtrSize, PoisonSize)});
807 assert((
CGM.getTarget().getCXXABI().hasConstructorVariants() ||
809 "can only generate complete ctor for this ABI");
814 CGM.getTarget().getCXXABI().hasConstructorVariants()) {
821 assert(
Definition == Ctor &&
"emitting wrong constructor body");
825 bool IsTryBody = isa_and_nonnull<CXXTryStmt>(Body);
862class CopyingValueRepresentation {
865 : CGF(CGF), OldSanOpts(CGF.SanOpts) {
869 ~CopyingValueRepresentation() { CGF.
SanOpts = OldSanOpts; }
878class FieldMemcpyizer {
880 FieldMemcpyizer(CodeGenFunction &CGF,
const CXXRecordDecl *ClassDecl,
881 const VarDecl *SrcRec)
882 : CGF(CGF), ClassDecl(ClassDecl), SrcRec(SrcRec),
883 RecLayout(CGF.getContext().getASTRecordLayout(ClassDecl)),
885 LastFieldOffset(0), LastAddedFieldIndex(0) {}
887 bool isMemcpyableField(FieldDecl *F)
const {
905 void addMemcpyableField(FieldDecl *F) {
914 CharUnits getMemcpySize(uint64_t FirstByteOffset)
const {
916 unsigned LastFieldSize =
917 LastField->isBitField()
918 ? LastField->getBitWidthValue()
921 uint64_t MemcpySizeBits = LastFieldOffset + LastFieldSize -
935 if (FirstField->isBitField()) {
936 const CGRecordLayout &RL =
943 FirstByteOffset = FirstFieldOffset;
946 CharUnits MemcpySize = getMemcpySize(FirstByteOffset);
955 emitMemcpyIR(Dest.isBitField() ? Dest.getBitFieldAddress()
957 Src.isBitField() ? Src.getBitFieldAddress() : Src.getAddress(),
962 void reset() { FirstField =
nullptr; }
965 CodeGenFunction &CGF;
966 const CXXRecordDecl *ClassDecl;
969 void emitMemcpyIR(Address DestPtr, Address SrcPtr, CharUnits Size) {
976 void addInitialField(FieldDecl *F) {
979 FirstFieldOffset = RecLayout.getFieldOffset(F->
getFieldIndex());
980 LastFieldOffset = FirstFieldOffset;
984 void addNextField(FieldDecl *F) {
990 "Cannot aggregate fields out of order.");
997 if (FOffset < FirstFieldOffset) {
999 FirstFieldOffset = FOffset;
1000 }
else if (FOffset >= LastFieldOffset) {
1002 LastFieldOffset = FOffset;
1006 const VarDecl *SrcRec;
1007 const ASTRecordLayout &RecLayout;
1008 FieldDecl *FirstField;
1009 FieldDecl *LastField;
1010 uint64_t FirstFieldOffset, LastFieldOffset;
1011 unsigned LastAddedFieldIndex;
1014class ConstructorMemcpyizer :
public FieldMemcpyizer {
1018 static const VarDecl *getTrivialCopySource(CodeGenFunction &CGF,
1019 const CXXConstructorDecl *CD,
1020 FunctionArgList &Args) {
1028 bool isMemberInitMemcpyable(CXXCtorInitializer *MemberInit)
const {
1029 if (!MemcpyableCtor)
1032 assert(Field &&
"No field for member init.");
1033 QualType FieldType =
Field->getType();
1034 CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(MemberInit->
getInit());
1044 if (!isMemcpyableField(Field))
1052 ConstructorMemcpyizer(CodeGenFunction &CGF,
const CXXConstructorDecl *CD,
1053 FunctionArgList &Args)
1054 : FieldMemcpyizer(CGF, CD->getParent(),
1055 getTrivialCopySource(CGF, CD, Args)),
1056 ConstructorDecl(CD),
1057 MemcpyableCtor(CD->isDefaulted() && CD->isCopyOrMoveConstructor() &&
1058 CGF.getLangOpts().getGC() == LangOptions::NonGC),
1061 void addMemberInitializer(CXXCtorInitializer *MemberInit) {
1062 if (isMemberInitMemcpyable(MemberInit)) {
1063 AggregatedInits.push_back(MemberInit);
1064 addMemcpyableField(MemberInit->
getMember());
1066 emitAggregatedInits();
1068 ConstructorDecl, Args);
1072 void emitAggregatedInits() {
1073 if (AggregatedInits.size() <= 1) {
1076 if (!AggregatedInits.empty()) {
1077 CopyingValueRepresentation CVR(CGF);
1079 AggregatedInits[0], ConstructorDecl, Args);
1080 AggregatedInits.clear();
1086 pushEHDestructors();
1089 AggregatedInits.clear();
1092 void pushEHDestructors() {
1097 for (
unsigned i = 0; i < AggregatedInits.size(); ++i) {
1098 CXXCtorInitializer *MemberInit = AggregatedInits[i];
1103 LValue FieldLHS = LHS;
1105 CGF.
pushEHDestroy(dtorKind, FieldLHS.getAddress(), FieldType);
1109 void finish() { emitAggregatedInits(); }
1112 const CXXConstructorDecl *ConstructorDecl;
1113 bool MemcpyableCtor;
1114 FunctionArgList &Args;
1115 SmallVector<CXXCtorInitializer *, 16> AggregatedInits;
1118class AssignmentMemcpyizer :
public FieldMemcpyizer {
1122 FieldDecl *getMemcpyableField(Stmt *S) {
1123 if (!AssignmentsMemcpyable)
1125 if (BinaryOperator *BO = dyn_cast<BinaryOperator>(S)) {
1127 if (BO->getOpcode() != BO_Assign)
1129 MemberExpr *ME = dyn_cast<MemberExpr>(BO->getLHS());
1133 if (!Field || !isMemcpyableField(Field))
1135 Stmt *RHS = BO->getRHS();
1136 if (ImplicitCastExpr *EC = dyn_cast<ImplicitCastExpr>(RHS))
1137 RHS = EC->getSubExpr();
1140 if (MemberExpr *ME2 = dyn_cast<MemberExpr>(RHS)) {
1141 if (ME2->getMemberDecl() == Field)
1145 }
else if (CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(S)) {
1146 CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MCE->getCalleeDecl());
1149 MemberExpr *IOA = dyn_cast<MemberExpr>(MCE->getImplicitObjectArgument());
1153 if (!Field || !isMemcpyableField(Field))
1155 MemberExpr *Arg0 = dyn_cast<MemberExpr>(MCE->getArg(0));
1156 if (!Arg0 || Field != dyn_cast<FieldDecl>(Arg0->
getMemberDecl()))
1159 }
else if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
1160 FunctionDecl *FD = dyn_cast<FunctionDecl>(CE->getCalleeDecl());
1161 if (!FD || FD->
getBuiltinID() != Builtin::BI__builtin_memcpy)
1163 Expr *DstPtr = CE->
getArg(0);
1164 if (ImplicitCastExpr *DC = dyn_cast<ImplicitCastExpr>(DstPtr))
1165 DstPtr = DC->getSubExpr();
1166 UnaryOperator *DUO = dyn_cast<UnaryOperator>(DstPtr);
1167 if (!DUO || DUO->
getOpcode() != UO_AddrOf)
1169 MemberExpr *ME = dyn_cast<MemberExpr>(DUO->
getSubExpr());
1173 if (!Field || !isMemcpyableField(Field))
1175 Expr *SrcPtr = CE->
getArg(1);
1176 if (ImplicitCastExpr *SC = dyn_cast<ImplicitCastExpr>(SrcPtr))
1177 SrcPtr = SC->getSubExpr();
1178 UnaryOperator *SUO = dyn_cast<UnaryOperator>(SrcPtr);
1179 if (!SUO || SUO->
getOpcode() != UO_AddrOf)
1181 MemberExpr *ME2 = dyn_cast<MemberExpr>(SUO->
getSubExpr());
1182 if (!ME2 || Field != dyn_cast<FieldDecl>(ME2->
getMemberDecl()))
1190 bool AssignmentsMemcpyable;
1191 SmallVector<Stmt *, 16> AggregatedStmts;
1194 AssignmentMemcpyizer(CodeGenFunction &CGF,
const CXXMethodDecl *AD,
1195 FunctionArgList &Args)
1196 : FieldMemcpyizer(CGF, AD->getParent(), Args[Args.size() - 1]),
1197 AssignmentsMemcpyable(CGF.getLangOpts().getGC() == LangOptions::NonGC) {
1198 assert(Args.size() == 2);
1201 void emitAssignment(Stmt *S) {
1202 FieldDecl *F = getMemcpyableField(S);
1204 addMemcpyableField(F);
1205 AggregatedStmts.push_back(S);
1207 emitAggregatedStmts();
1212 void emitAggregatedStmts() {
1213 if (AggregatedStmts.size() <= 1) {
1214 if (!AggregatedStmts.empty()) {
1215 CopyingValueRepresentation CVR(CGF);
1223 AggregatedStmts.clear();
1226 void finish() { emitAggregatedStmts(); }
1253 bool ConstructVBases = CtorType !=
Ctor_Base &&
1260 llvm::BasicBlock *BaseCtorContinueBB =
nullptr;
1261 if (ConstructVBases &&
1262 !
CGM.getTarget().getCXXABI().hasConstructorVariants()) {
1263 BaseCtorContinueBB =
1264 CGM.getCXXABI().EmitCtorCompleteObjectHandler(*
this, ClassDecl);
1265 assert(BaseCtorContinueBB);
1269 auto AllInits = CD->
inits();
1272 auto VirtualBaseEnd = std::find_if(
1274 return !(Init->isBaseInitializer() && Init->isBaseVirtual());
1277 auto NonVirtualBaseEnd = std::find_if(VirtualBaseEnd, AllInits.end(),
1279 return !Init->isBaseInitializer();
1283 auto VirtualBaseInits = llvm::make_range(AllInits.begin(), VirtualBaseEnd);
1284 auto NonVirtualBaseInits =
1285 llvm::make_range(VirtualBaseEnd, NonVirtualBaseEnd);
1286 auto MemberInits = llvm::make_range(NonVirtualBaseEnd, AllInits.end());
1289 if (ConstructVBases) {
1292 if (
CGM.getCodeGenOpts().StrictVTablePointers &&
1293 CGM.getCodeGenOpts().OptimizationLevel > 0 &&
1300 if (BaseCtorContinueBB) {
1302 Builder.CreateBr(BaseCtorContinueBB);
1310 if (
CGM.getCodeGenOpts().StrictVTablePointers &&
1311 CGM.getCodeGenOpts().OptimizationLevel > 0 &&
1321 ConstructorMemcpyizer CM(*
this, CD, Args);
1323 assert(!
Member->isBaseInitializer());
1324 assert(
Member->isAnyMemberInitializer() &&
1325 "Delegating initializer on non-delegating constructor");
1326 CM.addMemberInitializer(
Member);
1347 for (
const auto *Field : BaseClassDecl->
fields())
1352 for (
const auto &I : BaseClassDecl->
bases()) {
1358 MostDerivedClassDecl))
1362 if (BaseClassDecl == MostDerivedClassDecl) {
1364 for (
const auto &I : BaseClassDecl->
vbases()) {
1365 const auto *
VirtualBase = I.getType()->castAsCXXRecordDecl();
1376 QualType FieldBaseElementType = Context.getBaseElementType(Field->getType());
1379 if (!FieldClassDecl)
1383 if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
1402 if (!Dtor->hasTrivialBody())
1406 for (
const auto *Field : ClassDecl->
fields())
1428static llvm::Constant *
1432 "__global_delete wrapper is only used with the Microsoft ABI");
1434 llvm::LLVMContext &LLVMCtx = M.getContext();
1438 llvm::FunctionType *FnTy = GlobDeleteFn->getFunctionType();
1448 StringRef GlobDeleteMangledName = GlobDeleteFn->getName();
1449 StringRef Signature;
1450 const char *WrapperBase;
1451 if (GlobDeleteMangledName.starts_with(
"??3@")) {
1452 Signature = GlobDeleteMangledName.substr(4);
1453 WrapperBase =
"?__global_delete@@";
1454 }
else if (GlobDeleteMangledName.starts_with(
"??_V@")) {
1455 Signature = GlobDeleteMangledName.substr(5);
1456 WrapperBase =
"?__global_array_delete@@";
1458 llvm_unreachable(
"unexpected global operator delete mangling");
1461 std::string GlobalDeleteName = (WrapperBase + Signature).str();
1462 std::string EmptyGlobalDeleteName =
1463 (
"?__empty_global_delete@@" + Signature).str();
1466 if (llvm::Function *Existing = M.getFunction(GlobalDeleteName))
1475 llvm::Function *EmptyFn = M.getFunction(EmptyGlobalDeleteName);
1477 EmptyFn = llvm::Function::Create(
1478 FnTy, llvm::GlobalValue::LinkOnceODRLinkage, EmptyGlobalDeleteName, &M);
1479 EmptyFn->setComdat(M.getOrInsertComdat(EmptyGlobalDeleteName));
1480 EmptyFn->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1487 auto *BB = llvm::BasicBlock::Create(LLVMCtx,
"", EmptyFn);
1488 llvm::Function *TrapFn =
1489 llvm::Intrinsic::getOrInsertDeclaration(&M, llvm::Intrinsic::trap);
1490 auto *TrapCall = llvm::CallInst::Create(TrapFn, {},
"", BB);
1491 TrapCall->setDoesNotReturn();
1492 TrapCall->setDoesNotThrow();
1493 new llvm::UnreachableInst(LLVMCtx, BB);
1497 appendToUsed(M, {EmptyFn});
1502 std::string AltOption =
1503 "/alternatename:" + GlobalDeleteName +
"=" + EmptyGlobalDeleteName;
1505 llvm::MDNode::get(LLVMCtx, {llvm::MDString::get(LLVMCtx, AltOption)});
1506 M.getOrInsertNamedMetadata(
"llvm.linker.options")->addOperand(AltMD);
1509 auto GlobalDeleteCallee = M.getOrInsertFunction(GlobalDeleteName, FnTy);
1516 return GlobalDeleteFn;
1521 llvm::Value *ShouldDeleteCondition) {
1524 llvm::BasicBlock *callDeleteBB =
1528 llvm::Value *CheckTheBitForArrayDestroy = CGF.
Builder.CreateAnd(
1529 ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 2));
1530 llvm::Value *ShouldDestroyArray =
1532 CGF.
Builder.CreateCondBr(ShouldDestroyArray, ScalarBB, VectorBB);
1536 llvm::Value *numElements =
nullptr;
1537 llvm::Value *allocatedPtr =
nullptr;
1541 allocatedPtr, cookieSize);
1547 assert(numElements &&
"no element count for a type with a destructor!");
1555 ThisPtr.
getElementType(), arrayBegin, numElements,
"delete.end");
1566 llvm::Value *CheckTheBitForDeleteCall = CGF.
Builder.CreateAnd(
1567 ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 1));
1569 llvm::Value *ShouldCallDelete =
1576 if (Dtor->getArrayOperatorDelete()) {
1577 if (!Dtor->getGlobalArrayOperatorDelete()) {
1580 numElements, cookieSize);
1585 llvm::Value *CheckTheBitForGlobDeleteCall = CGF.
Builder.CreateAnd(
1586 ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 4));
1588 llvm::Value *ShouldCallGlobDelete =
1590 llvm::BasicBlock *GlobDelete =
1592 llvm::BasicBlock *ClassDelete =
1594 CGF.
Builder.CreateCondBr(ShouldCallGlobDelete, ClassDelete, GlobDelete);
1598 numElements, cookieSize);
1606 CGF.
CGM, Dtor->getGlobalArrayOperatorDelete());
1609 if (Dtor->hasAttr<DLLExportAttr>())
1611 CGF.
EmitDeleteCall(Dtor->getGlobalArrayOperatorDelete(), allocatedPtr,
1613 numElements, cookieSize, GlobalDeleteWrapper);
1617 llvm::CallInst *TrapCall = CGF.
EmitTrapCall(llvm::Intrinsic::trap);
1618 TrapCall->setDoesNotReturn();
1619 TrapCall->setDoesNotThrow();
1620 CGF.
Builder.CreateUnreachable();
1621 CGF.
Builder.ClearInsertionPoint();
1638 if (DtorType !=
Dtor_Base && Dtor->getParent()->isAbstract()) {
1639 llvm::CallInst *TrapCall =
EmitTrapCall(llvm::Intrinsic::trap);
1640 TrapCall->setDoesNotReturn();
1641 TrapCall->setDoesNotThrow();
1643 Builder.ClearInsertionPoint();
1647 Stmt *Body = Dtor->getBody();
1663 QualType ThisTy = Dtor->getFunctionObjectParameterType();
1672 bool isTryBody = isa_and_nonnull<CXXTryStmt>(Body);
1687 llvm_unreachable(
"not expecting a unified dtor");
1689 llvm_unreachable(
"not expecting a COMDAT");
1691 llvm_unreachable(
"already handled deleting case");
1693 llvm_unreachable(
"already handled vector deleting case");
1696 assert((Body ||
getTarget().getCXXABI().isMicrosoft()) &&
1697 "can't emit a dtor without a body for non-Microsoft ABIs");
1703 QualType ThisTy = Dtor->getFunctionObjectParameterType();
1722 if (
CGM.getCodeGenOpts().StrictVTablePointers &&
1723 CGM.getCodeGenOpts().OptimizationLevel > 0)
1733 assert(Dtor->isImplicit() &&
"bodyless dtor not implicit");
1739 CurFn->addFnAttr(llvm::Attribute::AlwaysInline);
1757 "Body of an implicit assignment operator should be compound stmt.");
1764 AssignmentMemcpyizer AM(*
this, AssignOp, Args);
1765 for (
auto *I : RootCS->
body())
1766 AM.emitAssignment(I);
1780struct CallDtorDelete final : EHScopeStack::Cleanup {
1787 LoadThisForDtorDelete(CGF, Dtor),
1798 llvm::Value *ShouldDeleteCondition,
1799 bool ReturnAfterDelete) {
1801 const CXXRecordDecl *ClassDecl =
Dtor->getParent();
1802 const FunctionDecl *OD =
Dtor->getOperatorDelete();
1804 "unexpected value for ReturnAfterDelete");
1819 llvm::Value *Check3rdBit = CGF.
Builder.CreateAnd(
1820 ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 4));
1822 CGF.
Builder.CreateCondBr(ShouldCallDtor, DontCallDtor, CallDtor);
1824 QualType ThisTy =
Dtor->getFunctionObjectParameterType();
1828 CGF.
Builder.CreateBr(DontCallDtor);
1834 llvm::Value *Check1stBit = CGF.
Builder.CreateAnd(
1835 ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 1));
1837 CGF.
Builder.CreateCondBr(ShouldCallDelete, continueBB, callDeleteBB);
1840 auto EmitDeleteAndGoToEnd = [&](
const FunctionDecl *DeleteOp,
1841 llvm::Constant *CalleeOverride =
nullptr) {
1844 nullptr, CharUnits(),
1846 if (ReturnAfterDelete)
1849 CGF.
Builder.CreateBr(continueBB);
1854 if (
const FunctionDecl *GlobOD =
Dtor->getOperatorGlobalDelete();
1858 llvm::Value *CheckTheBitForGlobDeleteCall = CGF.
Builder.CreateAnd(
1859 ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 4));
1860 llvm::Value *ShouldCallGlobDelete =
1862 llvm::BasicBlock *GlobDelete =
1864 llvm::BasicBlock *ClassDelete =
1866 CGF.
Builder.CreateCondBr(ShouldCallGlobDelete, ClassDelete, GlobDelete);
1872 llvm::Constant *GlobalDeleteWrapper =
1876 if (
Dtor->hasAttr<DLLExportAttr>())
1878 EmitDeleteAndGoToEnd(GlobOD, GlobalDeleteWrapper);
1881 EmitDeleteAndGoToEnd(OD);
1885struct CallDtorDeleteConditional final : EHScopeStack::Cleanup {
1886 llvm::Value *ShouldDeleteCondition;
1889 CallDtorDeleteConditional(llvm::Value *ShouldDeleteCondition)
1890 : ShouldDeleteCondition(ShouldDeleteCondition) {
1891 assert(ShouldDeleteCondition !=
nullptr);
1894 void Emit(CodeGenFunction &CGF, Flags flags)
override {
1895 EmitConditionalDtorDeleteCall(CGF, ShouldDeleteCondition,
1900class DestroyField final :
public EHScopeStack::Cleanup {
1901 const FieldDecl *field;
1903 bool useEHCleanupForArray;
1907 bool useEHCleanupForArray)
1908 : field(field), destroyer(destroyer),
1909 useEHCleanupForArray(useEHCleanupForArray) {}
1911 void Emit(CodeGenFunction &CGF, Flags flags)
override {
1918 assert(LV.isSimple());
1920 CGF.
emitDestroy(LV.getAddress(), field->getType(), destroyer,
1921 flags.isForNormalCleanup() && useEHCleanupForArray);
1925class DeclAsInlineDebugLocation {
1927 llvm::DILocation *InlinedAt;
1928 std::optional<ApplyDebugLocation> Location;
1931 DeclAsInlineDebugLocation(CodeGenFunction &CGF,
const NamedDecl &
Decl)
1932 : DI(CGF.getDebugInfo()) {
1937 Location.emplace(CGF,
Decl.getLocation());
1940 ~DeclAsInlineDebugLocation() {
1948static void EmitSanitizerDtorCallback(
1950 std::optional<CharUnits::QuantityType> PoisonSize = {}) {
1954 SmallVector<llvm::Value *, 2> Args = {Ptr};
1955 SmallVector<llvm::Type *, 2> ArgTypes = {CGF.
VoidPtrTy};
1957 if (PoisonSize.has_value()) {
1958 Args.emplace_back(llvm::ConstantInt::get(CGF.
SizeTy, *PoisonSize));
1959 ArgTypes.emplace_back(CGF.
SizeTy);
1962 llvm::FunctionType *FnType =
1963 llvm::FunctionType::get(CGF.
VoidTy, ArgTypes,
false);
1970EmitSanitizerDtorFieldsCallback(
CodeGenFunction &CGF, llvm::Value *Ptr,
1972 EmitSanitizerDtorCallback(CGF,
"__sanitizer_dtor_callback_fields", Ptr,
1977struct SanitizeDtorTrivialBase final : EHScopeStack::Cleanup {
1978 const CXXRecordDecl *BaseClass;
1980 SanitizeDtorTrivialBase(
const CXXRecordDecl *Base,
bool BaseIsVirtual)
1981 : BaseClass(
Base), BaseIsVirtual(BaseIsVirtual) {}
1983 void Emit(CodeGenFunction &CGF, Flags flags)
override {
1984 const CXXRecordDecl *DerivedClass =
1990 const ASTRecordLayout &BaseLayout =
1992 CharUnits BaseSize = BaseLayout.
getSize();
1999 DeclAsInlineDebugLocation InlineHere(CGF, *BaseClass);
2000 EmitSanitizerDtorFieldsCallback(CGF,
Addr.emitRawPointer(CGF),
2004 CGF.
CurFn->addFnAttr(
"disable-tail-calls",
"true");
2008class SanitizeDtorFieldRange final :
public EHScopeStack::Cleanup {
2009 const CXXDestructorDecl *
Dtor;
2010 unsigned StartIndex;
2014 SanitizeDtorFieldRange(
const CXXDestructorDecl *Dtor,
unsigned StartIndex,
2016 :
Dtor(
Dtor), StartIndex(StartIndex), EndIndex(EndIndex) {}
2021 void Emit(CodeGenFunction &CGF, Flags flags)
override {
2022 const ASTContext &Context = CGF.
getContext();
2023 const ASTRecordLayout &Layout =
2030 llvm::ConstantInt *OffsetSizePtr =
2033 llvm::Value *OffsetPtr =
2036 CharUnits PoisonEnd;
2042 CharUnits PoisonSize = PoisonEnd - PoisonStart;
2047 DeclAsInlineDebugLocation InlineHere(
2048 CGF, **std::next(
Dtor->getParent()->field_begin(), StartIndex));
2049 EmitSanitizerDtorFieldsCallback(CGF, OffsetPtr, PoisonSize.
getQuantity());
2052 CGF.
CurFn->addFnAttr(
"disable-tail-calls",
"true");
2056class SanitizeDtorVTable final :
public EHScopeStack::Cleanup {
2057 const CXXDestructorDecl *
Dtor;
2060 SanitizeDtorVTable(
const CXXDestructorDecl *Dtor) :
Dtor(
Dtor) {}
2063 void Emit(CodeGenFunction &CGF, Flags flags)
override {
2064 assert(
Dtor->getParent()->isDynamicClass());
2071 EmitSanitizerDtorCallback(CGF,
"__sanitizer_dtor_callback_vptr", VTablePtr);
2075class SanitizeDtorCleanupBuilder {
2076 ASTContext &Context;
2077 EHScopeStack &EHStack;
2078 const CXXDestructorDecl *DD;
2079 std::optional<unsigned> StartIndex;
2082 SanitizeDtorCleanupBuilder(ASTContext &Context, EHScopeStack &EHStack,
2083 const CXXDestructorDecl *DD)
2084 : Context(Context), EHStack(EHStack), DD(DD), StartIndex(std::nullopt) {}
2085 void PushCleanupForField(
const FieldDecl *Field) {
2088 unsigned FieldIndex =
Field->getFieldIndex();
2091 StartIndex = FieldIndex;
2092 }
else if (StartIndex) {
2094 *StartIndex, FieldIndex);
2095 StartIndex = std::nullopt;
2115 "Should not emit dtor epilogue for non-exported trivial dtor!");
2121 "operator delete missing - EnterDtorCleanups");
2122 if (CXXStructorImplicitParamValue) {
2126 EmitConditionalDtorDeleteCall(*
this, CXXStructorImplicitParamValue,
2129 EHStack.pushCleanup<CallDtorDeleteConditional>(
2135 LoadThisForDtorDelete(*
this, DD),
2136 getContext().getCanonicalTagType(ClassDecl));
2155 if (
CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor &&
2162 for (
const auto &
Base : ClassDecl->
vbases()) {
2163 auto *BaseClassDecl =
Base.getType()->castAsCXXRecordDecl();
2164 if (BaseClassDecl->hasTrivialDestructor()) {
2168 if (
CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor &&
2169 SanOpts.has(SanitizerKind::Memory) && !BaseClassDecl->isEmpty())
2185 if (
CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor &&
2191 for (
const auto &
Base : ClassDecl->
bases()) {
2193 if (
Base.isVirtual())
2199 if (
CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor &&
2212 bool SanitizeFields =
CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor &&
2213 SanOpts.has(SanitizerKind::Memory);
2217 for (
const auto *Field : ClassDecl->
fields()) {
2219 SanitizeBuilder.PushCleanupForField(Field);
2227 const RecordType *RT =
type->getAsUnionType();
2228 if (RT && RT->getDecl()->isAnonymousStructOrUnion())
2232 EHStack.pushCleanup<DestroyField>(
2237 SanitizeBuilder.End();
2252 bool NewPointerIsChecked,
2253 bool zeroInitialize) {
2255 llvm::Value *numElements =
2259 NewPointerIsChecked, zeroInitialize);
2273 const CXXConstructExpr *E,
bool NewPointerIsChecked,
bool zeroInitialize) {
2279 llvm::CondBrInst *zeroCheckBranch =
nullptr;
2282 llvm::ConstantInt *constantCount = dyn_cast<llvm::ConstantInt>(numElements);
2283 if (constantCount) {
2285 if (constantCount->isZero())
2291 llvm::Value *iszero =
Builder.CreateIsNull(numElements,
"isempty");
2292 zeroCheckBranch =
Builder.CreateCondBr(iszero, loopBB, loopBB);
2299 llvm::Value *arrayEnd =
Builder.CreateInBoundsGEP(
2300 elementType, arrayBegin, numElements,
"arrayctor.end");
2303 llvm::BasicBlock *entryBB =
Builder.GetInsertBlock();
2306 llvm::PHINode *cur =
2307 Builder.CreatePHI(arrayBegin->getType(), 2,
"arrayctor.cur");
2308 cur->addIncoming(arrayBegin, entryBB);
2311 if (
CGM.shouldEmitConvergenceTokens())
2359 llvm::Value *next =
Builder.CreateInBoundsGEP(
2360 elementType, cur, llvm::ConstantInt::get(
SizeTy, 1),
"arrayctor.next");
2361 cur->addIncoming(next,
Builder.GetInsertBlock());
2364 llvm::Value *done =
Builder.CreateICmpEQ(next, arrayEnd,
"arrayctor.done");
2366 Builder.CreateCondBr(done, contBB, loopBB);
2369 if (zeroCheckBranch)
2370 zeroCheckBranch->setSuccessor(0, contBB);
2372 if (
CGM.shouldEmitConvergenceTokens())
2393 llvm::Value *ThisPtr =
2396 if (SlotAS != ThisAS) {
2398 llvm::Type *NewType =
2410 assert(E->
getNumArgs() == 1 &&
"unexpected argcount for trivial ctor");
2461 bool NewPointerIsChecked, llvm::CallBase **CallOrInvoke) {
2464 if (!NewPointerIsChecked)
2470 assert(Args.size() == 1 &&
"trivial default ctor with args");
2478 assert(Args.size() == 2 &&
"unexpected argcount for trivial ctor");
2481 Args[1].getRValue(*this).getScalarVal(), SrcTy);
2489 bool PassPrototypeArgs =
true;
2502 CGM.getCXXABI().addImplicitConstructorArgs(*
this, D,
Type, ForVirtualBase,
2524 if (
CGM.getCodeGenOpts().OptimizationLevel > 0 &&
2526 CGM.getCXXABI().canSpeculativelyEmitVTable(ClassDecl) &&
2527 CGM.getCodeGenOpts().StrictVTablePointers)
2540 if (InheritedFromVBase &&
2541 CGM.getTarget().getCXXABI().hasConstructorVariants()) {
2546 Args.push_back(ThisArg);
2547 }
else if (!CXXInheritedCtorInitExprArgs.empty()) {
2549 assert(CXXInheritedCtorInitExprArgs.size() >= D->
getNumParams() &&
2550 "wrong number of parameters for inherited constructor call");
2551 Args = CXXInheritedCtorInitExprArgs;
2555 Args.push_back(ThisArg);
2557 assert(OuterCtor->getNumParams() == D->
getNumParams());
2558 assert(!OuterCtor->isVariadic() &&
"should have been inlined");
2560 for (
const auto *Param : OuterCtor->parameters()) {
2562 OuterCtor->getParamDecl(Param->getFunctionScopeIndex())->getType(),
2567 if (Param->hasAttr<PassObjectSizeAttr>()) {
2568 auto *POSParam = SizeArguments[Param];
2569 assert(POSParam &&
"missing pass_object_size value for forwarding");
2589 CXXInheritedCtorInitExprArgs = Args;
2596 CGM.getCXXABI().addImplicitConstructorArgs(*
this, Ctor, CtorType,
2600 assert(Args.size() >= Params.size() &&
"too few arguments for call");
2601 for (
unsigned I = 0, N = Args.size(); I != N; ++I) {
2603 const RValue &RV = Args[I].getRValue(*
this);
2604 assert(!RV.
isComplex() &&
"complex indirect params not supported");
2618 CGM.getCXXABI().EmitInstanceFunctionProlog(*
this);
2619 CXXThisValue = CXXABIThisValue;
2626 llvm::Value *VTableGlobal =
2634 if (!NonVirtualOffset.
isZero())
2639 llvm::Value *VPtrValue =
2642 Builder.CreateICmpEQ(VPtrValue, VTableGlobal,
"cmp.vtables");
2648 if (
CGM.getCXXABI().doStructorsInitializeVPtrs(ClassDecl))
2666 llvm::Type *t =
CGM.getTypes().ConvertType(QT);
2668 llvm::Value *SrcVal =
Builder.CreateBitCast(Val, t);
2686 FunctionArgList::const_iterator I = Args.begin(), E = Args.end();
2687 assert(I != E &&
"no parameters to constructor");
2692 This, (*I)->getType()->getPointeeType())),
2698 if (
CGM.getCXXABI().NeedsVTTParameter(
CurGD)) {
2699 assert(I != E &&
"cannot skip vtt parameter, already done with args");
2700 assert((*I)->getType()->isPointerType() &&
2701 "skipping parameter not of vtt type");
2706 for (; I != E; ++I) {
2713 true,
This, DelegateArgs,
2719struct CallDelegatingCtorDtor final : EHScopeStack::Cleanup {
2731 QualType ThisTy = Dtor->getFunctionObjectParameterType();
2733 true,
Addr, ThisTy);
2758 EHStack.pushCleanup<CallDelegatingCtorDtor>(
2765 bool ForVirtualBase,
2768 CGM.getCXXABI().EmitDestructorCall(*
this, DD,
Type, ForVirtualBase,
2773struct CallLocalDtor final : EHScopeStack::Cleanup {
2802 assert(D && D->
isUsed() &&
"destructor not marked as used!");
2808 llvm::Value *VTableAddressPoint =
2809 CGM.getCXXABI().getVTableAddressPointInStructor(
2812 if (!VTableAddressPoint)
2816 llvm::Value *VirtualOffset =
nullptr;
2819 if (
CGM.getCXXABI().isVirtualOffsetNeededForVTableField(*
this, Vptr)) {
2823 VirtualOffset =
CGM.getCXXABI().GetVirtualBaseClassOffset(
2833 if (!NonVirtualOffset.
isZero() || VirtualOffset)
2835 *
this, VTableField, NonVirtualOffset, VirtualOffset, Vptr.
VTableClass,
2840 unsigned GlobalsAS =
CGM.getDataLayout().getDefaultGlobalsAddressSpace();
2841 llvm::Type *PtrTy = llvm::PointerType::get(
CGM.getLLVMContext(), GlobalsAS);
2846 if (
auto AuthenticationInfo =
CGM.getVTablePointerAuthInfo(
2848 VTableAddressPoint =
2851 llvm::StoreInst *Store =
Builder.CreateStore(VTableAddressPoint, VTableField);
2853 CGM.DecorateInstructionWithTBAA(Store, TBAAInfo);
2854 if (
CGM.getCodeGenOpts().OptimizationLevel > 0 &&
2855 CGM.getCodeGenOpts().StrictVTablePointers)
2856 CGM.DecorateInstructionWithInvariantGroup(Store, Vptr.
VTableClass);
2866 false, VTableClass, VBases,
2874 bool BaseIsNonVirtualPrimaryBase,
2880 if (!BaseIsNonVirtualPrimaryBase) {
2882 VPtr Vptr = {
Base, NearestVBase, OffsetFromNearestVBase, VTableClass};
2883 Vptrs.push_back(Vptr);
2889 for (
const auto &I : RD->
bases()) {
2890 auto *BaseDecl = I.getType()->castAsCXXRecordDecl();
2892 if (!BaseDecl->isDynamicClass())
2897 bool BaseDeclIsNonVirtualPrimaryBase;
2899 if (I.isVirtual()) {
2901 if (!VBases.insert(BaseDecl).second)
2909 BaseDeclIsNonVirtualPrimaryBase =
false;
2914 BaseOffsetFromNearestVBase =
2916 BaseDeclIsNonVirtualPrimaryBase = Layout.
getPrimaryBase() == BaseDecl;
2921 I.isVirtual() ? BaseDecl : NearestVBase, BaseOffsetFromNearestVBase,
2922 BaseDeclIsNonVirtualPrimaryBase, VTableClass, VBases, Vptrs);
2932 if (
CGM.getCXXABI().doStructorsInitializeVPtrs(RD))
2937 CGM.getCXXABI().initializeHiddenVirtualInheritanceMembers(*
this, RD);
2943 Address VTablePtrSrc =
This.withElementType(VTableTy);
2944 llvm::Instruction *VTable =
Builder.CreateLoad(VTablePtrSrc,
"vtable");
2946 CGM.DecorateInstructionWithTBAA(VTable, TBAAInfo);
2948 if (
auto AuthenticationInfo =
2949 CGM.getVTablePointerAuthInfo(
this, RD,
This.emitRawPointer(*
this))) {
2970 if (
CGM.getCodeGenOpts().OptimizationLevel > 0 &&
2971 CGM.getCodeGenOpts().StrictVTablePointers)
2972 CGM.DecorateInstructionWithInvariantGroup(VTable, RD);
3013 llvm::Value *VTable,
3015 if (
SanOpts.has(SanitizerKind::CFIVCall))
3023 else if ((
CGM.getCodeGenOpts().WholeProgramVTables &&
3024 !
CGM.AlwaysHasLTOVisibilityPublic(RD)) ||
3025 CGM.getCodeGenOpts().DevirtualizeSpeculatively) {
3027 llvm::Metadata *MD =
CGM.CreateMetadataIdentifierForType(Ty);
3028 llvm::Value *TypeId = llvm::MetadataAsValue::get(
CGM.getLLVMContext(), MD);
3034 llvm::Intrinsic::ID IID =
CGM.HasHiddenLTOVisibility(RD)
3035 ? llvm::Intrinsic::type_test
3036 : llvm::Intrinsic::public_type_test;
3037 llvm::Value *TypeTest =
3038 Builder.CreateCall(
CGM.getIntrinsic(IID), {VTable, TypeId});
3039 Builder.CreateCall(
CGM.getIntrinsic(llvm::Intrinsic::assume), TypeTest);
3045static std::pair<SanitizerKind::SanitizerOrdinal, llvm::SanitizerStatKind>
3049 return std::make_pair(SanitizerKind::SO_CFIVCall, llvm::SanStat_CFI_VCall);
3051 return std::make_pair(SanitizerKind::SO_CFINVCall,
3052 llvm::SanStat_CFI_NVCall);
3054 return std::make_pair(SanitizerKind::SO_CFIDerivedCast,
3055 llvm::SanStat_CFI_DerivedCast);
3057 return std::make_pair(SanitizerKind::SO_CFIUnrelatedCast,
3058 llvm::SanStat_CFI_UnrelatedCast);
3062 llvm_unreachable(
"unexpected sanitizer kind");
3064 llvm_unreachable(
"Unknown CFITypeCheckKind enum");
3068 llvm::Value *VTable,
3071 if (!
SanOpts.has(SanitizerKind::CFICastStrict))
3076 SanitizerHandler::CFICheckFail);
3088 const auto *ClassDecl = T->getAsCXXRecordDecl();
3095 if (!
SanOpts.has(SanitizerKind::CFICastStrict))
3100 SanitizerHandler::CFICheckFail);
3102 llvm::BasicBlock *ContBlock =
nullptr;
3105 llvm::Value *DerivedNotNull =
3111 Builder.CreateCondBr(DerivedNotNull, CheckBlock, ContBlock);
3116 llvm::Value *VTable;
3117 std::tie(VTable, ClassDecl) =
3118 CGM.getCXXABI().LoadVTablePtr(*
this, Derived, ClassDecl);
3129 llvm::Value *VTable,
3134 if (!
CGM.getCodeGenOpts().SanitizeCfiCrossDso &&
3135 !
CGM.HasHiddenLTOVisibility(RD))
3141 if (
getContext().getNoSanitizeList().containsType(
3148 llvm::Metadata *MD =
CGM.CreateMetadataIdentifierForType(T);
3149 llvm::Value *TypeId = llvm::MetadataAsValue::get(
getLLVMContext(), MD);
3151 llvm::Value *TypeTest =
Builder.CreateCall(
3152 CGM.getIntrinsic(llvm::Intrinsic::type_test), {VTable, TypeId});
3154 llvm::Constant *StaticData[] = {
3155 llvm::ConstantInt::get(
Int8Ty, TCK),
3160 auto CrossDsoTypeId =
CGM.CreateCrossDsoCfiTypeId(MD);
3161 if (
CGM.getCodeGenOpts().SanitizeCfiCrossDso && CrossDsoTypeId) {
3166 if (
CGM.getCodeGenOpts().SanitizeTrap.has(M)) {
3167 bool NoMerge = !
CGM.getCodeGenOpts().SanitizeMergeHandlers.has(M);
3168 EmitTrapCheck(TypeTest, SanitizerHandler::CFICheckFail, NoMerge);
3172 llvm::Value *AllVtables = llvm::MetadataAsValue::get(
3173 CGM.getLLVMContext(),
3174 llvm::MDString::get(
CGM.getLLVMContext(),
"all-vtables"));
3175 llvm::Value *ValidVtable =
Builder.CreateCall(
3176 CGM.getIntrinsic(llvm::Intrinsic::type_test), {VTable, AllVtables});
3177 EmitCheck(std::make_pair(TypeTest, M), SanitizerHandler::CFICheckFail,
3178 StaticData, {VTable, ValidVtable});
3182 if ((!
CGM.getCodeGenOpts().WholeProgramVTables ||
3183 !
CGM.HasHiddenLTOVisibility(RD)) &&
3184 !
CGM.getCodeGenOpts().DevirtualizeSpeculatively)
3187 if (
CGM.getCodeGenOpts().VirtualFunctionElimination)
3190 if (!
SanOpts.has(SanitizerKind::CFIVCall) ||
3191 !
CGM.getCodeGenOpts().SanitizeTrap.has(SanitizerKind::CFIVCall))
3200 const CXXRecordDecl *RD, llvm::Value *VTable, llvm::Type *VTableTy,
3201 uint64_t VTableByteOffset) {
3202 auto CheckOrdinal = SanitizerKind::SO_CFIVCall;
3203 auto CheckHandler = SanitizerHandler::CFICheckFail;
3209 llvm::Metadata *MD =
CGM.CreateMetadataIdentifierForType(T);
3210 llvm::Value *TypeId = llvm::MetadataAsValue::get(
CGM.getLLVMContext(), MD);
3212 auto CheckedLoadIntrinsic =
CGM.getLangOpts().RelativeCXXABIVTables
3213 ? llvm::Intrinsic::type_checked_load_relative
3214 : llvm::Intrinsic::type_checked_load;
3215 llvm::Value *CheckedLoad =
Builder.CreateCall(
3216 CGM.getIntrinsic(CheckedLoadIntrinsic),
3217 {VTable, llvm::ConstantInt::get(Int32Ty, VTableByteOffset), TypeId});
3219 llvm::Value *CheckResult =
Builder.CreateExtractValue(CheckedLoad, 1);
3222 if (
SanOpts.has(SanitizerKind::CFIVCall) &&
3223 !
getContext().getNoSanitizeList().containsType(SanitizerKind::CFIVCall,
3225 EmitCheck(std::make_pair(CheckResult, CheckOrdinal), CheckHandler, {}, {});
3228 return Builder.CreateBitCast(
Builder.CreateExtractValue(CheckedLoad, 0),
3237 calleeFnInfo = &
CGM.getTypes().arrangeCXXMethodDeclaration(callOperator);
3242 CGM.getTypes().GetFunctionType(*calleeFnInfo));
3249 if (!resultType->isVoidType() &&
3262 RValue RV =
EmitCall(*calleeFnInfo, callee, returnSlot, callArgs);
3265 if (!resultType->isVoidType() && returnSlot.
isNull()) {
3266 if (
getLangOpts().ObjCAutoRefCount && resultType->isObjCRetainableType()) {
3269 EmitReturnOfRValue(RV, resultType);
3280 if (CallOp->isVariadic()) {
3284 CGM.ErrorUnsupported(
CurCodeDecl,
"lambda conversion to variadic function");
3301 "generic lambda interconversion to block not implemented");
3310 CGM.ErrorUnsupported(MD,
"lambda conversion to variadic function");
3341 CallOp->getDescribedFunctionTemplate();
3342 void *InsertPos =
nullptr;
3345 assert(CorrespondingCallOpSpecialization);
3350 if (hasInAllocaArg(MD)) {
3352 llvm::Function *ImplFn =
nullptr;
3367 CGM.ErrorUnsupported(MD,
"lambda conversion to variadic function");
3375 llvm::Value *ThisArg =
CurFn->getArg(0);
3383 llvm::Function **ImplFn) {
3385 CGM.getTypes().arrangeCXXMethodDeclaration(CallOp);
3386 llvm::Function *CallOpFn =
3393 ArgTypes.push_back(I->type);
3394 *ImplFnInfo = &
CGM.getTypes().arrangeLLVMFunctionInfo(
3403 StringRef CallOpName = CallOpFn->getName();
3404 std::string ImplName;
3405 if (
size_t Pos = CallOpName.find_first_of(
"<lambda"))
3406 ImplName = (
"?__impl@" + CallOpName.drop_front(Pos)).str();
3408 ImplName = (
"__impl" + CallOpName).str();
3410 llvm::Function *Fn = CallOpFn->getParent()->getFunction(ImplName);
3412 Fn = llvm::Function::Create(
CGM.getTypes().GetFunctionType(**ImplFnInfo),
3413 llvm::GlobalValue::InternalLinkage, ImplName,
3415 CGM.SetInternalFunctionAttributes(CallOp, Fn, **ImplFnInfo);
3419 CodeGenFunction(
CGM).GenerateCode(GD, Fn, **ImplFnInfo);
3420 CGM.SetLLVMFunctionAttributesForDefinition(D, Fn);
static Address ApplyNonVirtualAndVirtualOffset(CodeGenFunction &CGF, Address addr, CharUnits nonVirtualOffset, llvm::Value *virtualOffset, const CXXRecordDecl *derivedClass, const CXXRecordDecl *nearestVBase)
static bool CanSkipVTablePointerInitialization(CodeGenFunction &CGF, const CXXDestructorDecl *Dtor)
CanSkipVTablePointerInitialization - Check whether we need to initialize any vtable pointers before c...
static llvm::Constant * getOrCreateMSVCGlobalDeleteWrapper(CodeGenModule &CGM, const FunctionDecl *GlobOD)
Get or create the MSVC-compatible __global_delete wrapper function.
static const CXXRecordDecl * LeastDerivedClassWithSameLayout(const CXXRecordDecl *RD)
static void EmitBaseInitializer(CodeGenFunction &CGF, const CXXRecordDecl *ClassDecl, CXXCtorInitializer *BaseInit)
static std::pair< SanitizerKind::SanitizerOrdinal, llvm::SanitizerStatKind > SanitizerInfoFromCFICheckKind(CodeGenFunction::CFITypeCheckKind TCK)
Converts the CFITypeCheckKind into SanitizerKind::SanitizerOrdinal and llvm::SanitizerStatKind.
static bool BaseInitializerUsesThis(ASTContext &C, const Expr *Init)
static bool FieldHasTrivialDestructorBody(ASTContext &Context, const FieldDecl *Field)
static void EmitConditionalArrayDtorCall(const CXXDestructorDecl *DD, CodeGenFunction &CGF, llvm::Value *ShouldDeleteCondition)
static bool HasTrivialDestructorBody(ASTContext &Context, const CXXRecordDecl *BaseClassDecl, const CXXRecordDecl *MostDerivedClassDecl)
static void EmitMemberInitializer(CodeGenFunction &CGF, const CXXRecordDecl *ClassDecl, CXXCtorInitializer *MemberInit, const CXXConstructorDecl *Constructor, FunctionArgList &Args)
static void EmitLValueForAnyFieldInitialization(CodeGenFunction &CGF, CXXCtorInitializer *MemberInit, LValue &LHS)
static bool isInitializerOfDynamicClass(const CXXCtorInitializer *baseInit)
static bool canEmitDelegateCallArgs(CIRGenModule &cgm, ASTContext &ctx, const CXXConstructorDecl *d, CXXCtorType type)
Defines the C++ template declaration subclasses.
a trap message and trap category.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const ConstantArrayType * getAsConstantArrayType(QualType T) const
bool isPFPField(const FieldDecl *Field) const
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
const LangOptions & getLangOpts() const
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
const NoSanitizeList & getNoSanitizeList() const
bool arePFPFieldsTriviallyCopyable(const RecordDecl *RD) const
Returns whether this record's PFP fields (if any) are trivially copyable (i.e.
TypeInfoChars getTypeInfoDataSizeInChars(QualType T) const
int64_t toBits(CharUnits CharSize) const
Convert a size in characters to a size in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
const TargetInfo & getTargetInfo() const
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
CanQualType getCanonicalTagType(const TagDecl *TD) const
unsigned getTargetAddressSpace(LangAS AS) const
uint64_t getCharWidth() const
Return the size of the character type, in bits.
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
CharUnits getAlignment() const
getAlignment - Get the record alignment in characters.
CharUnits getSize() const
getSize - Get the record size in characters.
unsigned getFieldCount() const
getFieldCount - Get the number of fields in the layout.
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const
getVBaseClassOffset - Get the offset, in chars, for the given base class.
const CXXRecordDecl * getPrimaryBase() const
getPrimaryBase - Get the primary base for this record.
CharUnits getNonVirtualSize() const
getNonVirtualSize - Get the non-virtual size (in chars) of an object, which is the size of the object...
Represents an array type, per C99 6.7.5.2 - Array Declarators.
const CXXRecordDecl * getBase() const
getBase - Returns the base class declaration.
CharUnits getBaseOffset() const
getBaseOffset - Returns the base class offset.
Represents a block literal declaration, which is like an unnamed FunctionDecl.
capture_const_iterator capture_begin() const
ArrayRef< ParmVarDecl * > parameters() const
Represents a base class of a C++ class.
QualType getType() const
Retrieves the type of the base class.
Represents a call to a C++ constructor.
Expr * getArg(unsigned Arg)
Return the specified argument.
CXXConstructorDecl * getConstructor() const
Get the constructor that this expression will (ultimately) call.
bool isListInitialization() const
Whether this constructor call was written as list-initialization.
unsigned getNumArgs() const
Return the number of arguments to the constructor call.
Represents a C++ constructor within a class.
init_iterator init_begin()
Retrieve an iterator to the first initializer.
bool isDefaultConstructor() const
Whether this constructor is a default constructor (C++ [class.ctor]p5), which can be used to default-...
bool isDelegatingConstructor() const
Determine whether this constructor is a delegating constructor.
bool isCopyOrMoveConstructor(unsigned &TypeQuals) const
Determine whether this is a copy or move constructor.
InheritedConstructor getInheritedConstructor() const
Get the constructor that this inheriting constructor is based on.
Represents a C++ base or member initializer.
FieldDecl * getMember() const
If this is a member initializer, returns the declaration of the non-static data member being initiali...
Expr * getInit() const
Get the initializer.
SourceLocation getSourceLocation() const
Determine the source location of the initializer.
bool isAnyMemberInitializer() const
bool isBaseInitializer() const
Determine whether this initializer is initializing a base class.
bool isIndirectMemberInitializer() const
const Type * getBaseClass() const
If this is a base class initializer, returns the type of the base class.
FieldDecl * getAnyMember() const
IndirectFieldDecl * getIndirectMember() const
bool isBaseVirtual() const
Returns whether the base is virtual or not.
Represents a C++ destructor within a class.
const FunctionDecl * getOperatorDelete() const
Expr * getOperatorDeleteThisArg() const
Represents a call to an inherited base class constructor from an inheriting constructor.
SourceLocation getLocation() const LLVM_READONLY
Represents a static or instance method of a struct/union/class.
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
QualType getThisType() const
Return the type of the this pointer.
QualType getFunctionObjectParameterType() const
bool isMemcpyEquivalentSpecialMember(const ASTContext &Ctx) const
Returns whether this is a copy/move constructor or assignment operator that can be implemented as a m...
Represents a C++ struct/union/class.
bool isEffectivelyFinal() const
Determine whether it's impossible for a class to be derived from this class.
bool isGenericLambda() const
Determine whether this class describes a generic lambda function object (i.e.
bool hasTrivialDestructor() const
Determine whether this class has a trivial destructor (C++ [class.dtor]p3)
method_range methods() const
bool isPolymorphic() const
Whether this class is polymorphic (C++ [class.virtual]), which means that the class contains or inher...
unsigned getNumBases() const
Retrieves the number of base classes of this class.
base_class_iterator bases_begin()
base_class_range vbases()
bool isAbstract() const
Determine whether this class has a pure virtual function.
bool isDynamicClass() const
bool hasDefinition() const
bool isEmpty() const
Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).
CXXDestructorDecl * getDestructor() const
Returns the destructor decl for this class.
CXXMethodDecl * getLambdaCallOperator() const
Retrieve the lambda call operator of the closure type if this is a closure type.
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
const CXXBaseSpecifier *const * path_const_iterator
CharUnits - This is an opaque type for sizes expressed in character units.
CharUnits alignmentAtOffset(CharUnits offset) const
Given that this is a non-zero alignment value, what is the alignment at the given offset?
bool isPositive() const
isPositive - Test whether the quantity is greater than zero.
bool isZero() const
isZero - Test whether the quantity equals zero.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
static CharUnits One()
One - Construct a CharUnits quantity of one.
CharUnits alignmentOfArrayElement(CharUnits elementSize) const
Given that this is the alignment of the first element of an array, return the minimum alignment of an...
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
@ Indirect
Indirect - Pass the argument indirectly via a hidden pointer with the specified alignment (0 indicate...
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
CharUnits getAlignment() const
llvm::Type * getElementType() const
Return the type of the values stored in this address.
Address withElementType(llvm::Type *ElemTy) const
Return address with different element type, but same pointer and alignment.
bool isSanitizerChecked() const
Address getAddress() const
Qualifiers getQualifiers() const
static AggValueSlot forLValue(const LValue &LV, IsDestructed_t isDestructed, NeedsGCBarriers_t needsGC, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed, IsSanitizerChecked_t isChecked=IsNotSanitizerChecked)
static AggValueSlot forAddr(Address addr, Qualifiers quals, IsDestructed_t isDestructed, NeedsGCBarriers_t needsGC, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed, IsSanitizerChecked_t isChecked=IsNotSanitizerChecked)
forAddr - Make a slot for an aggregate value.
Overlap_t mayOverlap() const
A scoped helper to set the current source atom group for CGDebugInfo::addInstToCurrentSourceAtom.
A scoped helper to set the current debug location to the specified location or preferred location of ...
A scoped helper to set the current debug location to an inlined location.
llvm::Value * CreateIsNull(Address Addr, const Twine &Name="")
Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index, const llvm::Twine &Name="")
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
llvm::CallInst * CreateMemCpy(Address Dest, Address Src, llvm::Value *Size, bool IsVolatile=false)
Address CreateInBoundsGEP(Address Addr, ArrayRef< llvm::Value * > IdxList, llvm::Type *ElementType, CharUnits Align, const Twine &Name="")
virtual size_t getSrcArgforCopyCtor(const CXXConstructorDecl *, FunctionArgList &Args) const =0
virtual void ReadArrayCookie(CodeGenFunction &CGF, Address Ptr, const CXXDeleteExpr *expr, QualType ElementType, llvm::Value *&NumElements, llvm::Value *&AllocPtr, CharUnits &CookieSize)
Reads the array cookie associated with the given pointer, if it has one.
All available information about a concrete callee.
static CGCallee forDirect(llvm::Constant *functionPtr, const CGCalleeInfo &abstractInfo=CGCalleeInfo())
void setInlinedAt(llvm::DILocation *InlinedAt)
Update the current inline scope.
llvm::DILocation * getInlinedAt() const
CGFunctionInfo - Class to encapsulate the information about a function definition.
bool usesInAlloca() const
Return true if this function uses inalloca arguments.
FunctionType::ExtInfo getExtInfo() const
ABIArgInfo & getReturnInfo()
const_arg_iterator arg_begin() const
CanQualType getReturnType() const
const_arg_iterator arg_end() const
RequiredArgs getRequiredArgs() const
const CGBitFieldInfo & getBitFieldInfo(const FieldDecl *FD) const
Return the BitFieldInfo that corresponds to the field FD.
CallArgList - Type for representing both the value and type of arguments in a call.
void add(RValue rvalue, QualType type)
A scope within which we are constructing the fields of an object which might use a CXXDefaultInitExpr...
static ParamValue forIndirect(Address addr)
static ParamValue forDirect(llvm::Value *value)
Enters a new scope for capturing cleanups, all of which will be executed once the scope is exited.
void ForceCleanup(std::initializer_list< llvm::Value ** > ValuesToReload={})
Force the emission of cleanups now, instead of waiting until this object is destroyed.
RAII object to set/unset CodeGenFunction::IsSanitizerScope.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
void emitArrayDestroy(llvm::Value *begin, llvm::Value *end, QualType elementType, CharUnits elementAlign, Destroyer *destroyer, bool checkZeroLength, bool useEHCleanup)
emitArrayDestroy - Destroys all the elements of the given array, beginning from last to first.
llvm::Value * GetVTablePtr(Address This, llvm::Type *VTableTy, const CXXRecordDecl *VTableClass, VTableAuthMode AuthMode=VTableAuthMode::Authenticate)
GetVTablePtr - Return the Value of the vtable pointer member pointed to by This.
GlobalDecl CurGD
CurGD - The GlobalDecl for the current function being compiled.
void EmitDelegatingCXXConstructorCall(const CXXConstructorDecl *Ctor, const FunctionArgList &Args)
void emitDestroy(Address addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray)
emitDestroy - Immediately perform the destruction of the given object.
AggValueSlot::Overlap_t getOverlapForFieldInit(const FieldDecl *FD)
Determine whether a field initialization may overlap some other object.
void EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor, CXXCtorType CtorType, const FunctionArgList &Args, SourceLocation Loc)
llvm::Value * performAddrSpaceCast(llvm::Value *Src, llvm::Type *DestTy)
SanitizerSet SanOpts
Sanitizers enabled for this function.
void EmitAsanPrologueOrEpilogue(bool Prologue)
void EmitInlinedInheritingCXXConstructorCall(const CXXConstructorDecl *Ctor, CXXCtorType CtorType, bool ForVirtualBase, bool Delegating, CallArgList &Args)
Emit a call to an inheriting constructor (that is, one that invokes a constructor inherited from a ba...
void EmitNullInitialization(Address DestPtr, QualType Ty)
EmitNullInitialization - Generate code to set a value of the given type to null, If the type contains...
Address LoadCXXThisAddress()
void EmitComplexExprIntoLValue(const Expr *E, LValue dest, bool isInit)
EmitComplexExprIntoLValue - Emit the given expression of complex type and place its result into the s...
static bool hasScalarEvaluationKind(QualType T)
llvm::Type * ConvertType(QualType T)
void EmitSanitizerStatReport(llvm::SanitizerStatKind SSK)
void pushEHDestroy(QualType::DestructionKind dtorKind, Address addr, QualType type)
pushEHDestroy - Push the standard destructor for the given type as an EH-only cleanup.
void EmitVTablePtrCheckForCall(const CXXRecordDecl *RD, llvm::Value *VTable, CFITypeCheckKind TCK, SourceLocation Loc)
EmitVTablePtrCheckForCall - Virtual method MD is being called via VTable.
void EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD)
void EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD, CallArgList &CallArgs)
Address GetAddressOfBaseClass(Address Value, const CXXRecordDecl *Derived, CastExpr::path_const_iterator PathBegin, CastExpr::path_const_iterator PathEnd, bool NullCheckValue, SourceLocation Loc)
GetAddressOfBaseClass - This function will add the necessary delta to the load of 'this' and returns ...
LValue MakeNaturalAlignPointeeAddrLValue(llvm::Value *V, QualType T)
Given a value of type T* that may not be to a complete object, construct an l-value with the natural ...
void pushRegularPartialArrayCleanup(llvm::Value *arrayBegin, llvm::Value *arrayEnd, QualType elementType, CharUnits elementAlignment, Destroyer *destroyer)
pushRegularPartialArrayCleanup - Push an EH cleanup to destroy already-constructed elements of the gi...
SmallVector< llvm::ConvergenceControlInst *, 4 > ConvergenceTokenStack
Stack to track the controlled convergence tokens.
llvm::Constant * EmitCheckSourceLocation(SourceLocation Loc)
Emit a description of a source location in a format suitable for passing to a runtime sanitizer handl...
void EmitForwardingCallToLambda(const CXXMethodDecl *LambdaCallOperator, CallArgList &CallArgs, const CGFunctionInfo *CallOpFnInfo=nullptr, llvm::Constant *CallOpFn=nullptr)
llvm::Value * getAsNaturalPointerTo(Address Addr, QualType PointeeType)
void EmitDelegateCallArg(CallArgList &args, const VarDecl *param, SourceLocation loc)
EmitDelegateCallArg - We are performing a delegate call; that is, the current function is delegating ...
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
void addInstToCurrentSourceAtom(llvm::Instruction *KeyInstruction, llvm::Value *Backup)
See CGDebugInfo::addInstToCurrentSourceAtom.
AggValueSlot::Overlap_t getOverlapForBaseInit(const CXXRecordDecl *RD, const CXXRecordDecl *BaseRD, bool IsVirtual)
Determine whether a base class initialization may overlap some other object.
const LangOptions & getLangOpts() const
llvm::Value * EmitARCRetainAutoreleasedReturnValue(llvm::Value *value)
Retain the given object which is the result of a function call.
LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
static bool IsConstructorDelegationValid(const CXXConstructorDecl *Ctor)
Checks whether the given constructor is a valid subject for the complete-to-base constructor delegati...
Address GetAddressOfDerivedClass(Address Value, const CXXRecordDecl *Derived, CastExpr::path_const_iterator PathBegin, CastExpr::path_const_iterator PathEnd, bool NullCheckValue)
void EmitVTablePtrCheck(const CXXRecordDecl *RD, llvm::Value *VTable, CFITypeCheckKind TCK, SourceLocation Loc)
EmitVTablePtrCheck - Emit a check that VTable is a valid virtual table for RD using llvm....
void EmitConstructorBody(FunctionArgList &Args)
EmitConstructorBody - Emits the body of the current constructor.
const CodeGen::CGBlockInfo * BlockInfo
void EmitAggregateCopyCtor(LValue Dest, LValue Src, AggValueSlot::Overlap_t MayOverlap)
Address makeNaturalAddressForPointer(llvm::Value *Ptr, QualType T, CharUnits Alignment=CharUnits::Zero(), bool ForPointeeType=false, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
Construct an address with the natural alignment of T.
static Destroyer destroyCXXObject
void EmitLambdaInAllocaImplFn(const CXXMethodDecl *CallOp, const CGFunctionInfo **ImplFnInfo, llvm::Function **ImplFn)
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...
VPtrsVector getVTablePointers(const CXXRecordDecl *VTableClass)
void EmitVTablePtrCheckForCast(QualType T, Address Derived, bool MayBeNull, CFITypeCheckKind TCK, SourceLocation Loc)
Derived is the presumed address of an object of type T after a cast.
@ TCK_ConstructorCall
Checking the 'this' pointer for a constructor call.
@ TCK_UpcastToVirtualBase
Checking the operand of a cast to a virtual base object.
@ TCK_Load
Checking the operand of a load. Must be suitably sized and aligned.
@ TCK_Upcast
Checking the operand of a cast to a base object.
void EmitCXXDestructorCall(const CXXDestructorDecl *D, CXXDtorType Type, bool ForVirtualBase, bool Delegating, Address This, QualType ThisTy)
void EmitBranchThroughCleanup(JumpDest Dest)
EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...
const Decl * CurCodeDecl
CurCodeDecl - This is the inner-most code context, which includes blocks.
Destroyer * getDestroyer(QualType::DestructionKind destructionKind)
void PushDestructorCleanup(QualType T, Address Addr)
PushDestructorCleanup - Push a cleanup to call the complete-object destructor of an object of the giv...
JumpDest ReturnBlock
ReturnBlock - Unified return block.
llvm::Constant * EmitCheckTypeDescriptor(QualType T)
Emit a description of a type in a format suitable for passing to a runtime sanitizer handler.
@ ForceLeftToRight
! Language semantics require left-to-right evaluation.
@ Default
! No language constraints on evaluation order.
llvm::ConvergenceControlInst * emitConvergenceLoopToken(llvm::BasicBlock *BB)
llvm::SmallPtrSet< const CXXRecordDecl *, 4 > VisitedVirtualBasesSetTy
void EmitAggregateCopy(LValue Dest, LValue Src, QualType EltTy, AggValueSlot::Overlap_t MayOverlap, bool isVolatile=false)
EmitAggregateCopy - Emit an aggregate copy.
LValue EmitLValueForField(LValue Base, const FieldDecl *Field, bool IsInBounds=true)
const TargetInfo & getTarget() const
Address EmitCXXMemberDataPointerAddress(const Expr *E, Address base, llvm::Value *memberPtr, const MemberPointerType *memberPtrType, bool IsInBounds, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr)
Emit the address of a field using a member data pointer.
void maybeCreateMCDCCondBitmap()
Allocate a temp value on the stack that MCDC can use to track condition results.
Address GetAddrOfBlockDecl(const VarDecl *var)
RawAddress CreateIRTempWithoutCast(QualType T, const Twine &Name="tmp")
CreateIRTempWithoutCast - Create a temporary IR object of the given type, with appropriate alignment.
void EnterDtorCleanups(const CXXDestructorDecl *Dtor, CXXDtorType Type)
EnterDtorCleanups - Enter the cleanups necessary to complete the given phase of destruction for a des...
llvm::Value * EmitPointerAuthSign(const CGPointerAuthInfo &Info, llvm::Value *Pointer)
void EmitCXXConstructorCall(const CXXConstructorDecl *D, CXXCtorType Type, bool ForVirtualBase, bool Delegating, AggValueSlot ThisAVS, const CXXConstructExpr *E)
void EmitCheck(ArrayRef< std::pair< llvm::Value *, SanitizerKind::SanitizerOrdinal > > Checked, SanitizerHandler Check, ArrayRef< llvm::Constant * > StaticArgs, ArrayRef< llvm::Value * > DynamicArgs, const TrapReason *TR=nullptr)
Create a basic block that will either trap or call a handler function in the UBSan runtime with the p...
llvm::Value * emitArrayLength(const ArrayType *arrayType, QualType &baseType, Address &addr)
emitArrayLength - Compute the length of an array, even if it's a VLA, and drill down to the base elem...
bool HaveInsertPoint() const
HaveInsertPoint - True if an insertion point is defined.
void EmitVTableAssumptionLoads(const CXXRecordDecl *ClassDecl, Address This)
Emit assumption load for all bases.
CGDebugInfo * getDebugInfo()
void EmitDestructorBody(FunctionArgList &Args)
EmitDestructorBody - Emits the body of the current destructor.
LValue EmitLValueForFieldInitialization(LValue Base, const FieldDecl *Field)
EmitLValueForFieldInitialization - Like EmitLValueForField, except that if the Field is a reference,...
Address GetAddressOfDirectBaseInCompleteClass(Address Value, const CXXRecordDecl *Derived, const CXXRecordDecl *Base, bool BaseIsVirtual)
GetAddressOfBaseOfCompleteClass - Convert the given pointer to a complete class to the given direct b...
RValue EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee, ReturnValueSlot ReturnValue, const CallArgList &Args, llvm::CallBase **CallOrInvoke, bool IsMustTail, SourceLocation Loc, bool IsVirtualFunctionPointerThunk=false)
EmitCall - Generate a call of the given function, expecting the given result type,...
void EmitCtorPrologue(const CXXConstructorDecl *CD, CXXCtorType Type, FunctionArgList &Args)
EmitCtorPrologue - This routine generates necessary code to initialize base classes and non-static da...
RawAddress CreateMemTempWithoutCast(QualType T, const Twine &Name="tmp")
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen without...
void EmitTypeMetadataCodeForVCall(const CXXRecordDecl *RD, llvm::Value *VTable, SourceLocation Loc)
If whole-program virtual table optimization is enabled, emit an assumption that VTable is a member of...
llvm::CallInst * EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
ASTContext & getContext() const
void Destroyer(CodeGenFunction &CGF, Address addr, QualType ty)
const Decl * CurFuncDecl
CurFuncDecl - Holds the Decl for the current outermost non-closure context.
void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit=false)
EmitStoreThroughLValue - Store the specified rvalue into the specified lvalue, where both are guarant...
llvm::Value * LoadCXXVTT()
LoadCXXVTT - Load the VTT parameter to base constructors/destructors have virtual bases.
void EmitParmDecl(const VarDecl &D, ParamValue Arg, unsigned ArgNo)
EmitParmDecl - Emit a ParmVarDecl or an ImplicitParamDecl.
void EmitInitializerForField(FieldDecl *Field, LValue LHS, Expr *Init)
void EmitLambdaInAllocaCallOpBody(const CXXMethodDecl *MD)
bool needsEHCleanup(QualType::DestructionKind kind)
Determines whether an EH cleanup is required to destroy a type with the given destruction kind.
void EmitStmt(const Stmt *S, ArrayRef< const Attr * > Attrs={})
EmitStmt - Emit the code for the statement.
CleanupKind getCleanupKind(QualType::DestructionKind kind)
llvm::Type * ConvertTypeForMem(QualType T)
void EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D, Address This, Address Src, const CXXConstructExpr *E)
CodeGenTypes & getTypes() const
static TypeEvaluationKind getEvaluationKind(QualType T)
getEvaluationKind - Return the TypeEvaluationKind of QualType T.
void ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock=false)
bool IsSanitizerScope
True if CodeGen currently emits code implementing sanitizer checks.
void emitImplicitAssignmentOperatorBody(FunctionArgList &Args)
void EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc, LValue LV, QualType Type, SanitizerSet SkippedChecks=SanitizerSet(), llvm::Value *ArraySize=nullptr)
void EmitLambdaBlockInvokeBody()
void EmitCfiSlowPathCheck(SanitizerKind::SanitizerOrdinal Ordinal, llvm::Value *Cond, llvm::ConstantInt *TypeId, llvm::Value *Ptr, ArrayRef< llvm::Constant * > StaticArgs)
Emit a slow path cross-DSO CFI check which calls __cfi_slowpath if Cond if false.
LValue EmitCheckedLValue(const Expr *E, TypeCheckKind TCK)
Same as EmitLValue but additionally we generate checking code to guard against undefined behavior.
void EmitInheritedCXXConstructorCall(const CXXConstructorDecl *D, bool ForVirtualBase, Address This, bool InheritedFromVBase, const CXXInheritedCtorInitExpr *E)
Emit a call to a constructor inherited from a base class, passing the current constructor's arguments...
bool sanitizePerformTypeCheck() const
Whether any type-checking sanitizers are enabled.
void EmitAggExpr(const Expr *E, AggValueSlot AS)
EmitAggExpr - Emit the computation of the specified expression of aggregate type.
llvm::Value * GetVTTParameter(GlobalDecl GD, bool ForVirtualBase, bool Delegating)
GetVTTParameter - Return the VTT parameter that should be passed to a base constructor/destructor wit...
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
void EmitDeleteCall(const FunctionDecl *DeleteFD, llvm::Value *Ptr, QualType DeleteTy, llvm::Value *NumElements=nullptr, CharUnits CookieSize=CharUnits(), llvm::Constant *CalleeOverride=nullptr)
void EmitCallArgs(CallArgList &Args, PrototypeWrapper Prototype, llvm::iterator_range< CallExpr::const_arg_iterator > ArgRange, AbstractCallee AC=AbstractCallee(), unsigned ParamsToSkip=0, EvaluationOrder Order=EvaluationOrder::Default)
EmitCallArgs - Emit call arguments for a function.
llvm::CallInst * EmitTrapCall(llvm::Intrinsic::ID IntrID)
Emit a call to trap or debugtrap and attach function attribute "trap-func-name" if specified.
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
void EmitTrapCheck(llvm::Value *Checked, SanitizerHandler CheckHandlerID, bool NoMerge=false, const TrapReason *TR=nullptr)
Create a basic block that will call the trap intrinsic, and emit a conditional branch to it,...
llvm::Value * LoadCXXThis()
LoadCXXThis - Load the value of 'this'.
void EnterCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock=false)
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
void InitializeVTablePointer(const VPtr &vptr)
Initialize the vtable pointer of the given subobject.
llvm::Value * EmitVTableTypeCheckedLoad(const CXXRecordDecl *RD, llvm::Value *VTable, llvm::Type *VTableTy, uint64_t VTableByteOffset)
Emit a type checked load from the given vtable.
Address ReturnValue
ReturnValue - The temporary alloca to hold the return value.
bool ShouldEmitVTableTypeCheckedLoad(const CXXRecordDecl *RD)
Returns whether we should perform a type checked load when loading a virtual function for virtual cal...
llvm::LLVMContext & getLLVMContext()
void incrementProfileCounter(const Stmt *S, llvm::Value *StepV=nullptr)
Increment the profiler's counter for the given statement by StepV.
llvm::SmallVector< VPtr, 4 > VPtrsVector
void InitializeVTablePointers(const CXXRecordDecl *ClassDecl)
void EmitVTableAssumptionLoad(const VPtr &vptr, Address This)
Emit assumption that vptr load == global vtable.
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
void EmitExprAsInit(const Expr *init, const ValueDecl *D, LValue lvalue, bool capturedByInit)
EmitExprAsInit - Emits the code necessary to initialize a location in memory with the given initializ...
QualType BuildFunctionArgList(GlobalDecl GD, FunctionArgList &Args)
llvm::Value * EmitPointerAuthAuth(const CGPointerAuthInfo &Info, llvm::Value *Pointer)
This class organizes the cross-function state that is used while generating LLVM code.
llvm::Module & getModule() const
llvm::FunctionCallee CreateRuntimeFunction(llvm::FunctionType *Ty, StringRef Name, llvm::AttributeList ExtraAttrs=llvm::AttributeList(), bool Local=false, bool AssumeConvergent=false)
Create or return a runtime function declaration with the specified type and name.
CharUnits getMinimumClassObjectSize(const CXXRecordDecl *CD)
Returns the minimum object size for an object of the given class type (or a class derived from it).
llvm::Constant * GetAddrOfFunction(GlobalDecl GD, llvm::Type *Ty=nullptr, bool ForVTable=false, bool DontDefer=false, ForDefinition_t IsForDefinition=NotForDefinition)
Return the address of the given function.
const LangOptions & getLangOpts() const
CodeGenTypes & getTypes()
void addPendingGlobalDelete(llvm::Function *GlobalDeleteFn, const FunctionDecl *OperatorDeleteFD)
Record a pending __global_delete variant that may need a forwarding body.
const TargetInfo & getTarget() const
llvm::Constant * GetNonVirtualBaseClassOffset(const CXXRecordDecl *ClassDecl, CastExpr::path_const_iterator PathBegin, CastExpr::path_const_iterator PathEnd)
Returns the offset from a derived class to a class.
CharUnits computeNonVirtualBaseClassOffset(const CXXRecordDecl *DerivedClass, CastExpr::path_const_iterator Start, CastExpr::path_const_iterator End)
CGCXXABI & getCXXABI() const
CharUnits getVBaseAlignment(CharUnits DerivedAlign, const CXXRecordDecl *Derived, const CXXRecordDecl *VBase)
Returns the assumed alignment of a virtual base of a class.
CharUnits getClassPointerAlignment(const CXXRecordDecl *CD)
Returns the assumed alignment of an opaque pointer to the given class.
CharUnits getDynamicOffsetAlignment(CharUnits ActualAlign, const CXXRecordDecl *Class, CharUnits ExpectedTargetAlign)
Given a class pointer with an actual known alignment, and the expected alignment of an object at a dy...
void noteDirectGlobalDelete()
Note that global operator delete is directly used in this TU.
ASTContext & getContext() const
const TargetCodeGenInfo & getTargetCodeGenInfo()
void SetLLVMFunctionAttributes(GlobalDecl GD, const CGFunctionInfo &Info, llvm::Function *F, bool IsThunk)
Set the LLVM function attributes (sext, zext, etc).
void SetLLVMFunctionAttributesForDefinition(const Decl *D, llvm::Function *F)
Set the LLVM function attributes which only apply to a function definition.
llvm::Type * ConvertType(QualType T)
ConvertType - Convert type T into a llvm::Type.
bool inheritingCtorHasParams(const InheritedConstructor &Inherited, CXXCtorType Type)
Determine if a C++ inheriting constructor should have parameters matching those of its inherited cons...
const CGRecordLayout & getCGRecordLayout(const RecordDecl *)
getCGRecordLayout - Return record layout info for the given record decl.
const CGFunctionInfo & arrangeGlobalDeclaration(GlobalDecl GD)
const CGFunctionInfo & arrangeCXXConstructorCall(const CallArgList &Args, const CXXConstructorDecl *D, CXXCtorType CtorKind, unsigned ExtraPrefixArgs, unsigned ExtraSuffixArgs, bool PassProtoArgs=true)
Arrange a call to a C++ method, passing the given arguments.
FunctionArgList - Type for representing both the decl and type of parameters to a function.
LValue - This represents an lvalue references.
Address getAddress() const
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(llvm::Value *V)
Address getAggregateAddress() const
getAggregateAddr() - Return the Value* of the address of the aggregate.
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
An abstract representation of an aligned address.
ReturnValueSlot - Contains the address where the return value of a function can be stored,...
virtual void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const
setTargetAttributes - Provides a convenient hook to handle extra target-specific attributes for the g...
CompoundStmt - This represents a group of statements like { stmt stmt }.
Represents the canonical version of C arrays with a specified constant size.
SourceLocation getEndLoc() const LLVM_READONLY
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
bool isUsed(bool CheckUsedAttr=true) const
Whether any (re-)declaration of the entity was used, meaning that a definition is required.
This represents one expression.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Represents a member of a struct/union/class.
bool isBitField() const
Determines whether this field is a bitfield.
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
Represents a function declaration or definition.
const ParmVarDecl * getParamDecl(unsigned i) const
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
bool hasTrivialBody() const
Returns whether the function has a trivial body that does not require any specific codegen.
bool isFunctionTemplateSpecialization() const
Determine whether this function is a function template specialization.
bool isDestroyingOperatorDelete() const
Determine whether this is a destroying operator delete.
unsigned getBuiltinID(bool ConsiderWrapperFunctions=false) const
Returns a value indicating whether this function corresponds to a builtin function.
ArrayRef< ParmVarDecl * > parameters() const
bool isTrivial() const
Whether this function is "trivial" in some specialized C++ senses.
bool isVariadic() const
Whether this function is variadic.
const TemplateArgumentList * getTemplateSpecializationArgs() const
Retrieve the template arguments used to produce this function template specialization from the primar...
bool isDefaulted() const
Whether this function is defaulted.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Represents a prototype with parameter type info, e.g.
param_type_iterator param_type_begin() const
bool isVariadic() const
Whether this function prototype is variadic.
Declaration of a template function.
FunctionDecl * findSpecialization(ArrayRef< TemplateArgument > Args, void *&InsertPos)
Return the specialization with the provided arguments if it exists, otherwise return the insertion po...
QualType getReturnType() const
GlobalDecl - represents a global declaration.
CXXCtorType getCtorType() const
const Decl * getDecl() const
Represents a field injected from an anonymous union/struct into the parent scope.
ArrayRef< NamedDecl * > chain() const
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
A pointer to member type per C++ 8.3.3 - Pointers to members.
CXXRecordDecl * getMostRecentCXXRecordDecl() const
Note: this can trigger extra deserialization when external AST sources are used.
QualType getPointeeType() const
std::string getQualifiedNameAsString() const
bool containsType(SanitizerMask Mask, StringRef MangledTypeName, StringRef Category=StringRef()) const
bool isAddressDiscriminated() const
A (possibly-)qualified type.
bool isTriviallyCopyableType(const ASTContext &Context) const
Return true if this is a trivially copyable type (C++0x [basic.types]p9)
PointerAuthQualifier getPointerAuth() const
LangAS getAddressSpace() const
Return the address space of this type.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
DestructionKind isDestructedType() const
Returns a nonzero value if objects of this type require non-trivial work to clean up after.
bool isPODType(const ASTContext &Context) const
Determine whether this is a Plain Old Data (POD) type (C++ 3.9p10).
The collection of all-type qualifiers we support.
bool hasObjCLifetime() const
LangAS getAddressSpace() const
field_range fields() const
bool mayInsertExtraPadding(bool EmitRemark=false) const
Whether we are allowed to insert extra padding between fields.
static constexpr SanitizerMask bitPosToMask(const unsigned Pos)
Create a mask with a bit enabled at position Pos.
Scope - A scope is a transient data structure that is used while parsing the program.
Encodes a location in the source.
Stmt - This represents one statement.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
bool areArgsDestroyedLeftToRightInCallee() const
Are arguments to a call destroyed left to right in the callee?
bool isMicrosoft() const
Is this ABI an MSVC-compatible ABI?
TargetCXXABI getCXXABI() const
Get the C++ ABI currently in use.
virtual bool callGlobalDeleteInDeletingDtor(const LangOptions &) const
Controls whether global operator delete is called by the deleting destructor or at the point where de...
A template argument list.
ArrayRef< TemplateArgument > asArray() const
Produce this as an array ref.
The base class of the type hierarchy.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
CXXRecordDecl * castAsCXXRecordDecl() const
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Expr * getSubExpr() const
Represents a variable declaration or definition.
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
bool isEmptyFieldForLayout(const ASTContext &Context, const FieldDecl *FD)
isEmptyFieldForLayout - Return true iff the field is "empty", that is, either a zero-width bit-field ...
@ EHCleanup
Denotes a cleanup that should run when a scope is exited using exceptional control flow (a throw stat...
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const AstTypeMatcher< ArrayType > arrayType
@ Address
A pointer to a ValueDecl.
The JSON file list parser is used to communicate input to InstallAPI.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
CXXCtorType
C++ constructor types.
@ Ctor_Base
Base object ctor.
@ Ctor_Complete
Complete object ctor.
bool isa(CodeGen::Address addr)
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
CXXDtorType
C++ destructor types.
@ Dtor_VectorDeleting
Vector deleting dtor.
@ Dtor_Comdat
The COMDAT used for dtors.
@ Dtor_Unified
GCC-style unified dtor.
@ Dtor_Base
Base object dtor.
@ Dtor_Complete
Complete object dtor.
@ Dtor_Deleting
Deleting dtor.
LangAS
Defines the address space values used by the address space qualifier of QualType.
U cast(CodeGen::Address addr)
CharUnits StorageOffset
The offset of the bitfield storage from the start of the struct.
Similar to AddedStructorArgs, but only notes the number of additional arguments.
llvm::BasicBlock * getBlock() const
Struct with all information about dynamic [sub]class needed to set vptr.
const CXXRecordDecl * NearestVBase
const CXXRecordDecl * VTableClass
CharUnits OffsetFromNearestVBase
llvm::PointerType * VoidPtrTy
llvm::IntegerType * Int8Ty
i8, i16, i32, and i64
llvm::IntegerType * SizeTy
llvm::IntegerType * Int32Ty
llvm::IntegerType * IntPtrTy
llvm::PointerType * Int8PtrTy
llvm::IntegerType * PtrDiffTy
void set(SanitizerMask K, bool Value)
Enable or disable a certain (single) sanitizer.