//===--- CGClass.cpp - Emit LLVM Code for C++ classes -----------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This contains code dealing with C++ code generation of classes
//
//===----------------------------------------------------------------------===//

#include "ABIInfoImpl.h"
#include "CGBlocks.h"
#include "CGCXXABI.h"
#include "CGDebugInfo.h"
#include "CGRecordLayout.h"
#include "CodeGenFunction.h"
#include "TargetInfo.h"
#include "clang/AST/Attr.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/StmtCXX.h"
#include "clang/Basic/CodeGenOptions.h"
#include "clang/CodeGen/CGFunctionInfo.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Metadata.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
#include "llvm/Transforms/Utils/SanitizerStats.h"
#include <optional>

using namespace clang;
using namespace CodeGen;

/// Return the best known alignment for an unknown pointer to a
/// particular class.
CharUnits CodeGenModule::getClassPointerAlignment(const CXXRecordDecl *RD) {
  if (!RD->hasDefinition())
    return CharUnits::One(); // Hopefully won't be used anywhere.

  auto &layout = getContext().getASTRecordLayout(RD);

  // If the class is final, then we know that the pointer points to an
  // object of that type and can use the full alignment.
  if (RD->isEffectivelyFinal())
    return layout.getAlignment();

  // Otherwise, we have to assume it could be a subclass.
  return layout.getNonVirtualAlignment();
}

/// Return the smallest possible amount of storage that might be allocated
/// starting from the beginning of an object of a particular class.
///
/// This may be smaller than sizeof(RD) if RD has virtual base classes.
CharUnits CodeGenModule::getMinimumClassObjectSize(const CXXRecordDecl *RD) {
  if (!RD->hasDefinition())
    return CharUnits::One();

  auto &layout = getContext().getASTRecordLayout(RD);

  // If the class is final, then we know that the pointer points to an
  // object of that type and can use the full alignment.
  if (RD->isEffectivelyFinal())
    return layout.getSize();

  // Otherwise, we have to assume it could be a subclass.
  return std::max(layout.getNonVirtualSize(), CharUnits::One());
}

/// Return the best known alignment for a pointer to a virtual base,
/// given the alignment of a pointer to the derived class.
CharUnits CodeGenModule::getVBaseAlignment(CharUnits actualDerivedAlign,
                                           const CXXRecordDecl *derivedClass,
                                           const CXXRecordDecl *vbaseClass) {
  // The basic idea here is that an underaligned derived pointer might
  // indicate an underaligned base pointer.

  assert(vbaseClass->isCompleteDefinition());
  auto &baseLayout = getContext().getASTRecordLayout(vbaseClass);
  CharUnits expectedVBaseAlign = baseLayout.getNonVirtualAlignment();

  return getDynamicOffsetAlignment(actualDerivedAlign, derivedClass,
                                   expectedVBaseAlign);
}

CharUnits
CodeGenModule::getDynamicOffsetAlignment(CharUnits actualBaseAlign,
                                         const CXXRecordDecl *baseDecl,
                                         CharUnits expectedTargetAlign) {
  // If the base is an incomplete type (which is, alas, possible with
  // member pointers), be pessimistic.
  if (!baseDecl->isCompleteDefinition())
    return std::min(actualBaseAlign, expectedTargetAlign);

  auto &baseLayout = getContext().getASTRecordLayout(baseDecl);
  CharUnits expectedBaseAlign = baseLayout.getNonVirtualAlignment();

  // If the class is properly aligned, assume the target offset is, too.
  //
  // This actually isn't necessarily the right thing to do --- if the
  // class is a complete object, but it's only properly aligned for a
  // base subobject, then the alignments of things relative to it are
  // probably off as well.  (Note that this requires the alignment of
  // the target to be greater than the NV alignment of the derived
  // class.)
  //
  // However, our approach to this kind of under-alignment can only
  // ever be best effort; after all, we're never going to propagate
  // alignments through variables or parameters.  Note, in particular,
  // that constructing a polymorphic type in an address that's less
  // than pointer-aligned will generally trap in the constructor,
  // unless we someday add some sort of attribute to change the
  // assumed alignment of 'this'.  So our goal here is pretty much
  // just to allow the user to explicitly say that a pointer is
  // under-aligned and then safely access its fields and vtables.
  if (actualBaseAlign >= expectedBaseAlign) {
    return expectedTargetAlign;
  }

  // Otherwise, we might be offset by an arbitrary multiple of the
  // actual alignment.  The correct adjustment is to take the min of
  // the two alignments.
  return std::min(actualBaseAlign, expectedTargetAlign);
}

Address CodeGenFunction::LoadCXXThisAddress() {
  assert(CurFuncDecl && "loading 'this' without a func declaration?");
  auto *MD = cast<CXXMethodDecl>(CurFuncDecl);

  // Lazily compute CXXThisAlignment.
  if (CXXThisAlignment.isZero()) {
    // Just use the best known alignment for the parent.
    // TODO: if we're currently emitting a complete-object ctor/dtor,
    // we can always use the complete-object alignment.
    CXXThisAlignment = CGM.getClassPointerAlignment(MD->getParent());
  }

  return makeNaturalAddressForPointer(
      LoadCXXThis(), MD->getFunctionObjectParameterType(), CXXThisAlignment,
      false, nullptr, nullptr, KnownNonNull);
}

/// Emit the address of a field using a member data pointer.
///
/// \param E Only used for emergency diagnostics
Address CodeGenFunction::EmitCXXMemberDataPointerAddress(
    const Expr *E, Address base, llvm::Value *memberPtr,
    const MemberPointerType *memberPtrType, bool IsInBounds,
    LValueBaseInfo *BaseInfo, TBAAAccessInfo *TBAAInfo) {
  // Ask the ABI to compute the actual address.
  llvm::Value *ptr = CGM.getCXXABI().EmitMemberDataPointerAddress(
      *this, E, base, memberPtr, memberPtrType, IsInBounds);

  QualType memberType = memberPtrType->getPointeeType();
  CharUnits memberAlign =
      CGM.getNaturalTypeAlignment(memberType, BaseInfo, TBAAInfo);
  memberAlign = CGM.getDynamicOffsetAlignment(
      base.getAlignment(), memberPtrType->getMostRecentCXXRecordDecl(),
      memberAlign);
  return Address(ptr, ConvertTypeForMem(memberPtrType->getPointeeType()),
                 memberAlign);
}

CharUnits CodeGenModule::computeNonVirtualBaseClassOffset(
    const CXXRecordDecl *DerivedClass, CastExpr::path_const_iterator Start,
    CastExpr::path_const_iterator End) {
  CharUnits Offset = CharUnits::Zero();

  const ASTContext &Context = getContext();
  const CXXRecordDecl *RD = DerivedClass;

  for (CastExpr::path_const_iterator I = Start; I != End; ++I) {
    const CXXBaseSpecifier *Base = *I;
    assert(!Base->isVirtual() && "Should not see virtual bases here!");

    // Get the layout.
    const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);

    const auto *BaseDecl = Base->getType()->castAsCXXRecordDecl();
    // Add the offset.
    Offset += Layout.getBaseClassOffset(BaseDecl);

    RD = BaseDecl;
  }

  return Offset;
}

llvm::Constant *CodeGenModule::GetNonVirtualBaseClassOffset(
    const CXXRecordDecl *ClassDecl, CastExpr::path_const_iterator PathBegin,
    CastExpr::path_const_iterator PathEnd) {
  assert(PathBegin != PathEnd && "Base path should not be empty!");

  CharUnits Offset =
      computeNonVirtualBaseClassOffset(ClassDecl, PathBegin, PathEnd);
  if (Offset.isZero())
    return nullptr;

  llvm::Type *PtrDiffTy =
      getTypes().ConvertType(getContext().getPointerDiffType());

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

/// Gets the address of a direct base class within a complete object.
/// This should only be used for (1) non-virtual bases or (2) virtual bases
/// when the type is known to be complete (e.g. in complete destructors).
///
/// The object pointed to by 'This' is assumed to be non-null.
Address CodeGenFunction::GetAddressOfDirectBaseInCompleteClass(
    Address This, const CXXRecordDecl *Derived, const CXXRecordDecl *Base,
    bool BaseIsVirtual) {
  // 'this' must be a pointer (in some address space) to Derived.
  assert(This.getElementType() == ConvertType(Derived));

  // Compute the offset of the virtual base.
  CharUnits Offset;
  const ASTRecordLayout &Layout = getContext().getASTRecordLayout(Derived);
  if (BaseIsVirtual)
    Offset = Layout.getVBaseClassOffset(Base);
  else
    Offset = Layout.getBaseClassOffset(Base);

  // Shift and cast down to the base type.
  // TODO: for complete types, this should be possible with a GEP.
  Address V = This;
  if (!Offset.isZero()) {
    V = V.withElementType(Int8Ty);
    V = Builder.CreateConstInBoundsByteGEP(V, Offset);
  }
  return V.withElementType(ConvertType(Base));
}

static Address ApplyNonVirtualAndVirtualOffset(
    CodeGenFunction &CGF, Address addr, CharUnits nonVirtualOffset,
    llvm::Value *virtualOffset, const CXXRecordDecl *derivedClass,
    const CXXRecordDecl *nearestVBase) {
  // Assert that we have something to do.
  assert(!nonVirtualOffset.isZero() || virtualOffset != nullptr);

  // Compute the offset from the static and dynamic components.
  llvm::Value *baseOffset;
  if (!nonVirtualOffset.isZero()) {
    llvm::Type *OffsetType =
        (CGF.CGM.getTarget().getCXXABI().isItaniumFamily() &&
         CGF.CGM.getLangOpts().RelativeCXXABIVTables)
            ? CGF.Int32Ty
            : CGF.PtrDiffTy;
    baseOffset =
        llvm::ConstantInt::get(OffsetType, nonVirtualOffset.getQuantity());
    if (virtualOffset) {
      baseOffset = CGF.Builder.CreateAdd(virtualOffset, baseOffset);
    }
  } else {
    baseOffset = virtualOffset;
  }

  // Apply the base offset.
  llvm::Value *ptr = addr.emitRawPointer(CGF);
  ptr = CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, ptr, baseOffset, "add.ptr");

  // If we have a virtual component, the alignment of the result will
  // be relative only to the known alignment of that vbase.
  CharUnits alignment;
  if (virtualOffset) {
    assert(nearestVBase && "virtual offset without vbase?");
    alignment = CGF.CGM.getVBaseAlignment(addr.getAlignment(), derivedClass,
                                          nearestVBase);
  } else {
    alignment = addr.getAlignment();
  }
  alignment = alignment.alignmentAtOffset(nonVirtualOffset);

  return Address(ptr, CGF.Int8Ty, alignment);
}

Address CodeGenFunction::GetAddressOfBaseClass(
    Address Value, const CXXRecordDecl *Derived,
    CastExpr::path_const_iterator PathBegin,
    CastExpr::path_const_iterator PathEnd, bool NullCheckValue,
    SourceLocation Loc) {
  assert(PathBegin != PathEnd && "Base path should not be empty!");

  CastExpr::path_const_iterator Start = PathBegin;
  const CXXRecordDecl *VBase = nullptr;

  // Sema has done some convenient canonicalization here: if the
  // access path involved any virtual steps, the conversion path will
  // *start* with a step down to the correct virtual base subobject,
  // and hence will not require any further steps.
  if ((*Start)->isVirtual()) {
    VBase = (*Start)->getType()->castAsCXXRecordDecl();
    ++Start;
  }

  // Compute the static offset of the ultimate destination within its
  // allocating subobject (the virtual base, if there is one, or else
  // the "complete" object that we see).
  CharUnits NonVirtualOffset = CGM.computeNonVirtualBaseClassOffset(
      VBase ? VBase : Derived, Start, PathEnd);

  // If there's a virtual step, we can sometimes "devirtualize" it.
  // For now, that's limited to when the derived type is final.
  // TODO: "devirtualize" this for accesses to known-complete objects.
  if (VBase && Derived->hasAttr<FinalAttr>()) {
    const ASTRecordLayout &layout = getContext().getASTRecordLayout(Derived);
    CharUnits vBaseOffset = layout.getVBaseClassOffset(VBase);
    NonVirtualOffset += vBaseOffset;
    VBase = nullptr; // we no longer have a virtual step
  }

  // Get the base pointer type.
  llvm::Type *BaseValueTy = ConvertType((PathEnd[-1])->getType());
  llvm::Type *PtrTy = llvm::PointerType::get(
      CGM.getLLVMContext(), Value.getType()->getPointerAddressSpace());

  CanQualType DerivedTy = getContext().getCanonicalTagType(Derived);
  CharUnits DerivedAlign = CGM.getClassPointerAlignment(Derived);

  // If the static offset is zero and we don't have a virtual step,
  // just do a bitcast; null checks are unnecessary.
  if (NonVirtualOffset.isZero() && !VBase) {
    if (sanitizePerformTypeCheck()) {
      SanitizerSet SkippedChecks;
      SkippedChecks.set(SanitizerKind::Null, !NullCheckValue);
      EmitTypeCheck(TCK_Upcast, Loc, Value.emitRawPointer(*this), DerivedTy,
                    DerivedAlign, SkippedChecks);
    }
    return Value.withElementType(BaseValueTy);
  }

  llvm::BasicBlock *origBB = nullptr;
  llvm::BasicBlock *endBB = nullptr;

  // Skip over the offset (and the vtable load) if we're supposed to
  // null-check the pointer.
  if (NullCheckValue) {
    origBB = Builder.GetInsertBlock();
    llvm::BasicBlock *notNullBB = createBasicBlock("cast.notnull");
    endBB = createBasicBlock("cast.end");

    llvm::Value *isNull = Builder.CreateIsNull(Value);
    Builder.CreateCondBr(isNull, endBB, notNullBB);
    EmitBlock(notNullBB);
  }

  if (sanitizePerformTypeCheck()) {
    SanitizerSet SkippedChecks;
    SkippedChecks.set(SanitizerKind::Null, true);
    EmitTypeCheck(VBase ? TCK_UpcastToVirtualBase : TCK_Upcast, Loc,
                  Value.emitRawPointer(*this), DerivedTy, DerivedAlign,
                  SkippedChecks);
  }

  // Compute the virtual offset.
  llvm::Value *VirtualOffset = nullptr;
  if (VBase) {
    VirtualOffset =
        CGM.getCXXABI().GetVirtualBaseClassOffset(*this, Value, Derived, VBase);
  }

  // Apply both offsets.
  Value = ApplyNonVirtualAndVirtualOffset(*this, Value, NonVirtualOffset,
                                          VirtualOffset, Derived, VBase);

  // Cast to the destination type.
  Value = Value.withElementType(BaseValueTy);

  // Build a phi if we needed a null check.
  if (NullCheckValue) {
    llvm::BasicBlock *notNullBB = Builder.GetInsertBlock();
    Builder.CreateBr(endBB);
    EmitBlock(endBB);

    llvm::PHINode *PHI = Builder.CreatePHI(PtrTy, 2, "cast.result");
    PHI->addIncoming(Value.emitRawPointer(*this), notNullBB);
    PHI->addIncoming(llvm::Constant::getNullValue(PtrTy), origBB);
    Value = Value.withPointer(PHI, NotKnownNonNull);
  }

  return Value;
}

Address CodeGenFunction::GetAddressOfDerivedClass(
    Address BaseAddr, const CXXRecordDecl *Derived,
    CastExpr::path_const_iterator PathBegin,
    CastExpr::path_const_iterator PathEnd, bool NullCheckValue) {
  assert(PathBegin != PathEnd && "Base path should not be empty!");

  CanQualType DerivedTy = getContext().getCanonicalTagType(Derived);
  llvm::Type *DerivedValueTy = ConvertType(DerivedTy);

  llvm::Value *NonVirtualOffset =
      CGM.GetNonVirtualBaseClassOffset(Derived, PathBegin, PathEnd);

  if (!NonVirtualOffset) {
    // No offset, we can just cast back.
    return BaseAddr.withElementType(DerivedValueTy);
  }

  llvm::BasicBlock *CastNull = nullptr;
  llvm::BasicBlock *CastNotNull = nullptr;
  llvm::BasicBlock *CastEnd = nullptr;

  if (NullCheckValue) {
    CastNull = createBasicBlock("cast.null");
    CastNotNull = createBasicBlock("cast.notnull");
    CastEnd = createBasicBlock("cast.end");

    llvm::Value *IsNull = Builder.CreateIsNull(BaseAddr);
    Builder.CreateCondBr(IsNull, CastNull, CastNotNull);
    EmitBlock(CastNotNull);
  }

  // Apply the offset.
  Address Addr = BaseAddr.withElementType(Int8Ty);
  Addr = Builder.CreateInBoundsGEP(
      Addr, Builder.CreateNeg(NonVirtualOffset), Int8Ty,
      CGM.getClassPointerAlignment(Derived), "sub.ptr");

  // Just cast.
  Addr = Addr.withElementType(DerivedValueTy);

  // Produce a PHI if we had a null-check.
  if (NullCheckValue) {
    Builder.CreateBr(CastEnd);
    EmitBlock(CastNull);
    Builder.CreateBr(CastEnd);
    EmitBlock(CastEnd);

    llvm::Value *Value = Addr.emitRawPointer(*this);
    llvm::PHINode *PHI = Builder.CreatePHI(Value->getType(), 2);
    PHI->addIncoming(Value, CastNotNull);
    PHI->addIncoming(llvm::Constant::getNullValue(Value->getType()), CastNull);
    return Address(PHI, Addr.getElementType(),
                   CGM.getClassPointerAlignment(Derived));
  }

  return Addr;
}

llvm::Value *CodeGenFunction::GetVTTParameter(GlobalDecl GD,
                                              bool ForVirtualBase,
                                              bool Delegating) {
  if (!CGM.getCXXABI().NeedsVTTParameter(GD)) {
    // This constructor/destructor does not need a VTT parameter.
    return nullptr;
  }

  const CXXRecordDecl *RD = cast<CXXMethodDecl>(CurCodeDecl)->getParent();
  const CXXRecordDecl *Base = cast<CXXMethodDecl>(GD.getDecl())->getParent();

  uint64_t SubVTTIndex;

  if (Delegating) {
    // If this is a delegating constructor call, just load the VTT.
    return LoadCXXVTT();
  } else if (RD == Base) {
    // If the record matches the base, this is the complete ctor/dtor
    // variant calling the base variant in a class with virtual bases.
    assert(!CGM.getCXXABI().NeedsVTTParameter(CurGD) &&
           "doing no-op VTT offset in base dtor/ctor?");
    assert(!ForVirtualBase && "Can't have same class as virtual base!");
    SubVTTIndex = 0;
  } else {
    const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
    CharUnits BaseOffset = ForVirtualBase ? Layout.getVBaseClassOffset(Base)
                                          : Layout.getBaseClassOffset(Base);

    SubVTTIndex =
        CGM.getVTables().getSubVTTIndex(RD, BaseSubobject(Base, BaseOffset));
    assert(SubVTTIndex != 0 && "Sub-VTT index must be greater than zero!");
  }

  llvm::Value *VTT;
  if (CGM.getCXXABI().NeedsVTTParameter(CurGD)) {
    // A VTT parameter was passed to the constructor, use it.
    VTT = LoadCXXVTT();
  } else {
    // We're the complete constructor, so get the VTT by name.
    VTT = CGM.getVTables().GetAddrOfVTT(RD);
  }
  return Builder.CreateConstInBoundsGEP1_64(CGM.GlobalsInt8PtrTy, VTT,
                                            SubVTTIndex);
}

namespace {
/// Call the destructor for a direct base class.
struct CallBaseDtor final : EHScopeStack::Cleanup {
  const CXXRecordDecl *BaseClass;
  bool BaseIsVirtual;
  CallBaseDtor(const CXXRecordDecl *Base, bool BaseIsVirtual)
      : BaseClass(Base), BaseIsVirtual(BaseIsVirtual) {}

  void Emit(CodeGenFunction &CGF, Flags flags) override {
    const CXXRecordDecl *DerivedClass =
        cast<CXXMethodDecl>(CGF.CurCodeDecl)->getParent();

    const CXXDestructorDecl *D = BaseClass->getDestructor();
    // We are already inside a destructor, so presumably the object being
    // destroyed should have the expected type.
    QualType ThisTy = D->getFunctionObjectParameterType();
    Address Addr = CGF.GetAddressOfDirectBaseInCompleteClass(
        CGF.LoadCXXThisAddress(), DerivedClass, BaseClass, BaseIsVirtual);
    CGF.EmitCXXDestructorCall(D, Dtor_Base, BaseIsVirtual,
                              /*Delegating=*/false, Addr, ThisTy);
  }
};

/// A visitor which checks whether an initializer uses 'this' in a
/// way which requires the vtable to be properly set.
struct DynamicThisUseChecker
    : ConstEvaluatedExprVisitor<DynamicThisUseChecker> {
  typedef ConstEvaluatedExprVisitor<DynamicThisUseChecker> super;

  bool UsesThis;

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

  // Black-list all explicit and implicit references to 'this'.
  //
  // Do we need to worry about external references to 'this' derived
  // from arbitrary code?  If so, then anything which runs arbitrary
  // external code might potentially access the vtable.
  void VisitCXXThisExpr(const CXXThisExpr *E) { UsesThis = true; }
};
} // end anonymous namespace

static bool BaseInitializerUsesThis(ASTContext &C, const Expr *Init) {
  DynamicThisUseChecker Checker(C);
  Checker.Visit(Init);
  return Checker.UsesThis;
}

static void EmitBaseInitializer(CodeGenFunction &CGF,
                                const CXXRecordDecl *ClassDecl,
                                CXXCtorInitializer *BaseInit) {
  assert(BaseInit->isBaseInitializer() && "Must have base initializer!");

  Address ThisPtr = CGF.LoadCXXThisAddress();

  const auto *BaseClassDecl = BaseInit->getBaseClass()->castAsCXXRecordDecl();

  bool isBaseVirtual = BaseInit->isBaseVirtual();

  // If the initializer for the base (other than the constructor
  // itself) accesses 'this' in any way, we need to initialize the
  // vtables.
  if (BaseInitializerUsesThis(CGF.getContext(), BaseInit->getInit()))
    CGF.InitializeVTablePointers(ClassDecl);

  // We can pretend to be a complete class because it only matters for
  // virtual bases, and we only do virtual bases for complete ctors.
  Address V = CGF.GetAddressOfDirectBaseInCompleteClass(
      ThisPtr, ClassDecl, BaseClassDecl, isBaseVirtual);
  AggValueSlot AggSlot = AggValueSlot::forAddr(
      V, Qualifiers(), AggValueSlot::IsDestructed,
      AggValueSlot::DoesNotNeedGCBarriers, AggValueSlot::IsNotAliased,
      CGF.getOverlapForBaseInit(ClassDecl, BaseClassDecl, isBaseVirtual));

  CGF.EmitAggExpr(BaseInit->getInit(), AggSlot);

  if (CGF.CGM.getLangOpts().Exceptions &&
      !BaseClassDecl->hasTrivialDestructor())
    CGF.EHStack.pushCleanup<CallBaseDtor>(EHCleanup, BaseClassDecl,
                                          isBaseVirtual);
}

static void EmitLValueForAnyFieldInitialization(CodeGenFunction &CGF,
                                                CXXCtorInitializer *MemberInit,
                                                LValue &LHS) {
  FieldDecl *Field = MemberInit->getAnyMember();
  if (MemberInit->isIndirectMemberInitializer()) {
    // If we are initializing an anonymous union field, drill down to the field.
    IndirectFieldDecl *IndirectField = MemberInit->getIndirectMember();
    for (const auto *I : IndirectField->chain())
      LHS = CGF.EmitLValueForFieldInitialization(LHS, cast<FieldDecl>(I));
  } else {
    LHS = CGF.EmitLValueForFieldInitialization(LHS, Field);
  }
}

static void EmitMemberInitializer(CodeGenFunction &CGF,
                                  const CXXRecordDecl *ClassDecl,
                                  CXXCtorInitializer *MemberInit,
                                  const CXXConstructorDecl *Constructor,
                                  FunctionArgList &Args) {
  ApplyAtomGroup Grp(CGF.getDebugInfo());
  ApplyDebugLocation Loc(CGF, MemberInit->getSourceLocation());
  assert(MemberInit->isAnyMemberInitializer() &&
         "Must have member initializer!");
  assert(MemberInit->getInit() && "Must have initializer!");

  // non-static data member initializers.
  FieldDecl *Field = MemberInit->getAnyMember();
  QualType FieldType = Field->getType();

  llvm::Value *ThisPtr = CGF.LoadCXXThis();
  CanQualType RecordTy = CGF.getContext().getCanonicalTagType(ClassDecl);
  LValue LHS;

  // If a base constructor is being emitted, create an LValue that has the
  // non-virtual alignment.
  if (CGF.CurGD.getCtorType() == Ctor_Base)
    LHS = CGF.MakeNaturalAlignPointeeAddrLValue(ThisPtr, RecordTy);
  else
    LHS = CGF.MakeNaturalAlignAddrLValue(ThisPtr, RecordTy);

  EmitLValueForAnyFieldInitialization(CGF, MemberInit, LHS);

  // Special case: if we are in a copy or move constructor, and we are copying
  // an array of PODs or classes with trivial copy constructors, ignore the
  // AST and perform the copy we know is equivalent.
  // FIXME: This is hacky at best... if we had a bit more explicit information
  // in the AST, we could generalize it more easily.
  const ConstantArrayType *Array =
      CGF.getContext().getAsConstantArrayType(FieldType);
  if (Array && Constructor->isDefaulted() &&
      Constructor->isCopyOrMoveConstructor()) {
    QualType BaseElementTy = CGF.getContext().getBaseElementType(Array);
    CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(MemberInit->getInit());
    if (BaseElementTy.isPODType(CGF.getContext()) ||
        (CE && CE->getConstructor()->isMemcpyEquivalentSpecialMember(
                   CGF.getContext()))) {
      unsigned SrcArgIndex =
          CGF.CGM.getCXXABI().getSrcArgforCopyCtor(Constructor, Args);
      llvm::Value *SrcPtr =
          CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(Args[SrcArgIndex]));
      LValue ThisRHSLV = CGF.MakeNaturalAlignAddrLValue(SrcPtr, RecordTy);
      LValue Src = CGF.EmitLValueForFieldInitialization(ThisRHSLV, Field);

      // Copy the aggregate.
      CGF.EmitAggregateCopy(LHS, Src, FieldType,
                            CGF.getOverlapForFieldInit(Field),
                            LHS.isVolatileQualified());
      // Ensure that we destroy the objects if an exception is thrown later in
      // the constructor.
      QualType::DestructionKind dtorKind = FieldType.isDestructedType();
      if (CGF.needsEHCleanup(dtorKind))
        CGF.pushEHDestroy(dtorKind, LHS.getAddress(), FieldType);
      return;
    }
  }

  CGF.EmitInitializerForField(Field, LHS, MemberInit->getInit());
}

void CodeGenFunction::EmitInitializerForField(FieldDecl *Field, LValue LHS,
                                              Expr *Init) {
  QualType FieldType = Field->getType();
  switch (getEvaluationKind(FieldType)) {
  case TEK_Scalar:
    if (LHS.isSimple()) {
      EmitExprAsInit(Init, Field, LHS, false);
    } else {
      RValue RHS = RValue::get(EmitScalarExpr(Init));
      EmitStoreThroughLValue(RHS, LHS);
    }
    break;
  case TEK_Complex:
    EmitComplexExprIntoLValue(Init, LHS, /*isInit*/ true);
    break;
  case TEK_Aggregate: {
    AggValueSlot Slot = AggValueSlot::forLValue(
        LHS, AggValueSlot::IsDestructed, AggValueSlot::DoesNotNeedGCBarriers,
        AggValueSlot::IsNotAliased, getOverlapForFieldInit(Field),
        AggValueSlot::IsNotZeroed,
        // Checks are made by the code that calls constructor.
        AggValueSlot::IsSanitizerChecked);
    EmitAggExpr(Init, Slot);
    break;
  }
  }

  // Ensure that we destroy this object if an exception is thrown
  // later in the constructor.
  QualType::DestructionKind dtorKind = FieldType.isDestructedType();
  if (needsEHCleanup(dtorKind))
    pushEHDestroy(dtorKind, LHS.getAddress(), FieldType);
}

/// Checks whether the given constructor is a valid subject for the
/// complete-to-base constructor delegation optimization, i.e.
/// emitting the complete constructor as a simple call to the base
/// constructor.
bool CodeGenFunction::IsConstructorDelegationValid(
    const CXXConstructorDecl *Ctor) {

  // Currently we disable the optimization for classes with virtual
  // bases because (1) the addresses of parameter variables need to be
  // consistent across all initializers but (2) the delegate function
  // call necessarily creates a second copy of the parameter variable.
  //
  // The limiting example (purely theoretical AFAIK):
  //   struct A { A(int &c) { c++; } };
  //   struct B : virtual A {
  //     B(int count) : A(count) { printf("%d\n", count); }
  //   };
  // ...although even this example could in principle be emitted as a
  // delegation since the address of the parameter doesn't escape.
  if (Ctor->getParent()->getNumVBases()) {
    // TODO: white-list trivial vbase initializers.  This case wouldn't
    // be subject to the restrictions below.

    // TODO: white-list cases where:
    //  - there are no non-reference parameters to the constructor
    //  - the initializers don't access any non-reference parameters
    //  - the initializers don't take the address of non-reference
    //    parameters
    //  - etc.
    // If we ever add any of the above cases, remember that:
    //  - function-try-blocks will always exclude this optimization
    //  - we need to perform the constructor prologue and cleanup in
    //    EmitConstructorBody.

    return false;
  }

  // We also disable the optimization for variadic functions because
  // it's impossible to "re-pass" varargs.
  if (Ctor->getType()->castAs<FunctionProtoType>()->isVariadic())
    return false;

  // FIXME: Decide if we can do a delegation of a delegating constructor.
  if (Ctor->isDelegatingConstructor())
    return false;

  return true;
}

// Emit code in ctor (Prologue==true) or dtor (Prologue==false)
// to poison the extra field paddings inserted under
// -fsanitize-address-field-padding=1|2.
void CodeGenFunction::EmitAsanPrologueOrEpilogue(bool Prologue) {
  ASTContext &Context = getContext();
  const CXXRecordDecl *ClassDecl =
      Prologue ? cast<CXXConstructorDecl>(CurGD.getDecl())->getParent()
               : cast<CXXDestructorDecl>(CurGD.getDecl())->getParent();
  if (!ClassDecl->mayInsertExtraPadding())
    return;

  struct SizeAndOffset {
    uint64_t Size;
    uint64_t Offset;
  };

  unsigned PtrSize = CGM.getDataLayout().getPointerSizeInBits();
  const ASTRecordLayout &Info = Context.getASTRecordLayout(ClassDecl);

  // Populate sizes and offsets of fields.
  SmallVector<SizeAndOffset, 16> SSV(Info.getFieldCount());
  for (unsigned i = 0, e = Info.getFieldCount(); i != e; ++i)
    SSV[i].Offset =
        Context.toCharUnitsFromBits(Info.getFieldOffset(i)).getQuantity();

  size_t NumFields = 0;
  for (const auto *Field : ClassDecl->fields()) {
    const FieldDecl *D = Field;
    auto FieldInfo = Context.getTypeInfoInChars(D->getType());
    CharUnits FieldSize = FieldInfo.Width;
    assert(NumFields < SSV.size());
    SSV[NumFields].Size = D->isBitField() ? 0 : FieldSize.getQuantity();
    NumFields++;
  }
  assert(NumFields == SSV.size());
  if (SSV.size() <= 1)
    return;

  // We will insert calls to __asan_* run-time functions.
  // LLVM AddressSanitizer pass may decide to inline them later.
  llvm::Type *Args[2] = {IntPtrTy, IntPtrTy};
  llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, Args, false);
  llvm::FunctionCallee F = CGM.CreateRuntimeFunction(
      FTy, Prologue ? "__asan_poison_intra_object_redzone"
                    : "__asan_unpoison_intra_object_redzone");

  llvm::Value *ThisPtr = LoadCXXThis();
  ThisPtr = Builder.CreatePtrToInt(ThisPtr, IntPtrTy);
  uint64_t TypeSize = Info.getNonVirtualSize().getQuantity();
  // For each field check if it has sufficient padding,
  // if so (un)poison it with a call.
  for (size_t i = 0; i < SSV.size(); i++) {
    uint64_t AsanAlignment = 8;
    uint64_t NextField = i == SSV.size() - 1 ? TypeSize : SSV[i + 1].Offset;
    uint64_t PoisonSize = NextField - SSV[i].Offset - SSV[i].Size;
    uint64_t EndOffset = SSV[i].Offset + SSV[i].Size;
    if (PoisonSize < AsanAlignment || !SSV[i].Size ||
        (NextField % AsanAlignment) != 0)
      continue;
    Builder.CreateCall(
        F, {Builder.CreateAdd(ThisPtr, Builder.getIntN(PtrSize, EndOffset)),
            Builder.getIntN(PtrSize, PoisonSize)});
  }
}

/// EmitConstructorBody - Emits the body of the current constructor.
void CodeGenFunction::EmitConstructorBody(FunctionArgList &Args) {
  EmitAsanPrologueOrEpilogue(true);
  const CXXConstructorDecl *Ctor = cast<CXXConstructorDecl>(CurGD.getDecl());
  CXXCtorType CtorType = CurGD.getCtorType();

  assert((CGM.getTarget().getCXXABI().hasConstructorVariants() ||
          CtorType == Ctor_Complete) &&
         "can only generate complete ctor for this ABI");

  // Before we go any further, try the complete->base constructor
  // delegation optimization.
  if (CtorType == Ctor_Complete && IsConstructorDelegationValid(Ctor) &&
      CGM.getTarget().getCXXABI().hasConstructorVariants()) {
    EmitDelegateCXXConstructorCall(Ctor, Ctor_Base, Args, Ctor->getEndLoc());
    return;
  }

  const FunctionDecl *Definition = nullptr;
  Stmt *Body = Ctor->getBody(Definition);
  assert(Definition == Ctor && "emitting wrong constructor body");

  // Enter the function-try-block before the constructor prologue if
  // applicable.
  bool IsTryBody = isa_and_nonnull<CXXTryStmt>(Body);
  if (IsTryBody)
    EnterCXXTryStmt(*cast<CXXTryStmt>(Body), true);

  incrementProfileCounter(Body);
  maybeCreateMCDCCondBitmap();

  RunCleanupsScope RunCleanups(*this);

  // TODO: in restricted cases, we can emit the vbase initializers of
  // a complete ctor and then delegate to the base ctor.

  // Emit the constructor prologue, i.e. the base and member
  // initializers.
  EmitCtorPrologue(Ctor, CtorType, Args);

  // Emit the body of the statement.
  if (IsTryBody)
    EmitStmt(cast<CXXTryStmt>(Body)->getTryBlock());
  else if (Body)
    EmitStmt(Body);

  // Emit any cleanup blocks associated with the member or base
  // initializers, which includes (along the exceptional path) the
  // destructors for those members and bases that were fully
  // constructed.
  RunCleanups.ForceCleanup();

  if (IsTryBody)
    ExitCXXTryStmt(*cast<CXXTryStmt>(Body), true);
}

namespace {
/// RAII object to indicate that codegen is copying the value representation
/// instead of the object representation. Useful when copying a struct or
/// class which has uninitialized members and we're only performing
/// lvalue-to-rvalue conversion on the object but not its members.
class CopyingValueRepresentation {
public:
  explicit CopyingValueRepresentation(CodeGenFunction &CGF)
      : CGF(CGF), OldSanOpts(CGF.SanOpts) {
    CGF.SanOpts.set(SanitizerKind::Bool, false);
    CGF.SanOpts.set(SanitizerKind::Enum, false);
  }
  ~CopyingValueRepresentation() { CGF.SanOpts = OldSanOpts; }

private:
  CodeGenFunction &CGF;
  SanitizerSet OldSanOpts;
};
} // end anonymous namespace

namespace {
class FieldMemcpyizer {
public:
  FieldMemcpyizer(CodeGenFunction &CGF, const CXXRecordDecl *ClassDecl,
                  const VarDecl *SrcRec)
      : CGF(CGF), ClassDecl(ClassDecl), SrcRec(SrcRec),
        RecLayout(CGF.getContext().getASTRecordLayout(ClassDecl)),
        FirstField(nullptr), LastField(nullptr), FirstFieldOffset(0),
        LastFieldOffset(0), LastAddedFieldIndex(0) {}

  bool isMemcpyableField(FieldDecl *F) const {
    // Never memcpy fields when we are adding poisoned paddings.
    if (CGF.getContext().getLangOpts().SanitizeAddressFieldPadding)
      return false;
    Qualifiers Qual = F->getType().getQualifiers();
    if (Qual.hasVolatile() || Qual.hasObjCLifetime())
      return false;
    if (PointerAuthQualifier Q = F->getType().getPointerAuth();
        Q && Q.isAddressDiscriminated())
      return false;
    // Non-trivially-copyable fields with pointer field protection need to be
    // copied one by one.
    if (!CGF.getContext().arePFPFieldsTriviallyCopyable(ClassDecl) &&
        CGF.getContext().isPFPField(F))
      return false;
    return true;
  }

  void addMemcpyableField(FieldDecl *F) {
    if (isEmptyFieldForLayout(CGF.getContext(), F))
      return;
    if (!FirstField)
      addInitialField(F);
    else
      addNextField(F);
  }

  CharUnits getMemcpySize(uint64_t FirstByteOffset) const {
    ASTContext &Ctx = CGF.getContext();
    unsigned LastFieldSize =
        LastField->isBitField()
            ? LastField->getBitWidthValue()
            : Ctx.toBits(
                  Ctx.getTypeInfoDataSizeInChars(LastField->getType()).Width);
    uint64_t MemcpySizeBits = LastFieldOffset + LastFieldSize -
                              FirstByteOffset + Ctx.getCharWidth() - 1;
    CharUnits MemcpySize = Ctx.toCharUnitsFromBits(MemcpySizeBits);
    return MemcpySize;
  }

  void emitMemcpy() {
    // Give the subclass a chance to bail out if it feels the memcpy isn't
    // worth it (e.g. Hasn't aggregated enough data).
    if (!FirstField) {
      return;
    }

    uint64_t FirstByteOffset;
    if (FirstField->isBitField()) {
      const CGRecordLayout &RL =
          CGF.getTypes().getCGRecordLayout(FirstField->getParent());
      const CGBitFieldInfo &BFInfo = RL.getBitFieldInfo(FirstField);
      // FirstFieldOffset is not appropriate for bitfields,
      // we need to use the storage offset instead.
      FirstByteOffset = CGF.getContext().toBits(BFInfo.StorageOffset);
    } else {
      FirstByteOffset = FirstFieldOffset;
    }

    CharUnits MemcpySize = getMemcpySize(FirstByteOffset);
    CanQualType RecordTy = CGF.getContext().getCanonicalTagType(ClassDecl);
    Address ThisPtr = CGF.LoadCXXThisAddress();
    LValue DestLV = CGF.MakeAddrLValue(ThisPtr, RecordTy);
    LValue Dest = CGF.EmitLValueForFieldInitialization(DestLV, FirstField);
    llvm::Value *SrcPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(SrcRec));
    LValue SrcLV = CGF.MakeNaturalAlignAddrLValue(SrcPtr, RecordTy);
    LValue Src = CGF.EmitLValueForFieldInitialization(SrcLV, FirstField);

    emitMemcpyIR(Dest.isBitField() ? Dest.getBitFieldAddress()
                                   : Dest.getAddress(),
                 Src.isBitField() ? Src.getBitFieldAddress() : Src.getAddress(),
                 MemcpySize);
    reset();
  }

  void reset() { FirstField = nullptr; }

protected:
  CodeGenFunction &CGF;
  const CXXRecordDecl *ClassDecl;

private:
  void emitMemcpyIR(Address DestPtr, Address SrcPtr, CharUnits Size) {
    DestPtr = DestPtr.withElementType(CGF.Int8Ty);
    SrcPtr = SrcPtr.withElementType(CGF.Int8Ty);
    auto *I = CGF.Builder.CreateMemCpy(DestPtr, SrcPtr, Size.getQuantity());
    CGF.addInstToCurrentSourceAtom(I, nullptr);
  }

  void addInitialField(FieldDecl *F) {
    FirstField = F;
    LastField = F;
    FirstFieldOffset = RecLayout.getFieldOffset(F->getFieldIndex());
    LastFieldOffset = FirstFieldOffset;
    LastAddedFieldIndex = F->getFieldIndex();
  }

  void addNextField(FieldDecl *F) {
    // For the most part, the following invariant will hold:
    //   F->getFieldIndex() == LastAddedFieldIndex + 1
    // The one exception is that Sema won't add a copy-initializer for an
    // unnamed bitfield, which will show up here as a gap in the sequence.
    assert(F->getFieldIndex() >= LastAddedFieldIndex + 1 &&
           "Cannot aggregate fields out of order.");
    LastAddedFieldIndex = F->getFieldIndex();

    // The 'first' and 'last' fields are chosen by offset, rather than field
    // index. This allows the code to support bitfields, as well as regular
    // fields.
    uint64_t FOffset = RecLayout.getFieldOffset(F->getFieldIndex());
    if (FOffset < FirstFieldOffset) {
      FirstField = F;
      FirstFieldOffset = FOffset;
    } else if (FOffset >= LastFieldOffset) {
      LastField = F;
      LastFieldOffset = FOffset;
    }
  }

  const VarDecl *SrcRec;
  const ASTRecordLayout &RecLayout;
  FieldDecl *FirstField;
  FieldDecl *LastField;
  uint64_t FirstFieldOffset, LastFieldOffset;
  unsigned LastAddedFieldIndex;
};

class ConstructorMemcpyizer : public FieldMemcpyizer {
private:
  /// Get source argument for copy constructor. Returns null if not a copy
  /// constructor.
  static const VarDecl *getTrivialCopySource(CodeGenFunction &CGF,
                                             const CXXConstructorDecl *CD,
                                             FunctionArgList &Args) {
    if (CD->isCopyOrMoveConstructor() && CD->isDefaulted())
      return Args[CGF.CGM.getCXXABI().getSrcArgforCopyCtor(CD, Args)];
    return nullptr;
  }

  // Returns true if a CXXCtorInitializer represents a member initialization
  // that can be rolled into a memcpy.
  bool isMemberInitMemcpyable(CXXCtorInitializer *MemberInit) const {
    if (!MemcpyableCtor)
      return false;
    FieldDecl *Field = MemberInit->getMember();
    assert(Field && "No field for member init.");
    QualType FieldType = Field->getType();
    CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(MemberInit->getInit());

    // Bail out on non-memcpyable, not-trivially-copyable members.
    if (!(CE && CE->getConstructor()->isMemcpyEquivalentSpecialMember(
                    CGF.getContext())) &&
        !(FieldType.isTriviallyCopyableType(CGF.getContext()) ||
          FieldType->isReferenceType()))
      return false;

    // Bail out on volatile fields.
    if (!isMemcpyableField(Field))
      return false;

    // Otherwise we're good.
    return true;
  }

public:
  ConstructorMemcpyizer(CodeGenFunction &CGF, const CXXConstructorDecl *CD,
                        FunctionArgList &Args)
      : FieldMemcpyizer(CGF, CD->getParent(),
                        getTrivialCopySource(CGF, CD, Args)),
        ConstructorDecl(CD),
        MemcpyableCtor(CD->isDefaulted() && CD->isCopyOrMoveConstructor() &&
                       CGF.getLangOpts().getGC() == LangOptions::NonGC),
        Args(Args) {}

  void addMemberInitializer(CXXCtorInitializer *MemberInit) {
    if (isMemberInitMemcpyable(MemberInit)) {
      AggregatedInits.push_back(MemberInit);
      addMemcpyableField(MemberInit->getMember());
    } else {
      emitAggregatedInits();
      EmitMemberInitializer(CGF, ConstructorDecl->getParent(), MemberInit,
                            ConstructorDecl, Args);
    }
  }

  void emitAggregatedInits() {
    if (AggregatedInits.size() <= 1) {
      // This memcpy is too small to be worthwhile. Fall back on default
      // codegen.
      if (!AggregatedInits.empty()) {
        CopyingValueRepresentation CVR(CGF);
        EmitMemberInitializer(CGF, ConstructorDecl->getParent(),
                              AggregatedInits[0], ConstructorDecl, Args);
        AggregatedInits.clear();
      }
      reset();
      return;
    }

    pushEHDestructors();
    ApplyAtomGroup Grp(CGF.getDebugInfo());
    emitMemcpy();
    AggregatedInits.clear();
  }

  void pushEHDestructors() {
    Address ThisPtr = CGF.LoadCXXThisAddress();
    CanQualType RecordTy = CGF.getContext().getCanonicalTagType(ClassDecl);
    LValue LHS = CGF.MakeAddrLValue(ThisPtr, RecordTy);

    for (unsigned i = 0; i < AggregatedInits.size(); ++i) {
      CXXCtorInitializer *MemberInit = AggregatedInits[i];
      QualType FieldType = MemberInit->getAnyMember()->getType();
      QualType::DestructionKind dtorKind = FieldType.isDestructedType();
      if (!CGF.needsEHCleanup(dtorKind))
        continue;
      LValue FieldLHS = LHS;
      EmitLValueForAnyFieldInitialization(CGF, MemberInit, FieldLHS);
      CGF.pushEHDestroy(dtorKind, FieldLHS.getAddress(), FieldType);
    }
  }

  void finish() { emitAggregatedInits(); }

private:
  const CXXConstructorDecl *ConstructorDecl;
  bool MemcpyableCtor;
  FunctionArgList &Args;
  SmallVector<CXXCtorInitializer *, 16> AggregatedInits;
};

class AssignmentMemcpyizer : public FieldMemcpyizer {
private:
  // Returns the memcpyable field copied by the given statement, if one
  // exists. Otherwise returns null.
  FieldDecl *getMemcpyableField(Stmt *S) {
    if (!AssignmentsMemcpyable)
      return nullptr;
    if (BinaryOperator *BO = dyn_cast<BinaryOperator>(S)) {
      // Recognise trivial assignments.
      if (BO->getOpcode() != BO_Assign)
        return nullptr;
      MemberExpr *ME = dyn_cast<MemberExpr>(BO->getLHS());
      if (!ME)
        return nullptr;
      FieldDecl *Field = dyn_cast<FieldDecl>(ME->getMemberDecl());
      if (!Field || !isMemcpyableField(Field))
        return nullptr;
      Stmt *RHS = BO->getRHS();
      if (ImplicitCastExpr *EC = dyn_cast<ImplicitCastExpr>(RHS))
        RHS = EC->getSubExpr();
      if (!RHS)
        return nullptr;
      if (MemberExpr *ME2 = dyn_cast<MemberExpr>(RHS)) {
        if (ME2->getMemberDecl() == Field)
          return Field;
      }
      return nullptr;
    } else if (CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(S)) {
      CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MCE->getCalleeDecl());
      if (!(MD && MD->isMemcpyEquivalentSpecialMember(CGF.getContext())))
        return nullptr;
      MemberExpr *IOA = dyn_cast<MemberExpr>(MCE->getImplicitObjectArgument());
      if (!IOA)
        return nullptr;
      FieldDecl *Field = dyn_cast<FieldDecl>(IOA->getMemberDecl());
      if (!Field || !isMemcpyableField(Field))
        return nullptr;
      MemberExpr *Arg0 = dyn_cast<MemberExpr>(MCE->getArg(0));
      if (!Arg0 || Field != dyn_cast<FieldDecl>(Arg0->getMemberDecl()))
        return nullptr;
      return Field;
    } else if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
      FunctionDecl *FD = dyn_cast<FunctionDecl>(CE->getCalleeDecl());
      if (!FD || FD->getBuiltinID() != Builtin::BI__builtin_memcpy)
        return nullptr;
      Expr *DstPtr = CE->getArg(0);
      if (ImplicitCastExpr *DC = dyn_cast<ImplicitCastExpr>(DstPtr))
        DstPtr = DC->getSubExpr();
      UnaryOperator *DUO = dyn_cast<UnaryOperator>(DstPtr);
      if (!DUO || DUO->getOpcode() != UO_AddrOf)
        return nullptr;
      MemberExpr *ME = dyn_cast<MemberExpr>(DUO->getSubExpr());
      if (!ME)
        return nullptr;
      FieldDecl *Field = dyn_cast<FieldDecl>(ME->getMemberDecl());
      if (!Field || !isMemcpyableField(Field))
        return nullptr;
      Expr *SrcPtr = CE->getArg(1);
      if (ImplicitCastExpr *SC = dyn_cast<ImplicitCastExpr>(SrcPtr))
        SrcPtr = SC->getSubExpr();
      UnaryOperator *SUO = dyn_cast<UnaryOperator>(SrcPtr);
      if (!SUO || SUO->getOpcode() != UO_AddrOf)
        return nullptr;
      MemberExpr *ME2 = dyn_cast<MemberExpr>(SUO->getSubExpr());
      if (!ME2 || Field != dyn_cast<FieldDecl>(ME2->getMemberDecl()))
        return nullptr;
      return Field;
    }

    return nullptr;
  }

  bool AssignmentsMemcpyable;
  SmallVector<Stmt *, 16> AggregatedStmts;

public:
  AssignmentMemcpyizer(CodeGenFunction &CGF, const CXXMethodDecl *AD,
                       FunctionArgList &Args)
      : FieldMemcpyizer(CGF, AD->getParent(), Args[Args.size() - 1]),
        AssignmentsMemcpyable(CGF.getLangOpts().getGC() == LangOptions::NonGC) {
    assert(Args.size() == 2);
  }

  void emitAssignment(Stmt *S) {
    FieldDecl *F = getMemcpyableField(S);
    if (F) {
      addMemcpyableField(F);
      AggregatedStmts.push_back(S);
    } else {
      emitAggregatedStmts();
      CGF.EmitStmt(S);
    }
  }

  void emitAggregatedStmts() {
    if (AggregatedStmts.size() <= 1) {
      if (!AggregatedStmts.empty()) {
        CopyingValueRepresentation CVR(CGF);
        CGF.EmitStmt(AggregatedStmts[0]);
      }
      reset();
    }

    ApplyAtomGroup Grp(CGF.getDebugInfo());
    emitMemcpy();
    AggregatedStmts.clear();
  }

  void finish() { emitAggregatedStmts(); }
};

} // end anonymous namespace

static bool isInitializerOfDynamicClass(const CXXCtorInitializer *BaseInit) {
  const Type *BaseType = BaseInit->getBaseClass();
  return BaseType->castAsCXXRecordDecl()->isDynamicClass();
}

/// EmitCtorPrologue - This routine generates necessary code to initialize
/// base classes and non-static data members belonging to this constructor.
void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
                                       CXXCtorType CtorType,
                                       FunctionArgList &Args) {
  if (CD->isDelegatingConstructor())
    return EmitDelegatingCXXConstructorCall(CD, Args);

  const CXXRecordDecl *ClassDecl = CD->getParent();

  // Virtual base initializers aren't needed if:
  // - This is a base ctor variant
  // - There are no vbases
  // - The class is abstract, so a complete object of it cannot be constructed
  //
  // The check for an abstract class is necessary because sema may not have
  // marked virtual base destructors referenced.
  bool ConstructVBases = CtorType != Ctor_Base &&
                         ClassDecl->getNumVBases() != 0 &&
                         !ClassDecl->isAbstract();

  // In the Microsoft C++ ABI, there are no constructor variants. Instead, the
  // constructor of a class with virtual bases takes an additional parameter to
  // conditionally construct the virtual bases. Emit that check here.
  llvm::BasicBlock *BaseCtorContinueBB = nullptr;
  if (ConstructVBases &&
      !CGM.getTarget().getCXXABI().hasConstructorVariants()) {
    BaseCtorContinueBB =
        CGM.getCXXABI().EmitCtorCompleteObjectHandler(*this, ClassDecl);
    assert(BaseCtorContinueBB);
  }

  // Create three separate ranges for the different types of initializers.
  auto AllInits = CD->inits();

  // Find the boundaries between the three groups.
  auto VirtualBaseEnd = std::find_if(
      AllInits.begin(), AllInits.end(), [](const CXXCtorInitializer *Init) {
        return !(Init->isBaseInitializer() && Init->isBaseVirtual());
      });

  auto NonVirtualBaseEnd = std::find_if(VirtualBaseEnd, AllInits.end(),
                                        [](const CXXCtorInitializer *Init) {
                                          return !Init->isBaseInitializer();
                                        });

  // Create the three ranges.
  auto VirtualBaseInits = llvm::make_range(AllInits.begin(), VirtualBaseEnd);
  auto NonVirtualBaseInits =
      llvm::make_range(VirtualBaseEnd, NonVirtualBaseEnd);
  auto MemberInits = llvm::make_range(NonVirtualBaseEnd, AllInits.end());

  // Process virtual base initializers, if necessary.
  if (ConstructVBases) {
    for (CXXCtorInitializer *Initializer : VirtualBaseInits) {
      SaveAndRestore ThisRAII(CXXThisValue);
      if (CGM.getCodeGenOpts().StrictVTablePointers &&
          CGM.getCodeGenOpts().OptimizationLevel > 0 &&
          isInitializerOfDynamicClass(Initializer))
        CXXThisValue = Builder.CreateLaunderInvariantGroup(LoadCXXThis());
      EmitBaseInitializer(*this, ClassDecl, Initializer);
    }
  }

  if (BaseCtorContinueBB) {
    // Complete object handler should continue to the remaining initializers.
    Builder.CreateBr(BaseCtorContinueBB);
    EmitBlock(BaseCtorContinueBB);
  }

  // Then, non-virtual base initializers.
  for (CXXCtorInitializer *Initializer : NonVirtualBaseInits) {
    assert(!Initializer->isBaseVirtual());
    SaveAndRestore ThisRAII(CXXThisValue);
    if (CGM.getCodeGenOpts().StrictVTablePointers &&
        CGM.getCodeGenOpts().OptimizationLevel > 0 &&
        isInitializerOfDynamicClass(Initializer))
      CXXThisValue = Builder.CreateLaunderInvariantGroup(LoadCXXThis());
    EmitBaseInitializer(*this, ClassDecl, Initializer);
  }

  InitializeVTablePointers(ClassDecl);

  // And finally, initialize class members.
  FieldConstructionScope FCS(*this, LoadCXXThisAddress());
  ConstructorMemcpyizer CM(*this, CD, Args);
  for (CXXCtorInitializer *Member : MemberInits) {
    assert(!Member->isBaseInitializer());
    assert(Member->isAnyMemberInitializer() &&
           "Delegating initializer on non-delegating constructor");
    CM.addMemberInitializer(Member);
  }

  CM.finish();
}

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

static bool
HasTrivialDestructorBody(ASTContext &Context,
                         const CXXRecordDecl *BaseClassDecl,
                         const CXXRecordDecl *MostDerivedClassDecl) {
  // If the destructor is trivial we don't have to check anything else.
  if (BaseClassDecl->hasTrivialDestructor())
    return true;

  if (!BaseClassDecl->getDestructor()->hasTrivialBody())
    return false;

  // Check fields.
  for (const auto *Field : BaseClassDecl->fields())
    if (!FieldHasTrivialDestructorBody(Context, Field))
      return false;

  // Check non-virtual bases.
  for (const auto &I : BaseClassDecl->bases()) {
    if (I.isVirtual())
      continue;

    const auto *NonVirtualBase = I.getType()->castAsCXXRecordDecl();
    if (!HasTrivialDestructorBody(Context, NonVirtualBase,
                                  MostDerivedClassDecl))
      return false;
  }

  if (BaseClassDecl == MostDerivedClassDecl) {
    // Check virtual bases.
    for (const auto &I : BaseClassDecl->vbases()) {
      const auto *VirtualBase = I.getType()->castAsCXXRecordDecl();
      if (!HasTrivialDestructorBody(Context, VirtualBase, MostDerivedClassDecl))
        return false;
    }
  }

  return true;
}

static bool FieldHasTrivialDestructorBody(ASTContext &Context,
                                          const FieldDecl *Field) {
  QualType FieldBaseElementType = Context.getBaseElementType(Field->getType());

  auto *FieldClassDecl = FieldBaseElementType->getAsCXXRecordDecl();
  if (!FieldClassDecl)
    return true;

  // The destructor for an implicit anonymous union member is never invoked.
  if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
    return true;

  return HasTrivialDestructorBody(Context, FieldClassDecl, FieldClassDecl);
}

/// CanSkipVTablePointerInitialization - Check whether we need to initialize
/// any vtable pointers before calling this destructor.
static bool CanSkipVTablePointerInitialization(CodeGenFunction &CGF,
                                               const CXXDestructorDecl *Dtor) {
  const CXXRecordDecl *ClassDecl = Dtor->getParent();
  if (!ClassDecl->isDynamicClass())
    return true;

  // For a final class, the vtable pointer is known to already point to the
  // class's vtable.
  if (ClassDecl->isEffectivelyFinal())
    return true;

  if (!Dtor->hasTrivialBody())
    return false;

  // Check the fields.
  for (const auto *Field : ClassDecl->fields())
    if (!FieldHasTrivialDestructorBody(CGF.getContext(), Field))
      return false;

  return true;
}

static void EmitConditionalArrayDtorCall(const CXXDestructorDecl *DD,
                                         CodeGenFunction &CGF,
                                         llvm::Value *ShouldDeleteCondition) {
  Address ThisPtr = CGF.LoadCXXThisAddress();
  llvm::BasicBlock *ScalarBB = CGF.createBasicBlock("dtor.scalar");
  llvm::BasicBlock *callDeleteBB =
      CGF.createBasicBlock("dtor.call_delete_after_array_destroy");
  llvm::BasicBlock *VectorBB = CGF.createBasicBlock("dtor.vector");
  auto *CondTy = cast<llvm::IntegerType>(ShouldDeleteCondition->getType());
  llvm::Value *CheckTheBitForArrayDestroy = CGF.Builder.CreateAnd(
      ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 2));
  llvm::Value *ShouldDestroyArray =
      CGF.Builder.CreateIsNull(CheckTheBitForArrayDestroy);
  CGF.Builder.CreateCondBr(ShouldDestroyArray, ScalarBB, VectorBB);

  CGF.EmitBlock(VectorBB);

  llvm::Value *numElements = nullptr;
  llvm::Value *allocatedPtr = nullptr;
  CharUnits cookieSize;
  QualType EltTy = DD->getThisType()->getPointeeType();
  CGF.CGM.getCXXABI().ReadArrayCookie(CGF, ThisPtr, EltTy, numElements,
                                      allocatedPtr, cookieSize);

  // Destroy the elements.
  QualType::DestructionKind dtorKind = EltTy.isDestructedType();

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

  CharUnits elementSize = CGF.getContext().getTypeSizeInChars(EltTy);
  CharUnits elementAlign =
      ThisPtr.getAlignment().alignmentOfArrayElement(elementSize);

  llvm::Value *arrayBegin = ThisPtr.emitRawPointer(CGF);
  llvm::Value *arrayEnd = CGF.Builder.CreateInBoundsGEP(
      ThisPtr.getElementType(), arrayBegin, numElements, "delete.end");

  // We already checked that the array is not 0-length before entering vector
  // deleting dtor.
  CGF.emitArrayDestroy(arrayBegin, arrayEnd, EltTy, elementAlign,
                       CGF.getDestroyer(dtorKind),
                       /*checkZeroLength*/ false, CGF.needsEHCleanup(dtorKind));

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

  llvm::Value *CheckTheBitForDeleteCall = CGF.Builder.CreateAnd(
      ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 1));

  llvm::Value *ShouldCallDelete =
      CGF.Builder.CreateIsNull(CheckTheBitForDeleteCall);
  CGF.Builder.CreateCondBr(ShouldCallDelete, CGF.ReturnBlock.getBlock(),
                           callDeleteBB);
  CGF.EmitBlock(callDeleteBB);
  const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CGF.CurCodeDecl);
  const CXXRecordDecl *ClassDecl = Dtor->getParent();
  if (Dtor->getArrayOperatorDelete()) {
    if (!Dtor->getGlobalArrayOperatorDelete()) {
      CGF.EmitDeleteCall(Dtor->getArrayOperatorDelete(), allocatedPtr,
                         CGF.getContext().getCanonicalTagType(ClassDecl),
                         numElements, cookieSize);
    } else {
      // If global operator[] is set, the class had its own operator delete[].
      // In that case, check the 4th bit. If it is set, we need to call
      // ::delete[].
      llvm::Value *CheckTheBitForGlobDeleteCall = CGF.Builder.CreateAnd(
          ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 4));

      llvm::Value *ShouldCallGlobDelete =
          CGF.Builder.CreateIsNull(CheckTheBitForGlobDeleteCall);
      llvm::BasicBlock *GlobDelete =
          CGF.createBasicBlock("dtor.call_glob_delete_after_array_destroy");
      llvm::BasicBlock *ClassDelete =
          CGF.createBasicBlock("dtor.call_class_delete_after_array_destroy");
      CGF.Builder.CreateCondBr(ShouldCallGlobDelete, ClassDelete, GlobDelete);
      CGF.EmitBlock(ClassDelete);
      CGF.EmitDeleteCall(Dtor->getArrayOperatorDelete(), allocatedPtr,
                         CGF.getContext().getCanonicalTagType(ClassDecl),
                         numElements, cookieSize);
      CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);

      CGF.EmitBlock(GlobDelete);
      // Use __global_delete wrapper instead of directly calling
      // ::operator delete to match MSVC's behavior. See the doc comment on
      // getOrCreateMSVCGlobalDeleteWrapper for details.
      llvm::Constant *GlobalDeleteWrapper =
          CGF.CGM.getOrCreateMSVCGlobalDeleteWrapper(
              Dtor->getGlobalArrayOperatorDelete());
      // For dllexport classes, emit forwarding bodies since the dtor is
      // exported and another TU may not provide the forwarding body.
      if (Dtor->hasAttr<DLLExportAttr>())
        CGF.CGM.noteDirectGlobalDelete();
      CGF.EmitDeleteCall(Dtor->getGlobalArrayOperatorDelete(), allocatedPtr,
                         CGF.getContext().getCanonicalTagType(ClassDecl),
                         numElements, cookieSize, GlobalDeleteWrapper);
    }
  } else {
    // No operators delete[] were found, so emit a trap.
    llvm::CallInst *TrapCall = CGF.EmitTrapCall(llvm::Intrinsic::trap);
    TrapCall->setDoesNotReturn();
    TrapCall->setDoesNotThrow();
    CGF.Builder.CreateUnreachable();
    CGF.Builder.ClearInsertionPoint();
  }

  CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
  CGF.EmitBlock(ScalarBB);
}

/// EmitDestructorBody - Emits the body of the current destructor.
void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
  const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CurGD.getDecl());
  CXXDtorType DtorType = CurGD.getDtorType();

  // For an abstract class, non-base destructors are never used (and can't
  // be emitted in general, because vbase dtors may not have been validated
  // by Sema), but the Itanium ABI doesn't make them optional and Clang may
  // in fact emit references to them from other compilations, so emit them
  // as functions containing a trap instruction.
  if (DtorType != Dtor_Base && Dtor->getParent()->isAbstract()) {
    llvm::CallInst *TrapCall = EmitTrapCall(llvm::Intrinsic::trap);
    TrapCall->setDoesNotReturn();
    TrapCall->setDoesNotThrow();
    Builder.CreateUnreachable();
    Builder.ClearInsertionPoint();
    return;
  }

  Stmt *Body = Dtor->getBody();
  if (Body) {
    incrementProfileCounter(Body);
    maybeCreateMCDCCondBitmap();
  }

  // The call to operator delete in a deleting destructor happens
  // outside of the function-try-block, which means it's always
  // possible to delegate the destructor body to the complete
  // destructor.  Do so.
  if (DtorType == Dtor_Deleting || DtorType == Dtor_VectorDeleting) {
    if (CXXStructorImplicitParamValue && DtorType == Dtor_VectorDeleting)
      EmitConditionalArrayDtorCall(Dtor, *this, CXXStructorImplicitParamValue);
    RunCleanupsScope DtorEpilogue(*this);
    EnterDtorCleanups(Dtor, Dtor_Deleting);
    if (HaveInsertPoint()) {
      QualType ThisTy = Dtor->getFunctionObjectParameterType();
      EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false,
                            /*Delegating=*/false, LoadCXXThisAddress(), ThisTy);
    }
    return;
  }

  // If the body is a function-try-block, enter the try before
  // anything else.
  bool isTryBody = isa_and_nonnull<CXXTryStmt>(Body);
  if (isTryBody)
    EnterCXXTryStmt(*cast<CXXTryStmt>(Body), true);
  EmitAsanPrologueOrEpilogue(false);

  // Enter the epilogue cleanups.
  RunCleanupsScope DtorEpilogue(*this);

  // If this is the complete variant, just invoke the base variant;
  // the epilogue will destruct the virtual bases.  But we can't do
  // this optimization if the body is a function-try-block, because
  // we'd introduce *two* handler blocks.  In the Microsoft ABI, we
  // always delegate because we might not have a definition in this TU.
  switch (DtorType) {
  case Dtor_Unified:
    llvm_unreachable("not expecting a unified dtor");
  case Dtor_Comdat:
    llvm_unreachable("not expecting a COMDAT");
  case Dtor_Deleting:
    llvm_unreachable("already handled deleting case");
  case Dtor_VectorDeleting:
    llvm_unreachable("already handled vector deleting case");

  case Dtor_Complete:
    assert((Body || getTarget().getCXXABI().isMicrosoft()) &&
           "can't emit a dtor without a body for non-Microsoft ABIs");

    // Enter the cleanup scopes for virtual bases.
    EnterDtorCleanups(Dtor, Dtor_Complete);

    if (!isTryBody) {
      QualType ThisTy = Dtor->getFunctionObjectParameterType();
      EmitCXXDestructorCall(Dtor, Dtor_Base, /*ForVirtualBase=*/false,
                            /*Delegating=*/false, LoadCXXThisAddress(), ThisTy);
      break;
    }

    // Fallthrough: act like we're in the base variant.
    [[fallthrough]];

  case Dtor_Base:
    assert(Body);

    // Enter the cleanup scopes for fields and non-virtual bases.
    EnterDtorCleanups(Dtor, Dtor_Base);

    // Initialize the vtable pointers before entering the body.
    if (!CanSkipVTablePointerInitialization(*this, Dtor)) {
      // Insert the llvm.launder.invariant.group intrinsic before initializing
      // the vptrs to cancel any previous assumptions we might have made.
      if (CGM.getCodeGenOpts().StrictVTablePointers &&
          CGM.getCodeGenOpts().OptimizationLevel > 0)
        CXXThisValue = Builder.CreateLaunderInvariantGroup(LoadCXXThis());
      InitializeVTablePointers(Dtor->getParent());
    }

    if (isTryBody)
      EmitStmt(cast<CXXTryStmt>(Body)->getTryBlock());
    else if (Body)
      EmitStmt(Body);
    else {
      assert(Dtor->isImplicit() && "bodyless dtor not implicit");
      // nothing to do besides what's in the epilogue
    }
    // -fapple-kext must inline any call to this dtor into
    // the caller's body.
    if (getLangOpts().AppleKext)
      CurFn->addFnAttr(llvm::Attribute::AlwaysInline);

    break;
  }

  // Jump out through the epilogue cleanups.
  DtorEpilogue.ForceCleanup();

  // Exit the try if applicable.
  if (isTryBody)
    ExitCXXTryStmt(*cast<CXXTryStmt>(Body), true);
}

void CodeGenFunction::emitImplicitAssignmentOperatorBody(
    FunctionArgList &Args) {
  const CXXMethodDecl *AssignOp = cast<CXXMethodDecl>(CurGD.getDecl());
  const Stmt *RootS = AssignOp->getBody();
  assert(isa<CompoundStmt>(RootS) &&
         "Body of an implicit assignment operator should be compound stmt.");
  const CompoundStmt *RootCS = cast<CompoundStmt>(RootS);

  LexicalScope Scope(*this, RootCS->getSourceRange());

  incrementProfileCounter(RootCS);
  maybeCreateMCDCCondBitmap();
  AssignmentMemcpyizer AM(*this, AssignOp, Args);
  for (auto *I : RootCS->body())
    AM.emitAssignment(I);

  AM.finish();
}

namespace {
llvm::Value *LoadThisForDtorDelete(CodeGenFunction &CGF,
                                   const CXXDestructorDecl *DD) {
  if (Expr *ThisArg = DD->getOperatorDeleteThisArg())
    return CGF.EmitScalarExpr(ThisArg);
  return CGF.LoadCXXThis();
}

/// Call the operator delete associated with the current destructor.
struct CallDtorDelete final : EHScopeStack::Cleanup {
  CallDtorDelete() {}

  void Emit(CodeGenFunction &CGF, Flags flags) override {
    const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CGF.CurCodeDecl);
    const CXXRecordDecl *ClassDecl = Dtor->getParent();
    CGF.EmitDeleteCall(Dtor->getOperatorDelete(),
                       LoadThisForDtorDelete(CGF, Dtor),
                       CGF.getContext().getCanonicalTagType(ClassDecl));
  }
};

// This function implements generation of scalar deleting destructor body for
// the case when the destructor also accepts an implicit flag. Right now only
// Microsoft ABI requires deleting destructors to accept implicit flags.
// The flag indicates whether an operator delete should be called and whether
// it should be a class-specific operator delete or a global one.
void EmitConditionalDtorDeleteCall(CodeGenFunction &CGF,
                                   llvm::Value *ShouldDeleteCondition,
                                   bool ReturnAfterDelete) {
  const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CGF.CurCodeDecl);
  const CXXRecordDecl *ClassDecl = Dtor->getParent();
  const FunctionDecl *OD = Dtor->getOperatorDelete();
  assert(OD->isDestroyingOperatorDelete() == ReturnAfterDelete &&
         "unexpected value for ReturnAfterDelete");
  auto *CondTy = cast<llvm::IntegerType>(ShouldDeleteCondition->getType());
  // MSVC calls global operator delete inside of the dtor body, but clang
  // aligned with this behavior only after a particular version. This is not
  // ABI-compatible with previous versions.
  ASTContext &Context = CGF.getContext();
  bool CallGlobDelete = Context.getTargetInfo().callGlobalDeleteInDeletingDtor(
      Context.getLangOpts());
  if (CallGlobDelete && OD->isDestroyingOperatorDelete()) {
    llvm::BasicBlock *CallDtor = CGF.createBasicBlock("dtor.call_dtor");
    llvm::BasicBlock *DontCallDtor = CGF.createBasicBlock("dtor.entry_cont");
    // Third bit set signals that global operator delete is called. That means
    // despite class having destroying operator delete which is responsible
    // for calling dtor, we need to call dtor because global operator delete
    // won't do that.
    llvm::Value *Check3rdBit = CGF.Builder.CreateAnd(
        ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 4));
    llvm::Value *ShouldCallDtor = CGF.Builder.CreateIsNull(Check3rdBit);
    CGF.Builder.CreateCondBr(ShouldCallDtor, DontCallDtor, CallDtor);
    CGF.EmitBlock(CallDtor);
    QualType ThisTy = Dtor->getFunctionObjectParameterType();
    CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false,
                              /*Delegating=*/false, CGF.LoadCXXThisAddress(),
                              ThisTy);
    CGF.Builder.CreateBr(DontCallDtor);
    CGF.EmitBlock(DontCallDtor);
  }
  llvm::BasicBlock *callDeleteBB = CGF.createBasicBlock("dtor.call_delete");
  llvm::BasicBlock *continueBB = CGF.createBasicBlock("dtor.continue");
  // First bit set signals that operator delete must be called.
  llvm::Value *Check1stBit = CGF.Builder.CreateAnd(
      ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 1));
  llvm::Value *ShouldCallDelete = CGF.Builder.CreateIsNull(Check1stBit);
  CGF.Builder.CreateCondBr(ShouldCallDelete, continueBB, callDeleteBB);

  CGF.EmitBlock(callDeleteBB);
  auto EmitDeleteAndGoToEnd = [&](const FunctionDecl *DeleteOp,
                                  llvm::Constant *CalleeOverride = nullptr) {
    CGF.EmitDeleteCall(DeleteOp, LoadThisForDtorDelete(CGF, Dtor),
                       Context.getCanonicalTagType(ClassDecl),
                       /*NumElements=*/nullptr, /*CookieSize=*/CharUnits(),
                       CalleeOverride);
    if (ReturnAfterDelete)
      CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
    else
      CGF.Builder.CreateBr(continueBB);
  };
  // If Sema only found a global operator delete previously, the dtor can
  // always call it. Otherwise we need to check the third bit and call the
  // appropriate operator delete, i.e. global or class-specific.
  if (const FunctionDecl *GlobOD = Dtor->getOperatorGlobalDelete();
      isa<CXXMethodDecl>(OD) && GlobOD && CallGlobDelete) {
    // Third bit set signals that global operator delete is called, i.e.
    // ::delete appears on the callsite.
    llvm::Value *CheckTheBitForGlobDeleteCall = CGF.Builder.CreateAnd(
        ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 4));
    llvm::Value *ShouldCallGlobDelete =
        CGF.Builder.CreateIsNull(CheckTheBitForGlobDeleteCall);
    llvm::BasicBlock *GlobDelete =
        CGF.createBasicBlock("dtor.call_glob_delete");
    llvm::BasicBlock *ClassDelete =
        CGF.createBasicBlock("dtor.call_class_delete");
    CGF.Builder.CreateCondBr(ShouldCallGlobDelete, ClassDelete, GlobDelete);
    CGF.EmitBlock(GlobDelete);

    // Use __global_delete wrapper instead of directly calling
    // ::operator delete to match MSVC's behavior. See the doc comment on
    // getOrCreateMSVCGlobalDeleteWrapper for details.
    llvm::Constant *GlobalDeleteWrapper =
        CGF.CGM.getOrCreateMSVCGlobalDeleteWrapper(GlobOD);
    // For dllexport classes, emit forwarding bodies since the dtor is
    // exported and another TU may not provide the forwarding body.
    if (Dtor->hasAttr<DLLExportAttr>())
      CGF.CGM.noteDirectGlobalDelete();
    EmitDeleteAndGoToEnd(GlobOD, GlobalDeleteWrapper);
    CGF.EmitBlock(ClassDelete);
  }
  EmitDeleteAndGoToEnd(OD);
  CGF.EmitBlock(continueBB);
}

struct CallDtorDeleteConditional final : EHScopeStack::Cleanup {
  llvm::Value *ShouldDeleteCondition;

public:
  CallDtorDeleteConditional(llvm::Value *ShouldDeleteCondition)
      : ShouldDeleteCondition(ShouldDeleteCondition) {
    assert(ShouldDeleteCondition != nullptr);
  }

  void Emit(CodeGenFunction &CGF, Flags flags) override {
    EmitConditionalDtorDeleteCall(CGF, ShouldDeleteCondition,
                                  /*ReturnAfterDelete*/ false);
  }
};

class DestroyField final : public EHScopeStack::Cleanup {
  const FieldDecl *field;
  CodeGenFunction::Destroyer *destroyer;
  bool useEHCleanupForArray;

public:
  DestroyField(const FieldDecl *field, CodeGenFunction::Destroyer *destroyer,
               bool useEHCleanupForArray)
      : field(field), destroyer(destroyer),
        useEHCleanupForArray(useEHCleanupForArray) {}

  void Emit(CodeGenFunction &CGF, Flags flags) override {
    // Find the address of the field.
    Address thisValue = CGF.LoadCXXThisAddress();
    CanQualType RecordTy =
        CGF.getContext().getCanonicalTagType(field->getParent());
    LValue ThisLV = CGF.MakeAddrLValue(thisValue, RecordTy);
    LValue LV = CGF.EmitLValueForField(ThisLV, field);
    assert(LV.isSimple());

    CGF.emitDestroy(LV.getAddress(), field->getType(), destroyer,
                    flags.isForNormalCleanup() && useEHCleanupForArray);
  }
};

class DeclAsInlineDebugLocation {
  CGDebugInfo *DI;
  llvm::DILocation *InlinedAt;
  std::optional<ApplyDebugLocation> Location;

public:
  DeclAsInlineDebugLocation(CodeGenFunction &CGF, const NamedDecl &Decl)
      : DI(CGF.getDebugInfo()) {
    if (!DI)
      return;
    InlinedAt = DI->getInlinedAt();
    DI->setInlinedAt(CGF.Builder.getCurrentDebugLocation());
    Location.emplace(CGF, Decl.getLocation());
  }

  ~DeclAsInlineDebugLocation() {
    if (!DI)
      return;
    Location.reset();
    DI->setInlinedAt(InlinedAt);
  }
};

static void EmitSanitizerDtorCallback(
    CodeGenFunction &CGF, StringRef Name, llvm::Value *Ptr,
    std::optional<CharUnits::QuantityType> PoisonSize = {}) {
  CodeGenFunction::SanitizerScope SanScope(&CGF);
  // Pass in void pointer and size of region as arguments to runtime
  // function
  SmallVector<llvm::Value *, 2> Args = {Ptr};
  SmallVector<llvm::Type *, 2> ArgTypes = {CGF.VoidPtrTy};

  if (PoisonSize.has_value()) {
    Args.emplace_back(llvm::ConstantInt::get(CGF.SizeTy, *PoisonSize));
    ArgTypes.emplace_back(CGF.SizeTy);
  }

  llvm::FunctionType *FnType =
      llvm::FunctionType::get(CGF.VoidTy, ArgTypes, false);
  llvm::FunctionCallee Fn = CGF.CGM.CreateRuntimeFunction(FnType, Name);

  CGF.EmitNounwindRuntimeCall(Fn, Args);
}

static void
EmitSanitizerDtorFieldsCallback(CodeGenFunction &CGF, llvm::Value *Ptr,
                                CharUnits::QuantityType PoisonSize) {
  EmitSanitizerDtorCallback(CGF, "__sanitizer_dtor_callback_fields", Ptr,
                            PoisonSize);
}

/// Poison base class with a trivial destructor.
struct SanitizeDtorTrivialBase final : EHScopeStack::Cleanup {
  const CXXRecordDecl *BaseClass;
  bool BaseIsVirtual;
  SanitizeDtorTrivialBase(const CXXRecordDecl *Base, bool BaseIsVirtual)
      : BaseClass(Base), BaseIsVirtual(BaseIsVirtual) {}

  void Emit(CodeGenFunction &CGF, Flags flags) override {
    const CXXRecordDecl *DerivedClass =
        cast<CXXMethodDecl>(CGF.CurCodeDecl)->getParent();

    Address Addr = CGF.GetAddressOfDirectBaseInCompleteClass(
        CGF.LoadCXXThisAddress(), DerivedClass, BaseClass, BaseIsVirtual);

    const ASTRecordLayout &BaseLayout =
        CGF.getContext().getASTRecordLayout(BaseClass);
    CharUnits BaseSize = BaseLayout.getSize();

    if (!BaseSize.isPositive())
      return;

    // Use the base class declaration location as inline DebugLocation. All
    // fields of the class are destroyed.
    DeclAsInlineDebugLocation InlineHere(CGF, *BaseClass);
    EmitSanitizerDtorFieldsCallback(CGF, Addr.emitRawPointer(CGF),
                                    BaseSize.getQuantity());

    // Prevent the current stack frame from disappearing from the stack trace.
    CGF.CurFn->addFnAttr("disable-tail-calls", "true");
  }
};

class SanitizeDtorFieldRange final : public EHScopeStack::Cleanup {
  const CXXDestructorDecl *Dtor;
  unsigned StartIndex;
  unsigned EndIndex;

public:
  SanitizeDtorFieldRange(const CXXDestructorDecl *Dtor, unsigned StartIndex,
                         unsigned EndIndex)
      : Dtor(Dtor), StartIndex(StartIndex), EndIndex(EndIndex) {}

  // Generate function call for handling object poisoning.
  // Disables tail call elimination, to prevent the current stack frame
  // from disappearing from the stack trace.
  void Emit(CodeGenFunction &CGF, Flags flags) override {
    const ASTContext &Context = CGF.getContext();
    const ASTRecordLayout &Layout =
        Context.getASTRecordLayout(Dtor->getParent());

    // It's a first trivial field so it should be at the begining of a char,
    // still round up start offset just in case.
    CharUnits PoisonStart = Context.toCharUnitsFromBits(
        Layout.getFieldOffset(StartIndex) + Context.getCharWidth() - 1);
    llvm::ConstantInt *OffsetSizePtr =
        llvm::ConstantInt::get(CGF.SizeTy, PoisonStart.getQuantity());

    llvm::Value *OffsetPtr =
        CGF.Builder.CreateGEP(CGF.Int8Ty, CGF.LoadCXXThis(), OffsetSizePtr);

    CharUnits PoisonEnd;
    if (EndIndex >= Layout.getFieldCount()) {
      PoisonEnd = Layout.getNonVirtualSize();
    } else {
      PoisonEnd = Context.toCharUnitsFromBits(Layout.getFieldOffset(EndIndex));
    }
    CharUnits PoisonSize = PoisonEnd - PoisonStart;
    if (!PoisonSize.isPositive())
      return;

    // Use the top field declaration location as inline DebugLocation.
    DeclAsInlineDebugLocation InlineHere(
        CGF, **std::next(Dtor->getParent()->field_begin(), StartIndex));
    EmitSanitizerDtorFieldsCallback(CGF, OffsetPtr, PoisonSize.getQuantity());

    // Prevent the current stack frame from disappearing from the stack trace.
    CGF.CurFn->addFnAttr("disable-tail-calls", "true");
  }
};

class SanitizeDtorVTable final : public EHScopeStack::Cleanup {
  const CXXDestructorDecl *Dtor;

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

  // Generate function call for handling vtable pointer poisoning.
  void Emit(CodeGenFunction &CGF, Flags flags) override {
    assert(Dtor->getParent()->isDynamicClass());
    (void)Dtor;
    // Poison vtable and vtable ptr if they exist for this class.
    llvm::Value *VTablePtr = CGF.LoadCXXThis();

    // Pass in void pointer and size of region as arguments to runtime
    // function
    EmitSanitizerDtorCallback(CGF, "__sanitizer_dtor_callback_vptr", VTablePtr);
  }
};

class SanitizeDtorCleanupBuilder {
  ASTContext &Context;
  EHScopeStack &EHStack;
  const CXXDestructorDecl *DD;
  std::optional<unsigned> StartIndex;

public:
  SanitizeDtorCleanupBuilder(ASTContext &Context, EHScopeStack &EHStack,
                             const CXXDestructorDecl *DD)
      : Context(Context), EHStack(EHStack), DD(DD), StartIndex(std::nullopt) {}
  void PushCleanupForField(const FieldDecl *Field) {
    if (isEmptyFieldForLayout(Context, Field))
      return;
    unsigned FieldIndex = Field->getFieldIndex();
    if (FieldHasTrivialDestructorBody(Context, Field)) {
      if (!StartIndex)
        StartIndex = FieldIndex;
    } else if (StartIndex) {
      EHStack.pushCleanup<SanitizeDtorFieldRange>(NormalAndEHCleanup, DD,
                                                  *StartIndex, FieldIndex);
      StartIndex = std::nullopt;
    }
  }
  void End() {
    if (StartIndex)
      EHStack.pushCleanup<SanitizeDtorFieldRange>(NormalAndEHCleanup, DD,
                                                  *StartIndex, -1);
  }
};
} // end anonymous namespace

/// Emit all code that comes at the end of class's
/// destructor. This is to call destructors on members and base classes
/// in reverse order of their construction.
///
/// For a deleting destructor, this also handles the case where a destroying
/// operator delete completely overrides the definition.
void CodeGenFunction::EnterDtorCleanups(const CXXDestructorDecl *DD,
                                        CXXDtorType DtorType) {
  assert((!DD->isTrivial() || DD->hasAttr<DLLExportAttr>()) &&
         "Should not emit dtor epilogue for non-exported trivial dtor!");

  // The deleting-destructor phase just needs to call the appropriate
  // operator delete that Sema picked up.
  if (DtorType == Dtor_Deleting) {
    assert(DD->getOperatorDelete() &&
           "operator delete missing - EnterDtorCleanups");
    if (CXXStructorImplicitParamValue) {
      // If there is an implicit param to the deleting dtor, it's a boolean
      // telling whether this is a deleting destructor.
      if (DD->getOperatorDelete()->isDestroyingOperatorDelete())
        EmitConditionalDtorDeleteCall(*this, CXXStructorImplicitParamValue,
                                      /*ReturnAfterDelete*/ true);
      else
        EHStack.pushCleanup<CallDtorDeleteConditional>(
            NormalAndEHCleanup, CXXStructorImplicitParamValue);
    } else {
      if (DD->getOperatorDelete()->isDestroyingOperatorDelete()) {
        const CXXRecordDecl *ClassDecl = DD->getParent();
        EmitDeleteCall(DD->getOperatorDelete(),
                       LoadThisForDtorDelete(*this, DD),
                       getContext().getCanonicalTagType(ClassDecl));
        EmitBranchThroughCleanup(ReturnBlock);
      } else {
        EHStack.pushCleanup<CallDtorDelete>(NormalAndEHCleanup);
      }
    }
    return;
  }

  const CXXRecordDecl *ClassDecl = DD->getParent();

  // Unions have no bases and do not call field destructors.
  if (ClassDecl->isUnion())
    return;

  // The complete-destructor phase just destructs all the virtual bases.
  if (DtorType == Dtor_Complete) {
    // Poison the vtable pointer such that access after the base
    // and member destructors are invoked is invalid.
    if (CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor &&
        SanOpts.has(SanitizerKind::Memory) && ClassDecl->getNumVBases() &&
        ClassDecl->isPolymorphic())
      EHStack.pushCleanup<SanitizeDtorVTable>(NormalAndEHCleanup, DD);

    // We push them in the forward order so that they'll be popped in
    // the reverse order.
    for (const auto &Base : ClassDecl->vbases()) {
      auto *BaseClassDecl = Base.getType()->castAsCXXRecordDecl();
      if (BaseClassDecl->hasTrivialDestructor()) {
        // Under SanitizeMemoryUseAfterDtor, poison the trivial base class
        // memory. For non-trival base classes the same is done in the class
        // destructor.
        if (CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor &&
            SanOpts.has(SanitizerKind::Memory) && !BaseClassDecl->isEmpty())
          EHStack.pushCleanup<SanitizeDtorTrivialBase>(NormalAndEHCleanup,
                                                       BaseClassDecl,
                                                       /*BaseIsVirtual*/ true);
      } else {
        EHStack.pushCleanup<CallBaseDtor>(NormalAndEHCleanup, BaseClassDecl,
                                          /*BaseIsVirtual*/ true);
      }
    }

    return;
  }

  assert(DtorType == Dtor_Base);
  // Poison the vtable pointer if it has no virtual bases, but inherits
  // virtual functions.
  if (CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor &&
      SanOpts.has(SanitizerKind::Memory) && !ClassDecl->getNumVBases() &&
      ClassDecl->isPolymorphic())
    EHStack.pushCleanup<SanitizeDtorVTable>(NormalAndEHCleanup, DD);

  // Destroy non-virtual bases.
  for (const auto &Base : ClassDecl->bases()) {
    // Ignore virtual bases.
    if (Base.isVirtual())
      continue;

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

    if (BaseClassDecl->hasTrivialDestructor()) {
      if (CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor &&
          SanOpts.has(SanitizerKind::Memory) && !BaseClassDecl->isEmpty())
        EHStack.pushCleanup<SanitizeDtorTrivialBase>(NormalAndEHCleanup,
                                                     BaseClassDecl,
                                                     /*BaseIsVirtual*/ false);
    } else {
      EHStack.pushCleanup<CallBaseDtor>(NormalAndEHCleanup, BaseClassDecl,
                                        /*BaseIsVirtual*/ false);
    }
  }

  // Poison fields such that access after their destructors are
  // invoked, and before the base class destructor runs, is invalid.
  bool SanitizeFields = CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor &&
                        SanOpts.has(SanitizerKind::Memory);
  SanitizeDtorCleanupBuilder SanitizeBuilder(getContext(), EHStack, DD);

  // Destroy direct fields.
  for (const auto *Field : ClassDecl->fields()) {
    if (SanitizeFields)
      SanitizeBuilder.PushCleanupForField(Field);

    QualType type = Field->getType();
    QualType::DestructionKind dtorKind = type.isDestructedType();
    if (!dtorKind)
      continue;

    // Anonymous union members do not have their destructors called.
    const RecordType *RT = type->getAsUnionType();
    if (RT && RT->getDecl()->isAnonymousStructOrUnion())
      continue;

    CleanupKind cleanupKind = getCleanupKind(dtorKind);
    EHStack.pushCleanup<DestroyField>(
        cleanupKind, Field, getDestroyer(dtorKind), cleanupKind & EHCleanup);
  }

  if (SanitizeFields)
    SanitizeBuilder.End();
}

/// EmitCXXAggrConstructorCall - Emit a loop to call a particular
/// constructor for each of several members of an array.
///
/// \param ctor the constructor to call for each element
/// \param arrayType the type of the array to initialize
/// \param arrayBegin an arrayType*
/// \param zeroInitialize true if each element should be
///   zero-initialized before it is constructed
void CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor,
                                                 const ArrayType *arrayType,
                                                 Address arrayBegin,
                                                 const CXXConstructExpr *E,
                                                 bool NewPointerIsChecked,
                                                 bool zeroInitialize) {
  QualType elementType;
  llvm::Value *numElements =
      emitArrayLength(arrayType, elementType, arrayBegin);

  EmitCXXAggrConstructorCall(ctor, numElements, arrayBegin, E,
                             NewPointerIsChecked, zeroInitialize);
}

/// EmitCXXAggrConstructorCall - Emit a loop to call a particular
/// constructor for each of several members of an array.
///
/// \param ctor the constructor to call for each element
/// \param numElements the number of elements in the array;
///   may be zero
/// \param arrayBase a T*, where T is the type constructed by ctor
/// \param zeroInitialize true if each element should be
///   zero-initialized before it is constructed
void CodeGenFunction::EmitCXXAggrConstructorCall(
    const CXXConstructorDecl *ctor, llvm::Value *numElements, Address arrayBase,
    const CXXConstructExpr *E, bool NewPointerIsChecked, bool zeroInitialize) {
  // It's legal for numElements to be zero.  This can happen both
  // dynamically, because x can be zero in 'new A[x]', and statically,
  // because of GCC extensions that permit zero-length arrays.  There
  // are probably legitimate places where we could assume that this
  // doesn't happen, but it's not clear that it's worth it.
  llvm::CondBrInst *zeroCheckBranch = nullptr;

  // Optimize for a constant count.
  llvm::ConstantInt *constantCount = dyn_cast<llvm::ConstantInt>(numElements);
  if (constantCount) {
    // Just skip out if the constant count is zero.
    if (constantCount->isZero())
      return;

    // Otherwise, emit the check.
  } else {
    llvm::BasicBlock *loopBB = createBasicBlock("new.ctorloop");
    llvm::Value *iszero = Builder.CreateIsNull(numElements, "isempty");
    zeroCheckBranch = Builder.CreateCondBr(iszero, loopBB, loopBB);
    EmitBlock(loopBB);
  }

  // Find the end of the array.
  llvm::Type *elementType = arrayBase.getElementType();
  llvm::Value *arrayBegin = arrayBase.emitRawPointer(*this);
  llvm::Value *arrayEnd = Builder.CreateInBoundsGEP(
      elementType, arrayBegin, numElements, "arrayctor.end");

  // Enter the loop, setting up a phi for the current location to initialize.
  llvm::BasicBlock *entryBB = Builder.GetInsertBlock();
  llvm::BasicBlock *loopBB = createBasicBlock("arrayctor.loop");
  EmitBlock(loopBB);
  llvm::PHINode *cur =
      Builder.CreatePHI(arrayBegin->getType(), 2, "arrayctor.cur");
  cur->addIncoming(arrayBegin, entryBB);

  // Inside the loop body, emit the constructor call on the array element.
  if (CGM.shouldEmitConvergenceTokens())
    ConvergenceTokenStack.push_back(emitConvergenceLoopToken(loopBB));

  // The alignment of the base, adjusted by the size of a single element,
  // provides a conservative estimate of the alignment of every element.
  // (This assumes we never start tracking offsetted alignments.)
  //
  // Note that these are complete objects and so we don't need to
  // use the non-virtual size or alignment.
  CanQualType type = getContext().getCanonicalTagType(ctor->getParent());
  CharUnits eltAlignment = arrayBase.getAlignment().alignmentOfArrayElement(
      getContext().getTypeSizeInChars(type));
  Address curAddr = Address(cur, elementType, eltAlignment);

  // Zero initialize the storage, if requested.
  if (zeroInitialize)
    EmitNullInitialization(curAddr, type);

  // C++ [class.temporary]p4:
  // There are two contexts in which temporaries are destroyed at a different
  // point than the end of the full-expression. The first context is when a
  // default constructor is called to initialize an element of an array.
  // If the constructor has one or more default arguments, the destruction of
  // every temporary created in a default argument expression is sequenced
  // before the construction of the next array element, if any.

  {
    RunCleanupsScope Scope(*this);

    // Evaluate the constructor and its arguments in a regular
    // partial-destroy cleanup.
    if (getLangOpts().Exceptions &&
        !ctor->getParent()->hasTrivialDestructor()) {
      Destroyer *destroyer = destroyCXXObject;
      pushRegularPartialArrayCleanup(arrayBegin, cur, type, eltAlignment,
                                     *destroyer);
    }
    auto currAVS = AggValueSlot::forAddr(
        curAddr, type.getQualifiers(), AggValueSlot::IsDestructed,
        AggValueSlot::DoesNotNeedGCBarriers, AggValueSlot::IsNotAliased,
        AggValueSlot::DoesNotOverlap, AggValueSlot::IsNotZeroed,
        NewPointerIsChecked ? AggValueSlot::IsSanitizerChecked
                            : AggValueSlot::IsNotSanitizerChecked);
    EmitCXXConstructorCall(ctor, Ctor_Complete, /*ForVirtualBase=*/false,
                           /*Delegating=*/false, currAVS, E);
  }

  // Go to the next element.
  llvm::Value *next = Builder.CreateInBoundsGEP(
      elementType, cur, llvm::ConstantInt::get(SizeTy, 1), "arrayctor.next");
  cur->addIncoming(next, Builder.GetInsertBlock());

  // Check whether that's the end of the loop.
  llvm::Value *done = Builder.CreateICmpEQ(next, arrayEnd, "arrayctor.done");
  llvm::BasicBlock *contBB = createBasicBlock("arrayctor.cont");
  Builder.CreateCondBr(done, contBB, loopBB);

  // Patch the earlier check to skip over the loop.
  if (zeroCheckBranch)
    zeroCheckBranch->setSuccessor(0, contBB);

  if (CGM.shouldEmitConvergenceTokens())
    ConvergenceTokenStack.pop_back();

  EmitBlock(contBB);
}

void CodeGenFunction::destroyCXXObject(CodeGenFunction &CGF, Address addr,
                                       QualType type) {
  const CXXDestructorDecl *dtor = type->castAsCXXRecordDecl()->getDestructor();
  assert(!dtor->isTrivial());
  CGF.EmitCXXDestructorCall(dtor, Dtor_Complete, /*for vbase*/ false,
                            /*Delegating=*/false, addr, type);
}

void CodeGenFunction::EmitCXXConstructorCall(
    const CXXConstructorDecl *D, CXXCtorType Type, bool ForVirtualBase,
    bool Delegating, AggValueSlot ThisAVS, const CXXConstructExpr *E) {
  CallArgList Args;
  Address This = ThisAVS.getAddress();
  LangAS SlotAS = ThisAVS.getQualifiers().getAddressSpace();
  LangAS ThisAS = D->getFunctionObjectParameterType().getAddressSpace();
  llvm::Value *ThisPtr =
      getAsNaturalPointerTo(This, D->getThisType()->getPointeeType());

  if (SlotAS != ThisAS) {
    unsigned TargetThisAS = getContext().getTargetAddressSpace(ThisAS);
    llvm::Type *NewType =
        llvm::PointerType::get(getLLVMContext(), TargetThisAS);
    ThisPtr = performAddrSpaceCast(ThisPtr, NewType);
  }

  // Push the this ptr.
  Args.add(RValue::get(ThisPtr), D->getThisType());

  // If this is a trivial constructor, emit a memcpy now before we lose
  // the alignment information on the argument.
  // FIXME: It would be better to preserve alignment information into CallArg.
  if (D->isMemcpyEquivalentSpecialMember(getContext())) {
    assert(E->getNumArgs() == 1 && "unexpected argcount for trivial ctor");

    const Expr *Arg = E->getArg(0);
    LValue Src = EmitCheckedLValue(Arg, TCK_Load);
    CanQualType DestTy = getContext().getCanonicalTagType(D->getParent());
    LValue Dest = MakeAddrLValue(This, DestTy);
    EmitAggregateCopyCtor(Dest, Src, ThisAVS.mayOverlap());
    return;
  }

  // Add the rest of the user-supplied arguments.
  const FunctionProtoType *FPT = D->getType()->castAs<FunctionProtoType>();
  EvaluationOrder Order = E->isListInitialization()
                              ? EvaluationOrder::ForceLeftToRight
                              : EvaluationOrder::Default;
  EmitCallArgs(Args, FPT, E->arguments(), E->getConstructor(),
               /*ParamsToSkip*/ 0, Order);

  EmitCXXConstructorCall(D, Type, ForVirtualBase, Delegating, This, Args,
                         ThisAVS.mayOverlap(), E->getExprLoc(),
                         ThisAVS.isSanitizerChecked());
}

static bool canEmitDelegateCallArgs(CodeGenFunction &CGF,
                                    const CXXConstructorDecl *Ctor,
                                    CXXCtorType Type, CallArgList &Args) {
  // We can't forward a variadic call.
  if (Ctor->isVariadic())
    return false;

  if (CGF.getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee()) {
    // If the parameters are callee-cleanup, it's not safe to forward.
    for (auto *P : Ctor->parameters())
      if (P->needsDestruction(CGF.getContext()))
        return false;

    // Likewise if they're inalloca.
    const CGFunctionInfo &Info = CGF.CGM.getTypes().arrangeCXXConstructorCall(
        Args, Ctor, Type, 0, 0, CGF.getCurrentFunctionDecl());
    if (Info.usesInAlloca())
      return false;
  }

  // Anything else should be OK.
  return true;
}

void CodeGenFunction::EmitCXXConstructorCall(
    const CXXConstructorDecl *D, CXXCtorType Type, bool ForVirtualBase,
    bool Delegating, Address This, CallArgList &Args,
    AggValueSlot::Overlap_t Overlap, SourceLocation Loc,
    bool NewPointerIsChecked, llvm::CallBase **CallOrInvoke) {
  const CXXRecordDecl *ClassDecl = D->getParent();

  if (!NewPointerIsChecked)
    EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, Loc, This,
                  getContext().getCanonicalTagType(ClassDecl),
                  CharUnits::Zero());

  if (D->isTrivial() && D->isDefaultConstructor()) {
    assert(Args.size() == 1 && "trivial default ctor with args");
    return;
  }

  // If this is a trivial constructor, just emit what's needed. If this is a
  // union copy constructor, we must emit a memcpy, because the AST does not
  // model that copy.
  if (D->isMemcpyEquivalentSpecialMember(getContext())) {
    assert(Args.size() == 2 && "unexpected argcount for trivial ctor");
    QualType SrcTy = D->getParamDecl(0)->getType().getNonReferenceType();
    Address Src = makeNaturalAddressForPointer(
        Args[1].getRValue(*this).getScalarVal(), SrcTy);
    LValue SrcLVal = MakeAddrLValue(Src, SrcTy);
    CanQualType DestTy = getContext().getCanonicalTagType(ClassDecl);
    LValue DestLVal = MakeAddrLValue(This, DestTy);
    EmitAggregateCopyCtor(DestLVal, SrcLVal, Overlap);
    return;
  }

  bool PassPrototypeArgs = true;
  // Check whether we can actually emit the constructor before trying to do so.
  if (auto Inherited = D->getInheritedConstructor()) {
    PassPrototypeArgs = getTypes().inheritingCtorHasParams(Inherited, Type);
    if (PassPrototypeArgs && !canEmitDelegateCallArgs(*this, D, Type, Args)) {
      EmitInlinedInheritingCXXConstructorCall(D, Type, ForVirtualBase,
                                              Delegating, Args);
      return;
    }
  }

  // Insert any ABI-specific implicit constructor arguments.
  CGCXXABI::AddedStructorArgCounts ExtraArgs =
      CGM.getCXXABI().addImplicitConstructorArgs(*this, D, Type, ForVirtualBase,
                                                 Delegating, Args);

  // Emit the call.
  llvm::Constant *CalleePtr = CGM.getAddrOfCXXStructor(GlobalDecl(D, Type));
  const CGFunctionInfo &Info = CGM.getTypes().arrangeCXXConstructorCall(
      Args, D, Type, ExtraArgs.Prefix, ExtraArgs.Suffix,
      getCurrentFunctionDecl(), PassPrototypeArgs);
  CGCallee Callee = CGCallee::forDirect(CalleePtr, GlobalDecl(D, Type));
  EmitCall(Info, Callee, ReturnValueSlot(), Args, CallOrInvoke, false, Loc);

  // Generate vtable assumptions if we're constructing a complete object
  // with a vtable.  We don't do this for base subobjects for two reasons:
  // first, it's incorrect for classes with virtual bases, and second, we're
  // about to overwrite the vptrs anyway.
  // We also have to make sure if we can refer to vtable:
  // - Otherwise we can refer to vtable if it's safe to speculatively emit.
  // FIXME: If vtable is used by ctor/dtor, or if vtable is external and we are
  // sure that definition of vtable is not hidden,
  // then we are always safe to refer to it.
  // FIXME: It looks like InstCombine is very inefficient on dealing with
  // assumes. Make assumption loads require -fstrict-vtable-pointers
  // temporarily.
  if (CGM.getCodeGenOpts().OptimizationLevel > 0 &&
      ClassDecl->isDynamicClass() && Type != Ctor_Base &&
      CGM.getCXXABI().canSpeculativelyEmitVTable(ClassDecl) &&
      CGM.getCodeGenOpts().StrictVTablePointers)
    EmitVTableAssumptionLoads(ClassDecl, This);
}

void CodeGenFunction::EmitInheritedCXXConstructorCall(
    const CXXConstructorDecl *D, bool ForVirtualBase, Address This,
    bool InheritedFromVBase, const CXXInheritedCtorInitExpr *E) {
  CallArgList Args;
  CallArg ThisArg(RValue::get(getAsNaturalPointerTo(
                      This, D->getThisType()->getPointeeType())),
                  D->getThisType());

  // Forward the parameters.
  if (InheritedFromVBase &&
      CGM.getTarget().getCXXABI().hasConstructorVariants()) {
    // Nothing to do; this construction is not responsible for constructing
    // the base class containing the inherited constructor.
    // FIXME: Can we just pass undef's for the remaining arguments if we don't
    // have constructor variants?
    Args.push_back(ThisArg);
  } else if (!CXXInheritedCtorInitExprArgs.empty()) {
    // The inheriting constructor was inlined; just inject its arguments.
    assert(CXXInheritedCtorInitExprArgs.size() >= D->getNumParams() &&
           "wrong number of parameters for inherited constructor call");
    Args = CXXInheritedCtorInitExprArgs;
    Args[0] = ThisArg;
  } else {
    // The inheriting constructor was not inlined. Emit delegating arguments.
    Args.push_back(ThisArg);
    const auto *OuterCtor = cast<CXXConstructorDecl>(CurCodeDecl);
    assert(OuterCtor->getNumParams() == D->getNumParams());
    assert(!OuterCtor->isVariadic() && "should have been inlined");

    for (const auto *Param : OuterCtor->parameters()) {
      assert(getContext().hasSameUnqualifiedType(
          OuterCtor->getParamDecl(Param->getFunctionScopeIndex())->getType(),
          Param->getType()));
      EmitDelegateCallArg(Args, Param, E->getLocation());

      // Forward __attribute__(pass_object_size).
      if (Param->hasAttr<PassObjectSizeAttr>()) {
        auto *POSParam = SizeArguments[Param];
        assert(POSParam && "missing pass_object_size value for forwarding");
        EmitDelegateCallArg(Args, POSParam, E->getLocation());
      }
    }
  }

  EmitCXXConstructorCall(D, Ctor_Base, ForVirtualBase, /*Delegating*/ false,
                         This, Args, AggValueSlot::MayOverlap, E->getLocation(),
                         /*NewPointerIsChecked*/ true);
}

void CodeGenFunction::EmitInlinedInheritingCXXConstructorCall(
    const CXXConstructorDecl *Ctor, CXXCtorType CtorType, bool ForVirtualBase,
    bool Delegating, CallArgList &Args) {
  GlobalDecl GD(Ctor, CtorType);
  InlinedInheritingConstructorScope Scope(*this, GD);
  ApplyInlineDebugLocation DebugScope(*this, GD);
  RunCleanupsScope RunCleanups(*this);

  // Save the arguments to be passed to the inherited constructor.
  CXXInheritedCtorInitExprArgs = Args;

  FunctionArgList Params;
  QualType RetType = BuildFunctionArgList(CurGD, Params);
  FnRetTy = RetType;

  // Insert any ABI-specific implicit constructor arguments.
  CGM.getCXXABI().addImplicitConstructorArgs(*this, Ctor, CtorType,
                                             ForVirtualBase, Delegating, Args);

  // Emit a simplified prolog. We only need to emit the implicit params.
  assert(Args.size() >= Params.size() && "too few arguments for call");
  for (unsigned I = 0, N = Args.size(); I != N; ++I) {
    if (I < Params.size() && isa<ImplicitParamDecl>(Params[I])) {
      const RValue &RV = Args[I].getRValue(*this);
      assert(!RV.isComplex() && "complex indirect params not supported");
      ParamValue Val = RV.isScalar()
                           ? ParamValue::forDirect(RV.getScalarVal())
                           : ParamValue::forIndirect(RV.getAggregateAddress());
      EmitParmDecl(*Params[I], Val, I + 1);
    }
  }

  // Create a return value slot if the ABI implementation wants one.
  // FIXME: This is dumb, we should ask the ABI not to try to set the return
  // value instead.
  if (!RetType->isVoidType())
    ReturnValue = CreateIRTempWithoutCast(RetType, "retval.inhctor");

  CGM.getCXXABI().EmitInstanceFunctionProlog(*this);
  CXXThisValue = CXXABIThisValue;

  // Directly emit the constructor initializers.
  EmitCtorPrologue(Ctor, CtorType, Params);
}

void CodeGenFunction::EmitVTableAssumptionLoad(const VPtr &Vptr, Address This) {
  llvm::Value *VTableGlobal =
      CGM.getCXXABI().getVTableAddressPoint(Vptr.Base, Vptr.VTableClass);
  if (!VTableGlobal)
    return;

  // We can just use the base offset in the complete class.
  CharUnits NonVirtualOffset = Vptr.Base.getBaseOffset();

  if (!NonVirtualOffset.isZero())
    This =
        ApplyNonVirtualAndVirtualOffset(*this, This, NonVirtualOffset, nullptr,
                                        Vptr.VTableClass, Vptr.NearestVBase);

  llvm::Value *VPtrValue =
      GetVTablePtr(This, VTableGlobal->getType(), Vptr.VTableClass);
  llvm::Value *Cmp =
      Builder.CreateICmpEQ(VPtrValue, VTableGlobal, "cmp.vtables");
  Builder.CreateAssumption(Cmp);
}

void CodeGenFunction::EmitVTableAssumptionLoads(const CXXRecordDecl *ClassDecl,
                                                Address This) {
  if (CGM.getCXXABI().doStructorsInitializeVPtrs(ClassDecl))
    for (const VPtr &Vptr : getVTablePointers(ClassDecl))
      EmitVTableAssumptionLoad(Vptr, This);
}

void CodeGenFunction::EmitSynthesizedCXXCopyCtorCall(
    const CXXConstructorDecl *D, Address This, Address Src,
    const CXXConstructExpr *E) {
  const FunctionProtoType *FPT = D->getType()->castAs<FunctionProtoType>();

  CallArgList Args;

  // Push the this ptr.
  Args.add(RValue::get(getAsNaturalPointerTo(This, D->getThisType())),
           D->getThisType());

  // Push the src ptr.
  QualType QT = *(FPT->param_type_begin());
  llvm::Type *t = CGM.getTypes().ConvertType(QT);
  llvm::Value *Val = getAsNaturalPointerTo(Src, D->getThisType());
  llvm::Value *SrcVal = Builder.CreateBitCast(Val, t);
  Args.add(RValue::get(SrcVal), QT);

  // Skip over first argument (Src).
  EmitCallArgs(Args, FPT, drop_begin(E->arguments(), 1), E->getConstructor(),
               /*ParamsToSkip*/ 1);

  EmitCXXConstructorCall(D, Ctor_Complete, /*ForVirtualBase*/ false,
                         /*Delegating*/ false, This, Args,
                         AggValueSlot::MayOverlap, E->getExprLoc(),
                         /*NewPointerIsChecked*/ false);
}

void CodeGenFunction::EmitDelegateCXXConstructorCall(
    const CXXConstructorDecl *Ctor, CXXCtorType CtorType,
    const FunctionArgList &Args, SourceLocation Loc) {
  CallArgList DelegateArgs;

  FunctionArgList::const_iterator I = Args.begin(), E = Args.end();
  assert(I != E && "no parameters to constructor");

  // this
  Address This = LoadCXXThisAddress();
  DelegateArgs.add(RValue::get(getAsNaturalPointerTo(
                       This, (*I)->getType()->getPointeeType())),
                   (*I)->getType());
  ++I;

  // FIXME: The location of the VTT parameter in the parameter list is
  // specific to the Itanium ABI and shouldn't be hardcoded here.
  if (CGM.getCXXABI().NeedsVTTParameter(CurGD)) {
    assert(I != E && "cannot skip vtt parameter, already done with args");
    assert((*I)->getType()->isPointerType() &&
           "skipping parameter not of vtt type");
    ++I;
  }

  // Explicit arguments.
  for (; I != E; ++I) {
    const VarDecl *param = *I;
    // FIXME: per-argument source location
    EmitDelegateCallArg(DelegateArgs, param, Loc);
  }

  EmitCXXConstructorCall(Ctor, CtorType, /*ForVirtualBase=*/false,
                         /*Delegating=*/true, This, DelegateArgs,
                         AggValueSlot::MayOverlap, Loc,
                         /*NewPointerIsChecked=*/true);
}

namespace {
struct CallDelegatingCtorDtor final : EHScopeStack::Cleanup {
  const CXXDestructorDecl *Dtor;
  Address Addr;
  CXXDtorType Type;

  CallDelegatingCtorDtor(const CXXDestructorDecl *D, Address Addr,
                         CXXDtorType Type)
      : Dtor(D), Addr(Addr), Type(Type) {}

  void Emit(CodeGenFunction &CGF, Flags flags) override {
    // We are calling the destructor from within the constructor.
    // Therefore, "this" should have the expected type.
    QualType ThisTy = Dtor->getFunctionObjectParameterType();
    CGF.EmitCXXDestructorCall(Dtor, Type, /*ForVirtualBase=*/false,
                              /*Delegating=*/true, Addr, ThisTy);
  }
};
} // end anonymous namespace

void CodeGenFunction::EmitDelegatingCXXConstructorCall(
    const CXXConstructorDecl *Ctor, const FunctionArgList &Args) {
  assert(Ctor->isDelegatingConstructor());

  Address ThisPtr = LoadCXXThisAddress();

  AggValueSlot AggSlot = AggValueSlot::forAddr(
      ThisPtr, Qualifiers(), AggValueSlot::IsDestructed,
      AggValueSlot::DoesNotNeedGCBarriers, AggValueSlot::IsNotAliased,
      AggValueSlot::MayOverlap, AggValueSlot::IsNotZeroed,
      // Checks are made by the code that calls constructor.
      AggValueSlot::IsSanitizerChecked);

  EmitAggExpr(Ctor->init_begin()[0]->getInit(), AggSlot);

  const CXXRecordDecl *ClassDecl = Ctor->getParent();
  if (CGM.getLangOpts().Exceptions && !ClassDecl->hasTrivialDestructor()) {
    CXXDtorType Type =
        CurGD.getCtorType() == Ctor_Complete ? Dtor_Complete : Dtor_Base;

    EHStack.pushCleanup<CallDelegatingCtorDtor>(
        EHCleanup, ClassDecl->getDestructor(), ThisPtr, Type);
  }
}

void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *DD,
                                            CXXDtorType Type,
                                            bool ForVirtualBase,
                                            bool Delegating, Address This,
                                            QualType ThisTy) {
  CGM.getCXXABI().EmitDestructorCall(*this, DD, Type, ForVirtualBase,
                                     Delegating, This, ThisTy);
}

namespace {
struct CallLocalDtor final : EHScopeStack::Cleanup {
  const CXXDestructorDecl *Dtor;
  Address Addr;
  QualType Ty;

  CallLocalDtor(const CXXDestructorDecl *D, Address Addr, QualType Ty)
      : Dtor(D), Addr(Addr), Ty(Ty) {}

  void Emit(CodeGenFunction &CGF, Flags flags) override {
    CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete,
                              /*ForVirtualBase=*/false,
                              /*Delegating=*/false, Addr, Ty);
  }
};
} // end anonymous namespace

void CodeGenFunction::PushDestructorCleanup(const CXXDestructorDecl *D,
                                            QualType T, Address Addr) {
  EHStack.pushCleanup<CallLocalDtor>(NormalAndEHCleanup, D, Addr, T);
}

void CodeGenFunction::PushDestructorCleanup(QualType T, Address Addr) {
  CXXRecordDecl *ClassDecl = T->getAsCXXRecordDecl();
  if (!ClassDecl)
    return;
  if (ClassDecl->hasTrivialDestructor())
    return;

  const CXXDestructorDecl *D = ClassDecl->getDestructor();
  assert(D && D->isUsed() && "destructor not marked as used!");
  PushDestructorCleanup(D, T, Addr);
}

void CodeGenFunction::InitializeVTablePointer(const VPtr &Vptr) {
  // Compute the address point.
  llvm::Value *VTableAddressPoint =
      CGM.getCXXABI().getVTableAddressPointInStructor(
          *this, Vptr.VTableClass, Vptr.Base, Vptr.NearestVBase);

  if (!VTableAddressPoint)
    return;

  // Compute where to store the address point.
  llvm::Value *VirtualOffset = nullptr;
  CharUnits NonVirtualOffset = CharUnits::Zero();

  if (CGM.getCXXABI().isVirtualOffsetNeededForVTableField(*this, Vptr)) {
    // We need to use the virtual base offset offset because the virtual base
    // might have a different offset in the most derived class.

    VirtualOffset = CGM.getCXXABI().GetVirtualBaseClassOffset(
        *this, LoadCXXThisAddress(), Vptr.VTableClass, Vptr.NearestVBase);
    NonVirtualOffset = Vptr.OffsetFromNearestVBase;
  } else {
    // We can just use the base offset in the complete class.
    NonVirtualOffset = Vptr.Base.getBaseOffset();
  }

  // Apply the offsets.
  Address VTableField = LoadCXXThisAddress();
  if (!NonVirtualOffset.isZero() || VirtualOffset)
    VTableField = ApplyNonVirtualAndVirtualOffset(
        *this, VTableField, NonVirtualOffset, VirtualOffset, Vptr.VTableClass,
        Vptr.NearestVBase);

  // Finally, store the address point. Use the same LLVM types as the field to
  // support optimization.
  unsigned GlobalsAS = CGM.getDataLayout().getDefaultGlobalsAddressSpace();
  llvm::Type *PtrTy = llvm::PointerType::get(CGM.getLLVMContext(), GlobalsAS);
  // vtable field is derived from `this` pointer, therefore they should be in
  // the same addr space. Note that this might not be LLVM address space 0.
  VTableField = VTableField.withElementType(PtrTy);

  if (auto AuthenticationInfo = CGM.getVTablePointerAuthInfo(
          this, Vptr.Base.getBase(), VTableField.emitRawPointer(*this)))
    VTableAddressPoint =
        EmitPointerAuthSign(*AuthenticationInfo, VTableAddressPoint);

  llvm::StoreInst *Store = Builder.CreateStore(VTableAddressPoint, VTableField);
  TBAAAccessInfo TBAAInfo = CGM.getTBAAVTablePtrAccessInfo(PtrTy);
  CGM.DecorateInstructionWithTBAA(Store, TBAAInfo);
  if (CGM.getCodeGenOpts().OptimizationLevel > 0 &&
      CGM.getCodeGenOpts().StrictVTablePointers)
    CGM.DecorateInstructionWithInvariantGroup(Store, Vptr.VTableClass);
}

CodeGenFunction::VPtrsVector
CodeGenFunction::getVTablePointers(const CXXRecordDecl *VTableClass) {
  CodeGenFunction::VPtrsVector VPtrsResult;
  VisitedVirtualBasesSetTy VBases;
  getVTablePointers(BaseSubobject(VTableClass, CharUnits::Zero()),
                    /*NearestVBase=*/nullptr,
                    /*OffsetFromNearestVBase=*/CharUnits::Zero(),
                    /*BaseIsNonVirtualPrimaryBase=*/false, VTableClass, VBases,
                    VPtrsResult);
  return VPtrsResult;
}

void CodeGenFunction::getVTablePointers(BaseSubobject Base,
                                        const CXXRecordDecl *NearestVBase,
                                        CharUnits OffsetFromNearestVBase,
                                        bool BaseIsNonVirtualPrimaryBase,
                                        const CXXRecordDecl *VTableClass,
                                        VisitedVirtualBasesSetTy &VBases,
                                        VPtrsVector &Vptrs) {
  // If this base is a non-virtual primary base the address point has already
  // been set.
  if (!BaseIsNonVirtualPrimaryBase) {
    // Initialize the vtable pointer for this base.
    VPtr Vptr = {Base, NearestVBase, OffsetFromNearestVBase, VTableClass};
    Vptrs.push_back(Vptr);
  }

  const CXXRecordDecl *RD = Base.getBase();

  // Traverse bases.
  for (const auto &I : RD->bases()) {
    auto *BaseDecl = I.getType()->castAsCXXRecordDecl();
    // Ignore classes without a vtable.
    if (!BaseDecl->isDynamicClass())
      continue;

    CharUnits BaseOffset;
    CharUnits BaseOffsetFromNearestVBase;
    bool BaseDeclIsNonVirtualPrimaryBase;

    if (I.isVirtual()) {
      // Check if we've visited this virtual base before.
      if (!VBases.insert(BaseDecl).second)
        continue;

      const ASTRecordLayout &Layout =
          getContext().getASTRecordLayout(VTableClass);

      BaseOffset = Layout.getVBaseClassOffset(BaseDecl);
      BaseOffsetFromNearestVBase = CharUnits::Zero();
      BaseDeclIsNonVirtualPrimaryBase = false;
    } else {
      const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);

      BaseOffset = Base.getBaseOffset() + Layout.getBaseClassOffset(BaseDecl);
      BaseOffsetFromNearestVBase =
          OffsetFromNearestVBase + Layout.getBaseClassOffset(BaseDecl);
      BaseDeclIsNonVirtualPrimaryBase = Layout.getPrimaryBase() == BaseDecl;
    }

    getVTablePointers(
        BaseSubobject(BaseDecl, BaseOffset),
        I.isVirtual() ? BaseDecl : NearestVBase, BaseOffsetFromNearestVBase,
        BaseDeclIsNonVirtualPrimaryBase, VTableClass, VBases, Vptrs);
  }
}

void CodeGenFunction::InitializeVTablePointers(const CXXRecordDecl *RD) {
  // Ignore classes without a vtable.
  if (!RD->isDynamicClass())
    return;

  // Initialize the vtable pointers for this class and all of its bases.
  if (CGM.getCXXABI().doStructorsInitializeVPtrs(RD))
    for (const VPtr &Vptr : getVTablePointers(RD))
      InitializeVTablePointer(Vptr);

  if (RD->getNumVBases())
    CGM.getCXXABI().initializeHiddenVirtualInheritanceMembers(*this, RD);
}

llvm::Value *CodeGenFunction::GetVTablePtr(Address This, llvm::Type *VTableTy,
                                           const CXXRecordDecl *RD,
                                           VTableAuthMode AuthMode) {
  Address VTablePtrSrc = This.withElementType(VTableTy);
  llvm::Instruction *VTable = Builder.CreateLoad(VTablePtrSrc, "vtable");
  TBAAAccessInfo TBAAInfo = CGM.getTBAAVTablePtrAccessInfo(VTableTy);
  CGM.DecorateInstructionWithTBAA(VTable, TBAAInfo);

  if (auto AuthenticationInfo =
          CGM.getVTablePointerAuthInfo(this, RD, This.emitRawPointer(*this))) {
    if (AuthMode != VTableAuthMode::UnsafeUbsanStrip) {
      VTable = cast<llvm::Instruction>(
          EmitPointerAuthAuth(*AuthenticationInfo, VTable));
      if (AuthMode == VTableAuthMode::MustTrap) {
        // This is clearly suboptimal but until we have an ability
        // to rely on the authentication intrinsic trapping and force
        // an authentication to occur we don't really have a choice.
        VTable =
            cast<llvm::Instruction>(Builder.CreateBitCast(VTable, Int8PtrTy));
        Builder.CreateLoad(RawAddress(VTable, Int8Ty, CGM.getPointerAlign()),
                           /* IsVolatile */ true);
      }
    } else {
      VTable = cast<llvm::Instruction>(EmitPointerAuthAuth(
          CGPointerAuthInfo(0, PointerAuthenticationMode::Strip, false, false,
                            nullptr),
          VTable));
    }
  }

  if (CGM.getCodeGenOpts().OptimizationLevel > 0 &&
      CGM.getCodeGenOpts().StrictVTablePointers)
    CGM.DecorateInstructionWithInvariantGroup(VTable, RD);

  return VTable;
}

// If a class has a single non-virtual base and does not introduce or override
// virtual member functions or fields, it will have the same layout as its base.
// This function returns the least derived such class.
//
// Casting an instance of a base class to such a derived class is technically
// undefined behavior, but it is a relatively common hack for introducing member
// functions on class instances with specific properties (e.g. llvm::Operator)
// that works under most compilers and should not have security implications, so
// we allow it by default. It can be disabled with -fsanitize=cfi-cast-strict.
static const CXXRecordDecl *
LeastDerivedClassWithSameLayout(const CXXRecordDecl *RD) {
  if (!RD->field_empty())
    return RD;

  if (RD->getNumVBases() != 0)
    return RD;

  if (RD->getNumBases() != 1)
    return RD;

  for (const CXXMethodDecl *MD : RD->methods()) {
    if (MD->isVirtual()) {
      // Virtual member functions are only ok if they are implicit destructors
      // because the implicit destructor will have the same semantics as the
      // base class's destructor if no fields are added.
      if (isa<CXXDestructorDecl>(MD) && MD->isImplicit())
        continue;
      return RD;
    }
  }

  return LeastDerivedClassWithSameLayout(
      RD->bases_begin()->getType()->getAsCXXRecordDecl());
}

void CodeGenFunction::EmitTypeMetadataCodeForVCall(const CXXRecordDecl *RD,
                                                   llvm::Value *VTable,
                                                   SourceLocation Loc) {
  if (SanOpts.has(SanitizerKind::CFIVCall))
    EmitVTablePtrCheckForCall(RD, VTable, CodeGenFunction::CFITCK_VCall, Loc);
  // Emit the intrinsics of (type_test and assume) for the features of WPD and
  // speculative devirtualization. For WPD, emit the intrinsics only for the
  // case of non_public LTO visibility.
  // TODO: refactor this condition and similar ones into a function (e.g.,
  // ShouldEmitDevirtualizationMD) to encapsulate the details of the different
  // types of devirtualization.
  else if ((CGM.getCodeGenOpts().WholeProgramVTables &&
            !CGM.AlwaysHasLTOVisibilityPublic(RD)) ||
           CGM.getCodeGenOpts().DevirtualizeSpeculatively) {
    CanQualType Ty = CGM.getContext().getCanonicalTagType(RD);
    llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(Ty);
    llvm::Value *TypeId = llvm::MetadataAsValue::get(CGM.getLLVMContext(), MD);

    // If we already know that the call has hidden LTO visibility, emit
    // @llvm.type.test(). Otherwise emit @llvm.public.type.test(), which WPD
    // will convert to @llvm.type.test() if we assert at link time that we have
    // whole program visibility.
    llvm::Intrinsic::ID IID = CGM.HasHiddenLTOVisibility(RD)
                                  ? llvm::Intrinsic::type_test
                                  : llvm::Intrinsic::public_type_test;
    llvm::Value *TypeTest =
        Builder.CreateCall(CGM.getIntrinsic(IID), {VTable, TypeId});
    Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::assume), TypeTest);
  }
}

/// Converts the CFITypeCheckKind into SanitizerKind::SanitizerOrdinal and
/// llvm::SanitizerStatKind.
static std::pair<SanitizerKind::SanitizerOrdinal, llvm::SanitizerStatKind>
SanitizerInfoFromCFICheckKind(CodeGenFunction::CFITypeCheckKind TCK) {
  switch (TCK) {
  case CodeGenFunction::CFITCK_VCall:
    return std::make_pair(SanitizerKind::SO_CFIVCall, llvm::SanStat_CFI_VCall);
  case CodeGenFunction::CFITCK_NVCall:
    return std::make_pair(SanitizerKind::SO_CFINVCall,
                          llvm::SanStat_CFI_NVCall);
  case CodeGenFunction::CFITCK_DerivedCast:
    return std::make_pair(SanitizerKind::SO_CFIDerivedCast,
                          llvm::SanStat_CFI_DerivedCast);
  case CodeGenFunction::CFITCK_UnrelatedCast:
    return std::make_pair(SanitizerKind::SO_CFIUnrelatedCast,
                          llvm::SanStat_CFI_UnrelatedCast);
  case CodeGenFunction::CFITCK_ICall:
  case CodeGenFunction::CFITCK_NVMFCall:
  case CodeGenFunction::CFITCK_VMFCall:
    llvm_unreachable("unexpected sanitizer kind");
  }
  llvm_unreachable("Unknown CFITypeCheckKind enum");
}

void CodeGenFunction::EmitVTablePtrCheckForCall(const CXXRecordDecl *RD,
                                                llvm::Value *VTable,
                                                CFITypeCheckKind TCK,
                                                SourceLocation Loc) {
  if (!SanOpts.has(SanitizerKind::CFICastStrict))
    RD = LeastDerivedClassWithSameLayout(RD);

  auto [Ordinal, _] = SanitizerInfoFromCFICheckKind(TCK);
  SanitizerDebugLocation SanScope(this, {Ordinal},
                                  SanitizerHandler::CFICheckFail);

  EmitVTablePtrCheck(RD, VTable, TCK, Loc);
}

void CodeGenFunction::EmitVTablePtrCheckForCast(QualType T, Address Derived,
                                                bool MayBeNull,
                                                CFITypeCheckKind TCK,
                                                SourceLocation Loc) {
  if (!getLangOpts().CPlusPlus)
    return;

  const auto *ClassDecl = T->getAsCXXRecordDecl();
  if (!ClassDecl)
    return;

  if (!ClassDecl->isCompleteDefinition() || !ClassDecl->isDynamicClass())
    return;

  if (!SanOpts.has(SanitizerKind::CFICastStrict))
    ClassDecl = LeastDerivedClassWithSameLayout(ClassDecl);

  auto [Ordinal, _] = SanitizerInfoFromCFICheckKind(TCK);
  SanitizerDebugLocation SanScope(this, {Ordinal},
                                  SanitizerHandler::CFICheckFail);

  llvm::BasicBlock *ContBlock = nullptr;

  if (MayBeNull) {
    llvm::Value *DerivedNotNull =
        Builder.CreateIsNotNull(Derived.emitRawPointer(*this), "cast.nonnull");

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

    Builder.CreateCondBr(DerivedNotNull, CheckBlock, ContBlock);

    EmitBlock(CheckBlock);
  }

  llvm::Value *VTable;
  std::tie(VTable, ClassDecl) =
      CGM.getCXXABI().LoadVTablePtr(*this, Derived, ClassDecl);

  EmitVTablePtrCheck(ClassDecl, VTable, TCK, Loc);

  if (MayBeNull) {
    Builder.CreateBr(ContBlock);
    EmitBlock(ContBlock);
  }
}

void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD,
                                         llvm::Value *VTable,
                                         CFITypeCheckKind TCK,
                                         SourceLocation Loc) {
  assert(IsSanitizerScope);

  if (!CGM.getCodeGenOpts().SanitizeCfiCrossDso &&
      !CGM.HasHiddenLTOVisibility(RD))
    return;

  auto [M, SSK] = SanitizerInfoFromCFICheckKind(TCK);

  std::string TypeName = RD->getQualifiedNameAsString();
  if (getContext().getNoSanitizeList().containsType(
          SanitizerMask::bitPosToMask(M), TypeName))
    return;

  EmitSanitizerStatReport(SSK);

  CanQualType T = CGM.getContext().getCanonicalTagType(RD);
  llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(T);
  llvm::Value *TypeId = llvm::MetadataAsValue::get(getLLVMContext(), MD);

  llvm::Value *TypeTest = Builder.CreateCall(
      CGM.getIntrinsic(llvm::Intrinsic::type_test), {VTable, TypeId});

  llvm::Constant *StaticData[] = {
      llvm::ConstantInt::get(Int8Ty, TCK),
      EmitCheckSourceLocation(Loc),
      EmitCheckTypeDescriptor(T),
  };

  auto CrossDsoTypeId = CGM.CreateCrossDsoCfiTypeId(MD);
  if (CGM.getCodeGenOpts().SanitizeCfiCrossDso && CrossDsoTypeId) {
    EmitCfiSlowPathCheck(M, TypeTest, CrossDsoTypeId, VTable, StaticData);
    return;
  }

  if (CGM.getCodeGenOpts().SanitizeTrap.has(M)) {
    bool NoMerge = !CGM.getCodeGenOpts().SanitizeMergeHandlers.has(M);
    EmitTrapCheck(TypeTest, SanitizerHandler::CFICheckFail, NoMerge);
    return;
  }

  llvm::Value *AllVtables = llvm::MetadataAsValue::get(
      CGM.getLLVMContext(),
      llvm::MDString::get(CGM.getLLVMContext(), "all-vtables"));
  llvm::Value *ValidVtable = Builder.CreateCall(
      CGM.getIntrinsic(llvm::Intrinsic::type_test), {VTable, AllVtables});
  EmitCheck(std::make_pair(TypeTest, M), SanitizerHandler::CFICheckFail,
            StaticData, {VTable, ValidVtable});
}

bool CodeGenFunction::ShouldEmitVTableTypeCheckedLoad(const CXXRecordDecl *RD) {
  if ((!CGM.getCodeGenOpts().WholeProgramVTables ||
       !CGM.HasHiddenLTOVisibility(RD)) &&
      !CGM.getCodeGenOpts().DevirtualizeSpeculatively)
    return false;

  if (CGM.getCodeGenOpts().VirtualFunctionElimination)
    return true;

  if (!SanOpts.has(SanitizerKind::CFIVCall) ||
      !CGM.getCodeGenOpts().SanitizeTrap.has(SanitizerKind::CFIVCall))
    return false;

  std::string TypeName = RD->getQualifiedNameAsString();
  return !getContext().getNoSanitizeList().containsType(SanitizerKind::CFIVCall,
                                                        TypeName);
}

llvm::Value *CodeGenFunction::EmitVTableTypeCheckedLoad(
    const CXXRecordDecl *RD, llvm::Value *VTable, llvm::Type *VTableTy,
    uint64_t VTableByteOffset) {
  auto CheckOrdinal = SanitizerKind::SO_CFIVCall;
  auto CheckHandler = SanitizerHandler::CFICheckFail;
  SanitizerDebugLocation SanScope(this, {CheckOrdinal}, CheckHandler);

  EmitSanitizerStatReport(llvm::SanStat_CFI_VCall);

  CanQualType T = CGM.getContext().getCanonicalTagType(RD);
  llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(T);
  llvm::Value *TypeId = llvm::MetadataAsValue::get(CGM.getLLVMContext(), MD);

  auto CheckedLoadIntrinsic = CGM.getLangOpts().RelativeCXXABIVTables
                                  ? llvm::Intrinsic::type_checked_load_relative
                                  : llvm::Intrinsic::type_checked_load;
  llvm::Value *CheckedLoad = Builder.CreateCall(
      CGM.getIntrinsic(CheckedLoadIntrinsic),
      {VTable, llvm::ConstantInt::get(Int32Ty, VTableByteOffset), TypeId});

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

  std::string TypeName = RD->getQualifiedNameAsString();
  if (SanOpts.has(SanitizerKind::CFIVCall) &&
      !getContext().getNoSanitizeList().containsType(SanitizerKind::CFIVCall,
                                                     TypeName)) {
    EmitCheck(std::make_pair(CheckResult, CheckOrdinal), CheckHandler, {}, {});
  }

  return Builder.CreateBitCast(Builder.CreateExtractValue(CheckedLoad, 0),
                               VTableTy);
}

void CodeGenFunction::EmitForwardingCallToLambda(
    const CXXMethodDecl *callOperator, CallArgList &callArgs,
    const CGFunctionInfo *calleeFnInfo, llvm::Constant *calleePtr) {
  // Get the address of the call operator.
  if (!calleeFnInfo)
    calleeFnInfo = &CGM.getTypes().arrangeCXXMethodDeclaration(callOperator);

  if (!calleePtr)
    calleePtr =
        CGM.GetAddrOfFunction(GlobalDecl(callOperator),
                              CGM.getTypes().GetFunctionType(*calleeFnInfo));

  // Prepare the return slot.
  const FunctionProtoType *FPT =
      callOperator->getType()->castAs<FunctionProtoType>();
  QualType resultType = FPT->getReturnType();
  ReturnValueSlot returnSlot;
  if (!resultType->isVoidType() &&
      calleeFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect &&
      !hasScalarEvaluationKind(calleeFnInfo->getReturnType()))
    returnSlot =
        ReturnValueSlot(ReturnValue, resultType.isVolatileQualified(),
                        /*IsUnused=*/false, /*IsExternallyDestructed=*/true);

  // We don't need to separately arrange the call arguments because
  // the call can't be variadic anyway --- it's impossible to forward
  // variadic arguments.

  // Now emit our call.
  auto callee = CGCallee::forDirect(calleePtr, GlobalDecl(callOperator));
  RValue RV = EmitCall(*calleeFnInfo, callee, returnSlot, callArgs);

  // If necessary, copy the returned value into the slot.
  if (!resultType->isVoidType() && returnSlot.isNull()) {
    if (getLangOpts().ObjCAutoRefCount && resultType->isObjCRetainableType()) {
      RV = RValue::get(EmitARCRetainAutoreleasedReturnValue(RV.getScalarVal()));
    }
    EmitReturnOfRValue(RV, resultType);
  } else
    EmitBranchThroughCleanup(ReturnBlock);
}

void CodeGenFunction::EmitLambdaBlockInvokeBody() {
  const BlockDecl *BD = BlockInfo->getBlockDecl();
  const VarDecl *variable = BD->capture_begin()->getVariable();
  const CXXRecordDecl *Lambda = variable->getType()->getAsCXXRecordDecl();
  const CXXMethodDecl *CallOp = Lambda->getLambdaCallOperator();

  if (CallOp->isVariadic()) {
    // FIXME: Making this work correctly is nasty because it requires either
    // cloning the body of the call operator or making the call operator
    // forward.
    CGM.ErrorUnsupported(CurCodeDecl, "lambda conversion to variadic function");
    return;
  }

  // Start building arguments for forwarding call
  CallArgList CallArgs;

  CanQualType ThisType =
      getContext().getPointerType(getContext().getCanonicalTagType(Lambda));
  Address ThisPtr = GetAddrOfBlockDecl(variable);
  CallArgs.add(RValue::get(getAsNaturalPointerTo(ThisPtr, ThisType)), ThisType);

  // Add the rest of the parameters.
  for (auto *param : BD->parameters())
    EmitDelegateCallArg(CallArgs, param, param->getBeginLoc());

  assert(!Lambda->isGenericLambda() &&
         "generic lambda interconversion to block not implemented");
  EmitForwardingCallToLambda(CallOp, CallArgs);
}

void CodeGenFunction::EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD) {
  if (MD->isVariadic()) {
    // FIXME: Making this work correctly is nasty because it requires either
    // cloning the body of the call operator or making the call operator
    // forward.
    CGM.ErrorUnsupported(MD, "lambda conversion to variadic function");
    return;
  }

  const CXXRecordDecl *Lambda = MD->getParent();

  // Start building arguments for forwarding call
  CallArgList CallArgs;

  CanQualType LambdaType = getContext().getCanonicalTagType(Lambda);
  CanQualType ThisType = getContext().getPointerType(LambdaType);
  Address ThisPtr = CreateMemTempWithoutCast(LambdaType, "unused.capture");
  CallArgs.add(RValue::get(ThisPtr.emitRawPointer(*this)), ThisType);

  EmitLambdaDelegatingInvokeBody(MD, CallArgs);
}

void CodeGenFunction::EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD,
                                                     CallArgList &CallArgs) {
  // Add the rest of the forwarded parameters.
  for (auto *Param : MD->parameters())
    EmitDelegateCallArg(CallArgs, Param, Param->getBeginLoc());

  const CXXRecordDecl *Lambda = MD->getParent();
  const CXXMethodDecl *CallOp = Lambda->getLambdaCallOperator();
  // For a generic lambda, find the corresponding call operator specialization
  // to which the call to the static-invoker shall be forwarded.
  if (Lambda->isGenericLambda()) {
    assert(MD->isFunctionTemplateSpecialization());
    const TemplateArgumentList *TAL = MD->getTemplateSpecializationArgs();
    FunctionTemplateDecl *CallOpTemplate =
        CallOp->getDescribedFunctionTemplate();
    void *InsertPos = nullptr;
    FunctionDecl *CorrespondingCallOpSpecialization =
        CallOpTemplate->findSpecialization(TAL->asArray(), InsertPos);
    assert(CorrespondingCallOpSpecialization);
    CallOp = cast<CXXMethodDecl>(CorrespondingCallOpSpecialization);
  }

  // Special lambda forwarding when there are inalloca parameters.
  if (hasInAllocaArg(MD)) {
    const CGFunctionInfo *ImplFnInfo = nullptr;
    llvm::Function *ImplFn = nullptr;
    EmitLambdaInAllocaImplFn(CallOp, &ImplFnInfo, &ImplFn);

    EmitForwardingCallToLambda(CallOp, CallArgs, ImplFnInfo, ImplFn);
    return;
  }

  EmitForwardingCallToLambda(CallOp, CallArgs);
}

void CodeGenFunction::EmitLambdaInAllocaCallOpBody(const CXXMethodDecl *MD) {
  if (MD->isVariadic()) {
    // FIXME: Making this work correctly is nasty because it requires either
    // cloning the body of the call operator or making the call operator
    // forward.
    CGM.ErrorUnsupported(MD, "lambda conversion to variadic function");
    return;
  }

  // Forward %this argument.
  CallArgList CallArgs;
  CanQualType LambdaType = getContext().getCanonicalTagType(MD->getParent());
  CanQualType ThisType = getContext().getPointerType(LambdaType);
  llvm::Value *ThisArg = CurFn->getArg(0);
  CallArgs.add(RValue::get(ThisArg), ThisType);

  EmitLambdaDelegatingInvokeBody(MD, CallArgs);
}

void CodeGenFunction::EmitLambdaInAllocaImplFn(
    const CXXMethodDecl *CallOp, const CGFunctionInfo **ImplFnInfo,
    llvm::Function **ImplFn) {
  const CGFunctionInfo &FnInfo =
      CGM.getTypes().arrangeCXXMethodDeclaration(CallOp);
  llvm::Function *CallOpFn =
      cast<llvm::Function>(CGM.GetAddrOfFunction(GlobalDecl(CallOp)));

  // Emit function containing the original call op body. __invoke will delegate
  // to this function.
  SmallVector<CanQualType, 4> ArgTypes;
  for (auto I = FnInfo.arg_begin(); I != FnInfo.arg_end(); ++I)
    ArgTypes.push_back(I->type);
  *ImplFnInfo = &CGM.getTypes().arrangeLLVMFunctionInfo(
      FnInfo.getReturnType(), FnInfoOpts::IsDelegateCall, ArgTypes,
      FnInfo.getExtInfo(), {}, FnInfo.getRequiredArgs(), CallOp);

  // Create mangled name as if this was a method named __impl. If for some
  // reason the name doesn't look as expected then just tack __impl to the
  // front.
  // TODO: Use the name mangler to produce the right name instead of using
  // string replacement.
  StringRef CallOpName = CallOpFn->getName();
  std::string ImplName;
  if (size_t Pos = CallOpName.find_first_of("<lambda"))
    ImplName = ("?__impl@" + CallOpName.drop_front(Pos)).str();
  else
    ImplName = ("__impl" + CallOpName).str();

  llvm::Function *Fn = CallOpFn->getParent()->getFunction(ImplName);
  if (!Fn) {
    Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(**ImplFnInfo),
                                llvm::GlobalValue::InternalLinkage, ImplName,
                                CGM.getModule());
    CGM.SetInternalFunctionAttributes(CallOp, Fn, **ImplFnInfo);

    const GlobalDecl &GD = GlobalDecl(CallOp);
    const auto *D = cast<FunctionDecl>(GD.getDecl());
    CodeGenFunction(CGM).GenerateCode(GD, Fn, **ImplFnInfo);
    CGM.SetLLVMFunctionAttributesForDefinition(D, Fn);
  }
  *ImplFn = Fn;
}
