19#include "llvm/ADT/SetOperations.h" 
   20#include "llvm/ADT/SetVector.h" 
   21#include "llvm/ADT/SmallPtrSet.h" 
   22#include "llvm/Support/Format.h" 
   23#include "llvm/Support/raw_ostream.h" 
   29#define DUMP_OVERRIDERS 0 
   50  BaseOffset() : DerivedClass(
nullptr), 
VirtualBase(
nullptr),
 
   55    NonVirtualOffset(NonVirtualOffset) { }
 
   62class FinalOverriders {
 
   65  struct OverriderInfo {
 
  102  typedef std::pair<const CXXMethodDecl *, CharUnits> MethodBaseOffsetPairTy;
 
  104  typedef llvm::DenseMap<MethodBaseOffsetPairTy,
 
  105                         OverriderInfo> OverridersMapTy;
 
  109  OverridersMapTy OverridersMap;
 
  114  typedef llvm::DenseMap<std::pair<const CXXRecordDecl *, unsigned>,
 
  117  typedef llvm::DenseMap<const CXXRecordDecl *, unsigned> SubobjectCountMapTy;
 
  123                          SubobjectOffsetMapTy &SubobjectOffsets,
 
  124                          SubobjectOffsetMapTy &SubobjectLayoutClassOffsets,
 
  125                          SubobjectCountMapTy &SubobjectCounts);
 
  132            VisitedVirtualBasesSetTy& VisitedVirtualBases);
 
  143    assert(OverridersMap.count(std::make_pair(MD, BaseOffset)) &&
 
  144           "Did not find overrider!");
 
  146    return OverridersMap.lookup(std::make_pair(MD, BaseOffset));
 
  151    VisitedVirtualBasesSetTy VisitedVirtualBases;
 
  153         VisitedVirtualBases);
 
  158FinalOverriders::FinalOverriders(
const CXXRecordDecl *MostDerivedClass,
 
  161  : MostDerivedClass(MostDerivedClass),
 
  162  MostDerivedClassOffset(MostDerivedClassOffset), LayoutClass(LayoutClass),
 
  164  MostDerivedClassLayout(Context.getASTRecordLayout(MostDerivedClass)) {
 
  167  SubobjectOffsetMapTy SubobjectOffsets;
 
  168  SubobjectOffsetMapTy SubobjectLayoutClassOffsets;
 
  169  SubobjectCountMapTy SubobjectCounts;
 
  172                     MostDerivedClassOffset,
 
  173                     SubobjectOffsets, SubobjectLayoutClassOffsets,
 
  180  for (
const auto &Overrider : FinalOverriders) {
 
  184    for (
const auto &M : Methods) {
 
  185      unsigned SubobjectNumber = M.first;
 
  186      assert(SubobjectOffsets.count(std::make_pair(MD->
getParent(),
 
  188             "Did not find subobject offset!");
 
  193      assert(M.second.size() == 1 && 
"Final overrider is not unique!");
 
  197      assert(SubobjectLayoutClassOffsets.count(
 
  198             std::make_pair(OverriderRD, Method.Subobject))
 
  199             && 
"Did not find subobject offset!");
 
  201        SubobjectLayoutClassOffsets[std::make_pair(OverriderRD,
 
  204      OverriderInfo& Overrider = OverridersMap[std::make_pair(MD, BaseOffset)];
 
  205      assert(!Overrider.Method && 
"Overrider should not exist yet!");
 
  207      Overrider.Offset = OverriderOffset;
 
  208      Overrider.Method = Method.Method;
 
  209      Overrider.VirtualBase = Method.InVirtualSubobject;
 
  219static BaseOffset ComputeBaseOffset(
const ASTContext &Context,
 
  224  unsigned NonVirtualStart = 0;
 
  228  for (
int I = Path.size(), E = 0; I != E; --I) {
 
  240  for (
unsigned I = NonVirtualStart, E = Path.size(); I != E; ++I) {
 
  254  return BaseOffset(DerivedRD, 
VirtualBase, NonVirtualOffset);
 
  258static BaseOffset ComputeBaseOffset(
const ASTContext &Context,
 
  265    llvm_unreachable(
"Class must be derived from the passed in base class!");
 
  267  return ComputeBaseOffset(Context, DerivedRD, Paths.
front());
 
  271ComputeReturnAdjustmentBaseOffset(
ASTContext &Context,
 
  281      Context.getCanonicalType(BaseFT->getReturnType());
 
  283  assert(CanDerivedReturnType->getTypeClass() ==
 
  284         CanBaseReturnType->getTypeClass() &&
 
  285         "Types must have same type class!");
 
  287  if (CanDerivedReturnType == CanBaseReturnType) {
 
  293    CanDerivedReturnType =
 
  298    CanDerivedReturnType =
 
  303    llvm_unreachable(
"Unexpected return type!");
 
  309  if (CanDerivedReturnType.getUnqualifiedType() ==
 
  315  const auto *DerivedRD =
 
  317          ->getDefinitionOrSelf();
 
  322  return ComputeBaseOffset(Context, BaseRD, DerivedRD);
 
  328                              SubobjectOffsetMapTy &SubobjectOffsets,
 
  329                              SubobjectOffsetMapTy &SubobjectLayoutClassOffsets,
 
  330                              SubobjectCountMapTy &SubobjectCounts) {
 
  333  unsigned SubobjectNumber = 0;
 
  335    SubobjectNumber = ++SubobjectCounts[RD];
 
  338  assert(!SubobjectOffsets.count(std::make_pair(RD, SubobjectNumber))
 
  339         && 
"Subobject offset already exists!");
 
  340  assert(!SubobjectLayoutClassOffsets.count(std::make_pair(RD, SubobjectNumber))
 
  341         && 
"Subobject offset already exists!");
 
  343  SubobjectOffsets[std::make_pair(RD, SubobjectNumber)] = 
Base.getBaseOffset();
 
  344  SubobjectLayoutClassOffsets[std::make_pair(RD, SubobjectNumber)] =
 
  348  for (
const auto &B : RD->
bases()) {
 
  349    const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
 
  355      if (SubobjectOffsets.count(std::make_pair(BaseDecl, 0)))
 
  359        Context.getASTRecordLayout(LayoutClass);
 
  362      BaseOffsetInLayoutClass =
 
  368      BaseOffset = 
Base.getBaseOffset() + Offset;
 
  369      BaseOffsetInLayoutClass = OffsetInLayoutClass + Offset;
 
  373                       B.isVirtual(), BaseOffsetInLayoutClass,
 
  374                       SubobjectOffsets, SubobjectLayoutClassOffsets,
 
  380                           VisitedVirtualBasesSetTy &VisitedVirtualBases) {
 
  384  for (
const auto &B : RD->
bases()) {
 
  385    const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
 
  393      if (!VisitedVirtualBases.insert(BaseDecl).second) {
 
  406  Out << 
"Final overriders for (";
 
  409  Out << 
Base.getBaseOffset().getQuantity() << 
")\n";
 
  412  for (
const auto *MD : RD->
methods()) {
 
  415    MD = MD->getCanonicalDecl();
 
  417    OverriderInfo Overrider = getOverrider(MD, 
Base.getBaseOffset());
 
  420    MD->printQualifiedName(Out);
 
  422    Overrider.Method->printQualifiedName(Out);
 
  423    Out << 
", " << Overrider.Offset.getQuantity() << 
')';
 
  426    if (!Overrider.Method->isPureVirtual())
 
  427      Offset = ComputeReturnAdjustmentBaseOffset(Context, Overrider.Method, MD);
 
  429    if (!Offset.isEmpty()) {
 
  430      Out << 
" [ret-adj: ";
 
  431      if (Offset.VirtualBase) {
 
  432        Offset.VirtualBase->printQualifiedName(Out);
 
  436      Out << Offset.NonVirtualOffset.getQuantity() << 
" nv]";
 
  444struct VCallOffsetMap {
 
  446  typedef std::pair<const CXXMethodDecl *, CharUnits> MethodAndOffsetPairTy;
 
  454  static bool MethodsCanShareVCallOffset(
const CXXMethodDecl *LHS,
 
  468  bool empty()
 const { 
return Offsets.empty(); }
 
  479  if (LT == RT) 
return true;
 
  489bool VCallOffsetMap::MethodsCanShareVCallOffset(
const CXXMethodDecl *LHS,
 
  503  if (LHSName != RHSName)
 
  507  return HasSameVirtualSignature(LHS, RHS);
 
  513  for (
const auto &OffsetPair : Offsets) {
 
  514    if (MethodsCanShareVCallOffset(OffsetPair.first, MD))
 
  519  Offsets.push_back(MethodAndOffsetPairTy(MD, OffsetOffset));
 
  525  for (
const auto &OffsetPair : Offsets) {
 
  526    if (MethodsCanShareVCallOffset(OffsetPair.first, MD))
 
  527      return OffsetPair.second;
 
  530  llvm_unreachable(
"Should always find a vcall offset offset!");
 
  534class VCallAndVBaseOffsetBuilder {
 
  536  typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits>
 
  537    VBaseOffsetOffsetsMapTy;
 
  556  VTableComponentVectorTy Components;
 
  562  VCallOffsetMap VCallOffsets;
 
  567  VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
 
  571  const FinalOverriders *Overriders;
 
  587  CharUnits getCurrentOffsetOffset() 
const;
 
  593                             const FinalOverriders *Overriders,
 
  596      : VTables(VTables), MostDerivedClass(MostDerivedClass),
 
  597        LayoutClass(LayoutClass), Context(MostDerivedClass->
getASTContext()),
 
  598        Overriders(Overriders) {
 
  601    AddVCallAndVBaseOffsets(
Base, BaseIsVirtual, OffsetInLayoutClass);
 
  605  typedef VTableComponentVectorTy::const_reverse_iterator 
const_iterator;
 
  606  const_iterator components_begin()
 const { 
return Components.rbegin(); }
 
  607  const_iterator components_end()
 const { 
return Components.rend(); }
 
  609  const VCallOffsetMap &getVCallOffsets()
 const { 
return VCallOffsets; }
 
  610  const VBaseOffsetOffsetsMapTy &getVBaseOffsetOffsets()
 const {
 
  611    return VBaseOffsetOffsets;
 
  636    if (PrimaryBaseIsVirtual) {
 
  638             "Primary vbase should have a zero offset!");
 
  641        Context.getASTRecordLayout(MostDerivedClass);
 
  647             "Primary base should have a zero offset!");
 
  649      PrimaryBaseOffset = 
Base.getBaseOffset();
 
  652    AddVCallAndVBaseOffsets(
 
  654      PrimaryBaseIsVirtual, RealBaseOffset);
 
  657  AddVBaseOffsets(
Base.getBase(), RealBaseOffset);
 
  661    AddVCallOffsets(
Base, RealBaseOffset);
 
  664CharUnits VCallAndVBaseOffsetBuilder::getCurrentOffsetOffset()
 const {
 
  669  size_t NumComponentsAboveAddrPoint = 3;
 
  670  if (Context.getLangOpts().OmitVTableRTTI)
 
  671    NumComponentsAboveAddrPoint--;
 
  672  int64_t OffsetIndex =
 
  673      -(int64_t)(NumComponentsAboveAddrPoint + Components.size());
 
  677  CharUnits OffsetWidth = Context.toCharUnitsFromBits(
 
  681  CharUnits OffsetOffset = OffsetWidth * OffsetIndex;
 
  699           "Primary base should have a zero offset!");
 
  706  for (
const auto *MD : RD->
methods()) {
 
  711    CharUnits OffsetOffset = getCurrentOffsetOffset();
 
  715    if (!VCallOffsets.AddVCallOffset(MD, OffsetOffset))
 
  722      FinalOverriders::OverriderInfo Overrider =
 
  723        Overriders->getOverrider(MD, 
Base.getBaseOffset());
 
  727      Offset = Overrider.Offset - VBaseOffset;
 
  730    Components.push_back(
 
  735  for (
const auto &B : RD->
bases()) {
 
  739    const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
 
  740    if (BaseDecl == PrimaryBase)
 
  753VCallAndVBaseOffsetBuilder::AddVBaseOffsets(
const CXXRecordDecl *RD,
 
  756    Context.getASTRecordLayout(LayoutClass);
 
  759  for (
const auto &B : RD->
bases()) {
 
  760    const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
 
  763    if (B.isVirtual() && VisitedVirtualBases.insert(BaseDecl).second) {
 
  768      assert(!VBaseOffsetOffsets.count(BaseDecl) &&
 
  769             "vbase offset offset already exists!");
 
  771      CharUnits VBaseOffsetOffset = getCurrentOffsetOffset();
 
  772      VBaseOffsetOffsets.insert(
 
  773          std::make_pair(BaseDecl, VBaseOffsetOffset));
 
  775      Components.push_back(
 
  780    AddVBaseOffsets(BaseDecl, OffsetInLayoutClass);
 
  785class ItaniumVTableBuilder {
 
  790    PrimaryBasesSetVectorTy;
 
  792  typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits>
 
  793    VBaseOffsetOffsetsMapTy;
 
  797  typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVTableIndicesTy;
 
  813  bool MostDerivedClassIsVirtual;
 
  824  const FinalOverriders Overriders;
 
  828  llvm::DenseMap<const CXXRecordDecl *, VCallOffsetMap> VCallOffsetsForVBases;
 
  832  VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
 
  838  AddressPointsMapTy AddressPoints;
 
  852    const uint64_t VTableIndex;
 
  855               uint64_t VTableIndex)
 
  856      : BaseOffset(BaseOffset),
 
  857      BaseOffsetInLayoutClass(BaseOffsetInLayoutClass),
 
  858      VTableIndex(VTableIndex) { }
 
  865    MethodInfo(MethodInfo 
const&) = 
default;
 
  868  typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy;
 
  872  MethodInfoMapTy MethodInfoMap;
 
  876  MethodVTableIndicesTy MethodVTableIndices;
 
  878  typedef llvm::DenseMap<uint64_t, ThunkInfo> VTableThunksMapTy;
 
  882  VTableThunksMapTy VTableThunks;
 
  885  typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
 
  896  void ComputeThisAdjustments();
 
  902  VisitedVirtualBasesSetTy PrimaryVirtualBases;
 
  919                        FinalOverriders::OverriderInfo Overrider);
 
  947                       CharUnits FirstBaseOffsetInLayoutClass) 
const;
 
  955                  PrimaryBasesSetVectorTy &PrimaryBases);
 
  970                                        bool BaseIsMorallyVirtual,
 
  971                                        bool BaseIsVirtualInLayoutClass,
 
  986                                    VisitedVirtualBasesSetTy &VBases);
 
  991                                    VisitedVirtualBasesSetTy &VBases);
 
  995  bool isBuildingConstructorVTable()
 const {
 
  996    return MostDerivedClass != LayoutClass;
 
 1007                       bool MostDerivedClassIsVirtual,
 
 1009      : VTables(VTables), MostDerivedClass(MostDerivedClass),
 
 1010        MostDerivedClassOffset(MostDerivedClassOffset),
 
 1011        MostDerivedClassIsVirtual(MostDerivedClassIsVirtual),
 
 1012        LayoutClass(LayoutClass), Context(MostDerivedClass->
getASTContext()),
 
 1013        Overriders(MostDerivedClass, MostDerivedClassOffset, LayoutClass) {
 
 1014    assert(!Context.getTargetInfo().getCXXABI().isMicrosoft());
 
 1018    if (Context.getLangOpts().DumpVTableLayouts)
 
 1019      dumpLayout(llvm::outs());
 
 1022  uint64_t getNumThunks()
 const {
 
 1023    return Thunks.size();
 
 1026  ThunksMapTy::const_iterator thunks_begin()
 const {
 
 1027    return Thunks.begin();
 
 1030  ThunksMapTy::const_iterator thunks_end()
 const {
 
 1031    return Thunks.end();
 
 1034  const VBaseOffsetOffsetsMapTy &getVBaseOffsetOffsets()
 const {
 
 1035    return VBaseOffsetOffsets;
 
 1038  const AddressPointsMapTy &getAddressPoints()
 const {
 
 1039    return AddressPoints;
 
 1042  MethodVTableIndicesTy::const_iterator vtable_indices_begin()
 const {
 
 1043    return MethodVTableIndices.begin();
 
 1046  MethodVTableIndicesTy::const_iterator vtable_indices_end()
 const {
 
 1047    return MethodVTableIndices.end();
 
 1052  AddressPointsMapTy::const_iterator address_points_begin()
 const {
 
 1053    return AddressPoints.begin();
 
 1056  AddressPointsMapTy::const_iterator address_points_end()
 const {
 
 1057    return AddressPoints.end();
 
 1060  VTableThunksMapTy::const_iterator vtable_thunks_begin()
 const {
 
 1061    return VTableThunks.begin();
 
 1064  VTableThunksMapTy::const_iterator vtable_thunks_end()
 const {
 
 1065    return VTableThunks.end();
 
 1069  void dumpLayout(raw_ostream&);
 
 1074  assert(!isBuildingConstructorVTable() &&
 
 1075         "Can't add thunks for construction vtable");
 
 1080  if (llvm::is_contained(ThunksVector, Thunk))
 
 1083  ThunksVector.push_back(Thunk);
 
 1092template <
class VisitorTy>
 
 1094visitAllOverriddenMethods(
const CXXMethodDecl *MD, VisitorTy &Visitor) {
 
 1098    if (!Visitor(OverriddenMD))
 
 1100    visitAllOverriddenMethods(OverriddenMD, Visitor);
 
 1108                            OverriddenMethodsSetTy& OverriddenMethods) {
 
 1109  auto OverriddenMethodsCollector = [&](
const CXXMethodDecl *MD) {
 
 1111    return OverriddenMethods.insert(MD).second;
 
 1113  visitAllOverriddenMethods(MD, OverriddenMethodsCollector);
 
 1116void ItaniumVTableBuilder::ComputeThisAdjustments() {
 
 1119  for (
const auto &MI : MethodInfoMap) {
 
 1121    const MethodInfo &MethodInfo = MI.second;
 
 1124    uint64_t VTableIndex = MethodInfo.VTableIndex;
 
 1125    if (Components[VTableIndex].
getKind() ==
 
 1130    FinalOverriders::OverriderInfo Overrider =
 
 1131      Overriders.getOverrider(MD, MethodInfo.BaseOffset);
 
 1134    if (MethodInfo.BaseOffsetInLayoutClass == Overrider.Offset) {
 
 1140      if (VTableThunks.lookup(VTableIndex).Return.isEmpty())
 
 1145      ComputeThisAdjustment(MD, MethodInfo.BaseOffsetInLayoutClass, Overrider);
 
 1151    auto SetThisAdjustmentThunk = [&](uint64_t Idx) {
 
 1173      auto [It, Inserted] = VTableThunks.try_emplace(Idx);
 
 1176        It->second.Method = Method;
 
 1182    SetThisAdjustmentThunk(VTableIndex);
 
 1186      SetThisAdjustmentThunk(VTableIndex + 1);
 
 1191  MethodInfoMap.clear();
 
 1193  if (isBuildingConstructorVTable()) {
 
 1198  for (
const auto &TI : VTableThunks) {
 
 1203    switch (Component.
getKind()) {
 
 1205      llvm_unreachable(
"Unexpected vtable component kind!");
 
 1217    if (MD->
getParent() == MostDerivedClass)
 
 1218      AddThunk(MD, Thunk);
 
 1223ItaniumVTableBuilder::ComputeReturnAdjustment(BaseOffset Offset) {
 
 1226  if (!Offset.isEmpty()) {
 
 1227    if (Offset.VirtualBase) {
 
 1229      if (Offset.DerivedClass == MostDerivedClass) {
 
 1232          VBaseOffsetOffsets.lookup(Offset.VirtualBase).getQuantity();
 
 1240    Adjustment.
NonVirtual = Offset.NonVirtualOffset.getQuantity();
 
 1246BaseOffset ItaniumVTableBuilder::ComputeThisAdjustmentBaseOffset(
 
 1255    llvm_unreachable(
"Class must be derived from the passed in base class!");
 
 1260    BaseOffset Offset = ComputeBaseOffset(Context, DerivedRD, Path);
 
 1262    CharUnits OffsetToBaseSubobject = Offset.NonVirtualOffset;
 
 1264    if (Offset.VirtualBase) {
 
 1268        Context.getASTRecordLayout(LayoutClass);
 
 1272      OffsetToBaseSubobject +=
 
 1281    if (OffsetToBaseSubobject == 
Base.getBaseOffset()) {
 
 1284      Offset.NonVirtualOffset = -Offset.NonVirtualOffset;
 
 1289  return BaseOffset();
 
 1294    FinalOverriders::OverriderInfo Overrider) {
 
 1300                                        BaseOffsetInLayoutClass);
 
 1306  BaseOffset Offset = ComputeThisAdjustmentBaseOffset(OverriddenBaseSubobject,
 
 1307                                                      OverriderBaseSubobject);
 
 1308  if (Offset.isEmpty())
 
 1313  if (Offset.VirtualBase) {
 
 1315    VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[Offset.VirtualBase];
 
 1317    if (VCallOffsets.empty()) {
 
 1320      VCallAndVBaseOffsetBuilder Builder(
 
 1321          VTables, MostDerivedClass, MostDerivedClass,
 
 1328      VCallOffsets = Builder.getVCallOffsets();
 
 1332      VCallOffsets.getVCallOffsetOffset(MD).getQuantity();
 
 1336  Adjustment.
NonVirtual = Offset.NonVirtualOffset.getQuantity();
 
 1341void ItaniumVTableBuilder::AddMethod(
const CXXMethodDecl *MD,
 
 1345           "Destructor can't have return adjustment!");
 
 1371static bool OverridesIndirectMethodInBases(
 
 1373    ItaniumVTableBuilder::PrimaryBasesSetVectorTy &Bases) {
 
 1379    if (OverridesIndirectMethodInBases(OverriddenMD, Bases))
 
 1386bool ItaniumVTableBuilder::IsOverriderUsed(
 
 1389    CharUnits FirstBaseOffsetInLayoutClass)
 const {
 
 1392  if (BaseOffsetInLayoutClass == FirstBaseOffsetInLayoutClass)
 
 1401  if (Overrider->getParent() == FirstBaseInPrimaryBaseChain)
 
 1404  ItaniumVTableBuilder::PrimaryBasesSetVectorTy PrimaryBases;
 
 1407  PrimaryBases.insert(RD);
 
 1420             "Primary base should always be at offset 0!");
 
 1423        Context.getASTRecordLayout(LayoutClass);
 
 1428          FirstBaseOffsetInLayoutClass) {
 
 1434             "Primary base should always be at offset 0!");
 
 1437    if (!PrimaryBases.insert(PrimaryBase))
 
 1438      llvm_unreachable(
"Found a duplicate primary base!");
 
 1445  return OverridesIndirectMethodInBases(Overrider, PrimaryBases);
 
 1455                            BasesSetVectorTy &Bases) {
 
 1456  OverriddenMethodsSetTy OverriddenMethods;
 
 1457  ComputeAllOverriddenMethods(MD, OverriddenMethods);
 
 1459  for (
const CXXRecordDecl *PrimaryBase : llvm::reverse(Bases)) {
 
 1461    for (
const CXXMethodDecl *OverriddenMD : OverriddenMethods) {
 
 1463      if (OverriddenMD->getParent() == PrimaryBase)
 
 1464        return OverriddenMD;
 
 1471void ItaniumVTableBuilder::AddMethods(
 
 1475    PrimaryBasesSetVectorTy &PrimaryBases) {
 
 1490    CharUnits PrimaryBaseOffsetInLayoutClass;
 
 1493             "Primary vbase should have a zero offset!");
 
 1496        Context.getASTRecordLayout(MostDerivedClass);
 
 1502        Context.getASTRecordLayout(LayoutClass);
 
 1504      PrimaryBaseOffsetInLayoutClass =
 
 1508             "Primary base should have a zero offset!");
 
 1510      PrimaryBaseOffset = 
Base.getBaseOffset();
 
 1511      PrimaryBaseOffsetInLayoutClass = BaseOffsetInLayoutClass;
 
 1515               PrimaryBaseOffsetInLayoutClass, FirstBaseInPrimaryBaseChain,
 
 1516               FirstBaseOffsetInLayoutClass, PrimaryBases);
 
 1518    if (!PrimaryBases.insert(PrimaryBase))
 
 1519      llvm_unreachable(
"Found a duplicate primary base!");
 
 1523  NewVirtualFunctionsTy NewVirtualFunctions;
 
 1528  for (
const auto *MD : RD->
methods()) {
 
 1534    FinalOverriders::OverriderInfo Overrider =
 
 1535      Overriders.getOverrider(MD, 
Base.getBaseOffset());
 
 1541          FindNearestOverriddenMethod(MD, PrimaryBases)) {
 
 1542      if (ComputeReturnAdjustmentBaseOffset(Context, MD,
 
 1543                                            OverriddenMD).isEmpty()) {
 
 1548        assert(MethodInfoMap.count(OverriddenMD) &&
 
 1549               "Did not find the overridden method!");
 
 1550        MethodInfo &OverriddenMethodInfo = MethodInfoMap[OverriddenMD];
 
 1552        MethodInfo MethodInfo(
Base.getBaseOffset(), BaseOffsetInLayoutClass,
 
 1553                              OverriddenMethodInfo.VTableIndex);
 
 1555        assert(!MethodInfoMap.count(MD) &&
 
 1556               "Should not have method info for this method yet!");
 
 1558        MethodInfoMap.insert(std::make_pair(MD, MethodInfo));
 
 1559        MethodInfoMap.erase(OverriddenMD);
 
 1565        if (!isBuildingConstructorVTable() && OverriddenMD != MD) {
 
 1568            ComputeThisAdjustment(OverriddenMD, BaseOffsetInLayoutClass,
 
 1572              Overrider.Method->
getParent() == MostDerivedClass) {
 
 1577            BaseOffset ReturnAdjustmentOffset =
 
 1578              ComputeReturnAdjustmentBaseOffset(Context, Overrider.Method, MD);
 
 1580              ComputeReturnAdjustment(ReturnAdjustmentOffset);
 
 1583            AddThunk(Overrider.Method,
 
 1585                               OverriddenMD->getThisType().getTypePtr()));
 
 1594      NewImplicitVirtualFunctions.push_back(MD);
 
 1596      NewVirtualFunctions.push_back(MD);
 
 1600      NewImplicitVirtualFunctions,
 
 1612               "unexpected or duplicate implicit virtual function");
 
 1617  NewVirtualFunctions.append(NewImplicitVirtualFunctions.begin(),
 
 1618                             NewImplicitVirtualFunctions.end());
 
 1622    FinalOverriders::OverriderInfo Overrider =
 
 1623      Overriders.getOverrider(MD, 
Base.getBaseOffset());
 
 1626    MethodInfo MethodInfo(
Base.getBaseOffset(), BaseOffsetInLayoutClass,
 
 1629    assert(!MethodInfoMap.count(MD) &&
 
 1630           "Should not have method info for this method yet!");
 
 1631    MethodInfoMap.insert(std::make_pair(MD, MethodInfo));
 
 1635    if (!IsOverriderUsed(OverriderMD, BaseOffsetInLayoutClass,
 
 1636                         FirstBaseInPrimaryBaseChain,
 
 1637                         FirstBaseOffsetInLayoutClass)) {
 
 1644    BaseOffset ReturnAdjustmentOffset;
 
 1646      ReturnAdjustmentOffset =
 
 1647        ComputeReturnAdjustmentBaseOffset(Context, OverriderMD, MD);
 
 1651      ComputeReturnAdjustment(ReturnAdjustmentOffset);
 
 1658      auto &VTT = VTableThunks[Components.size()];
 
 1667void ItaniumVTableBuilder::LayoutVTable() {
 
 1668  LayoutPrimaryAndSecondaryVTables(
BaseSubobject(MostDerivedClass,
 
 1671                                   MostDerivedClassIsVirtual,
 
 1672                                   MostDerivedClassOffset);
 
 1674  VisitedVirtualBasesSetTy VBases;
 
 1677  DeterminePrimaryVirtualBases(MostDerivedClass, MostDerivedClassOffset,
 
 1681  LayoutVTablesForVirtualBases(MostDerivedClass, VBases);
 
 1684  bool IsAppleKext = Context.getLangOpts().AppleKext;
 
 1689void ItaniumVTableBuilder::LayoutPrimaryAndSecondaryVTables(
 
 1691    bool BaseIsVirtualInLayoutClass, 
CharUnits OffsetInLayoutClass) {
 
 1692  assert(
Base.getBase()->isDynamicClass() && 
"class does not have a vtable!");
 
 1694  unsigned VTableIndex = Components.size();
 
 1695  VTableIndices.push_back(VTableIndex);
 
 1698  VCallAndVBaseOffsetBuilder Builder(
 
 1699      VTables, MostDerivedClass, LayoutClass, &Overriders, 
Base,
 
 1700      BaseIsVirtualInLayoutClass, OffsetInLayoutClass);
 
 1701  Components.append(Builder.components_begin(), Builder.components_end());
 
 1704  if (BaseIsVirtualInLayoutClass && !Builder.getVCallOffsets().empty()) {
 
 1705    VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[
Base.getBase()];
 
 1707    if (VCallOffsets.empty())
 
 1708      VCallOffsets = Builder.getVCallOffsets();
 
 1713  if (
Base.getBase() == MostDerivedClass)
 
 1714    VBaseOffsetOffsets = Builder.getVBaseOffsetOffsets();
 
 1717  CharUnits OffsetToTop = MostDerivedClassOffset - OffsetInLayoutClass;
 
 1721  if (!Context.getLangOpts().OmitVTableRTTI)
 
 1724  uint64_t AddressPoint = Components.size();
 
 1727  PrimaryBasesSetVectorTy PrimaryBases;
 
 1728  AddMethods(
Base, OffsetInLayoutClass,
 
 1729             Base.getBase(), OffsetInLayoutClass,
 
 1733  if (RD == MostDerivedClass) {
 
 1734    assert(MethodVTableIndices.empty());
 
 1735    for (
const auto &I : MethodInfoMap) {
 
 1737      const MethodInfo &MI = I.second;
 
 1740            = MI.VTableIndex - AddressPoint;
 
 1742            = MI.VTableIndex + 1 - AddressPoint;
 
 1744        MethodVTableIndices[MD] = MI.VTableIndex - AddressPoint;
 
 1750  ComputeThisAdjustments();
 
 1754    AddressPoints.insert(
 
 1757                           unsigned(VTableIndices.size() - 1),
 
 1758                           unsigned(AddressPoint - VTableIndex)}));
 
 1770        Context.getASTRecordLayout(LayoutClass);
 
 1773          OffsetInLayoutClass) {
 
 1783  LayoutSecondaryVTables(
Base, BaseIsMorallyVirtual, OffsetInLayoutClass);
 
 1788                                             bool BaseIsMorallyVirtual,
 
 1799  for (
const auto &B : RD->
bases()) {
 
 1804    const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
 
 1810    if (isBuildingConstructorVTable()) {
 
 1816      if (!BaseIsMorallyVirtual && !BaseDecl->
getNumVBases())
 
 1822    CharUnits BaseOffset = 
Base.getBaseOffset() + RelativeBaseOffset;
 
 1825      OffsetInLayoutClass + RelativeBaseOffset;
 
 1829    if (BaseDecl == PrimaryBase) {
 
 1831                             BaseIsMorallyVirtual, BaseOffsetInLayoutClass);
 
 1836    LayoutPrimaryAndSecondaryVTables(
 
 1838      BaseIsMorallyVirtual,
 
 1840      BaseOffsetInLayoutClass);
 
 1844void ItaniumVTableBuilder::DeterminePrimaryVirtualBases(
 
 1846    VisitedVirtualBasesSetTy &VBases) {
 
 1854      bool IsPrimaryVirtualBase = 
true;
 
 1856      if (isBuildingConstructorVTable()) {
 
 1860          Context.getASTRecordLayout(LayoutClass);
 
 1862        CharUnits PrimaryBaseOffsetInLayoutClass =
 
 1867        if (PrimaryBaseOffsetInLayoutClass != OffsetInLayoutClass)
 
 1868          IsPrimaryVirtualBase = 
false;
 
 1871      if (IsPrimaryVirtualBase)
 
 1872        PrimaryVirtualBases.insert(PrimaryBase);
 
 1877  for (
const auto &B : RD->
bases()) {
 
 1878    const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
 
 1882    if (B.isVirtual()) {
 
 1883      if (!VBases.insert(BaseDecl).second)
 
 1887        Context.getASTRecordLayout(LayoutClass);
 
 1889      BaseOffsetInLayoutClass =
 
 1892      BaseOffsetInLayoutClass =
 
 1896    DeterminePrimaryVirtualBases(BaseDecl, BaseOffsetInLayoutClass, VBases);
 
 1900void ItaniumVTableBuilder::LayoutVTablesForVirtualBases(
 
 1901    const CXXRecordDecl *RD, VisitedVirtualBasesSetTy &VBases) {
 
 1906  for (
const auto &B : RD->
bases()) {
 
 1907    const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
 
 1912        !PrimaryVirtualBases.count(BaseDecl) &&
 
 1913        VBases.insert(BaseDecl).second) {
 
 1915        Context.getASTRecordLayout(MostDerivedClass);
 
 1920        Context.getASTRecordLayout(LayoutClass);
 
 1924      LayoutPrimaryAndSecondaryVTables(
 
 1928        BaseOffsetInLayoutClass);
 
 1934      LayoutVTablesForVirtualBases(BaseDecl, VBases);
 
 1938static void printThunkMethod(
const ThunkInfo &Info, raw_ostream &Out) {
 
 1943  Out << 
" method: " << Str;
 
 1947void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
 
 1951  Out << 
"Original map\n";
 
 1960    Out << 
" " << Str0 << 
" -> " << Str1 << 
"\n";
 
 1963  if (isBuildingConstructorVTable()) {
 
 1964    Out << 
"Construction vtable for ('";
 
 1967    Out << MostDerivedClassOffset.
getQuantity() << 
") in '";
 
 1970    Out << 
"Vtable for '";
 
 1973  Out << 
"' (" << Components.size() << 
" entries).\n";
 
 1979  std::multimap<uint64_t, BaseSubobject> AddressPointsByIndex;
 
 1980  for (
const auto &AP : AddressPoints) {
 
 1983        VTableIndices[AP.second.VTableIndex] + AP.second.AddressPointIndex;
 
 1985    AddressPointsByIndex.insert(std::make_pair(Index, 
Base));
 
 1988  for (
unsigned I = 0, E = Components.size(); I != E; ++I) {
 
 1991    Out << llvm::format(
"%4d | ", I);
 
 1996    switch (Component.
getKind()) {
 
 1999      Out << 
"vcall_offset (" 
 2005      Out << 
"vbase_offset (" 
 2011      Out << 
"offset_to_top (" 
 2031        Out << 
" [deleted]";
 
 2033      ThunkInfo Thunk = VTableThunks.lookup(I);
 
 2037          Out << 
"\n       [return adjustment: ";
 
 2042            Out << 
" vbase offset offset";
 
 2046          printThunkMethod(Thunk, Out);
 
 2051          Out << 
"\n       [this adjustment: ";
 
 2056            Out << 
" vcall offset offset";
 
 2060          printThunkMethod(Thunk, Out);
 
 2076        Out << 
"() [complete]";
 
 2078        Out << 
"() [deleting]";
 
 2083      ThunkInfo Thunk = VTableThunks.lookup(I);
 
 2087          Out << 
"\n       [this adjustment: ";
 
 2092            Out << 
" vcall offset offset";
 
 2097        printThunkMethod(Thunk, Out);
 
 2108      Out << 
"[unused] " << Str;
 
 2118    uint64_t NextIndex = Index + 1;
 
 2119    if (
unsigned Count = AddressPointsByIndex.count(NextIndex)) {
 
 2122          AddressPointsByIndex.find(NextIndex)->second;
 
 2125        Base.getBase()->printQualifiedName(Out);
 
 2126        Out << 
", " << 
Base.getBaseOffset().getQuantity();
 
 2127        Out << 
") vtable address --\n";
 
 2130          AddressPointsByIndex.lower_bound(NextIndex)->second.getBaseOffset();
 
 2133        std::set<std::string> ClassNames;
 
 2134        for (
const auto &I :
 
 2135             llvm::make_range(AddressPointsByIndex.equal_range(NextIndex))) {
 
 2136          assert(I.second.getBaseOffset() == BaseOffset &&
 
 2137                 "Invalid base offset!");
 
 2142        for (
const std::string &Name : ClassNames) {
 
 2143          Out << 
"       -- (" << Name;
 
 2144          Out << 
", " << BaseOffset.getQuantity() << 
") vtable address --\n";
 
 2152  if (isBuildingConstructorVTable())
 
 2159    std::map<std::string, CharUnits> ClassNamesAndOffsets;
 
 2160    for (
const auto &I : VBaseOffsetOffsets) {
 
 2161      std::string ClassName = I.first->getQualifiedNameAsString();
 
 2163      ClassNamesAndOffsets.insert(std::make_pair(ClassName, OffsetOffset));
 
 2166    Out << 
"Virtual base offset offsets for '";
 
 2169    Out << ClassNamesAndOffsets.size();
 
 2170    Out << (ClassNamesAndOffsets.size() == 1 ? 
" entry" : 
" entries") << 
").\n";
 
 2172    for (
const auto &I : ClassNamesAndOffsets)
 
 2173      Out << 
"   " << I.first << 
" | " << I.second.getQuantity() << 
'\n';
 
 2178  if (!Thunks.empty()) {
 
 2180    std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls;
 
 2182    for (
const auto &I : Thunks) {
 
 2187      MethodNamesAndDecls.insert(std::make_pair(MethodName, MD));
 
 2190    for (
const auto &I : MethodNamesAndDecls) {
 
 2191      const std::string &MethodName = I.first;
 
 2194      ThunkInfoVectorTy ThunksVector = Thunks[MD];
 
 2199      Out << 
"Thunks for '" << MethodName << 
"' (" << ThunksVector.size();
 
 2200      Out << (ThunksVector.size() == 1 ? 
" entry" : 
" entries") << 
").\n";
 
 2202      for (
unsigned I = 0, E = ThunksVector.size(); I != E; ++I) {
 
 2203        const ThunkInfo &Thunk = ThunksVector[I];
 
 2205        Out << llvm::format(
"%4d | ", I);
 
 2210          Out << 
" non-virtual";
 
 2213            Out << 
" vbase offset offset";
 
 2222          Out << 
"this adjustment: ";
 
 2227            Out << 
" vcall offset offset";
 
 2240  std::map<uint64_t, std::string> IndicesMap;
 
 2242  for (
const auto *MD : MostDerivedClass->
methods()) {
 
 2253      assert(MethodVTableIndices.count(GD));
 
 2254      uint64_t VTableIndex = MethodVTableIndices[GD];
 
 2255      IndicesMap[VTableIndex] = MethodName + 
" [complete]";
 
 2256      IndicesMap[VTableIndex + 1] = MethodName + 
" [deleting]";
 
 2258      assert(MethodVTableIndices.count(MD));
 
 2259      IndicesMap[MethodVTableIndices[MD]] = MethodName;
 
 2264  if (!IndicesMap.empty()) {
 
 2265    Out << 
"VTable indices for '";
 
 2267    Out << 
"' (" << IndicesMap.size() << 
" entries).\n";
 
 2269    for (
const auto &I : IndicesMap) {
 
 2270      uint64_t VTableIndex = I.first;
 
 2271      const std::string &MethodName = I.second;
 
 2273      Out << llvm::format(
"%4" PRIu64 
" | ", VTableIndex) << MethodName
 
 2284                        unsigned numVTables) {
 
 2287  for (
auto it = addressPoints.begin(); it != addressPoints.end(); ++it) {
 
 2288    const auto &addressPointLoc = it->second;
 
 2289    unsigned vtableIndex = addressPointLoc.VTableIndex;
 
 2290    unsigned addressPoint = addressPointLoc.AddressPointIndex;
 
 2291    if (indexMap[vtableIndex]) {
 
 2294      assert(indexMap[vtableIndex] == addressPoint &&
 
 2295             "Every vtable index should have a unique address point. Found a " 
 2296             "vtable that has two different address points.");
 
 2298      indexMap[vtableIndex] = addressPoint;
 
 
 2313    : VTableComponents(VTableComponents), VTableThunks(VTableThunks),
 
 2315                                        AddressPoints, VTableIndices.size())) {
 
 2316  if (VTableIndices.size() <= 1)
 
 2317    assert(VTableIndices.size() == 1 && VTableIndices[0] == 0);
 
 2323    assert((LHS.first != RHS.first || LHS.second == RHS.second) &&
 
 2324           "Different thunks should have unique indices!");
 
 2325    return LHS.first < RHS.first;
 
 
 2343  MethodVTableIndicesTy::iterator I = MethodVTableIndices.find(GD);
 
 2344  if (I != MethodVTableIndices.end())
 
 2349  computeVTableRelatedInformation(RD);
 
 2351  I = MethodVTableIndices.find(GD);
 
 2352  assert(I != MethodVTableIndices.end() && 
"Did not find index!");
 
 
 2359  ClassPairTy ClassPair(RD, VBase);
 
 2361  VirtualBaseClassOffsetOffsetsMapTy::iterator I =
 
 2362    VirtualBaseClassOffsetOffsets.find(ClassPair);
 
 2363  if (I != VirtualBaseClassOffsetOffsets.end())
 
 2366  VCallAndVBaseOffsetBuilder Builder(*
this, RD, RD, 
nullptr,
 
 2371  for (
const auto &I : Builder.getVBaseOffsetOffsets()) {
 
 2373    ClassPairTy ClassPair(RD, I.first);
 
 2375    VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I.second));
 
 2378  I = VirtualBaseClassOffsetOffsets.find(ClassPair);
 
 2379  assert(I != VirtualBaseClassOffsetOffsets.end() && 
"Did not find index!");
 
 
 2386  computeVTableRelatedInformation(MD->getParent());
 
 2389  if (
const auto *DD = dyn_cast<CXXDestructorDecl>(OriginalMD))
 
 
 2399    auto I = OriginalMethodMap.find(MD);
 
 2403    if (I == OriginalMethodMap.end())
 
 
 2413static std::unique_ptr<VTableLayout>
 
 2416    VTableThunks(Builder.vtable_thunks_begin(), Builder.vtable_thunks_end());
 
 2418  return std::make_unique<VTableLayout>(
 
 2419      Builder.VTableIndices, Builder.vtable_components(), VTableThunks,
 
 2420      Builder.getAddressPoints());
 
 
 2424ItaniumVTableContext::computeVTableRelatedInformation(
const CXXRecordDecl *RD) {
 
 2425  std::unique_ptr<const VTableLayout> &Entry = VTableLayouts[RD];
 
 2435  MethodVTableIndices.insert(Builder.vtable_indices_begin(),
 
 2436                             Builder.vtable_indices_end());
 
 2439  Thunks.insert(Builder.thunks_begin(), Builder.thunks_end());
 
 2447  const CXXRecordDecl *VBase =
 
 2450  if (VirtualBaseClassOffsetOffsets.count(std::make_pair(RD, VBase)))
 
 2453  for (
const auto &I : Builder.getVBaseOffsetOffsets()) {
 
 2455    ClassPairTy ClassPair(RD, I.first);
 
 2457    VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I.second));
 
 2461std::unique_ptr<VTableLayout>
 
 2464    bool MostDerivedClassIsVirtual, 
const CXXRecordDecl *LayoutClass) {
 
 2465  ItaniumVTableBuilder Builder(*
this, MostDerivedClass, MostDerivedClassOffset,
 
 2466                               MostDerivedClassIsVirtual, LayoutClass);
 
 
 2514class VFTableBuilder {
 
 2516  typedef llvm::DenseMap<GlobalDecl, MethodVFTableLocation>
 
 2517    MethodVFTableLocationsTy;
 
 2519  typedef llvm::iterator_range<MethodVFTableLocationsTy::const_iterator>
 
 2520    method_locations_range;
 
 2538  const FinalOverriders Overriders;
 
 2543  MethodVFTableLocationsTy MethodVFTableLocations;
 
 2546  bool HasRTTIComponent = 
false;
 
 2553    const uint64_t VBTableIndex;
 
 2556    const uint64_t VFTableIndex;
 
 2567    MethodInfo(uint64_t VBTableIndex, uint64_t VFTableIndex,
 
 2568               bool UsesExtraSlot = 
false)
 
 2569        : VBTableIndex(VBTableIndex), VFTableIndex(VFTableIndex),
 
 2570          Shadowed(
false), UsesExtraSlot(UsesExtraSlot) {}
 
 2573        : VBTableIndex(0), VFTableIndex(0), Shadowed(
false),
 
 2574          UsesExtraSlot(
false) {}
 
 2577  typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy;
 
 2581  MethodInfoMapTy MethodInfoMap;
 
 2583  typedef llvm::DenseMap<uint64_t, ThunkInfo> VTableThunksMapTy;
 
 2587  VTableThunksMapTy VTableThunks;
 
 2589  typedef SmallVector<ThunkInfo, 1> ThunkInfoVectorTy;
 
 2590  typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
 
 2597  void AddThunk(
const CXXMethodDecl *MD, 
const ThunkInfo &Thunk) {
 
 2598    SmallVector<ThunkInfo, 1> &ThunksVector = Thunks[MD];
 
 2601    if (llvm::is_contained(ThunksVector, Thunk))
 
 2604    ThunksVector.push_back(Thunk);
 
 2609  CharUnits ComputeThisOffset(FinalOverriders::OverriderInfo Overrider);
 
 2611  void CalculateVtordispAdjustment(FinalOverriders::OverriderInfo Overrider,
 
 2612                                   CharUnits ThisOffset, ThisAdjustment &TA);
 
 2616  void AddMethod(
const CXXMethodDecl *MD, ThunkInfo TI) {
 
 2618      VTableThunks[Components.size()] = TI;
 
 2621    if (
const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
 
 2623             "Destructor can't have return adjustment!");
 
 2632  void AddMethods(BaseSubobject Base, 
unsigned BaseDepth,
 
 2633                  const CXXRecordDecl *LastVBase,
 
 2634                  BasesSetVectorTy &VisitedBases);
 
 2636  void LayoutVFTable() {
 
 2638    if (HasRTTIComponent)
 
 2641    BasesSetVectorTy VisitedBases;
 
 2642    AddMethods(BaseSubobject(MostDerivedClass, 
CharUnits::Zero()), 0, 
nullptr,
 
 2646    assert(!Components.empty() && 
"vftable can't be empty");
 
 2648    assert(MethodVFTableLocations.empty());
 
 2649    for (
const auto &I : MethodInfoMap) {
 
 2650      const CXXMethodDecl *MD = I.first;
 
 2651      const MethodInfo &MI = I.second;
 
 2656      if (MD->
getParent() != MostDerivedClass || MI.Shadowed)
 
 2660      if (
const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
 
 2661        MethodVFTableLocations[GlobalDecl(DD, 
Dtor_Deleting)] = Loc;
 
 2663        MethodVFTableLocations[MD] = Loc;
 
 2669  VFTableBuilder(MicrosoftVTableContext &VTables,
 
 2670                 const CXXRecordDecl *MostDerivedClass, 
const VPtrInfo &Which)
 
 2672        Context(MostDerivedClass->getASTContext()),
 
 2673        MostDerivedClass(MostDerivedClass),
 
 2674        MostDerivedClassLayout(Context.getASTRecordLayout(MostDerivedClass)),
 
 2676        Overriders(MostDerivedClass, CharUnits(), MostDerivedClass) {
 
 2683      HasRTTIComponent = 
true;
 
 2688      dumpLayout(llvm::outs());
 
 2691  uint64_t getNumThunks()
 const { 
return Thunks.size(); }
 
 2693  ThunksMapTy::const_iterator thunks_begin()
 const { 
return Thunks.begin(); }
 
 2695  ThunksMapTy::const_iterator thunks_end()
 const { 
return Thunks.end(); }
 
 2697  method_locations_range vtable_locations()
 const {
 
 2698    return method_locations_range(MethodVFTableLocations.begin(),
 
 2699                                  MethodVFTableLocations.end());
 
 2702  ArrayRef<VTableComponent> vtable_components()
 const { 
return Components; }
 
 2704  VTableThunksMapTy::const_iterator vtable_thunks_begin()
 const {
 
 2705    return VTableThunks.begin();
 
 2708  VTableThunksMapTy::const_iterator vtable_thunks_end()
 const {
 
 2709    return VTableThunks.end();
 
 2712  void dumpLayout(raw_ostream &);
 
 2772VFTableBuilder::ComputeThisOffset(FinalOverriders::OverriderInfo Overrider) {
 
 2773  BasesSetVectorTy Bases;
 
 2777    OverriddenMethodsSetTy VisitedOverriddenMethods;
 
 2778    auto InitialOverriddenDefinitionCollector = [&](
 
 2780      if (OverriddenMD->size_overridden_methods() == 0)
 
 2781        Bases.insert(OverriddenMD->getParent());
 
 2783      return VisitedOverriddenMethods.insert(OverriddenMD).second;
 
 2785    visitAllOverriddenMethods(Overrider.Method,
 
 2786                              InitialOverriddenDefinitionCollector);
 
 2791  if (Bases.size() == 0)
 
 2792    return Overrider.Offset;
 
 2797        return Bases.count(
Specifier->getType()->getAsCXXRecordDecl());
 
 2811    CharUnits ThisOffset = Overrider.Offset;
 
 2818      QualType CurTy = Element.Base->getType();
 
 2823      if (Element.Base->isVirtual()) {
 
 2834        LastVBaseOffset = ThisOffset =
 
 2842      if (LastVBaseOffset.
isZero()) {
 
 2846        ThisOffset = Overrider.Offset;
 
 2850        ThisOffset = LastVBaseOffset;
 
 2854    if (Ret > ThisOffset || 
First) {
 
 2860  assert(!
First && 
"Method not found in the given subobject?");
 
 2962void VFTableBuilder::CalculateVtordispAdjustment(
 
 2963    FinalOverriders::OverriderInfo Overrider, 
CharUnits ThisOffset,
 
 2967  const ASTRecordLayout::VBaseOffsetsMapTy::const_iterator &VBaseMapEntry =
 
 2969  assert(VBaseMapEntry != VBaseMap.end());
 
 2973  if (!VBaseMapEntry->second.hasVtorDisp() ||
 
 2979  CharUnits OffsetOfVBaseWithVFPtr = VBaseMapEntry->second.VBaseOffset;
 
 2981      (OffsetOfVBaseWithVFPtr - WhichVFPtr.
FullOffsetInMDC).getQuantity() - 4;
 
 2985  if (Overrider.Method->
getParent() == MostDerivedClass ||
 
 2986      !Overrider.VirtualBase)
 
 2998  TA.
NonVirtual = (ThisOffset - Overrider.Offset).getQuantity();
 
 3012  typedef llvm::DenseMap<DeclarationName, unsigned> VisitedGroupIndicesTy;
 
 3013  VisitedGroupIndicesTy VisitedGroupIndices;
 
 3014  for (
const auto *D : RD->
decls()) {
 
 3015    const auto *ND = dyn_cast<NamedDecl>(D);
 
 3018    VisitedGroupIndicesTy::iterator J;
 
 3020    std::tie(J, Inserted) = VisitedGroupIndices.insert(
 
 3021        std::make_pair(ND->getDeclName(), Groups.size()));
 
 3023      Groups.push_back(MethodGroup());
 
 3024    if (
const auto *MD = dyn_cast<CXXMethodDecl>(ND))
 
 3029  for (
const MethodGroup &Group : Groups)
 
 3030    VirtualMethods.append(Group.rbegin(), Group.rend());
 
 
 3034  for (
const auto &B : RD->
bases()) {
 
 3035    if (B.isVirtual() && B.getType()->getAsCXXRecordDecl() == 
Base)
 
 
 3041void VFTableBuilder::AddMethods(
BaseSubobject Base, 
unsigned BaseDepth,
 
 3043                                BasesSetVectorTy &VisitedBases) {
 
 3053  const CXXRecordDecl *NextBase = 
nullptr, *NextLastVBase = LastVBase;
 
 3058      NextLastVBase = NextBase;
 
 3066           "No primary virtual bases in this ABI");
 
 3067    NextBase = PrimaryBase;
 
 3068    NextBaseOffset = 
Base.getBaseOffset();
 
 3072    AddMethods(
BaseSubobject(NextBase, NextBaseOffset), BaseDepth + 1,
 
 3073               NextLastVBase, VisitedBases);
 
 3074    if (!VisitedBases.insert(NextBase))
 
 3075      llvm_unreachable(
"Found a duplicate primary base!");
 
 3091    FinalOverriders::OverriderInfo FinalOverrider =
 
 3092        Overriders.getOverrider(MD, 
Base.getBaseOffset());
 
 3093    const CXXMethodDecl *FinalOverriderMD = FinalOverrider.Method;
 
 3095        FindNearestOverriddenMethod(MD, VisitedBases);
 
 3098    bool ReturnAdjustingThunk = 
false, ForceReturnAdjustmentMangling = 
false;
 
 3099    CharUnits ThisOffset = ComputeThisOffset(FinalOverrider);
 
 3102    if ((OverriddenMD || FinalOverriderMD != MD) &&
 
 3104      CalculateVtordispAdjustment(FinalOverrider, ThisOffset,
 
 3105                                  ThisAdjustmentOffset);
 
 3113      MethodInfoMapTy::iterator OverriddenMDIterator =
 
 3114          MethodInfoMap.find(OverriddenMD);
 
 3117      if (OverriddenMDIterator == MethodInfoMap.end())
 
 3120      MethodInfo &OverriddenMethodInfo = OverriddenMDIterator->second;
 
 3122      VBIndex = OverriddenMethodInfo.VBTableIndex;
 
 3129      ReturnAdjustingThunk = !ComputeReturnAdjustmentBaseOffset(
 
 3130                                  Context, MD, OverriddenMD).isEmpty() ||
 
 3131                             OverriddenMethodInfo.UsesExtraSlot;
 
 3133      if (!ReturnAdjustingThunk) {
 
 3136        MethodInfo MI(VBIndex, OverriddenMethodInfo.VFTableIndex);
 
 3137        MethodInfoMap.erase(OverriddenMDIterator);
 
 3139        assert(!MethodInfoMap.count(MD) &&
 
 3140               "Should not have method info for this method yet!");
 
 3141        MethodInfoMap.insert(std::make_pair(MD, MI));
 
 3147      OverriddenMethodInfo.Shadowed = 
true;
 
 3151      ForceReturnAdjustmentMangling =
 
 3152          !(MD == FinalOverriderMD && ThisAdjustmentOffset.
isEmpty());
 
 3163    MethodInfo MI(VBIndex,
 
 3164                  HasRTTIComponent ? Components.size() - 1 : Components.size(),
 
 3165                  ReturnAdjustingThunk);
 
 3167    assert(!MethodInfoMap.count(MD) &&
 
 3168           "Should not have method info for this method yet!");
 
 3169    MethodInfoMap.insert(std::make_pair(MD, MI));
 
 3173    BaseOffset ReturnAdjustmentOffset;
 
 3176      ReturnAdjustmentOffset =
 
 3177          ComputeReturnAdjustmentBaseOffset(Context, FinalOverriderMD, MD);
 
 3179    if (!ReturnAdjustmentOffset.isEmpty()) {
 
 3180      ForceReturnAdjustmentMangling = 
true;
 
 3182          ReturnAdjustmentOffset.NonVirtualOffset.
getQuantity();
 
 3183      if (ReturnAdjustmentOffset.VirtualBase) {
 
 3190                                    ReturnAdjustmentOffset.VirtualBase);
 
 3193    auto ThisType = (OverriddenMD ? OverriddenMD : MD)->getThisType().getTypePtr();
 
 3194    AddMethod(FinalOverriderMD,
 
 3196                        ForceReturnAdjustmentMangling ? MD : 
nullptr));
 
 3203    Elem->printQualifiedName(Out);
 
 
 3209                                         bool ContinueFirstLine) {
 
 3211  bool Multiline = 
false;
 
 3212  const char *LinePrefix = 
"\n       ";
 
 3214    if (!ContinueFirstLine)
 
 3216    Out << 
"[return adjustment (to type '" 
 3228    if (Multiline || !ContinueFirstLine)
 
 3230    Out << 
"[this adjustment: ";
 
 3232      assert(
T.Virtual.Microsoft.VtordispOffset < 0);
 
 3233      Out << 
"vtordisp at " << 
T.Virtual.Microsoft.VtordispOffset << 
", ";
 
 3234      if (
T.Virtual.Microsoft.VBPtrOffset) {
 
 3235        Out << 
"vbptr at " << 
T.Virtual.Microsoft.VBPtrOffset
 
 3237        assert(
T.Virtual.Microsoft.VBOffsetOffset > 0);
 
 3238        Out << LinePrefix << 
" vboffset at " 
 3239            << 
T.Virtual.Microsoft.VBOffsetOffset << 
" in the vbtable, ";
 
 3242    Out << 
T.NonVirtual << 
" non-virtual]";
 
 
 3246void VFTableBuilder::dumpLayout(raw_ostream &Out) {
 
 3247  Out << 
"VFTable for ";
 
 3251  Out << 
"' (" << Components.size()
 
 3252      << (Components.size() == 1 ? 
" entry" : 
" entries") << 
").\n";
 
 3254  for (
unsigned I = 0, E = Components.size(); I != E; ++I) {
 
 3255    Out << llvm::format(
"%4d | ", I);
 
 3260    switch (Component.
getKind()) {
 
 3278        Out << 
" [deleted]";
 
 3280      ThunkInfo Thunk = VTableThunks.lookup(I);
 
 3291      Out << 
"() [scalar deleting]";
 
 3296      ThunkInfo Thunk = VTableThunks.lookup(I);
 
 3299               "No return adjustment needed for destructors!");
 
 3310          "Unexpected vftable component type %0 for component number %1");
 
 3320  if (!Thunks.empty()) {
 
 3322    std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls;
 
 3324    for (
const auto &I : Thunks) {
 
 3329      MethodNamesAndDecls.insert(std::make_pair(MethodName, MD));
 
 3332    for (
const auto &MethodNameAndDecl : MethodNamesAndDecls) {
 
 3333      const std::string &MethodName = MethodNameAndDecl.first;
 
 3336      ThunkInfoVectorTy ThunksVector = Thunks[MD];
 
 3337      llvm::stable_sort(ThunksVector, [](
const ThunkInfo &LHS,
 
 3344      Out << 
"Thunks for '" << MethodName << 
"' (" << ThunksVector.size();
 
 3345      Out << (ThunksVector.size() == 1 ? 
" entry" : 
" entries") << 
").\n";
 
 3347      for (
unsigned I = 0, E = ThunksVector.size(); I != E; ++I) {
 
 3348        const ThunkInfo &Thunk = ThunksVector[I];
 
 3350        Out << llvm::format(
"%4d | ", I);
 
 3394void MicrosoftVTableContext::computeVTablePaths(
bool ForVBTables,
 
 3397  assert(Paths.empty());
 
 3398  const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
 
 3402    Paths.push_back(std::make_unique<VPtrInfo>(RD));
 
 3406  llvm::SmallPtrSet<const CXXRecordDecl*, 4> VBasesSeen;
 
 3407  for (
const auto &B : RD->
bases()) {
 
 3408    const CXXRecordDecl *
Base = B.getType()->getAsCXXRecordDecl();
 
 3409    if (B.isVirtual() && VBasesSeen.count(Base))
 
 3412    if (!
Base->isDynamicClass())
 
 3418    for (
const std::unique_ptr<VPtrInfo> &BaseInfo : BasePaths) {
 
 3425      auto P = std::make_unique<VPtrInfo>(*BaseInfo);
 
 3429      if (P->MangledPath.empty() || P->MangledPath.back() != Base)
 
 3430        P->NextBaseToMangle = 
Base;
 
 3435      if (P->ObjectWithVPtr == Base &&
 
 3438        P->ObjectWithVPtr = RD;
 
 3443        P->ContainingVBases.push_back(Base);
 
 3444      else if (P->ContainingVBases.empty())
 
 3448      P->FullOffsetInMDC = P->NonVirtualOffset;
 
 3449      if (
const CXXRecordDecl *VB = P->getVBaseWithVPtr())
 
 3452      Paths.push_back(std::move(P));
 
 3456      VBasesSeen.insert(Base);
 
 3460    for (
const auto &VB : 
Base->vbases())
 
 3461      VBasesSeen.insert(VB.getType()->getAsCXXRecordDecl());
 
 3488      llvm::make_pointee_range(Paths));
 
 3492  bool Changed = 
false;
 
 3493  for (
size_t I = 0, E = PathsSorted.size(); I != E;) {
 
 3495    size_t BucketStart = I;
 
 3499             PathsSorted[BucketStart].get().MangledPath ==
 
 3500                 PathsSorted[I].get().MangledPath);
 
 3503    if (I - BucketStart > 1) {
 
 3504      for (
size_t II = BucketStart; II != I; ++II)
 
 3506      assert(Changed && 
"no paths were extended to fix ambiguity");
 
 
 3515typedef llvm::SetVector<BaseSubobject, std::vector<BaseSubobject>,
 
 3516                        llvm::DenseSet<BaseSubobject>> FullPathTy;
 
 3525                                 FullPathTy &FullPath,
 
 3526                                 std::list<FullPathTy> &Paths) {
 
 3528    Paths.push_back(FullPath);
 
 3541                         IntroducingObject, FullPath, Paths);
 
 3542    FullPath.pop_back();
 
 
 3548  FullPaths.remove_if([&](
const FullPathTy &SpecificPath) {
 
 3549    for (
const FullPathTy &OtherPath : FullPaths) {
 
 3550      if (&SpecificPath == &OtherPath)
 
 3552      if (llvm::all_of(SpecificPath, [&](
const BaseSubobject &BSO) {
 
 3553            return OtherPath.contains(BSO);
 
 
 3564                                     const FullPathTy &FullPath) {
 
 3566      Context.getASTRecordLayout(RD);
 
 3572      assert(Offset.getQuantity() == -1);
 
 3576    assert(Offset.getQuantity() != -1);
 
 3582          return BS.getType()->getAsCXXRecordDecl() == Base;
 
 
 3597                                        std::list<FullPathTy> &FullPaths) {
 
 3599  if (FullPaths.empty())
 
 3601  if (FullPaths.size() == 1)
 
 3602    return &FullPaths.front();
 
 3604  const FullPathTy *BestPath = 
nullptr;
 
 3605  typedef std::set<const CXXMethodDecl *> OverriderSetTy;
 
 3606  OverriderSetTy LastOverrides;
 
 3607  for (
const FullPathTy &SpecificPath : FullPaths) {
 
 3608    assert(!SpecificPath.empty());
 
 3609    OverriderSetTy CurrentOverrides;
 
 3610    const CXXRecordDecl *TopLevelRD = SpecificPath.begin()->getBase();
 
 3615    FinalOverriders Overriders(TopLevelRD, 
CharUnits::Zero(), TopLevelRD);
 
 3619      FinalOverriders::OverriderInfo OI =
 
 3624      if (ComputeReturnAdjustmentBaseOffset(Context, OverridingMethod, MD)
 
 3630      if (llvm::none_of(SpecificPath, [&](
const BaseSubobject &BSO) {
 
 3631            return BSO.
getBase() == OverridingParent;
 
 3634      CurrentOverrides.insert(OverridingMethod);
 
 3636    OverriderSetTy NewOverrides =
 
 3637        llvm::set_difference(CurrentOverrides, LastOverrides);
 
 3638    if (NewOverrides.empty())
 
 3640    OverriderSetTy MissingOverrides =
 
 3641        llvm::set_difference(LastOverrides, CurrentOverrides);
 
 3642    if (MissingOverrides.empty()) {
 
 3644      BestPath = &SpecificPath;
 
 3645      std::swap(CurrentOverrides, LastOverrides);
 
 3650      const CXXMethodDecl *ConflictMD = *MissingOverrides.begin();
 
 3661  return BestPath ? BestPath : &FullPaths.front();
 
 
 3667  const ASTRecordLayout &MostDerivedLayout = Context.getASTRecordLayout(RD);
 
 3668  FullPathTy FullPath;
 
 3669  std::list<FullPathTy> FullPaths;
 
 3670  for (
const std::unique_ptr<VPtrInfo>& Info : Paths) {
 
 3673        BaseSubobject(Info->IntroducingObject, Info->FullOffsetInMDC), FullPath,
 
 3677    Info->PathToIntroducingObject.clear();
 
 3678    if (
const FullPathTy *BestPath =
 
 3681        Info->PathToIntroducingObject.push_back(BSO.getBase());
 
 
 3698void MicrosoftVTableContext::computeVTableRelatedInformation(
 
 3703  if (VFPtrLocations.count(RD))
 
 3709    auto VFPtrs = std::make_unique<VPtrInfoVector>();
 
 3710    computeVTablePaths(
false, RD, *VFPtrs);
 
 3712    VFPtrLocations[RD] = std::move(VFPtrs);
 
 3715  MethodVFTableLocationsTy NewMethodLocations;
 
 3716  for (
const std::unique_ptr<VPtrInfo> &VFPtr : *VFPtrLocations[RD]) {
 
 3717    VFTableBuilder Builder(*
this, RD, *VFPtr);
 
 3719    VFTableIdTy id(RD, VFPtr->FullOffsetInMDC);
 
 3720    assert(VFTableLayouts.count(
id) == 0);
 
 3721    SmallVector<VTableLayout::VTableThunkTy, 1> VTableThunks(
 
 3722        Builder.vtable_thunks_begin(), Builder.vtable_thunks_end());
 
 3723    VFTableLayouts[id] = std::make_unique<VTableLayout>(
 
 3724        ArrayRef<size_t>{0}, Builder.vtable_components(), VTableThunks,
 
 3725        EmptyAddressPointsMap);
 
 3726    Thunks.insert(Builder.thunks_begin(), Builder.thunks_end());
 
 3728    const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
 
 3729    for (
const auto &Loc : Builder.vtable_locations()) {
 
 3730      auto Insert = NewMethodLocations.insert(Loc);
 
 3732        const MethodVFTableLocation &NewLoc = Loc.second;
 
 3733        MethodVFTableLocation &OldLoc = 
Insert.first->second;
 
 3740  MethodVFTableLocations.insert_range(NewMethodLocations);
 
 3741  if (Context.getLangOpts().DumpVTableLayouts)
 
 3742    dumpMethodLocations(RD, NewMethodLocations, llvm::outs());
 
 3745void MicrosoftVTableContext::dumpMethodLocations(
 
 3746    const CXXRecordDecl *RD, 
const MethodVFTableLocationsTy &NewMethods,
 
 3750  std::map<MethodVFTableLocation, std::string> IndicesMap;
 
 3751  bool HasNonzeroOffset = 
false;
 
 3753  for (
const auto &I : NewMethods) {
 
 3761      IndicesMap[I.second] = MethodName + 
" [scalar deleting]";
 
 3763      IndicesMap[I.second] = MethodName;
 
 3766    if (!I.second.VFPtrOffset.isZero() || I.second.VBTableIndex != 0)
 
 3767      HasNonzeroOffset = 
true;
 
 3771  if (!IndicesMap.empty()) {
 
 3772    Out << 
"VFTable indices for ";
 
 3775    Out << 
"' (" << IndicesMap.size()
 
 3776        << (IndicesMap.size() == 1 ? 
" entry" : 
" entries") << 
").\n";
 
 3780    for (
const auto &I : IndicesMap) {
 
 3781      CharUnits VFPtrOffset = I.first.VFPtrOffset;
 
 3782      uint64_t VBIndex = I.first.VBTableIndex;
 
 3783      if (HasNonzeroOffset &&
 
 3784          (VFPtrOffset != LastVFPtrOffset || VBIndex != LastVBIndex)) {
 
 3785        assert(VBIndex > LastVBIndex || VFPtrOffset > LastVFPtrOffset);
 
 3786        Out << 
" -- accessible via ";
 
 3788          Out << 
"vbtable index " << VBIndex << 
", ";
 
 3789        Out << 
"vfptr at offset " << VFPtrOffset.
getQuantity() << 
" --\n";
 
 3790        LastVFPtrOffset = VFPtrOffset;
 
 3791        LastVBIndex = VBIndex;
 
 3794      uint64_t VTableIndex = I.first.Index;
 
 3795      const std::string &MethodName = I.second;
 
 3796      Out << llvm::format(
"%4" PRIu64 
" | ", VTableIndex) << MethodName << 
'\n';
 
 3804const VirtualBaseInfo &MicrosoftVTableContext::computeVBTableRelatedInformation(
 
 3806  VirtualBaseInfo *VBI;
 
 3811    std::unique_ptr<VirtualBaseInfo> &Entry = VBaseInfo[RD];
 
 3814    Entry = std::make_unique<VirtualBaseInfo>();
 
 3818  computeVTablePaths(
true, RD, VBI->
VBPtrPaths);
 
 3821  const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
 
 3825    const VirtualBaseInfo &BaseInfo =
 
 3826        computeVBTableRelatedInformation(VBPtrBase);
 
 3833  for (
const auto &VB : RD->
vbases()) {
 
 3834    const CXXRecordDecl *CurVBase = VB.getType()->getAsCXXRecordDecl();
 
 3835    if (VBI->
VBTableIndices.try_emplace(CurVBase, VBTableIndex).second)
 
 3844  const VirtualBaseInfo &VBInfo = computeVBTableRelatedInformation(Derived);
 
 
 3851  return computeVBTableRelatedInformation(RD).VBPtrPaths;
 
 
 3856  computeVTableRelatedInformation(RD);
 
 3858  assert(VFPtrLocations.count(RD) && 
"Couldn't find vfptr locations");
 
 3859  return *VFPtrLocations[RD];
 
 
 3865  computeVTableRelatedInformation(RD);
 
 3867  VFTableIdTy id(RD, VFPtrOffset);
 
 3868  assert(VFTableLayouts.count(
id) && 
"Couldn't find a VFTable at this offset");
 
 3869  return *VFTableLayouts[id];
 
 
 3875         "Only use this method for virtual methods or dtors");
 
 3881  MethodVFTableLocationsTy::iterator I = MethodVFTableLocations.find(GD);
 
 3882  if (I != MethodVFTableLocations.end())
 
 3887  computeVTableRelatedInformation(RD);
 
 3889  I = MethodVFTableLocations.find(GD);
 
 3890  assert(I != MethodVFTableLocations.end() && 
"Did not find index!");
 
 
Defines the clang::ASTContext interface.
static void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef< CounterExpression > Expressions, ArrayRef< CounterMappingRegion > Regions)
static Decl::Kind getKind(const Decl *D)
static QualType getPointeeType(const MemRegion *R)
static void findPathsToSubobject(ASTContext &Context, const ASTRecordLayout &MostDerivedLayout, const CXXRecordDecl *RD, CharUnits Offset, BaseSubobject IntroducingObject, FullPathTy &FullPath, std::list< FullPathTy > &Paths)
static const FullPathTy * selectBestPath(ASTContext &Context, const CXXRecordDecl *RD, const VPtrInfo &Info, std::list< FullPathTy > &FullPaths)
static CharUnits getOffsetOfFullPath(ASTContext &Context, const CXXRecordDecl *RD, const FullPathTy &FullPath)
static void removeRedundantPaths(std::list< FullPathTy > &FullPaths)
static std::unique_ptr< VTableLayout > CreateVTableLayout(const ItaniumVTableBuilder &Builder)
static bool vfptrIsEarlierInMDC(const ASTRecordLayout &Layout, const MethodVFTableLocation &LHS, const MethodVFTableLocation &RHS)
static bool isDirectVBase(const CXXRecordDecl *Base, const CXXRecordDecl *RD)
static void PrintBasePath(const VPtrInfo::BasePath &Path, raw_ostream &Out)
static VTableLayout::AddressPointsIndexMapTy MakeAddressPointIndices(const VTableLayout::AddressPointsMapTy &addressPoints, unsigned numVTables)
static bool rebucketPaths(VPtrInfoVector &Paths)
static bool extendPath(VPtrInfo &P)
static void dumpMicrosoftThunkAdjustment(const ThunkInfo &TI, raw_ostream &Out, bool ContinueFirstLine)
static void GroupNewVirtualOverloads(const CXXRecordDecl *RD, SmallVector< const CXXMethodDecl *, 10 > &VirtualMethods)
static void computeFullPathsForVFTables(ASTContext &Context, const CXXRecordDecl *RD, VPtrInfoVector &Paths)
static bool setsIntersect(const llvm::SmallPtrSet< const CXXRecordDecl *, 4 > &A, ArrayRef< const CXXRecordDecl * > B)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
const LangOptions & getLangOpts() const
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
DiagnosticsEngine & getDiagnostics() const
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
bool hasOwnVFPtr() const
hasOwnVFPtr - Does this class provide its own virtual-function table pointer, rather than inheriting ...
const CXXRecordDecl * getBaseSharingVBPtr() const
bool hasOwnVBPtr() const
hasOwnVBPtr - Does this class provide its own virtual-base table pointer, rather than inheriting one ...
llvm::DenseMap< const CXXRecordDecl *, VBaseInfo > VBaseOffsetsMapTy
CharUnits getVBPtrOffset() const
getVBPtrOffset - Get the offset for virtual base table pointer.
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const
getVBaseClassOffset - Get the offset, in chars, for the given base class.
const VBaseOffsetsMapTy & getVBaseOffsetsMap() const
const CXXRecordDecl * getPrimaryBase() const
getPrimaryBase - Get the primary base for this record.
bool isPrimaryBaseVirtual() const
isPrimaryBaseVirtual - Get whether the primary base for this record is virtual or not.
const CXXRecordDecl * getBase() const
getBase - Returns the base class declaration.
CharUnits getBaseOffset() const
getBaseOffset - Returns the base class offset.
Represents a path from a specific derived class (which is not represented as part of the path) to a p...
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
Represents a base class of a C++ class.
bool isVirtual() const
Determines whether the base class is a virtual base class (or not).
QualType getType() const
Retrieves the type of the base class.
Represents a C++ destructor within a class.
A mapping from each virtual member function to its set of final overriders.
Represents a static or instance method of a struct/union/class.
overridden_method_range overridden_methods() const
unsigned size_overridden_methods() const
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
QualType getThisType() const
Return the type of the this pointer.
bool isMoveAssignmentOperator() const
Determine whether this is a move assignment operator.
bool isCopyAssignmentOperator() const
Determine whether this is a copy-assignment operator, regardless of whether it was declared implicitl...
CXXMethodDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Represents a C++ struct/union/class.
base_class_iterator bases_end()
method_range methods() const
bool isPolymorphic() const
Whether this class is polymorphic (C++ [class.virtual]), which means that the class contains or inher...
bool lookupInBases(BaseMatchesCallback BaseMatches, CXXBasePaths &Paths, bool LookupInDependent=false) const
Look for entities within the base classes of this C++ class, transitively searching all base class su...
base_class_iterator bases_begin()
base_class_range vbases()
base_class_iterator vbases_begin()
bool isDynamicClass() const
void getFinalOverriders(CXXFinalOverriderMap &FinaOverriders) const
Retrieve the final overriders for each virtual member function in the class hierarchy where this clas...
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
bool isDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is derived from the class Base.
CanQual< T > getUnqualifiedType() const
Retrieve the unqualified form of this type.
CanProxy< U > getAs() const
Retrieve a canonical type pointer with a different static type, upcasting or downcasting as needed.
CharUnits - This is an opaque type for sizes expressed in character units.
bool isZero() const
isZero - Test whether the quantity equals zero.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
DeclContext * getParent()
getParent - Returns the containing DeclContext.
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
Decl - This represents one declaration (or definition), e.g.
ASTContext & getASTContext() const LLVM_READONLY
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
SourceLocation getLocation() const
The name of a declaration.
Concrete class used by the front-end to report problems and issues.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
unsigned getCustomDiagID(Level L, const char(&FormatString)[N])
Return an ID for a diagnostic with the specified format string and level.
bool isImmediateFunction() const
QualType getReturnType() const
bool isDeleted() const
Whether this function has been deleted.
bool isPureVirtual() const
Whether this virtual function is pure, i.e.
OverloadedOperatorKind getOverloadedOperator() const
getOverloadedOperator - Which C++ overloaded operator this function represents, if any.
Represents a prototype with parameter type info, e.g.
Qualifiers getMethodQuals() const
ArrayRef< QualType > getParamTypes() const
FunctionType - C99 6.7.5.3 - Function Declarators.
QualType getReturnType() const
GlobalDecl - represents a global declaration.
GlobalDecl getCanonicalDecl() const
CXXDtorType getDtorType() const
const Decl * getDecl() const
const CXXMethodDecl * findOriginalMethodInMap(const CXXMethodDecl *MD) const
const OriginalMethodMapTy & getOriginalMethodMap()
This method is reserved for the implementation and shouldn't be used directly.
uint64_t getMethodVTableIndex(GlobalDecl GD)
Locate a virtual function in the vtable.
bool isRelativeLayout() const
std::unique_ptr< VTableLayout > createConstructionVTableLayout(const CXXRecordDecl *MostDerivedClass, CharUnits MostDerivedClassOffset, bool MostDerivedClassIsVirtual, const CXXRecordDecl *LayoutClass)
~ItaniumVTableContext() override
CharUnits getVirtualBaseOffsetOffset(const CXXRecordDecl *RD, const CXXRecordDecl *VBase)
Return the offset in chars (relative to the vtable address point) where the offset of the virtual bas...
ItaniumVTableContext(ASTContext &Context, VTableComponentLayout ComponentLayout=Pointer)
GlobalDecl findOriginalMethod(GlobalDecl GD)
Return the method that added the v-table slot that will be used to call the given method.
void setOriginalMethod(const CXXMethodDecl *Key, const CXXMethodDecl *Val)
unsigned getVBTableIndex(const CXXRecordDecl *Derived, const CXXRecordDecl *VBase)
Returns the index of VBase in the vbtable of Derived.
const VPtrInfoVector & enumerateVBTables(const CXXRecordDecl *RD)
MethodVFTableLocation getMethodVFTableLocation(GlobalDecl GD)
const VPtrInfoVector & getVFPtrOffsets(const CXXRecordDecl *RD)
const VTableLayout & getVFTableLayout(const CXXRecordDecl *RD, CharUnits VFPtrOffset)
~MicrosoftVTableContext() override
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
std::string getQualifiedNameAsString() const
void printQualifiedName(raw_ostream &OS) const
Returns a human-readable qualified name for this declaration, like A::B::i, for i being member of nam...
The set of methods that override a given virtual method in each subobject where it occurs.
PointerType - C99 6.7.5.1 - Pointer Declarators.
static std::string ComputeName(PredefinedIdentKind IK, const Decl *CurrentDecl, bool ForceElaboratedPrinting=false)
A (possibly-)qualified type.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
QualType getCanonicalType() const
Base for LValueReferenceType and RValueReferenceType.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
const T * castAs() const
Member-template castAs<specific type>.
Represents a single component in a vtable.
static VTableComponent MakeCompleteDtor(const CXXDestructorDecl *DD)
static VTableComponent MakeRTTI(const CXXRecordDecl *RD)
const CXXMethodDecl * getUnusedFunctionDecl() const
static VTableComponent MakeOffsetToTop(CharUnits Offset)
CharUnits getVBaseOffset() const
static VTableComponent MakeUnusedFunction(const CXXMethodDecl *MD)
Kind getKind() const
Get the kind of this vtable component.
static VTableComponent MakeFunction(const CXXMethodDecl *MD)
@ CK_DeletingDtorPointer
A pointer to the deleting destructor.
@ CK_UnusedFunctionPointer
An entry that is never used.
@ CK_CompleteDtorPointer
A pointer to the complete destructor.
static VTableComponent MakeVBaseOffset(CharUnits Offset)
const CXXRecordDecl * getRTTIDecl() const
static VTableComponent MakeDeletingDtor(const CXXDestructorDecl *DD)
CharUnits getOffsetToTop() const
const CXXMethodDecl * getFunctionDecl() const
static VTableComponent MakeVCallOffset(CharUnits Offset)
CharUnits getVCallOffset() const
const CXXDestructorDecl * getDestructorDecl() const
VTableContextBase(bool MS)
static bool hasVtableSlot(const CXXMethodDecl *MD)
Determine whether this function should be assigned a vtable slot.
ThunksMapTy Thunks
Contains all thunks that a given method decl will need.
llvm::SmallVector< unsigned, 4 > AddressPointsIndexMapTy
VTableLayout(ArrayRef< size_t > VTableIndices, ArrayRef< VTableComponent > VTableComponents, ArrayRef< VTableThunkTy > VTableThunks, const AddressPointsMapTy &AddressPoints)
llvm::DenseMap< BaseSubobject, AddressPointLocation > AddressPointsMapTy
std::pair< uint64_t, ThunkInfo > VTableThunkTy
Defines the clang::TargetInfo interface.
bool Ret(InterpState &S, CodePtr &PC)
The JSON file list parser is used to communicate input to InstallAPI.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool isa(CodeGen::Address addr)
const FunctionProtoType * T
SmallVector< std::unique_ptr< VPtrInfo >, 2 > VPtrInfoVector
@ Dtor_Complete
Complete object dtor.
@ Dtor_Deleting
Deleting dtor.
for(const auto &A :T->param_types())
U cast(CodeGen::Address addr)
@ PrettyFunctionNoVirtual
The same as PrettyFunction, except that the 'virtual' keyword is omitted for virtual member functions...
Represents an element in a path from a derived class to a base class.
const CXXRecordDecl * Class
The record decl of the class that the base is a base of.
const CXXBaseSpecifier * Base
The base specifier that states the link from a derived class to a base class, which will be followed ...
const CXXRecordDecl * VBase
If nonnull, holds the last vbase which contains the vfptr that the method definition is adjusted to.
CharUnits VFPtrOffset
This is the offset of the vfptr from the start of the last vbase, or the complete type if there are n...
union clang::ReturnAdjustment::VirtualAdjustment Virtual
int64_t NonVirtual
The non-virtual adjustment from the derived object to its nearest virtual base.
A this pointer adjustment.
union clang::ThisAdjustment::VirtualAdjustment Virtual
int64_t NonVirtual
The non-virtual adjustment from the derived object to its nearest virtual base.
The this pointer adjustment as well as an optional return adjustment for a thunk.
ThisAdjustment This
The this pointer adjustment.
const CXXMethodDecl * Method
Holds a pointer to the overridden method this thunk is for, if needed by the ABI to distinguish diffe...
ReturnAdjustment Return
The return adjustment.
Uniquely identifies a virtual method within a class hierarchy by the method itself and a class subobj...
Holds information about the inheritance path to a virtual base or function table pointer.
CharUnits NonVirtualOffset
IntroducingObject is at this offset from its containing complete object or virtual base.
CharUnits FullOffsetInMDC
Static offset from the top of the most derived class to this vfptr, including any virtual base offset...
const CXXRecordDecl * getVBaseWithVPtr() const
The vptr is stored inside the non-virtual component of this virtual base.
SmallVector< const CXXRecordDecl *, 1 > BasePath
const CXXRecordDecl * IntroducingObject
This is the class that introduced the vptr by declaring new virtual methods or virtual bases.
BasePath MangledPath
The bases from the inheritance path that got used to mangle the vbtable name.
const CXXRecordDecl * NextBaseToMangle
The next base to push onto the mangled path if this path is ambiguous in a derived class.
BasePath PathToIntroducingObject
This holds the base classes path from the complete type to the first base with the given vfptr offset...
All virtual base related information about a given record decl.
VPtrInfoVector VBPtrPaths
Information on all virtual base tables used when this record is the most derived class.
llvm::DenseMap< const CXXRecordDecl *, unsigned > VBTableIndices
A map from virtual base to vbtable index for doing a conversion from the the derived class to the a b...
struct clang::ReturnAdjustment::VirtualAdjustment::@103031170252120233124322035264172076254313213024 Itanium
uint32_t VBPtrOffset
The offset (in bytes) of the vbptr, relative to the beginning of the derived class.
struct clang::ReturnAdjustment::VirtualAdjustment::@167242364125115315334113104006210160165266060257 Microsoft
int64_t VBaseOffsetOffset
The offset (in bytes), relative to the address point of the virtual base class offset.
uint32_t VBIndex
Index of the virtual base in the vbtable.
struct clang::ThisAdjustment::VirtualAdjustment::@106065375072164260365214033034320247050276346205 Itanium
int32_t VtordispOffset
The offset of the vtordisp (in bytes), relative to the ECX.
struct clang::ThisAdjustment::VirtualAdjustment::@312251255113040203233347230177110330127151157305 Microsoft
int32_t VBOffsetOffset
The offset (in bytes) of the vbase offset in the vbtable.
int64_t VCallOffsetOffset
The offset (in bytes), relative to the address point, of the virtual call offset.
int32_t VBPtrOffset
The offset of the vbptr of the derived class (in bytes), relative to the ECX after vtordisp adjustmen...