29#include "llvm/IR/Intrinsics.h"
30#include "llvm/IR/Metadata.h"
31#include "llvm/Support/SaveAndRestore.h"
32#include "llvm/Transforms/Utils/SanitizerStats.h"
52 return layout.getNonVirtualAlignment();
84 CharUnits expectedVBaseAlign = baseLayout.getNonVirtualAlignment();
97 return std::min(actualBaseAlign, expectedTargetAlign);
100 CharUnits expectedBaseAlign = baseLayout.getNonVirtualAlignment();
120 if (actualBaseAlign >= expectedBaseAlign) {
121 return expectedTargetAlign;
127 return std::min(actualBaseAlign, expectedTargetAlign);
131 assert(
CurFuncDecl &&
"loading 'this' without a func declaration?");
135 if (CXXThisAlignment.isZero()) {
139 CXXThisAlignment =
CGM.getClassPointerAlignment(MD->getParent());
143 LoadCXXThis(), MD->getFunctionObjectParameterType(), CXXThisAlignment,
151 const Expr *E,
Address base, llvm::Value *memberPtr,
155 llvm::Value *ptr =
CGM.getCXXABI().EmitMemberDataPointerAddress(
156 *
this, E, base, memberPtr, memberPtrType, IsInBounds);
160 CGM.getNaturalTypeAlignment(memberType, BaseInfo, TBAAInfo);
161 memberAlign =
CGM.getDynamicOffsetAlignment(
178 assert(!
Base->isVirtual() &&
"Should not see virtual bases here!");
183 const auto *BaseDecl =
Base->getType()->castAsCXXRecordDecl();
196 assert(PathBegin != PathEnd &&
"Base path should not be empty!");
206 return llvm::ConstantInt::get(
PtrDiffTy, Offset.getQuantity());
216 bool BaseIsVirtual) {
231 if (!Offset.isZero()) {
233 V =
Builder.CreateConstInBoundsByteGEP(
V, Offset);
240 llvm::Value *virtualOffset,
const CXXRecordDecl *derivedClass,
243 assert(!nonVirtualOffset.
isZero() || virtualOffset !=
nullptr);
246 llvm::Value *baseOffset;
247 if (!nonVirtualOffset.
isZero()) {
248 llvm::Type *OffsetType =
254 llvm::ConstantInt::get(OffsetType, nonVirtualOffset.
getQuantity());
256 baseOffset = CGF.
Builder.CreateAdd(virtualOffset, baseOffset);
259 baseOffset = virtualOffset;
270 assert(nearestVBase &&
"virtual offset without vbase?");
286 assert(PathBegin != PathEnd &&
"Base path should not be empty!");
295 if ((*Start)->isVirtual()) {
296 VBase = (*Start)->getType()->castAsCXXRecordDecl();
303 CharUnits NonVirtualOffset =
CGM.computeNonVirtualBaseClassOffset(
304 VBase ? VBase : Derived, Start, PathEnd);
309 if (VBase && Derived->
hasAttr<FinalAttr>()) {
312 NonVirtualOffset += vBaseOffset;
318 llvm::Type *PtrTy = llvm::PointerType::get(
322 CharUnits DerivedAlign =
CGM.getClassPointerAlignment(Derived);
326 if (NonVirtualOffset.
isZero() && !VBase) {
329 SkippedChecks.
set(SanitizerKind::Null, !NullCheckValue);
331 DerivedAlign, SkippedChecks);
333 return Value.withElementType(BaseValueTy);
336 llvm::BasicBlock *origBB =
nullptr;
337 llvm::BasicBlock *endBB =
nullptr;
341 if (NullCheckValue) {
342 origBB =
Builder.GetInsertBlock();
347 Builder.CreateCondBr(isNull, endBB, notNullBB);
353 SkippedChecks.
set(SanitizerKind::Null,
true);
355 Value.emitRawPointer(*
this), DerivedTy, DerivedAlign,
360 llvm::Value *VirtualOffset =
nullptr;
363 CGM.getCXXABI().GetVirtualBaseClassOffset(*
this,
Value, Derived, VBase);
368 VirtualOffset, Derived, VBase);
374 if (NullCheckValue) {
375 llvm::BasicBlock *notNullBB =
Builder.GetInsertBlock();
379 llvm::PHINode *PHI =
Builder.CreatePHI(PtrTy, 2,
"cast.result");
380 PHI->addIncoming(
Value.emitRawPointer(*
this), notNullBB);
381 PHI->addIncoming(llvm::Constant::getNullValue(PtrTy), origBB);
392 assert(PathBegin != PathEnd &&
"Base path should not be empty!");
395 llvm::Type *DerivedValueTy =
ConvertType(DerivedTy);
397 llvm::Value *NonVirtualOffset =
398 CGM.GetNonVirtualBaseClassOffset(Derived, PathBegin, PathEnd);
400 if (!NonVirtualOffset) {
405 llvm::BasicBlock *CastNull =
nullptr;
406 llvm::BasicBlock *CastNotNull =
nullptr;
407 llvm::BasicBlock *CastEnd =
nullptr;
409 if (NullCheckValue) {
423 CGM.getClassPointerAlignment(Derived),
"sub.ptr");
426 Addr =
Addr.withElementType(DerivedValueTy);
429 if (NullCheckValue) {
435 llvm::Value *
Value =
Addr.emitRawPointer(*
this);
437 PHI->addIncoming(
Value, CastNotNull);
438 PHI->addIncoming(llvm::Constant::getNullValue(
Value->
getType()), CastNull);
440 CGM.getClassPointerAlignment(Derived));
449 if (!
CGM.getCXXABI().NeedsVTTParameter(GD)) {
457 uint64_t SubVTTIndex;
462 }
else if (RD ==
Base) {
465 assert(!
CGM.getCXXABI().NeedsVTTParameter(
CurGD) &&
466 "doing no-op VTT offset in base dtor/ctor?");
467 assert(!ForVirtualBase &&
"Can't have same class as virtual base!");
476 assert(SubVTTIndex != 0 &&
"Sub-VTT index must be greater than zero!");
479 if (
CGM.getCXXABI().NeedsVTTParameter(
CurGD)) {
485 llvm::GlobalValue *VTT =
CGM.getVTables().GetAddrOfVTT(RD);
486 return Builder.CreateConstInBoundsGEP2_64(VTT->getValueType(), VTT, 0,
493struct CallBaseDtor final : EHScopeStack::Cleanup {
497 : BaseClass(
Base), BaseIsVirtual(BaseIsVirtual) {}
510 false,
Addr, ThisTy);
516struct DynamicThisUseChecker
517 : ConstEvaluatedExprVisitor<DynamicThisUseChecker> {
518 typedef ConstEvaluatedExprVisitor<DynamicThisUseChecker> super;
522 DynamicThisUseChecker(
const ASTContext &
C) : super(
C), UsesThis(
false) {}
529 void VisitCXXThisExpr(
const CXXThisExpr *E) { UsesThis =
true; }
534 DynamicThisUseChecker Checker(
C);
536 return Checker.UsesThis;
559 ThisPtr, ClassDecl, BaseClassDecl, isBaseVirtual);
568 !BaseClassDecl->hasTrivialDestructor())
574 auto *CD = dyn_cast<CXXConstructorDecl>(D);
575 if (!(CD && CD->isCopyOrMoveConstructor()) &&
597 for (
const auto *I : IndirectField->
chain())
612 "Must have member initializer!");
613 assert(MemberInit->
getInit() &&
"Must have initializer!");
617 QualType FieldType = Field->getType();
645 unsigned SrcArgIndex =
647 llvm::Value *SrcPtr =
655 LHS.isVolatileQualified());
670 QualType FieldType = Field->getType();
762 struct SizeAndOffset {
767 unsigned PtrSize =
CGM.getDataLayout().getPointerSizeInBits();
774 Context.toCharUnitsFromBits(Info.
getFieldOffset(i)).getQuantity();
776 size_t NumFields = 0;
777 for (
const auto *Field : ClassDecl->
fields()) {
779 auto FieldInfo = Context.getTypeInfoInChars(D->
getType());
781 assert(NumFields < SSV.size());
785 assert(NumFields == SSV.size());
792 llvm::FunctionType *FTy = llvm::FunctionType::get(
CGM.VoidTy, Args,
false);
793 llvm::FunctionCallee F =
CGM.CreateRuntimeFunction(
794 FTy, Prologue ?
"__asan_poison_intra_object_redzone"
795 :
"__asan_unpoison_intra_object_redzone");
802 for (
size_t i = 0; i < SSV.size(); i++) {
803 uint64_t AsanAlignment = 8;
804 uint64_t NextField = i == SSV.size() - 1 ? TypeSize : SSV[i + 1].Offset;
805 uint64_t PoisonSize = NextField - SSV[i].Offset - SSV[i].Size;
806 uint64_t EndOffset = SSV[i].Offset + SSV[i].Size;
807 if (PoisonSize < AsanAlignment || !SSV[i].Size ||
808 (NextField % AsanAlignment) != 0)
811 F, {
Builder.CreateAdd(ThisPtr,
Builder.getIntN(PtrSize, EndOffset)),
812 Builder.getIntN(PtrSize, PoisonSize)});
822 assert((
CGM.getTarget().getCXXABI().hasConstructorVariants() ||
824 "can only generate complete ctor for this ABI");
829 CGM.getTarget().getCXXABI().hasConstructorVariants()) {
836 assert(
Definition == Ctor &&
"emitting wrong constructor body");
840 bool IsTryBody = isa_and_nonnull<CXXTryStmt>(Body);
877class CopyingValueRepresentation {
880 : CGF(CGF), OldSanOpts(CGF.SanOpts) {
884 ~CopyingValueRepresentation() { CGF.
SanOpts = OldSanOpts; }
893class FieldMemcpyizer {
895 FieldMemcpyizer(CodeGenFunction &CGF,
const CXXRecordDecl *ClassDecl,
896 const VarDecl *SrcRec)
897 : CGF(CGF), ClassDecl(ClassDecl), SrcRec(SrcRec),
898 RecLayout(CGF.getContext().getASTRecordLayout(ClassDecl)),
900 LastFieldOffset(0), LastAddedFieldIndex(0) {}
902 bool isMemcpyableField(FieldDecl *F)
const {
915 void addMemcpyableField(FieldDecl *F) {
924 CharUnits getMemcpySize(uint64_t FirstByteOffset)
const {
926 unsigned LastFieldSize =
927 LastField->isBitField()
928 ? LastField->getBitWidthValue()
931 uint64_t MemcpySizeBits = LastFieldOffset + LastFieldSize -
945 if (FirstField->isBitField()) {
946 const CGRecordLayout &RL =
953 FirstByteOffset = FirstFieldOffset;
956 CharUnits MemcpySize = getMemcpySize(FirstByteOffset);
965 emitMemcpyIR(Dest.isBitField() ? Dest.getBitFieldAddress()
967 Src.isBitField() ? Src.getBitFieldAddress() : Src.getAddress(),
972 void reset() { FirstField =
nullptr; }
975 CodeGenFunction &CGF;
976 const CXXRecordDecl *ClassDecl;
979 void emitMemcpyIR(Address DestPtr, Address SrcPtr, CharUnits Size) {
986 void addInitialField(FieldDecl *F) {
989 FirstFieldOffset = RecLayout.getFieldOffset(F->
getFieldIndex());
990 LastFieldOffset = FirstFieldOffset;
994 void addNextField(FieldDecl *F) {
1000 "Cannot aggregate fields out of order.");
1007 if (FOffset < FirstFieldOffset) {
1009 FirstFieldOffset = FOffset;
1010 }
else if (FOffset >= LastFieldOffset) {
1012 LastFieldOffset = FOffset;
1016 const VarDecl *SrcRec;
1017 const ASTRecordLayout &RecLayout;
1018 FieldDecl *FirstField;
1019 FieldDecl *LastField;
1020 uint64_t FirstFieldOffset, LastFieldOffset;
1021 unsigned LastAddedFieldIndex;
1024class ConstructorMemcpyizer :
public FieldMemcpyizer {
1028 static const VarDecl *getTrivialCopySource(CodeGenFunction &CGF,
1029 const CXXConstructorDecl *CD,
1030 FunctionArgList &Args) {
1038 bool isMemberInitMemcpyable(CXXCtorInitializer *MemberInit)
const {
1039 if (!MemcpyableCtor)
1042 assert(Field &&
"No field for member init.");
1043 QualType FieldType =
Field->getType();
1044 CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(MemberInit->
getInit());
1053 if (!isMemcpyableField(Field))
1061 ConstructorMemcpyizer(CodeGenFunction &CGF,
const CXXConstructorDecl *CD,
1062 FunctionArgList &Args)
1063 : FieldMemcpyizer(CGF, CD->getParent(),
1064 getTrivialCopySource(CGF, CD, Args)),
1065 ConstructorDecl(CD),
1066 MemcpyableCtor(CD->isDefaulted() && CD->isCopyOrMoveConstructor() &&
1067 CGF.getLangOpts().getGC() == LangOptions::NonGC),
1070 void addMemberInitializer(CXXCtorInitializer *MemberInit) {
1071 if (isMemberInitMemcpyable(MemberInit)) {
1072 AggregatedInits.push_back(MemberInit);
1073 addMemcpyableField(MemberInit->
getMember());
1075 emitAggregatedInits();
1077 ConstructorDecl, Args);
1081 void emitAggregatedInits() {
1082 if (AggregatedInits.size() <= 1) {
1085 if (!AggregatedInits.empty()) {
1086 CopyingValueRepresentation CVR(CGF);
1088 AggregatedInits[0], ConstructorDecl, Args);
1089 AggregatedInits.clear();
1095 pushEHDestructors();
1098 AggregatedInits.clear();
1101 void pushEHDestructors() {
1106 for (
unsigned i = 0; i < AggregatedInits.size(); ++i) {
1107 CXXCtorInitializer *MemberInit = AggregatedInits[i];
1112 LValue FieldLHS = LHS;
1114 CGF.
pushEHDestroy(dtorKind, FieldLHS.getAddress(), FieldType);
1118 void finish() { emitAggregatedInits(); }
1121 const CXXConstructorDecl *ConstructorDecl;
1122 bool MemcpyableCtor;
1123 FunctionArgList &Args;
1124 SmallVector<CXXCtorInitializer *, 16> AggregatedInits;
1127class AssignmentMemcpyizer :
public FieldMemcpyizer {
1131 FieldDecl *getMemcpyableField(Stmt *S) {
1132 if (!AssignmentsMemcpyable)
1134 if (BinaryOperator *BO = dyn_cast<BinaryOperator>(S)) {
1136 if (BO->getOpcode() != BO_Assign)
1138 MemberExpr *ME = dyn_cast<MemberExpr>(BO->getLHS());
1142 if (!Field || !isMemcpyableField(Field))
1144 Stmt *RHS = BO->getRHS();
1145 if (ImplicitCastExpr *EC = dyn_cast<ImplicitCastExpr>(RHS))
1146 RHS = EC->getSubExpr();
1149 if (MemberExpr *ME2 = dyn_cast<MemberExpr>(RHS)) {
1150 if (ME2->getMemberDecl() == Field)
1154 }
else if (CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(S)) {
1155 CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MCE->getCalleeDecl());
1158 MemberExpr *IOA = dyn_cast<MemberExpr>(MCE->getImplicitObjectArgument());
1162 if (!Field || !isMemcpyableField(Field))
1164 MemberExpr *Arg0 = dyn_cast<MemberExpr>(MCE->getArg(0));
1165 if (!Arg0 || Field != dyn_cast<FieldDecl>(Arg0->
getMemberDecl()))
1168 }
else if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
1169 FunctionDecl *FD = dyn_cast<FunctionDecl>(CE->getCalleeDecl());
1170 if (!FD || FD->
getBuiltinID() != Builtin::BI__builtin_memcpy)
1172 Expr *DstPtr = CE->
getArg(0);
1173 if (ImplicitCastExpr *DC = dyn_cast<ImplicitCastExpr>(DstPtr))
1174 DstPtr = DC->getSubExpr();
1175 UnaryOperator *DUO = dyn_cast<UnaryOperator>(DstPtr);
1176 if (!DUO || DUO->
getOpcode() != UO_AddrOf)
1178 MemberExpr *ME = dyn_cast<MemberExpr>(DUO->
getSubExpr());
1182 if (!Field || !isMemcpyableField(Field))
1184 Expr *SrcPtr = CE->
getArg(1);
1185 if (ImplicitCastExpr *SC = dyn_cast<ImplicitCastExpr>(SrcPtr))
1186 SrcPtr = SC->getSubExpr();
1187 UnaryOperator *SUO = dyn_cast<UnaryOperator>(SrcPtr);
1188 if (!SUO || SUO->
getOpcode() != UO_AddrOf)
1190 MemberExpr *ME2 = dyn_cast<MemberExpr>(SUO->
getSubExpr());
1191 if (!ME2 || Field != dyn_cast<FieldDecl>(ME2->
getMemberDecl()))
1199 bool AssignmentsMemcpyable;
1200 SmallVector<Stmt *, 16> AggregatedStmts;
1203 AssignmentMemcpyizer(CodeGenFunction &CGF,
const CXXMethodDecl *AD,
1204 FunctionArgList &Args)
1205 : FieldMemcpyizer(CGF, AD->getParent(), Args[Args.size() - 1]),
1206 AssignmentsMemcpyable(CGF.getLangOpts().getGC() == LangOptions::NonGC) {
1207 assert(Args.size() == 2);
1210 void emitAssignment(Stmt *S) {
1211 FieldDecl *F = getMemcpyableField(S);
1213 addMemcpyableField(F);
1214 AggregatedStmts.push_back(S);
1216 emitAggregatedStmts();
1221 void emitAggregatedStmts() {
1222 if (AggregatedStmts.size() <= 1) {
1223 if (!AggregatedStmts.empty()) {
1224 CopyingValueRepresentation CVR(CGF);
1232 AggregatedStmts.clear();
1235 void finish() { emitAggregatedStmts(); }
1261 bool ConstructVBases = CtorType !=
Ctor_Base &&
1268 llvm::BasicBlock *BaseCtorContinueBB =
nullptr;
1269 if (ConstructVBases &&
1270 !
CGM.getTarget().getCXXABI().hasConstructorVariants()) {
1271 BaseCtorContinueBB =
1272 CGM.getCXXABI().EmitCtorCompleteObjectHandler(*
this, ClassDecl);
1273 assert(BaseCtorContinueBB);
1277 auto AllInits = CD->
inits();
1280 auto VirtualBaseEnd = std::find_if(
1282 return !(Init->isBaseInitializer() && Init->isBaseVirtual());
1285 auto NonVirtualBaseEnd = std::find_if(VirtualBaseEnd, AllInits.end(),
1287 return !Init->isBaseInitializer();
1291 auto VirtualBaseInits = llvm::make_range(AllInits.begin(), VirtualBaseEnd);
1292 auto NonVirtualBaseInits =
1293 llvm::make_range(VirtualBaseEnd, NonVirtualBaseEnd);
1294 auto MemberInits = llvm::make_range(NonVirtualBaseEnd, AllInits.end());
1297 if (ConstructVBases) {
1300 if (
CGM.getCodeGenOpts().StrictVTablePointers &&
1301 CGM.getCodeGenOpts().OptimizationLevel > 0 &&
1308 if (BaseCtorContinueBB) {
1310 Builder.CreateBr(BaseCtorContinueBB);
1318 if (
CGM.getCodeGenOpts().StrictVTablePointers &&
1319 CGM.getCodeGenOpts().OptimizationLevel > 0 &&
1329 ConstructorMemcpyizer CM(*
this, CD, Args);
1331 assert(!
Member->isBaseInitializer());
1332 assert(
Member->isAnyMemberInitializer() &&
1333 "Delegating initializer on non-delegating constructor");
1334 CM.addMemberInitializer(
Member);
1355 for (
const auto *Field : BaseClassDecl->
fields())
1360 for (
const auto &I : BaseClassDecl->
bases()) {
1366 MostDerivedClassDecl))
1370 if (BaseClassDecl == MostDerivedClassDecl) {
1372 for (
const auto &I : BaseClassDecl->
vbases()) {
1373 const auto *
VirtualBase = I.getType()->castAsCXXRecordDecl();
1384 QualType FieldBaseElementType = Context.getBaseElementType(Field->getType());
1387 if (!FieldClassDecl)
1391 if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
1414 for (
const auto *Field : ClassDecl->
fields())
1423 llvm::Value *ShouldDeleteCondition) {
1426 llvm::BasicBlock *callDeleteBB =
1430 llvm::Value *CheckTheBitForArrayDestroy = CGF.
Builder.CreateAnd(
1431 ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 2));
1432 llvm::Value *ShouldDestroyArray =
1434 CGF.
Builder.CreateCondBr(ShouldDestroyArray, ScalarBB, VectorBB);
1438 llvm::Value *numElements =
nullptr;
1439 llvm::Value *allocatedPtr =
nullptr;
1443 allocatedPtr, cookieSize);
1449 assert(numElements &&
"no element count for a type with a destructor!");
1457 ThisPtr.
getElementType(), arrayBegin, numElements,
"delete.end");
1468 llvm::Value *CheckTheBitForDeleteCall = CGF.
Builder.CreateAnd(
1469 ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 1));
1471 llvm::Value *ShouldCallDelete =
1482 numElements, cookieSize);
1487 llvm::Value *CheckTheBitForGlobDeleteCall = CGF.
Builder.CreateAnd(
1488 ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 4));
1490 llvm::Value *ShouldCallGlobDelete =
1492 llvm::BasicBlock *GlobDelete =
1494 llvm::BasicBlock *ClassDelete =
1496 CGF.
Builder.CreateCondBr(ShouldCallGlobDelete, ClassDelete, GlobDelete);
1500 numElements, cookieSize);
1506 numElements, cookieSize);
1510 llvm::CallInst *TrapCall = CGF.
EmitTrapCall(llvm::Intrinsic::trap);
1511 TrapCall->setDoesNotReturn();
1512 TrapCall->setDoesNotThrow();
1513 CGF.
Builder.CreateUnreachable();
1514 CGF.
Builder.ClearInsertionPoint();
1532 llvm::CallInst *TrapCall =
EmitTrapCall(llvm::Intrinsic::trap);
1533 TrapCall->setDoesNotReturn();
1534 TrapCall->setDoesNotThrow();
1536 Builder.ClearInsertionPoint();
1565 bool isTryBody = isa_and_nonnull<CXXTryStmt>(Body);
1580 llvm_unreachable(
"not expecting a unified dtor");
1582 llvm_unreachable(
"not expecting a COMDAT");
1584 llvm_unreachable(
"already handled deleting case");
1586 llvm_unreachable(
"already handled vector deleting case");
1589 assert((Body ||
getTarget().getCXXABI().isMicrosoft()) &&
1590 "can't emit a dtor without a body for non-Microsoft ABIs");
1615 if (
CGM.getCodeGenOpts().StrictVTablePointers &&
1616 CGM.getCodeGenOpts().OptimizationLevel > 0)
1626 assert(Dtor->
isImplicit() &&
"bodyless dtor not implicit");
1632 CurFn->addFnAttr(llvm::Attribute::AlwaysInline);
1650 "Body of an implicit assignment operator should be compound stmt.");
1657 AssignmentMemcpyizer AM(*
this, AssignOp, Args);
1658 for (
auto *I : RootCS->
body())
1659 AM.emitAssignment(I);
1673struct CallDtorDelete final : EHScopeStack::Cleanup {
1680 LoadThisForDtorDelete(CGF, Dtor),
1691 llvm::Value *ShouldDeleteCondition,
1692 bool ReturnAfterDelete) {
1694 const CXXRecordDecl *ClassDecl = Dtor->
getParent();
1697 "unexpected value for ReturnAfterDelete");
1712 llvm::Value *Check3rdBit = CGF.
Builder.CreateAnd(
1713 ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 4));
1715 CGF.
Builder.CreateCondBr(ShouldCallDtor, DontCallDtor, CallDtor);
1721 CGF.
Builder.CreateBr(DontCallDtor);
1727 llvm::Value *Check1stBit = CGF.
Builder.CreateAnd(
1728 ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 1));
1730 CGF.
Builder.CreateCondBr(ShouldCallDelete, continueBB, callDeleteBB);
1733 auto EmitDeleteAndGoToEnd = [&](
const FunctionDecl *DeleteOp) {
1736 if (ReturnAfterDelete)
1739 CGF.
Builder.CreateBr(continueBB);
1748 llvm::Value *CheckTheBitForGlobDeleteCall = CGF.
Builder.CreateAnd(
1749 ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 4));
1750 llvm::Value *ShouldCallGlobDelete =
1752 llvm::BasicBlock *GlobDelete =
1754 llvm::BasicBlock *ClassDelete =
1756 CGF.
Builder.CreateCondBr(ShouldCallGlobDelete, ClassDelete, GlobDelete);
1759 EmitDeleteAndGoToEnd(GlobOD);
1762 EmitDeleteAndGoToEnd(OD);
1766struct CallDtorDeleteConditional final : EHScopeStack::Cleanup {
1767 llvm::Value *ShouldDeleteCondition;
1770 CallDtorDeleteConditional(llvm::Value *ShouldDeleteCondition)
1771 : ShouldDeleteCondition(ShouldDeleteCondition) {
1772 assert(ShouldDeleteCondition !=
nullptr);
1775 void Emit(CodeGenFunction &CGF, Flags flags)
override {
1776 EmitConditionalDtorDeleteCall(CGF, ShouldDeleteCondition,
1781class DestroyField final :
public EHScopeStack::Cleanup {
1782 const FieldDecl *field;
1784 bool useEHCleanupForArray;
1788 bool useEHCleanupForArray)
1789 : field(field), destroyer(destroyer),
1790 useEHCleanupForArray(useEHCleanupForArray) {}
1792 void Emit(CodeGenFunction &CGF, Flags flags)
override {
1799 assert(LV.isSimple());
1801 CGF.
emitDestroy(LV.getAddress(), field->getType(), destroyer,
1802 flags.isForNormalCleanup() && useEHCleanupForArray);
1806class DeclAsInlineDebugLocation {
1808 llvm::MDNode *InlinedAt;
1809 std::optional<ApplyDebugLocation> Location;
1812 DeclAsInlineDebugLocation(CodeGenFunction &CGF,
const NamedDecl &
Decl)
1813 : DI(CGF.getDebugInfo()) {
1818 Location.emplace(CGF,
Decl.getLocation());
1821 ~DeclAsInlineDebugLocation() {
1829static void EmitSanitizerDtorCallback(
1831 std::optional<CharUnits::QuantityType> PoisonSize = {}) {
1835 SmallVector<llvm::Value *, 2> Args = {Ptr};
1836 SmallVector<llvm::Type *, 2> ArgTypes = {CGF.
VoidPtrTy};
1838 if (PoisonSize.has_value()) {
1839 Args.emplace_back(llvm::ConstantInt::get(CGF.
SizeTy, *PoisonSize));
1840 ArgTypes.emplace_back(CGF.
SizeTy);
1843 llvm::FunctionType *FnType =
1844 llvm::FunctionType::get(CGF.
VoidTy, ArgTypes,
false);
1851EmitSanitizerDtorFieldsCallback(
CodeGenFunction &CGF, llvm::Value *Ptr,
1853 EmitSanitizerDtorCallback(CGF,
"__sanitizer_dtor_callback_fields", Ptr,
1858struct SanitizeDtorTrivialBase final : EHScopeStack::Cleanup {
1859 const CXXRecordDecl *BaseClass;
1861 SanitizeDtorTrivialBase(
const CXXRecordDecl *Base,
bool BaseIsVirtual)
1862 : BaseClass(
Base), BaseIsVirtual(BaseIsVirtual) {}
1864 void Emit(CodeGenFunction &CGF, Flags flags)
override {
1865 const CXXRecordDecl *DerivedClass =
1871 const ASTRecordLayout &BaseLayout =
1873 CharUnits BaseSize = BaseLayout.
getSize();
1880 DeclAsInlineDebugLocation InlineHere(CGF, *BaseClass);
1881 EmitSanitizerDtorFieldsCallback(CGF,
Addr.emitRawPointer(CGF),
1885 CGF.
CurFn->addFnAttr(
"disable-tail-calls",
"true");
1889class SanitizeDtorFieldRange final :
public EHScopeStack::Cleanup {
1890 const CXXDestructorDecl *Dtor;
1891 unsigned StartIndex;
1895 SanitizeDtorFieldRange(
const CXXDestructorDecl *Dtor,
unsigned StartIndex,
1897 : Dtor(Dtor), StartIndex(StartIndex), EndIndex(EndIndex) {}
1902 void Emit(CodeGenFunction &CGF, Flags flags)
override {
1903 const ASTContext &Context = CGF.
getContext();
1904 const ASTRecordLayout &Layout =
1911 llvm::ConstantInt *OffsetSizePtr =
1914 llvm::Value *OffsetPtr =
1917 CharUnits PoisonEnd;
1923 CharUnits PoisonSize = PoisonEnd - PoisonStart;
1928 DeclAsInlineDebugLocation InlineHere(
1929 CGF, **std::next(Dtor->getParent()->field_begin(), StartIndex));
1930 EmitSanitizerDtorFieldsCallback(CGF, OffsetPtr, PoisonSize.
getQuantity());
1933 CGF.
CurFn->addFnAttr(
"disable-tail-calls",
"true");
1937class SanitizeDtorVTable final :
public EHScopeStack::Cleanup {
1938 const CXXDestructorDecl *Dtor;
1941 SanitizeDtorVTable(
const CXXDestructorDecl *Dtor) : Dtor(Dtor) {}
1944 void Emit(CodeGenFunction &CGF, Flags flags)
override {
1945 assert(Dtor->getParent()->isDynamicClass());
1952 EmitSanitizerDtorCallback(CGF,
"__sanitizer_dtor_callback_vptr", VTablePtr);
1956class SanitizeDtorCleanupBuilder {
1957 ASTContext &Context;
1958 EHScopeStack &EHStack;
1959 const CXXDestructorDecl *DD;
1960 std::optional<unsigned> StartIndex;
1963 SanitizeDtorCleanupBuilder(ASTContext &Context, EHScopeStack &EHStack,
1964 const CXXDestructorDecl *DD)
1965 : Context(Context), EHStack(EHStack), DD(DD), StartIndex(std::nullopt) {}
1966 void PushCleanupForField(
const FieldDecl *Field) {
1969 unsigned FieldIndex =
Field->getFieldIndex();
1972 StartIndex = FieldIndex;
1973 }
else if (StartIndex) {
1975 *StartIndex, FieldIndex);
1976 StartIndex = std::nullopt;
1996 "Should not emit dtor epilogue for non-exported trivial dtor!");
2002 "operator delete missing - EnterDtorCleanups");
2003 if (CXXStructorImplicitParamValue) {
2007 EmitConditionalDtorDeleteCall(*
this, CXXStructorImplicitParamValue,
2010 EHStack.pushCleanup<CallDtorDeleteConditional>(
2016 LoadThisForDtorDelete(*
this, DD),
2017 getContext().getCanonicalTagType(ClassDecl));
2036 if (
CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor &&
2043 for (
const auto &
Base : ClassDecl->
vbases()) {
2044 auto *BaseClassDecl =
Base.getType()->castAsCXXRecordDecl();
2045 if (BaseClassDecl->hasTrivialDestructor()) {
2049 if (
CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor &&
2050 SanOpts.has(SanitizerKind::Memory) && !BaseClassDecl->isEmpty())
2066 if (
CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor &&
2072 for (
const auto &
Base : ClassDecl->
bases()) {
2074 if (
Base.isVirtual())
2080 if (
CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor &&
2093 bool SanitizeFields =
CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor &&
2094 SanOpts.has(SanitizerKind::Memory);
2098 for (
const auto *Field : ClassDecl->
fields()) {
2100 SanitizeBuilder.PushCleanupForField(Field);
2108 const RecordType *RT =
type->getAsUnionType();
2109 if (RT && RT->getDecl()->isAnonymousStructOrUnion())
2113 EHStack.pushCleanup<DestroyField>(
2118 SanitizeBuilder.End();
2133 bool NewPointerIsChecked,
2134 bool zeroInitialize) {
2136 llvm::Value *numElements =
2140 NewPointerIsChecked, zeroInitialize);
2154 const CXXConstructExpr *E,
bool NewPointerIsChecked,
bool zeroInitialize) {
2160 llvm::BranchInst *zeroCheckBranch =
nullptr;
2163 llvm::ConstantInt *constantCount = dyn_cast<llvm::ConstantInt>(numElements);
2164 if (constantCount) {
2166 if (constantCount->isZero())
2172 llvm::Value *iszero =
Builder.CreateIsNull(numElements,
"isempty");
2173 zeroCheckBranch =
Builder.CreateCondBr(iszero, loopBB, loopBB);
2180 llvm::Value *arrayEnd =
Builder.CreateInBoundsGEP(
2181 elementType, arrayBegin, numElements,
"arrayctor.end");
2184 llvm::BasicBlock *entryBB =
Builder.GetInsertBlock();
2187 llvm::PHINode *cur =
2188 Builder.CreatePHI(arrayBegin->getType(), 2,
"arrayctor.cur");
2189 cur->addIncoming(arrayBegin, entryBB);
2192 if (
CGM.shouldEmitConvergenceTokens())
2240 llvm::Value *next =
Builder.CreateInBoundsGEP(
2241 elementType, cur, llvm::ConstantInt::get(
SizeTy, 1),
"arrayctor.next");
2242 cur->addIncoming(next,
Builder.GetInsertBlock());
2245 llvm::Value *done =
Builder.CreateICmpEQ(next, arrayEnd,
"arrayctor.done");
2247 Builder.CreateCondBr(done, contBB, loopBB);
2250 if (zeroCheckBranch)
2251 zeroCheckBranch->setSuccessor(0, contBB);
2253 if (
CGM.shouldEmitConvergenceTokens())
2274 llvm::Value *ThisPtr =
2277 if (SlotAS != ThisAS) {
2279 llvm::Type *NewType =
2292 assert(E->
getNumArgs() == 1 &&
"unexpected argcount for trivial ctor");
2343 bool NewPointerIsChecked, llvm::CallBase **CallOrInvoke) {
2346 if (!NewPointerIsChecked)
2352 assert(Args.size() == 1 &&
"trivial default ctor with args");
2360 assert(Args.size() == 2 &&
"unexpected argcount for trivial ctor");
2363 Args[1].getRValue(*this).getScalarVal(), SrcTy);
2371 bool PassPrototypeArgs =
true;
2384 CGM.getCXXABI().addImplicitConstructorArgs(*
this, D,
Type, ForVirtualBase,
2406 if (
CGM.getCodeGenOpts().OptimizationLevel > 0 &&
2408 CGM.getCXXABI().canSpeculativelyEmitVTable(ClassDecl) &&
2409 CGM.getCodeGenOpts().StrictVTablePointers)
2422 if (InheritedFromVBase &&
2423 CGM.getTarget().getCXXABI().hasConstructorVariants()) {
2428 Args.push_back(ThisArg);
2429 }
else if (!CXXInheritedCtorInitExprArgs.empty()) {
2431 assert(CXXInheritedCtorInitExprArgs.size() >= D->
getNumParams() &&
2432 "wrong number of parameters for inherited constructor call");
2433 Args = CXXInheritedCtorInitExprArgs;
2437 Args.push_back(ThisArg);
2439 assert(OuterCtor->getNumParams() == D->
getNumParams());
2440 assert(!OuterCtor->isVariadic() &&
"should have been inlined");
2442 for (
const auto *Param : OuterCtor->parameters()) {
2444 OuterCtor->getParamDecl(Param->getFunctionScopeIndex())->getType(),
2449 if (Param->hasAttr<PassObjectSizeAttr>()) {
2450 auto *POSParam = SizeArguments[Param];
2451 assert(POSParam &&
"missing pass_object_size value for forwarding");
2471 CXXInheritedCtorInitExprArgs = Args;
2478 CGM.getCXXABI().addImplicitConstructorArgs(*
this, Ctor, CtorType,
2482 assert(Args.size() >= Params.size() &&
"too few arguments for call");
2483 for (
unsigned I = 0, N = Args.size(); I != N; ++I) {
2485 const RValue &RV = Args[I].getRValue(*
this);
2486 assert(!RV.
isComplex() &&
"complex indirect params not supported");
2500 CGM.getCXXABI().EmitInstanceFunctionProlog(*
this);
2501 CXXThisValue = CXXABIThisValue;
2508 llvm::Value *VTableGlobal =
2516 if (!NonVirtualOffset.
isZero())
2521 llvm::Value *VPtrValue =
2524 Builder.CreateICmpEQ(VPtrValue, VTableGlobal,
"cmp.vtables");
2525 Builder.CreateAssumption(Cmp);
2530 if (
CGM.getCXXABI().doStructorsInitializeVPtrs(ClassDecl))
2548 llvm::Type *t =
CGM.getTypes().ConvertType(QT);
2550 llvm::Value *SrcVal =
Builder.CreateBitCast(Val, t);
2568 FunctionArgList::const_iterator I = Args.begin(), E = Args.end();
2569 assert(I != E &&
"no parameters to constructor");
2574 This, (*I)->getType()->getPointeeType())),
2580 if (
CGM.getCXXABI().NeedsVTTParameter(
CurGD)) {
2581 assert(I != E &&
"cannot skip vtt parameter, already done with args");
2582 assert((*I)->getType()->isPointerType() &&
2583 "skipping parameter not of vtt type");
2588 for (; I != E; ++I) {
2595 true,
This, DelegateArgs,
2601struct CallDelegatingCtorDtor final : EHScopeStack::Cleanup {
2613 QualType ThisTy = Dtor->getFunctionObjectParameterType();
2615 true,
Addr, ThisTy);
2640 EHStack.pushCleanup<CallDelegatingCtorDtor>(
2647 bool ForVirtualBase,
2650 CGM.getCXXABI().EmitDestructorCall(*
this, DD,
Type, ForVirtualBase,
2655struct CallLocalDtor final : EHScopeStack::Cleanup {
2684 assert(D && D->
isUsed() &&
"destructor not marked as used!");
2690 llvm::Value *VTableAddressPoint =
2691 CGM.getCXXABI().getVTableAddressPointInStructor(
2694 if (!VTableAddressPoint)
2698 llvm::Value *VirtualOffset =
nullptr;
2701 if (
CGM.getCXXABI().isVirtualOffsetNeededForVTableField(*
this, Vptr)) {
2705 VirtualOffset =
CGM.getCXXABI().GetVirtualBaseClassOffset(
2715 if (!NonVirtualOffset.
isZero() || VirtualOffset)
2717 *
this, VTableField, NonVirtualOffset, VirtualOffset, Vptr.
VTableClass,
2722 unsigned GlobalsAS =
CGM.getDataLayout().getDefaultGlobalsAddressSpace();
2723 llvm::Type *PtrTy = llvm::PointerType::get(
CGM.getLLVMContext(), GlobalsAS);
2728 if (
auto AuthenticationInfo =
CGM.getVTablePointerAuthInfo(
2730 VTableAddressPoint =
2733 llvm::StoreInst *Store =
Builder.CreateStore(VTableAddressPoint, VTableField);
2735 CGM.DecorateInstructionWithTBAA(Store, TBAAInfo);
2736 if (
CGM.getCodeGenOpts().OptimizationLevel > 0 &&
2737 CGM.getCodeGenOpts().StrictVTablePointers)
2738 CGM.DecorateInstructionWithInvariantGroup(Store, Vptr.
VTableClass);
2748 false, VTableClass, VBases,
2756 bool BaseIsNonVirtualPrimaryBase,
2762 if (!BaseIsNonVirtualPrimaryBase) {
2764 VPtr Vptr = {
Base, NearestVBase, OffsetFromNearestVBase, VTableClass};
2765 Vptrs.push_back(Vptr);
2771 for (
const auto &I : RD->
bases()) {
2772 auto *BaseDecl = I.getType()->castAsCXXRecordDecl();
2774 if (!BaseDecl->isDynamicClass())
2779 bool BaseDeclIsNonVirtualPrimaryBase;
2781 if (I.isVirtual()) {
2783 if (!VBases.insert(BaseDecl).second)
2791 BaseDeclIsNonVirtualPrimaryBase =
false;
2796 BaseOffsetFromNearestVBase =
2798 BaseDeclIsNonVirtualPrimaryBase = Layout.
getPrimaryBase() == BaseDecl;
2803 I.isVirtual() ? BaseDecl : NearestVBase, BaseOffsetFromNearestVBase,
2804 BaseDeclIsNonVirtualPrimaryBase, VTableClass, VBases, Vptrs);
2814 if (
CGM.getCXXABI().doStructorsInitializeVPtrs(RD))
2819 CGM.getCXXABI().initializeHiddenVirtualInheritanceMembers(*
this, RD);
2825 Address VTablePtrSrc =
This.withElementType(VTableTy);
2826 llvm::Instruction *VTable =
Builder.CreateLoad(VTablePtrSrc,
"vtable");
2828 CGM.DecorateInstructionWithTBAA(VTable, TBAAInfo);
2830 if (
auto AuthenticationInfo =
2831 CGM.getVTablePointerAuthInfo(
this, RD,
This.emitRawPointer(*
this))) {
2852 if (
CGM.getCodeGenOpts().OptimizationLevel > 0 &&
2853 CGM.getCodeGenOpts().StrictVTablePointers)
2854 CGM.DecorateInstructionWithInvariantGroup(VTable, RD);
2895 llvm::Value *VTable,
2897 if (
SanOpts.has(SanitizerKind::CFIVCall))
2905 else if ((
CGM.getCodeGenOpts().WholeProgramVTables &&
2906 !
CGM.AlwaysHasLTOVisibilityPublic(RD)) ||
2907 CGM.getCodeGenOpts().DevirtualizeSpeculatively) {
2909 llvm::Metadata *MD =
CGM.CreateMetadataIdentifierForType(Ty);
2910 llvm::Value *TypeId = llvm::MetadataAsValue::get(
CGM.getLLVMContext(), MD);
2916 llvm::Intrinsic::ID IID =
CGM.HasHiddenLTOVisibility(RD)
2917 ? llvm::Intrinsic::type_test
2918 : llvm::Intrinsic::public_type_test;
2919 llvm::Value *TypeTest =
2920 Builder.CreateCall(
CGM.getIntrinsic(IID), {VTable, TypeId});
2921 Builder.CreateCall(
CGM.getIntrinsic(llvm::Intrinsic::assume), TypeTest);
2927static std::pair<SanitizerKind::SanitizerOrdinal, llvm::SanitizerStatKind>
2931 return std::make_pair(SanitizerKind::SO_CFIVCall, llvm::SanStat_CFI_VCall);
2933 return std::make_pair(SanitizerKind::SO_CFINVCall,
2934 llvm::SanStat_CFI_NVCall);
2936 return std::make_pair(SanitizerKind::SO_CFIDerivedCast,
2937 llvm::SanStat_CFI_DerivedCast);
2939 return std::make_pair(SanitizerKind::SO_CFIUnrelatedCast,
2940 llvm::SanStat_CFI_UnrelatedCast);
2944 llvm_unreachable(
"unexpected sanitizer kind");
2946 llvm_unreachable(
"Unknown CFITypeCheckKind enum");
2950 llvm::Value *VTable,
2953 if (!
SanOpts.has(SanitizerKind::CFICastStrict))
2958 SanitizerHandler::CFICheckFail);
2970 const auto *ClassDecl =
T->getAsCXXRecordDecl();
2977 if (!
SanOpts.has(SanitizerKind::CFICastStrict))
2982 SanitizerHandler::CFICheckFail);
2984 llvm::BasicBlock *ContBlock =
nullptr;
2987 llvm::Value *DerivedNotNull =
2993 Builder.CreateCondBr(DerivedNotNull, CheckBlock, ContBlock);
2998 llvm::Value *VTable;
2999 std::tie(VTable, ClassDecl) =
3000 CGM.getCXXABI().LoadVTablePtr(*
this, Derived, ClassDecl);
3011 llvm::Value *VTable,
3016 if (!
CGM.getCodeGenOpts().SanitizeCfiCrossDso &&
3017 !
CGM.HasHiddenLTOVisibility(RD))
3023 if (
getContext().getNoSanitizeList().containsType(
3030 llvm::Metadata *MD =
CGM.CreateMetadataIdentifierForType(
T);
3031 llvm::Value *TypeId = llvm::MetadataAsValue::get(
getLLVMContext(), MD);
3033 llvm::Value *TypeTest =
Builder.CreateCall(
3034 CGM.getIntrinsic(llvm::Intrinsic::type_test), {VTable, TypeId});
3036 llvm::Constant *StaticData[] = {
3037 llvm::ConstantInt::get(
Int8Ty, TCK),
3042 auto CrossDsoTypeId =
CGM.CreateCrossDsoCfiTypeId(MD);
3043 if (
CGM.getCodeGenOpts().SanitizeCfiCrossDso && CrossDsoTypeId) {
3048 if (
CGM.getCodeGenOpts().SanitizeTrap.has(M)) {
3049 bool NoMerge = !
CGM.getCodeGenOpts().SanitizeMergeHandlers.has(M);
3050 EmitTrapCheck(TypeTest, SanitizerHandler::CFICheckFail, NoMerge);
3054 llvm::Value *AllVtables = llvm::MetadataAsValue::get(
3055 CGM.getLLVMContext(),
3056 llvm::MDString::get(
CGM.getLLVMContext(),
"all-vtables"));
3057 llvm::Value *ValidVtable =
Builder.CreateCall(
3058 CGM.getIntrinsic(llvm::Intrinsic::type_test), {VTable, AllVtables});
3059 EmitCheck(std::make_pair(TypeTest, M), SanitizerHandler::CFICheckFail,
3060 StaticData, {VTable, ValidVtable});
3064 if ((!
CGM.getCodeGenOpts().WholeProgramVTables ||
3065 !
CGM.HasHiddenLTOVisibility(RD)) &&
3066 !
CGM.getCodeGenOpts().DevirtualizeSpeculatively)
3069 if (
CGM.getCodeGenOpts().VirtualFunctionElimination)
3072 if (!
SanOpts.has(SanitizerKind::CFIVCall) ||
3073 !
CGM.getCodeGenOpts().SanitizeTrap.has(SanitizerKind::CFIVCall))
3082 const CXXRecordDecl *RD, llvm::Value *VTable, llvm::Type *VTableTy,
3083 uint64_t VTableByteOffset) {
3084 auto CheckOrdinal = SanitizerKind::SO_CFIVCall;
3085 auto CheckHandler = SanitizerHandler::CFICheckFail;
3091 llvm::Metadata *MD =
CGM.CreateMetadataIdentifierForType(
T);
3092 llvm::Value *TypeId = llvm::MetadataAsValue::get(
CGM.getLLVMContext(), MD);
3094 auto CheckedLoadIntrinsic =
CGM.getVTables().useRelativeLayout()
3095 ? llvm::Intrinsic::type_checked_load_relative
3096 : llvm::Intrinsic::type_checked_load;
3097 llvm::Value *CheckedLoad =
Builder.CreateCall(
3098 CGM.getIntrinsic(CheckedLoadIntrinsic),
3099 {VTable, llvm::ConstantInt::get(Int32Ty, VTableByteOffset), TypeId});
3101 llvm::Value *CheckResult =
Builder.CreateExtractValue(CheckedLoad, 1);
3104 if (
SanOpts.has(SanitizerKind::CFIVCall) &&
3105 !
getContext().getNoSanitizeList().containsType(SanitizerKind::CFIVCall,
3107 EmitCheck(std::make_pair(CheckResult, CheckOrdinal), CheckHandler, {}, {});
3110 return Builder.CreateBitCast(
Builder.CreateExtractValue(CheckedLoad, 0),
3119 calleeFnInfo = &
CGM.getTypes().arrangeCXXMethodDeclaration(callOperator);
3124 CGM.getTypes().GetFunctionType(*calleeFnInfo));
3131 if (!resultType->isVoidType() &&
3144 RValue RV =
EmitCall(*calleeFnInfo, callee, returnSlot, callArgs);
3147 if (!resultType->isVoidType() && returnSlot.
isNull()) {
3148 if (
getLangOpts().ObjCAutoRefCount && resultType->isObjCRetainableType()) {
3151 EmitReturnOfRValue(RV, resultType);
3162 if (CallOp->isVariadic()) {
3166 CGM.ErrorUnsupported(
CurCodeDecl,
"lambda conversion to variadic function");
3183 "generic lambda interconversion to block not implemented");
3192 CGM.ErrorUnsupported(MD,
"lambda conversion to variadic function");
3223 CallOp->getDescribedFunctionTemplate();
3224 void *InsertPos =
nullptr;
3227 assert(CorrespondingCallOpSpecialization);
3232 if (hasInAllocaArg(MD)) {
3234 llvm::Function *ImplFn =
nullptr;
3249 CGM.ErrorUnsupported(MD,
"lambda conversion to variadic function");
3257 llvm::Value *ThisArg =
CurFn->getArg(0);
3265 llvm::Function **ImplFn) {
3267 CGM.getTypes().arrangeCXXMethodDeclaration(CallOp);
3268 llvm::Function *CallOpFn =
3275 ArgTypes.push_back(I->type);
3276 *ImplFnInfo = &
CGM.getTypes().arrangeLLVMFunctionInfo(
3285 StringRef CallOpName = CallOpFn->getName();
3286 std::string ImplName;
3287 if (
size_t Pos = CallOpName.find_first_of(
"<lambda"))
3288 ImplName = (
"?__impl@" + CallOpName.drop_front(Pos)).str();
3290 ImplName = (
"__impl" + CallOpName).str();
3292 llvm::Function *Fn = CallOpFn->getParent()->getFunction(ImplName);
3294 Fn = llvm::Function::Create(
CGM.getTypes().GetFunctionType(**ImplFnInfo),
3295 llvm::GlobalValue::InternalLinkage, ImplName,
3297 CGM.SetInternalFunctionAttributes(CallOp, Fn, **ImplFnInfo);
3301 CodeGenFunction(
CGM).GenerateCode(GD, Fn, **ImplFnInfo);
3302 CGM.SetLLVMFunctionAttributesForDefinition(D, Fn);
static Address ApplyNonVirtualAndVirtualOffset(CodeGenFunction &CGF, Address addr, CharUnits nonVirtualOffset, llvm::Value *virtualOffset, const CXXRecordDecl *derivedClass, const CXXRecordDecl *nearestVBase)
static bool canEmitDelegateCallArgs(CodeGenFunction &CGF, const CXXConstructorDecl *Ctor, CXXCtorType Type, CallArgList &Args)
static bool CanSkipVTablePointerInitialization(CodeGenFunction &CGF, const CXXDestructorDecl *Dtor)
CanSkipVTablePointerInitialization - Check whether we need to initialize any vtable pointers before c...
static const CXXRecordDecl * LeastDerivedClassWithSameLayout(const CXXRecordDecl *RD)
static void EmitBaseInitializer(CodeGenFunction &CGF, const CXXRecordDecl *ClassDecl, CXXCtorInitializer *BaseInit)
static bool isMemcpyEquivalentSpecialMember(const CXXMethodDecl *D)
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)
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
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
const LangOptions & getLangOpts() const
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
const NoSanitizeList & getNoSanitizeList() const
TypeInfoChars getTypeInfoDataSizeInChars(QualType T) const
int64_t toBits(CharUnits CharSize) const
Convert a size in characters to a size in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
const TargetInfo & getTargetInfo() const
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
CanQualType getCanonicalTagType(const TagDecl *TD) const
unsigned getTargetAddressSpace(LangAS AS) const
uint64_t getCharWidth() const
Return the size of the character type, in bits.
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
CharUnits getAlignment() const
getAlignment - Get the record alignment in characters.
CharUnits getSize() const
getSize - Get the record size in characters.
unsigned getFieldCount() const
getFieldCount - Get the number of fields in the layout.
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const
getVBaseClassOffset - Get the offset, in chars, for the given base class.
const CXXRecordDecl * getPrimaryBase() const
getPrimaryBase - Get the primary base for this record.
CharUnits getNonVirtualSize() const
getNonVirtualSize - Get the non-virtual size (in chars) of an object, which is the size of the object...
Represents an array type, per C99 6.7.5.2 - Array Declarators.
const CXXRecordDecl * getBase() const
getBase - Returns the base class declaration.
CharUnits getBaseOffset() const
getBaseOffset - Returns the base class offset.
Represents a block literal declaration, which is like an unnamed FunctionDecl.
capture_const_iterator capture_begin() const
ArrayRef< ParmVarDecl * > parameters() const
Represents a base class of a C++ class.
QualType getType() const
Retrieves the type of the base class.
Represents a call to a C++ constructor.
Expr * getArg(unsigned Arg)
Return the specified argument.
CXXConstructorDecl * getConstructor() const
Get the constructor that this expression will (ultimately) call.
bool isListInitialization() const
Whether this constructor call was written as list-initialization.
unsigned getNumArgs() const
Return the number of arguments to the constructor call.
Represents a C++ constructor within a class.
init_iterator init_begin()
Retrieve an iterator to the first initializer.
bool isDefaultConstructor() const
Whether this constructor is a default constructor (C++ [class.ctor]p5), which can be used to default-...
bool isDelegatingConstructor() const
Determine whether this constructor is a delegating constructor.
bool isCopyOrMoveConstructor(unsigned &TypeQuals) const
Determine whether this is a copy or move constructor.
InheritedConstructor getInheritedConstructor() const
Get the constructor that this inheriting constructor is based on.
Represents a C++ base or member initializer.
FieldDecl * getMember() const
If this is a member initializer, returns the declaration of the non-static data member being initiali...
Expr * getInit() const
Get the initializer.
SourceLocation getSourceLocation() const
Determine the source location of the initializer.
bool isAnyMemberInitializer() const
bool isBaseInitializer() const
Determine whether this initializer is initializing a base class.
bool isIndirectMemberInitializer() const
const Type * getBaseClass() const
If this is a base class initializer, returns the type of the base class.
FieldDecl * getAnyMember() const
IndirectFieldDecl * getIndirectMember() const
bool isBaseVirtual() const
Returns whether the base is virtual or not.
Represents a C++ destructor within a class.
const FunctionDecl * getOperatorGlobalDelete() const
const FunctionDecl * getGlobalArrayOperatorDelete() const
const FunctionDecl * getOperatorDelete() const
Expr * getOperatorDeleteThisArg() const
const FunctionDecl * getArrayOperatorDelete() const
Represents a call to an inherited base class constructor from an inheriting constructor.
SourceLocation getLocation() const LLVM_READONLY
Represents a static or instance method of a struct/union/class.
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
QualType getThisType() const
Return the type of the this pointer.
bool isMoveAssignmentOperator() const
Determine whether this is a move assignment operator.
QualType getFunctionObjectParameterType() const
bool isCopyAssignmentOperator() const
Determine whether this is a copy-assignment operator, regardless of whether it was declared implicitl...
Represents a C++ struct/union/class.
bool isEffectivelyFinal() const
Determine whether it's impossible for a class to be derived from this class.
bool isGenericLambda() const
Determine whether this class describes a generic lambda function object (i.e.
bool hasTrivialDestructor() const
Determine whether this class has a trivial destructor (C++ [class.dtor]p3)
method_range methods() const
bool isPolymorphic() const
Whether this class is polymorphic (C++ [class.virtual]), which means that the class contains or inher...
unsigned getNumBases() const
Retrieves the number of base classes of this class.
base_class_iterator bases_begin()
base_class_range vbases()
bool isAbstract() const
Determine whether this class has a pure virtual function.
bool isDynamicClass() const
bool hasDefinition() const
bool isEmpty() const
Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).
CXXDestructorDecl * getDestructor() const
Returns the destructor decl for this class.
CXXMethodDecl * getLambdaCallOperator() const
Retrieve the lambda call operator of the closure type if this is a closure type.
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
const CXXBaseSpecifier *const * path_const_iterator
CharUnits - This is an opaque type for sizes expressed in character units.
CharUnits alignmentAtOffset(CharUnits offset) const
Given that this is a non-zero alignment value, what is the alignment at the given offset?
bool isPositive() const
isPositive - Test whether the quantity is greater than zero.
bool isZero() const
isZero - Test whether the quantity equals zero.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
static CharUnits One()
One - Construct a CharUnits quantity of one.
CharUnits alignmentOfArrayElement(CharUnits elementSize) const
Given that this is the alignment of the first element of an array, return the minimum alignment of an...
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
@ Indirect
Indirect - Pass the argument indirectly via a hidden pointer with the specified alignment (0 indicate...
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
CharUnits getAlignment() const
llvm::Type * getElementType() const
Return the type of the values stored in this address.
Address withElementType(llvm::Type *ElemTy) const
Return address with different element type, but same pointer and alignment.
bool isSanitizerChecked() const
Address getAddress() const
Qualifiers getQualifiers() const
static AggValueSlot forLValue(const LValue &LV, IsDestructed_t isDestructed, NeedsGCBarriers_t needsGC, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed, IsSanitizerChecked_t isChecked=IsNotSanitizerChecked)
static AggValueSlot forAddr(Address addr, Qualifiers quals, IsDestructed_t isDestructed, NeedsGCBarriers_t needsGC, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed, IsSanitizerChecked_t isChecked=IsNotSanitizerChecked)
forAddr - Make a slot for an aggregate value.
Overlap_t mayOverlap() const
A scoped helper to set the current source atom group for CGDebugInfo::addInstToCurrentSourceAtom.
A scoped helper to set the current debug location to the specified location or preferred location of ...
A scoped helper to set the current debug location to an inlined location.
llvm::Value * CreateIsNull(Address Addr, const Twine &Name="")
Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index, const llvm::Twine &Name="")
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
llvm::CallInst * CreateMemCpy(Address Dest, Address Src, llvm::Value *Size, bool IsVolatile=false)
Address CreateInBoundsGEP(Address Addr, ArrayRef< llvm::Value * > IdxList, llvm::Type *ElementType, CharUnits Align, const Twine &Name="")
virtual size_t getSrcArgforCopyCtor(const CXXConstructorDecl *, FunctionArgList &Args) const =0
virtual void ReadArrayCookie(CodeGenFunction &CGF, Address Ptr, const CXXDeleteExpr *expr, QualType ElementType, llvm::Value *&NumElements, llvm::Value *&AllocPtr, CharUnits &CookieSize)
Reads the array cookie associated with the given pointer, if it has one.
All available information about a concrete callee.
static CGCallee forDirect(llvm::Constant *functionPtr, const CGCalleeInfo &abstractInfo=CGCalleeInfo())
llvm::MDNode * getInlinedAt() const
void setInlinedAt(llvm::MDNode *InlinedAt)
Update the current inline scope.
CGFunctionInfo - Class to encapsulate the information about a function definition.
bool usesInAlloca() const
Return true if this function uses inalloca arguments.
FunctionType::ExtInfo getExtInfo() const
ABIArgInfo & getReturnInfo()
const_arg_iterator arg_begin() const
CanQualType getReturnType() const
const_arg_iterator arg_end() const
RequiredArgs getRequiredArgs() const
const CGBitFieldInfo & getBitFieldInfo(const FieldDecl *FD) const
Return the BitFieldInfo that corresponds to the field FD.
CallArgList - Type for representing both the value and type of arguments in a call.
void add(RValue rvalue, QualType type)
A scope within which we are constructing the fields of an object which might use a CXXDefaultInitExpr...
static ParamValue forIndirect(Address addr)
static ParamValue forDirect(llvm::Value *value)
Enters a new scope for capturing cleanups, all of which will be executed once the scope is exited.
void ForceCleanup(std::initializer_list< llvm::Value ** > ValuesToReload={})
Force the emission of cleanups now, instead of waiting until this object is destroyed.
RAII object to set/unset CodeGenFunction::IsSanitizerScope.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
void emitArrayDestroy(llvm::Value *begin, llvm::Value *end, QualType elementType, CharUnits elementAlign, Destroyer *destroyer, bool checkZeroLength, bool useEHCleanup)
emitArrayDestroy - Destroys all the elements of the given array, beginning from last to first.
llvm::Value * GetVTablePtr(Address This, llvm::Type *VTableTy, const CXXRecordDecl *VTableClass, VTableAuthMode AuthMode=VTableAuthMode::Authenticate)
GetVTablePtr - Return the Value of the vtable pointer member pointed to by This.
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)
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...
RawAddress CreateIRTemp(QualType T, const Twine &Name="tmp")
CreateIRTemp - Create a temporary IR object of the given type, with appropriate alignment.
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_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::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)
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,...
const TargetCodeGenInfo & getTargetHooks() const
void EmitCtorPrologue(const CXXConstructorDecl *CD, CXXCtorType Type, FunctionArgList &Args)
EmitCtorPrologue - This routine generates necessary code to initialize base classes and non-static da...
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)
void EmitDeleteCall(const FunctionDecl *DeleteFD, llvm::Value *Ptr, QualType DeleteTy, llvm::Value *NumElements=nullptr, CharUnits CookieSize=CharUnits())
CodeGenTypes & getTypes() const
static TypeEvaluationKind getEvaluationKind(QualType T)
getEvaluationKind - Return the TypeEvaluationKind of QualType T.
void ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock=false)
bool IsSanitizerScope
True if CodeGen currently emits code implementing sanitizer checks.
void emitImplicitAssignmentOperatorBody(FunctionArgList &Args)
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.
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...
RawAddress CreateMemTemp(QualType T, const Twine &Name="tmp", RawAddress *Alloca=nullptr)
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen and cas...
bool sanitizePerformTypeCheck() const
Whether any type-checking sanitizers are enabled.
void EmitAggExpr(const Expr *E, AggValueSlot AS)
EmitAggExpr - Emit the computation of the specified expression of aggregate type.
llvm::Value * GetVTTParameter(GlobalDecl GD, bool ForVirtualBase, bool Delegating)
GetVTTParameter - Return the VTT parameter that should be passed to a base constructor/destructor wit...
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
void EmitCallArgs(CallArgList &Args, PrototypeWrapper Prototype, llvm::iterator_range< CallExpr::const_arg_iterator > ArgRange, AbstractCallee AC=AbstractCallee(), unsigned ParamsToSkip=0, EvaluationOrder Order=EvaluationOrder::Default)
EmitCallArgs - Emit call arguments for a function.
llvm::CallInst * EmitTrapCall(llvm::Intrinsic::ID IntrID)
Emit a call to trap or debugtrap and attach function attribute "trap-func-name" if specified.
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
void EmitTrapCheck(llvm::Value *Checked, SanitizerHandler CheckHandlerID, bool NoMerge=false, const TrapReason *TR=nullptr)
Create a basic block that will call the trap intrinsic, and emit a conditional branch to it,...
llvm::Value * LoadCXXThis()
LoadCXXThis - Load the value of 'this'.
void EnterCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock=false)
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
void InitializeVTablePointer(const VPtr &vptr)
Initialize the vtable pointer of the given subobject.
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.
LValue EmitLValue(const Expr *E, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitLValue - Emit code to compute a designator that specifies the location of the expression.
bool ShouldEmitVTableTypeCheckedLoad(const CXXRecordDecl *RD)
Returns whether we should perform a type checked load when loading a virtual function for virtual cal...
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)
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).
const LangOptions & getLangOpts() const
CodeGenTypes & getTypes()
const TargetInfo & getTarget() const
llvm::Constant * GetNonVirtualBaseClassOffset(const CXXRecordDecl *ClassDecl, CastExpr::path_const_iterator PathBegin, CastExpr::path_const_iterator PathEnd)
Returns the offset from a derived class to a class.
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...
ItaniumVTableContext & getItaniumVTableContext()
ASTContext & getContext() const
llvm::Type * ConvertType(QualType T)
ConvertType - Convert type T into a llvm::Type.
bool inheritingCtorHasParams(const InheritedConstructor &Inherited, CXXCtorType Type)
Determine if a C++ inheriting constructor should have parameters matching those of its inherited cons...
const CGRecordLayout & getCGRecordLayout(const RecordDecl *)
getCGRecordLayout - Return record layout info for the given record decl.
const CGFunctionInfo & arrangeCXXConstructorCall(const CallArgList &Args, const CXXConstructorDecl *D, CXXCtorType CtorKind, unsigned ExtraPrefixArgs, unsigned ExtraSuffixArgs, bool PassProtoArgs=true)
Arrange a call to a C++ method, passing the given arguments.
FunctionArgList - Type for representing both the decl and type of parameters to a function.
LValue - This represents an lvalue references.
Address getAddress() const
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(llvm::Value *V)
Address getAggregateAddress() const
getAggregateAddr() - Return the Value* of the address of the aggregate.
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
An abstract representation of an aligned address.
ReturnValueSlot - Contains the address where the return value of a function can be stored,...
Address performAddrSpaceCast(CodeGen::CodeGenFunction &CGF, Address Addr, LangAS SrcAddr, llvm::Type *DestTy, bool IsNonNull=false) const
CompoundStmt - This represents a group of statements like { stmt stmt }.
Represents the canonical version of C arrays with a specified constant size.
SourceLocation getEndLoc() const LLVM_READONLY
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
bool isUsed(bool CheckUsedAttr=true) const
Whether any (re-)declaration of the entity was used, meaning that a definition is required.
This represents one expression.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Represents a member of a struct/union/class.
bool isBitField() const
Determines whether this field is a bitfield.
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
Represents a function declaration or definition.
const ParmVarDecl * getParamDecl(unsigned i) const
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
bool hasTrivialBody() const
Returns whether the function has a trivial body that does not require any specific codegen.
bool isFunctionTemplateSpecialization() const
Determine whether this function is a function template specialization.
bool isDestroyingOperatorDelete() const
Determine whether this is a destroying operator delete.
unsigned getBuiltinID(bool ConsiderWrapperFunctions=false) const
Returns a value indicating whether this function corresponds to a builtin function.
ArrayRef< ParmVarDecl * > parameters() const
bool isTrivial() const
Whether this function is "trivial" in some specialized C++ senses.
bool isVariadic() const
Whether this function is variadic.
const TemplateArgumentList * getTemplateSpecializationArgs() const
Retrieve the template arguments used to produce this function template specialization from the primar...
bool isDefaulted() const
Whether this function is defaulted.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Represents a prototype with parameter type info, e.g.
param_type_iterator param_type_begin() const
bool isVariadic() const
Whether this function prototype is variadic.
Declaration of a template function.
FunctionDecl * findSpecialization(ArrayRef< TemplateArgument > Args, void *&InsertPos)
Return the specialization with the provided arguments if it exists, otherwise return the insertion po...
QualType getReturnType() const
GlobalDecl - represents a global declaration.
CXXCtorType getCtorType() const
const Decl * getDecl() const
Represents a field injected from an anonymous union/struct into the parent scope.
ArrayRef< NamedDecl * > chain() const
bool isRelativeLayout() const
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
A pointer to member type per C++ 8.3.3 - Pointers to members.
CXXRecordDecl * getMostRecentCXXRecordDecl() const
Note: this can trigger extra deserialization when external AST sources are used.
QualType getPointeeType() const
std::string getQualifiedNameAsString() const
bool containsType(SanitizerMask Mask, StringRef MangledTypeName, StringRef Category=StringRef()) const
bool isAddressDiscriminated() const
A (possibly-)qualified type.
bool isTriviallyCopyableType(const ASTContext &Context) const
Return true if this is a trivially copyable type (C++0x [basic.types]p9)
PointerAuthQualifier getPointerAuth() const
LangAS getAddressSpace() const
Return the address space of this type.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
DestructionKind isDestructedType() const
Returns a nonzero value if objects of this type require non-trivial work to clean up after.
bool isPODType(const ASTContext &Context) const
Determine whether this is a Plain Old Data (POD) type (C++ 3.9p10).
The collection of all-type qualifiers we support.
bool hasObjCLifetime() const
LangAS getAddressSpace() const
field_range fields() const
bool mayInsertExtraPadding(bool EmitRemark=false) const
Whether we are allowed to insert extra padding between fields.
static constexpr SanitizerMask bitPosToMask(const unsigned Pos)
Create a mask with a bit enabled at position Pos.
Scope - A scope is a transient data structure that is used while parsing the program.
Encodes a location in the source.
Stmt - This represents one statement.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
bool areArgsDestroyedLeftToRightInCallee() const
Are arguments to a call destroyed left to right in the callee?
TargetCXXABI getCXXABI() const
Get the C++ ABI currently in use.
virtual bool callGlobalDeleteInDeletingDtor(const LangOptions &) const
Controls whether global operator delete is called by the deleting destructor or at the point where de...
A template argument list.
ArrayRef< TemplateArgument > asArray() const
Produce this as an array ref.
The base class of the type hierarchy.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
CXXRecordDecl * castAsCXXRecordDecl() const
const T * castAs() const
Member-template castAs<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
The JSON file list parser is used to communicate input to InstallAPI.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
CXXCtorType
C++ constructor types.
@ Ctor_Base
Base object ctor.
@ Ctor_Complete
Complete object ctor.
bool isa(CodeGen::Address addr)
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
const FunctionProtoType * T
CXXDtorType
C++ destructor types.
@ Dtor_VectorDeleting
Vector deleting dtor.
@ Dtor_Comdat
The COMDAT used for dtors.
@ Dtor_Unified
GCC-style unified dtor.
@ Dtor_Base
Base object dtor.
@ Dtor_Complete
Complete object dtor.
@ Dtor_Deleting
Deleting dtor.
LangAS
Defines the address space values used by the address space qualifier of QualType.
U cast(CodeGen::Address addr)
CharUnits StorageOffset
The offset of the bitfield storage from the start of the struct.
Similar to AddedStructorArgs, but only notes the number of additional arguments.
llvm::BasicBlock * getBlock() const
Struct with all information about dynamic [sub]class needed to set vptr.
const CXXRecordDecl * NearestVBase
const CXXRecordDecl * VTableClass
CharUnits OffsetFromNearestVBase
llvm::PointerType * VoidPtrTy
llvm::IntegerType * Int8Ty
i8, i16, i32, and i64
llvm::IntegerType * SizeTy
llvm::IntegerType * Int32Ty
llvm::IntegerType * IntPtrTy
llvm::PointerType * Int8PtrTy
llvm::IntegerType * PtrDiffTy
void set(SanitizerMask K, bool Value)
Enable or disable a certain (single) sanitizer.