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),
54 : DerivedClass(DerivedClass), VirtualBase(VirtualBase),
55 NonVirtualOffset(NonVirtualOffset) { }
57 bool isEmpty()
const {
return NonVirtualOffset.
isZero() && !VirtualBase; }
62class FinalOverriders {
65 struct OverriderInfo {
76 OverriderInfo() : Method(
nullptr), VirtualBase(
nullptr),
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),
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;
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,
283 assert(CanDerivedReturnType->getTypeClass() ==
284 CanBaseReturnType->getTypeClass() &&
285 "Types must have same type class!");
287 if (CanDerivedReturnType == CanBaseReturnType) {
292 if (isa<ReferenceType>(CanDerivedReturnType)) {
293 CanDerivedReturnType =
294 CanDerivedReturnType->getAs<
ReferenceType>()->getPointeeType();
297 }
else if (isa<PointerType>(CanDerivedReturnType)) {
298 CanDerivedReturnType =
299 CanDerivedReturnType->getAs<
PointerType>()->getPointeeType();
303 llvm_unreachable(
"Unexpected return type!");
309 if (CanDerivedReturnType.getUnqualifiedType() ==
316 cast<CXXRecordDecl>(cast<RecordType>(CanDerivedReturnType)->getDecl());
319 cast<CXXRecordDecl>(cast<RecordType>(CanBaseReturnType)->getDecl());
321 return ComputeBaseOffset(Context, BaseRD, DerivedRD);
327 SubobjectOffsetMapTy &SubobjectOffsets,
328 SubobjectOffsetMapTy &SubobjectLayoutClassOffsets,
329 SubobjectCountMapTy &SubobjectCounts) {
332 unsigned SubobjectNumber = 0;
334 SubobjectNumber = ++SubobjectCounts[RD];
337 assert(!SubobjectOffsets.count(std::make_pair(RD, SubobjectNumber))
338 &&
"Subobject offset already exists!");
339 assert(!SubobjectLayoutClassOffsets.count(std::make_pair(RD, SubobjectNumber))
340 &&
"Subobject offset already exists!");
342 SubobjectOffsets[std::make_pair(RD, SubobjectNumber)] =
Base.getBaseOffset();
343 SubobjectLayoutClassOffsets[std::make_pair(RD, SubobjectNumber)] =
347 for (
const auto &B : RD->
bases()) {
348 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
354 if (SubobjectOffsets.count(std::make_pair(BaseDecl, 0)))
360 BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
361 BaseOffsetInLayoutClass =
368 BaseOffsetInLayoutClass = OffsetInLayoutClass +
Offset;
372 B.isVirtual(), BaseOffsetInLayoutClass,
373 SubobjectOffsets, SubobjectLayoutClassOffsets,
379 VisitedVirtualBasesSetTy &VisitedVirtualBases) {
383 for (
const auto &B : RD->
bases()) {
384 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
392 if (!VisitedVirtualBases.insert(BaseDecl).second) {
397 BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
405 Out <<
"Final overriders for (";
408 Out <<
Base.getBaseOffset().getQuantity() <<
")\n";
411 for (
const auto *MD : RD->
methods()) {
414 MD = MD->getCanonicalDecl();
416 OverriderInfo Overrider = getOverrider(MD,
Base.getBaseOffset());
419 MD->printQualifiedName(Out);
421 Overrider.Method->printQualifiedName(Out);
422 Out <<
", " << Overrider.Offset.getQuantity() <<
')';
425 if (!Overrider.Method->isPure())
426 Offset = ComputeReturnAdjustmentBaseOffset(Context, Overrider.Method, MD);
429 Out <<
" [ret-adj: ";
431 Offset.VirtualBase->printQualifiedName(Out);
435 Out <<
Offset.NonVirtualOffset.getQuantity() <<
" nv]";
443struct VCallOffsetMap {
445 typedef std::pair<const CXXMethodDecl *, CharUnits> MethodAndOffsetPairTy;
453 static bool MethodsCanShareVCallOffset(
const CXXMethodDecl *LHS,
467 bool empty()
const {
return Offsets.empty(); }
478 if (
LT == RT)
return true;
488bool VCallOffsetMap::MethodsCanShareVCallOffset(
const CXXMethodDecl *LHS,
494 if (isa<CXXDestructorDecl>(LHS))
495 return isa<CXXDestructorDecl>(RHS);
502 if (LHSName != RHSName)
506 return HasSameVirtualSignature(LHS, RHS);
512 for (
const auto &OffsetPair : Offsets) {
513 if (MethodsCanShareVCallOffset(OffsetPair.first, MD))
518 Offsets.push_back(MethodAndOffsetPairTy(MD, OffsetOffset));
524 for (
const auto &OffsetPair : Offsets) {
525 if (MethodsCanShareVCallOffset(OffsetPair.first, MD))
526 return OffsetPair.second;
529 llvm_unreachable(
"Should always find a vcall offset offset!");
533class VCallAndVBaseOffsetBuilder {
535 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits>
536 VBaseOffsetOffsetsMapTy;
555 VTableComponentVectorTy Components;
561 VCallOffsetMap VCallOffsets;
566 VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
570 const FinalOverriders *Overriders;
586 CharUnits getCurrentOffsetOffset()
const;
592 const FinalOverriders *Overriders,
595 : VTables(VTables), MostDerivedClass(MostDerivedClass),
596 LayoutClass(LayoutClass), Context(MostDerivedClass->
getASTContext()),
597 Overriders(Overriders) {
600 AddVCallAndVBaseOffsets(
Base, BaseIsVirtual, OffsetInLayoutClass);
604 typedef VTableComponentVectorTy::const_reverse_iterator const_iterator;
605 const_iterator components_begin()
const {
return Components.rbegin(); }
606 const_iterator components_end()
const {
return Components.rend(); }
608 const VCallOffsetMap &getVCallOffsets()
const {
return VCallOffsets; }
609 const VBaseOffsetOffsetsMapTy &getVBaseOffsetOffsets()
const {
610 return VBaseOffsetOffsets;
635 if (PrimaryBaseIsVirtual) {
637 "Primary vbase should have a zero offset!");
646 "Primary base should have a zero offset!");
648 PrimaryBaseOffset =
Base.getBaseOffset();
651 AddVCallAndVBaseOffsets(
653 PrimaryBaseIsVirtual, RealBaseOffset);
656 AddVBaseOffsets(
Base.getBase(), RealBaseOffset);
660 AddVCallOffsets(
Base, RealBaseOffset);
663CharUnits VCallAndVBaseOffsetBuilder::getCurrentOffsetOffset()
const {
668 int64_t OffsetIndex = -(int64_t)(3 + Components.size());
673 VTables.isRelativeLayout()
676 CharUnits OffsetOffset = OffsetWidth * OffsetIndex;
694 "Primary base should have a zero offset!");
701 for (
const auto *MD : RD->
methods()) {
706 CharUnits OffsetOffset = getCurrentOffsetOffset();
710 if (!VCallOffsets.AddVCallOffset(MD, OffsetOffset))
717 FinalOverriders::OverriderInfo Overrider =
718 Overriders->getOverrider(MD,
Base.getBaseOffset());
722 Offset = Overrider.Offset - VBaseOffset;
725 Components.push_back(
730 for (
const auto &B : RD->
bases()) {
734 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
735 if (BaseDecl == PrimaryBase)
748VCallAndVBaseOffsetBuilder::AddVBaseOffsets(
const CXXRecordDecl *RD,
754 for (
const auto &B : RD->
bases()) {
755 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
758 if (B.isVirtual() && VisitedVirtualBases.insert(BaseDecl).second) {
763 assert(!VBaseOffsetOffsets.count(BaseDecl) &&
764 "vbase offset offset already exists!");
766 CharUnits VBaseOffsetOffset = getCurrentOffsetOffset();
767 VBaseOffsetOffsets.insert(
768 std::make_pair(BaseDecl, VBaseOffsetOffset));
770 Components.push_back(
775 AddVBaseOffsets(BaseDecl, OffsetInLayoutClass);
780class ItaniumVTableBuilder {
785 PrimaryBasesSetVectorTy;
787 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits>
788 VBaseOffsetOffsetsMapTy;
792 typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVTableIndicesTy;
808 bool MostDerivedClassIsVirtual;
819 const FinalOverriders Overriders;
823 llvm::DenseMap<const CXXRecordDecl *, VCallOffsetMap> VCallOffsetsForVBases;
827 VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
833 AddressPointsMapTy AddressPoints;
847 const uint64_t VTableIndex;
850 uint64_t VTableIndex)
851 : BaseOffset(BaseOffset),
852 BaseOffsetInLayoutClass(BaseOffsetInLayoutClass),
853 VTableIndex(VTableIndex) { }
860 MethodInfo(MethodInfo
const&) =
default;
863 typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy;
867 MethodInfoMapTy MethodInfoMap;
871 MethodVTableIndicesTy MethodVTableIndices;
873 typedef llvm::DenseMap<uint64_t, ThunkInfo> VTableThunksMapTy;
877 VTableThunksMapTy VTableThunks;
880 typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
891 void ComputeThisAdjustments();
897 VisitedVirtualBasesSetTy PrimaryVirtualBases;
914 FinalOverriders::OverriderInfo Overrider);
942 CharUnits FirstBaseOffsetInLayoutClass)
const;
950 PrimaryBasesSetVectorTy &PrimaryBases);
965 bool BaseIsMorallyVirtual,
966 bool BaseIsVirtualInLayoutClass,
981 VisitedVirtualBasesSetTy &VBases);
986 VisitedVirtualBasesSetTy &VBases);
990 bool isBuildingConstructorVTable()
const {
991 return MostDerivedClass != LayoutClass;
1002 bool MostDerivedClassIsVirtual,
1004 : VTables(VTables), MostDerivedClass(MostDerivedClass),
1005 MostDerivedClassOffset(MostDerivedClassOffset),
1006 MostDerivedClassIsVirtual(MostDerivedClassIsVirtual),
1007 LayoutClass(LayoutClass), Context(MostDerivedClass->
getASTContext()),
1008 Overriders(MostDerivedClass, MostDerivedClassOffset, LayoutClass) {
1014 dumpLayout(llvm::outs());
1017 uint64_t getNumThunks()
const {
1018 return Thunks.size();
1021 ThunksMapTy::const_iterator thunks_begin()
const {
1022 return Thunks.begin();
1025 ThunksMapTy::const_iterator thunks_end()
const {
1026 return Thunks.end();
1029 const VBaseOffsetOffsetsMapTy &getVBaseOffsetOffsets()
const {
1030 return VBaseOffsetOffsets;
1033 const AddressPointsMapTy &getAddressPoints()
const {
1034 return AddressPoints;
1037 MethodVTableIndicesTy::const_iterator vtable_indices_begin()
const {
1038 return MethodVTableIndices.begin();
1041 MethodVTableIndicesTy::const_iterator vtable_indices_end()
const {
1042 return MethodVTableIndices.end();
1047 AddressPointsMapTy::const_iterator address_points_begin()
const {
1048 return AddressPoints.begin();
1051 AddressPointsMapTy::const_iterator address_points_end()
const {
1052 return AddressPoints.end();
1055 VTableThunksMapTy::const_iterator vtable_thunks_begin()
const {
1056 return VTableThunks.begin();
1059 VTableThunksMapTy::const_iterator vtable_thunks_end()
const {
1060 return VTableThunks.end();
1064 void dumpLayout(raw_ostream&);
1069 assert(!isBuildingConstructorVTable() &&
1070 "Can't add thunks for construction vtable");
1075 if (llvm::is_contained(ThunksVector, Thunk))
1078 ThunksVector.push_back(Thunk);
1087template <
class VisitorTy>
1089visitAllOverriddenMethods(
const CXXMethodDecl *MD, VisitorTy &Visitor) {
1093 if (!Visitor(OverriddenMD))
1095 visitAllOverriddenMethods(OverriddenMD, Visitor);
1103 OverriddenMethodsSetTy& OverriddenMethods) {
1104 auto OverriddenMethodsCollector = [&](
const CXXMethodDecl *MD) {
1106 return OverriddenMethods.insert(MD).second;
1108 visitAllOverriddenMethods(MD, OverriddenMethodsCollector);
1111void ItaniumVTableBuilder::ComputeThisAdjustments() {
1114 for (
const auto &MI : MethodInfoMap) {
1116 const MethodInfo &MethodInfo = MI.second;
1119 uint64_t VTableIndex = MethodInfo.VTableIndex;
1120 if (Components[VTableIndex].
getKind() ==
1125 FinalOverriders::OverriderInfo Overrider =
1126 Overriders.getOverrider(MD, MethodInfo.BaseOffset);
1129 if (MethodInfo.BaseOffsetInLayoutClass == Overrider.Offset) {
1135 if (VTableThunks.lookup(VTableIndex).Return.isEmpty())
1140 ComputeThisAdjustment(MD, MethodInfo.BaseOffsetInLayoutClass, Overrider);
1148 if (isa<CXXDestructorDecl>(MD)) {
1155 MethodInfoMap.clear();
1157 if (isBuildingConstructorVTable()) {
1162 for (
const auto &TI : VTableThunks) {
1167 switch (Component.
getKind()) {
1169 llvm_unreachable(
"Unexpected vtable component kind!");
1181 if (MD->
getParent() == MostDerivedClass)
1182 AddThunk(MD, Thunk);
1187ItaniumVTableBuilder::ComputeReturnAdjustment(BaseOffset
Offset) {
1191 if (
Offset.VirtualBase) {
1193 if (
Offset.DerivedClass == MostDerivedClass) {
1196 VBaseOffsetOffsets.lookup(
Offset.VirtualBase).getQuantity();
1199 VTables.getVirtualBaseOffsetOffset(
Offset.DerivedClass,
1200 Offset.VirtualBase).getQuantity();
1210BaseOffset ItaniumVTableBuilder::ComputeThisAdjustmentBaseOffset(
1219 llvm_unreachable(
"Class must be derived from the passed in base class!");
1224 BaseOffset
Offset = ComputeBaseOffset(Context, DerivedRD, Path);
1228 if (
Offset.VirtualBase) {
1236 OffsetToBaseSubobject +=
1245 if (OffsetToBaseSubobject ==
Base.getBaseOffset()) {
1253 return BaseOffset();
1258 FinalOverriders::OverriderInfo Overrider) {
1260 if (Overrider.Method->isPure())
1264 BaseOffsetInLayoutClass);
1266 BaseSubobject OverriderBaseSubobject(Overrider.Method->getParent(),
1270 BaseOffset
Offset = ComputeThisAdjustmentBaseOffset(OverriddenBaseSubobject,
1271 OverriderBaseSubobject);
1277 if (
Offset.VirtualBase) {
1279 VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[
Offset.VirtualBase];
1281 if (VCallOffsets.empty()) {
1284 VCallAndVBaseOffsetBuilder Builder(
1285 VTables, MostDerivedClass, MostDerivedClass,
1292 VCallOffsets = Builder.getVCallOffsets();
1296 VCallOffsets.getVCallOffsetOffset(MD).getQuantity();
1305void ItaniumVTableBuilder::AddMethod(
const CXXMethodDecl *MD,
1309 "Destructor can't have return adjustment!");
1335static bool OverridesIndirectMethodInBases(
1343 if (OverridesIndirectMethodInBases(OverriddenMD, Bases))
1350bool ItaniumVTableBuilder::IsOverriderUsed(
1353 CharUnits FirstBaseOffsetInLayoutClass)
const {
1356 if (BaseOffsetInLayoutClass == FirstBaseOffsetInLayoutClass)
1365 if (Overrider->getParent() == FirstBaseInPrimaryBaseChain)
1371 PrimaryBases.insert(RD);
1384 "Primary base should always be at offset 0!");
1392 FirstBaseOffsetInLayoutClass) {
1398 "Primary base should always be at offset 0!");
1401 if (!PrimaryBases.insert(PrimaryBase))
1402 llvm_unreachable(
"Found a duplicate primary base!");
1409 return OverridesIndirectMethodInBases(Overrider, PrimaryBases);
1419 BasesSetVectorTy &Bases) {
1420 OverriddenMethodsSetTy OverriddenMethods;
1421 ComputeAllOverriddenMethods(MD, OverriddenMethods);
1423 for (
const CXXRecordDecl *PrimaryBase : llvm::reverse(Bases)) {
1425 for (
const CXXMethodDecl *OverriddenMD : OverriddenMethods) {
1427 if (OverriddenMD->getParent() == PrimaryBase)
1428 return OverriddenMD;
1435void ItaniumVTableBuilder::AddMethods(
1439 PrimaryBasesSetVectorTy &PrimaryBases) {
1454 CharUnits PrimaryBaseOffsetInLayoutClass;
1457 "Primary vbase should have a zero offset!");
1468 PrimaryBaseOffsetInLayoutClass =
1472 "Primary base should have a zero offset!");
1474 PrimaryBaseOffset =
Base.getBaseOffset();
1475 PrimaryBaseOffsetInLayoutClass = BaseOffsetInLayoutClass;
1479 PrimaryBaseOffsetInLayoutClass, FirstBaseInPrimaryBaseChain,
1480 FirstBaseOffsetInLayoutClass, PrimaryBases);
1482 if (!PrimaryBases.insert(PrimaryBase))
1483 llvm_unreachable(
"Found a duplicate primary base!");
1487 NewVirtualFunctionsTy NewVirtualFunctions;
1492 for (
const auto *MD : RD->
methods()) {
1493 if (!ItaniumVTableContext::hasVtableSlot(MD))
1498 FinalOverriders::OverriderInfo Overrider =
1499 Overriders.getOverrider(MD,
Base.getBaseOffset());
1505 FindNearestOverriddenMethod(MD, PrimaryBases)) {
1506 if (ComputeReturnAdjustmentBaseOffset(Context, MD,
1507 OverriddenMD).isEmpty()) {
1510 assert(MethodInfoMap.count(OverriddenMD) &&
1511 "Did not find the overridden method!");
1512 MethodInfo &OverriddenMethodInfo = MethodInfoMap[OverriddenMD];
1514 MethodInfo MethodInfo(
Base.getBaseOffset(), BaseOffsetInLayoutClass,
1515 OverriddenMethodInfo.VTableIndex);
1517 assert(!MethodInfoMap.count(MD) &&
1518 "Should not have method info for this method yet!");
1520 MethodInfoMap.insert(std::make_pair(MD, MethodInfo));
1521 MethodInfoMap.erase(OverriddenMD);
1527 if (!isBuildingConstructorVTable() && OverriddenMD != MD) {
1530 ComputeThisAdjustment(OverriddenMD, BaseOffsetInLayoutClass,
1534 Overrider.Method->getParent() == MostDerivedClass) {
1539 BaseOffset ReturnAdjustmentOffset =
1540 ComputeReturnAdjustmentBaseOffset(Context, Overrider.Method, MD);
1542 ComputeReturnAdjustment(ReturnAdjustmentOffset);
1545 AddThunk(Overrider.Method,
1555 NewImplicitVirtualFunctions.push_back(MD);
1557 NewVirtualFunctions.push_back(MD);
1561 NewImplicitVirtualFunctions.begin(), NewImplicitVirtualFunctions.end(),
1563 if (A->isCopyAssignmentOperator() != B->isCopyAssignmentOperator())
1564 return A->isCopyAssignmentOperator();
1565 if (A->isMoveAssignmentOperator() != B->isMoveAssignmentOperator())
1566 return A->isMoveAssignmentOperator();
1567 if (isa<CXXDestructorDecl>(A) != isa<CXXDestructorDecl>(B))
1568 return isa<CXXDestructorDecl>(A);
1569 assert(A->getOverloadedOperator() == OO_EqualEqual &&
1570 B->getOverloadedOperator() == OO_EqualEqual &&
1571 "unexpected or duplicate implicit virtual function");
1576 NewVirtualFunctions.append(NewImplicitVirtualFunctions.begin(),
1577 NewImplicitVirtualFunctions.end());
1581 FinalOverriders::OverriderInfo Overrider =
1582 Overriders.getOverrider(MD,
Base.getBaseOffset());
1585 MethodInfo MethodInfo(
Base.getBaseOffset(), BaseOffsetInLayoutClass,
1588 assert(!MethodInfoMap.count(MD) &&
1589 "Should not have method info for this method yet!");
1590 MethodInfoMap.insert(std::make_pair(MD, MethodInfo));
1594 if (!IsOverriderUsed(OverriderMD, BaseOffsetInLayoutClass,
1595 FirstBaseInPrimaryBaseChain,
1596 FirstBaseOffsetInLayoutClass)) {
1603 BaseOffset ReturnAdjustmentOffset;
1604 if (!OverriderMD->
isPure()) {
1605 ReturnAdjustmentOffset =
1606 ComputeReturnAdjustmentBaseOffset(Context, OverriderMD, MD);
1610 ComputeReturnAdjustment(ReturnAdjustmentOffset);
1616void ItaniumVTableBuilder::LayoutVTable() {
1617 LayoutPrimaryAndSecondaryVTables(
BaseSubobject(MostDerivedClass,
1620 MostDerivedClassIsVirtual,
1621 MostDerivedClassOffset);
1623 VisitedVirtualBasesSetTy VBases;
1626 DeterminePrimaryVirtualBases(MostDerivedClass, MostDerivedClassOffset,
1630 LayoutVTablesForVirtualBases(MostDerivedClass, VBases);
1633 bool IsAppleKext = Context.
getLangOpts().AppleKext;
1638void ItaniumVTableBuilder::LayoutPrimaryAndSecondaryVTables(
1640 bool BaseIsVirtualInLayoutClass,
CharUnits OffsetInLayoutClass) {
1641 assert(
Base.getBase()->isDynamicClass() &&
"class does not have a vtable!");
1643 unsigned VTableIndex = Components.size();
1644 VTableIndices.push_back(VTableIndex);
1647 VCallAndVBaseOffsetBuilder Builder(
1648 VTables, MostDerivedClass, LayoutClass, &Overriders,
Base,
1649 BaseIsVirtualInLayoutClass, OffsetInLayoutClass);
1650 Components.append(Builder.components_begin(), Builder.components_end());
1653 if (BaseIsVirtualInLayoutClass && !Builder.getVCallOffsets().empty()) {
1654 VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[
Base.getBase()];
1656 if (VCallOffsets.empty())
1657 VCallOffsets = Builder.getVCallOffsets();
1662 if (
Base.getBase() == MostDerivedClass)
1663 VBaseOffsetOffsets = Builder.getVBaseOffsetOffsets();
1666 CharUnits OffsetToTop = MostDerivedClassOffset - OffsetInLayoutClass;
1672 uint64_t AddressPoint = Components.size();
1675 PrimaryBasesSetVectorTy PrimaryBases;
1676 AddMethods(
Base, OffsetInLayoutClass,
1677 Base.getBase(), OffsetInLayoutClass,
1681 if (RD == MostDerivedClass) {
1682 assert(MethodVTableIndices.empty());
1683 for (
const auto &I : MethodInfoMap) {
1685 const MethodInfo &MI = I.second;
1688 = MI.VTableIndex - AddressPoint;
1690 = MI.VTableIndex + 1 - AddressPoint;
1692 MethodVTableIndices[MD] = MI.VTableIndex - AddressPoint;
1698 ComputeThisAdjustments();
1702 AddressPoints.insert(
1705 unsigned(VTableIndices.size() - 1),
1706 unsigned(AddressPoint - VTableIndex)}));
1721 OffsetInLayoutClass) {
1731 LayoutSecondaryVTables(
Base, BaseIsMorallyVirtual, OffsetInLayoutClass);
1736 bool BaseIsMorallyVirtual,
1747 for (
const auto &B : RD->
bases()) {
1752 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
1758 if (isBuildingConstructorVTable()) {
1764 if (!BaseIsMorallyVirtual && !BaseDecl->
getNumVBases())
1770 CharUnits BaseOffset =
Base.getBaseOffset() + RelativeBaseOffset;
1773 OffsetInLayoutClass + RelativeBaseOffset;
1777 if (BaseDecl == PrimaryBase) {
1779 BaseIsMorallyVirtual, BaseOffsetInLayoutClass);
1784 LayoutPrimaryAndSecondaryVTables(
1786 BaseIsMorallyVirtual,
1788 BaseOffsetInLayoutClass);
1792void ItaniumVTableBuilder::DeterminePrimaryVirtualBases(
1794 VisitedVirtualBasesSetTy &VBases) {
1802 bool IsPrimaryVirtualBase =
true;
1804 if (isBuildingConstructorVTable()) {
1810 CharUnits PrimaryBaseOffsetInLayoutClass =
1815 if (PrimaryBaseOffsetInLayoutClass != OffsetInLayoutClass)
1816 IsPrimaryVirtualBase =
false;
1819 if (IsPrimaryVirtualBase)
1820 PrimaryVirtualBases.insert(PrimaryBase);
1825 for (
const auto &B : RD->
bases()) {
1826 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
1830 if (B.isVirtual()) {
1831 if (!VBases.insert(BaseDecl).second)
1837 BaseOffsetInLayoutClass =
1840 BaseOffsetInLayoutClass =
1844 DeterminePrimaryVirtualBases(BaseDecl, BaseOffsetInLayoutClass, VBases);
1848void ItaniumVTableBuilder::LayoutVTablesForVirtualBases(
1849 const CXXRecordDecl *RD, VisitedVirtualBasesSetTy &VBases) {
1854 for (
const auto &B : RD->
bases()) {
1855 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
1860 !PrimaryVirtualBases.count(BaseDecl) &&
1861 VBases.insert(BaseDecl).second) {
1872 LayoutPrimaryAndSecondaryVTables(
1876 BaseOffsetInLayoutClass);
1882 LayoutVTablesForVirtualBases(BaseDecl, VBases);
1887void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
1891 if (isBuildingConstructorVTable()) {
1892 Out <<
"Construction vtable for ('";
1895 Out << MostDerivedClassOffset.
getQuantity() <<
") in '";
1898 Out <<
"Vtable for '";
1901 Out <<
"' (" << Components.size() <<
" entries).\n";
1907 std::multimap<uint64_t, BaseSubobject> AddressPointsByIndex;
1908 for (
const auto &AP : AddressPoints) {
1911 VTableIndices[AP.second.VTableIndex] + AP.second.AddressPointIndex;
1913 AddressPointsByIndex.insert(std::make_pair(Index,
Base));
1916 for (
unsigned I = 0, E = Components.size(); I != E; ++I) {
1919 Out << llvm::format(
"%4d | ", I);
1924 switch (Component.
getKind()) {
1927 Out <<
"vcall_offset ("
1933 Out <<
"vbase_offset ("
1939 Out <<
"offset_to_top ("
1960 Out <<
" [deleted]";
1962 ThunkInfo Thunk = VTableThunks.lookup(I);
1966 Out <<
"\n [return adjustment: ";
1971 Out <<
" vbase offset offset";
1979 Out <<
"\n [this adjustment: ";
1984 Out <<
" vcall offset offset";
2003 Out <<
"() [complete]";
2005 Out <<
"() [deleting]";
2010 ThunkInfo Thunk = VTableThunks.lookup(I);
2014 Out <<
"\n [this adjustment: ";
2019 Out <<
" vcall offset offset";
2035 Out <<
"[unused] " << Str;
2045 uint64_t NextIndex = Index + 1;
2046 if (AddressPointsByIndex.count(NextIndex)) {
2047 if (AddressPointsByIndex.count(NextIndex) == 1) {
2049 AddressPointsByIndex.find(NextIndex)->second;
2052 Base.getBase()->printQualifiedName(Out);
2053 Out <<
", " <<
Base.getBaseOffset().getQuantity();
2054 Out <<
") vtable address --\n";
2057 AddressPointsByIndex.lower_bound(NextIndex)->second.getBaseOffset();
2060 std::set<std::string> ClassNames;
2061 for (
const auto &I :
2062 llvm::make_range(AddressPointsByIndex.equal_range(NextIndex))) {
2063 assert(I.second.getBaseOffset() == BaseOffset &&
2064 "Invalid base offset!");
2069 for (
const std::string &Name : ClassNames) {
2070 Out <<
" -- (" << Name;
2071 Out <<
", " << BaseOffset.
getQuantity() <<
") vtable address --\n";
2079 if (isBuildingConstructorVTable())
2086 std::map<std::string, CharUnits> ClassNamesAndOffsets;
2087 for (
const auto &I : VBaseOffsetOffsets) {
2088 std::string ClassName = I.first->getQualifiedNameAsString();
2090 ClassNamesAndOffsets.insert(std::make_pair(ClassName, OffsetOffset));
2093 Out <<
"Virtual base offset offsets for '";
2096 Out << ClassNamesAndOffsets.size();
2097 Out << (ClassNamesAndOffsets.size() == 1 ?
" entry" :
" entries") <<
").\n";
2099 for (
const auto &I : ClassNamesAndOffsets)
2100 Out <<
" " << I.first <<
" | " << I.second.getQuantity() <<
'\n';
2105 if (!Thunks.empty()) {
2107 std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls;
2109 for (
const auto &I : Thunks) {
2111 std::string MethodName =
2115 MethodNamesAndDecls.insert(std::make_pair(MethodName, MD));
2118 for (
const auto &I : MethodNamesAndDecls) {
2119 const std::string &MethodName = I.first;
2122 ThunkInfoVectorTy ThunksVector = Thunks[MD];
2124 assert(LHS.
Method ==
nullptr && RHS.
Method ==
nullptr);
2128 Out <<
"Thunks for '" << MethodName <<
"' (" << ThunksVector.size();
2129 Out << (ThunksVector.size() == 1 ?
" entry" :
" entries") <<
").\n";
2131 for (
unsigned I = 0, E = ThunksVector.size(); I != E; ++I) {
2132 const ThunkInfo &Thunk = ThunksVector[I];
2134 Out << llvm::format(
"%4d | ", I);
2139 Out <<
" non-virtual";
2142 Out <<
" vbase offset offset";
2151 Out <<
"this adjustment: ";
2156 Out <<
" vcall offset offset";
2169 std::map<uint64_t, std::string> IndicesMap;
2171 for (
const auto *MD : MostDerivedClass->
methods()) {
2173 if (!ItaniumVTableContext::hasVtableSlot(MD))
2177 std::string MethodName =
2183 assert(MethodVTableIndices.count(GD));
2184 uint64_t VTableIndex = MethodVTableIndices[GD];
2185 IndicesMap[VTableIndex] = MethodName +
" [complete]";
2186 IndicesMap[VTableIndex + 1] = MethodName +
" [deleting]";
2188 assert(MethodVTableIndices.count(MD));
2189 IndicesMap[MethodVTableIndices[MD]] = MethodName;
2194 if (!IndicesMap.empty()) {
2195 Out <<
"VTable indices for '";
2197 Out <<
"' (" << IndicesMap.size() <<
" entries).\n";
2199 for (
const auto &I : IndicesMap) {
2200 uint64_t VTableIndex = I.first;
2201 const std::string &MethodName = I.second;
2203 Out << llvm::format(
"%4" PRIu64
" | ", VTableIndex) << MethodName
2214 unsigned numVTables) {
2217 for (
auto it = addressPoints.begin(); it != addressPoints.end(); ++it) {
2218 const auto &addressPointLoc = it->second;
2219 unsigned vtableIndex = addressPointLoc.VTableIndex;
2220 unsigned addressPoint = addressPointLoc.AddressPointIndex;
2221 if (indexMap[vtableIndex]) {
2224 assert(indexMap[vtableIndex] == addressPoint &&
2225 "Every vtable index should have a unique address point. Found a "
2226 "vtable that has two different address points.");
2228 indexMap[vtableIndex] = addressPoint;
2243 : VTableComponents(VTableComponents), VTableThunks(VTableThunks),
2245 AddressPoints, VTableIndices.size())) {
2246 if (VTableIndices.size() <= 1)
2247 assert(VTableIndices.size() == 1 && VTableIndices[0] == 0);
2253 assert((LHS.first != RHS.first || LHS.second == RHS.second) &&
2254 "Different thunks should have unique indices!");
2255 return LHS.first < RHS.first;
2273 MethodVTableIndicesTy::iterator I = MethodVTableIndices.find(GD);
2274 if (I != MethodVTableIndices.end())
2279 computeVTableRelatedInformation(RD);
2281 I = MethodVTableIndices.find(GD);
2282 assert(I != MethodVTableIndices.end() &&
"Did not find index!");
2289 ClassPairTy ClassPair(RD, VBase);
2291 VirtualBaseClassOffsetOffsetsMapTy::iterator I =
2292 VirtualBaseClassOffsetOffsets.find(ClassPair);
2293 if (I != VirtualBaseClassOffsetOffsets.end())
2296 VCallAndVBaseOffsetBuilder Builder(*
this, RD, RD,
nullptr,
2301 for (
const auto &I : Builder.getVBaseOffsetOffsets()) {
2303 ClassPairTy ClassPair(RD, I.first);
2305 VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I.second));
2308 I = VirtualBaseClassOffsetOffsets.find(ClassPair);
2309 assert(I != VirtualBaseClassOffsetOffsets.end() &&
"Did not find index!");
2314static std::unique_ptr<VTableLayout>
2317 VTableThunks(Builder.vtable_thunks_begin(), Builder.vtable_thunks_end());
2319 return std::make_unique<VTableLayout>(
2320 Builder.VTableIndices, Builder.vtable_components(), VTableThunks,
2321 Builder.getAddressPoints());
2325ItaniumVTableContext::computeVTableRelatedInformation(
const CXXRecordDecl *RD) {
2326 std::unique_ptr<const VTableLayout> &Entry = VTableLayouts[RD];
2336 MethodVTableIndices.insert(Builder.vtable_indices_begin(),
2337 Builder.vtable_indices_end());
2340 Thunks.insert(Builder.thunks_begin(), Builder.thunks_end());
2351 if (VirtualBaseClassOffsetOffsets.count(std::make_pair(RD, VBase)))
2354 for (
const auto &I : Builder.getVBaseOffsetOffsets()) {
2356 ClassPairTy ClassPair(RD, I.first);
2358 VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I.second));
2362std::unique_ptr<VTableLayout>
2365 bool MostDerivedClassIsVirtual,
const CXXRecordDecl *LayoutClass) {
2366 ItaniumVTableBuilder Builder(*
this, MostDerivedClass, MostDerivedClassOffset,
2367 MostDerivedClassIsVirtual, LayoutClass);
2415class VFTableBuilder {
2417 typedef llvm::DenseMap<GlobalDecl, MethodVFTableLocation>
2418 MethodVFTableLocationsTy;
2420 typedef llvm::iterator_range<MethodVFTableLocationsTy::const_iterator>
2421 method_locations_range;
2439 const FinalOverriders Overriders;
2444 MethodVFTableLocationsTy MethodVFTableLocations;
2447 bool HasRTTIComponent =
false;
2454 const uint64_t VBTableIndex;
2457 const uint64_t VFTableIndex;
2468 MethodInfo(uint64_t VBTableIndex, uint64_t VFTableIndex,
2469 bool UsesExtraSlot =
false)
2470 : VBTableIndex(VBTableIndex), VFTableIndex(VFTableIndex),
2471 Shadowed(
false), UsesExtraSlot(UsesExtraSlot) {}
2474 : VBTableIndex(0), VFTableIndex(0), Shadowed(
false),
2475 UsesExtraSlot(
false) {}
2478 typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy;
2482 MethodInfoMapTy MethodInfoMap;
2484 typedef llvm::DenseMap<uint64_t, ThunkInfo> VTableThunksMapTy;
2488 VTableThunksMapTy VTableThunks;
2491 typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
2502 if (llvm::is_contained(ThunksVector, Thunk))
2505 ThunksVector.push_back(Thunk);
2510 CharUnits ComputeThisOffset(FinalOverriders::OverriderInfo Overrider);
2512 void CalculateVtordispAdjustment(FinalOverriders::OverriderInfo Overrider,
2519 VTableThunks[Components.size()] = TI;
2524 "Destructor can't have return adjustment!");
2535 BasesSetVectorTy &VisitedBases);
2537 void LayoutVFTable() {
2539 if (HasRTTIComponent)
2542 BasesSetVectorTy VisitedBases;
2547 assert(!Components.empty() &&
"vftable can't be empty");
2549 assert(MethodVFTableLocations.empty());
2550 for (
const auto &I : MethodInfoMap) {
2552 const MethodInfo &MI = I.second;
2557 if (MD->
getParent() != MostDerivedClass || MI.Shadowed)
2564 MethodVFTableLocations[MD] = Loc;
2573 Context(MostDerivedClass->getASTContext()),
2574 MostDerivedClass(MostDerivedClass),
2575 MostDerivedClassLayout(Context.getASTRecordLayout(MostDerivedClass)),
2577 Overriders(MostDerivedClass,
CharUnits(), MostDerivedClass) {
2584 HasRTTIComponent =
true;
2589 dumpLayout(llvm::outs());
2592 uint64_t getNumThunks()
const {
return Thunks.size(); }
2594 ThunksMapTy::const_iterator thunks_begin()
const {
return Thunks.begin(); }
2596 ThunksMapTy::const_iterator thunks_end()
const {
return Thunks.end(); }
2598 method_locations_range vtable_locations()
const {
2599 return method_locations_range(MethodVFTableLocations.begin(),
2600 MethodVFTableLocations.end());
2605 VTableThunksMapTy::const_iterator vtable_thunks_begin()
const {
2606 return VTableThunks.begin();
2609 VTableThunksMapTy::const_iterator vtable_thunks_end()
const {
2610 return VTableThunks.end();
2613 void dumpLayout(raw_ostream &);
2673VFTableBuilder::ComputeThisOffset(FinalOverriders::OverriderInfo Overrider) {
2674 BasesSetVectorTy Bases;
2678 OverriddenMethodsSetTy VisitedOverriddenMethods;
2679 auto InitialOverriddenDefinitionCollector = [&](
2681 if (OverriddenMD->size_overridden_methods() == 0)
2682 Bases.insert(OverriddenMD->getParent());
2684 return VisitedOverriddenMethods.insert(OverriddenMD).second;
2686 visitAllOverriddenMethods(Overrider.Method,
2687 InitialOverriddenDefinitionCollector);
2692 if (Bases.size() == 0)
2693 return Overrider.Offset;
2696 Overrider.Method->getParent()->lookupInBases(
2698 return Bases.count(
Specifier->getType()->getAsCXXRecordDecl());
2712 CharUnits ThisOffset = Overrider.Offset;
2719 QualType CurTy = Element.Base->getType();
2724 if (Element.Base->isVirtual()) {
2735 LastVBaseOffset = ThisOffset =
2742 if (isa<CXXDestructorDecl>(Overrider.Method)) {
2743 if (LastVBaseOffset.
isZero()) {
2747 ThisOffset = Overrider.Offset;
2751 ThisOffset = LastVBaseOffset;
2755 if (Ret > ThisOffset ||
First) {
2761 assert(!
First &&
"Method not found in the given subobject?");
2863void VFTableBuilder::CalculateVtordispAdjustment(
2864 FinalOverriders::OverriderInfo Overrider,
CharUnits ThisOffset,
2868 const ASTRecordLayout::VBaseOffsetsMapTy::const_iterator &VBaseMapEntry =
2870 assert(VBaseMapEntry != VBaseMap.end());
2874 if (!VBaseMapEntry->second.hasVtorDisp() ||
2880 CharUnits OffsetOfVBaseWithVFPtr = VBaseMapEntry->second.VBaseOffset;
2882 (OffsetOfVBaseWithVFPtr - WhichVFPtr.
FullOffsetInMDC).getQuantity() - 4;
2886 if (Overrider.Method->getParent() == MostDerivedClass ||
2887 !Overrider.VirtualBase)
2899 TA.
NonVirtual = (ThisOffset - Overrider.Offset).getQuantity();
2913 typedef llvm::DenseMap<DeclarationName, unsigned> VisitedGroupIndicesTy;
2914 VisitedGroupIndicesTy VisitedGroupIndices;
2915 for (
const auto *D : RD->
decls()) {
2916 const auto *ND = dyn_cast<NamedDecl>(D);
2919 VisitedGroupIndicesTy::iterator J;
2921 std::tie(J, Inserted) = VisitedGroupIndices.insert(
2922 std::make_pair(ND->getDeclName(), Groups.size()));
2924 Groups.push_back(MethodGroup());
2925 if (
const auto *MD = dyn_cast<CXXMethodDecl>(ND))
2930 for (
const MethodGroup &Group : Groups)
2931 VirtualMethods.append(Group.rbegin(), Group.rend());
2935 for (
const auto &B : RD->
bases()) {
2936 if (B.isVirtual() && B.getType()->getAsCXXRecordDecl() ==
Base)
2944 BasesSetVectorTy &VisitedBases) {
2954 const CXXRecordDecl *NextBase =
nullptr, *NextLastVBase = LastVBase;
2959 NextLastVBase = NextBase;
2967 "No primary virtual bases in this ABI");
2968 NextBase = PrimaryBase;
2969 NextBaseOffset =
Base.getBaseOffset();
2973 AddMethods(
BaseSubobject(NextBase, NextBaseOffset), BaseDepth + 1,
2974 NextLastVBase, VisitedBases);
2975 if (!VisitedBases.insert(NextBase))
2976 llvm_unreachable(
"Found a duplicate primary base!");
2992 FinalOverriders::OverriderInfo FinalOverrider =
2993 Overriders.getOverrider(MD,
Base.getBaseOffset());
2994 const CXXMethodDecl *FinalOverriderMD = FinalOverrider.Method;
2996 FindNearestOverriddenMethod(MD, VisitedBases);
2999 bool ReturnAdjustingThunk =
false, ForceReturnAdjustmentMangling =
false;
3000 CharUnits ThisOffset = ComputeThisOffset(FinalOverrider);
3003 if ((OverriddenMD || FinalOverriderMD != MD) &&
3005 CalculateVtordispAdjustment(FinalOverrider, ThisOffset,
3006 ThisAdjustmentOffset);
3014 MethodInfoMapTy::iterator OverriddenMDIterator =
3015 MethodInfoMap.find(OverriddenMD);
3018 if (OverriddenMDIterator == MethodInfoMap.end())
3021 MethodInfo &OverriddenMethodInfo = OverriddenMDIterator->second;
3023 VBIndex = OverriddenMethodInfo.VBTableIndex;
3030 ReturnAdjustingThunk = !ComputeReturnAdjustmentBaseOffset(
3031 Context, MD, OverriddenMD).isEmpty() ||
3032 OverriddenMethodInfo.UsesExtraSlot;
3034 if (!ReturnAdjustingThunk) {
3037 MethodInfo MI(VBIndex, OverriddenMethodInfo.VFTableIndex);
3038 MethodInfoMap.erase(OverriddenMDIterator);
3040 assert(!MethodInfoMap.count(MD) &&
3041 "Should not have method info for this method yet!");
3042 MethodInfoMap.insert(std::make_pair(MD, MI));
3048 OverriddenMethodInfo.Shadowed =
true;
3052 ForceReturnAdjustmentMangling =
3053 !(MD == FinalOverriderMD && ThisAdjustmentOffset.
isEmpty());
3064 MethodInfo MI(VBIndex,
3065 HasRTTIComponent ? Components.size() - 1 : Components.size(),
3066 ReturnAdjustingThunk);
3068 assert(!MethodInfoMap.count(MD) &&
3069 "Should not have method info for this method yet!");
3070 MethodInfoMap.insert(std::make_pair(MD, MI));
3074 BaseOffset ReturnAdjustmentOffset;
3076 if (!FinalOverriderMD->
isPure()) {
3077 ReturnAdjustmentOffset =
3078 ComputeReturnAdjustmentBaseOffset(Context, FinalOverriderMD, MD);
3080 if (!ReturnAdjustmentOffset.isEmpty()) {
3081 ForceReturnAdjustmentMangling =
true;
3083 ReturnAdjustmentOffset.NonVirtualOffset.getQuantity();
3084 if (ReturnAdjustmentOffset.VirtualBase) {
3091 ReturnAdjustmentOffset.VirtualBase);
3095 AddMethod(FinalOverriderMD,
3097 ForceReturnAdjustmentMangling ? MD :
nullptr));
3104 Elem->printQualifiedName(Out);
3110 bool ContinueFirstLine) {
3112 bool Multiline =
false;
3113 const char *LinePrefix =
"\n ";
3115 if (!ContinueFirstLine)
3117 Out <<
"[return adjustment (to type '"
3129 if (Multiline || !ContinueFirstLine)
3131 Out <<
"[this adjustment: ";
3139 Out << LinePrefix <<
" vboffset at "
3147void VFTableBuilder::dumpLayout(raw_ostream &Out) {
3148 Out <<
"VFTable for ";
3152 Out <<
"' (" << Components.size()
3153 << (Components.size() == 1 ?
" entry" :
" entries") <<
").\n";
3155 for (
unsigned I = 0, E = Components.size(); I != E; ++I) {
3156 Out << llvm::format(
"%4d | ", I);
3161 switch (Component.
getKind()) {
3179 Out <<
" [deleted]";
3181 ThunkInfo Thunk = VTableThunks.lookup(I);
3192 Out <<
"() [scalar deleting]";
3197 ThunkInfo Thunk = VTableThunks.lookup(I);
3200 "No return adjustment needed for destructors!");
3211 "Unexpected vftable component type %0 for component number %1");
3221 if (!Thunks.empty()) {
3223 std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls;
3225 for (
const auto &I : Thunks) {
3230 MethodNamesAndDecls.insert(std::make_pair(MethodName, MD));
3233 for (
const auto &MethodNameAndDecl : MethodNamesAndDecls) {
3234 const std::string &MethodName = MethodNameAndDecl.first;
3237 ThunkInfoVectorTy ThunksVector = Thunks[MD];
3238 llvm::stable_sort(ThunksVector, [](
const ThunkInfo &LHS,
3245 Out <<
"Thunks for '" << MethodName <<
"' (" << ThunksVector.size();
3246 Out << (ThunksVector.size() == 1 ?
" entry" :
" entries") <<
").\n";
3248 for (
unsigned I = 0, E = ThunksVector.size(); I != E; ++I) {
3249 const ThunkInfo &Thunk = ThunksVector[I];
3251 Out << llvm::format(
"%4d | ", I);
3295void MicrosoftVTableContext::computeVTablePaths(
bool ForVBTables,
3298 assert(Paths.empty());
3303 Paths.push_back(std::make_unique<VPtrInfo>(RD));
3308 for (
const auto &B : RD->
bases()) {
3310 if (B.isVirtual() && VBasesSeen.count(
Base))
3313 if (!
Base->isDynamicClass())
3319 for (
const std::unique_ptr<VPtrInfo> &BaseInfo : BasePaths) {
3326 auto P = std::make_unique<VPtrInfo>(*BaseInfo);
3330 if (
P->MangledPath.empty() ||
P->MangledPath.back() !=
Base)
3331 P->NextBaseToMangle =
Base;
3336 if (
P->ObjectWithVPtr ==
Base &&
3339 P->ObjectWithVPtr = RD;
3344 P->ContainingVBases.push_back(
Base);
3345 else if (
P->ContainingVBases.empty())
3349 P->FullOffsetInMDC =
P->NonVirtualOffset;
3353 Paths.push_back(std::move(
P));
3357 VBasesSeen.insert(
Base);
3361 for (
const auto &VB :
Base->vbases())
3362 VBasesSeen.insert(VB.getType()->getAsCXXRecordDecl());
3373 if (
P.NextBaseToMangle) {
3374 P.MangledPath.push_back(
P.NextBaseToMangle);
3375 P.NextBaseToMangle =
nullptr;
3389 llvm::make_pointee_range(Paths));
3393 bool Changed =
false;
3394 for (
size_t I = 0, E = PathsSorted.size(); I != E;) {
3396 size_t BucketStart = I;
3400 PathsSorted[BucketStart].get().MangledPath ==
3401 PathsSorted[I].get().MangledPath);
3404 if (I - BucketStart > 1) {
3405 for (
size_t II = BucketStart; II != I; ++II)
3407 assert(Changed &&
"no paths were extended to fix ambiguity");
3416typedef llvm::SetVector<BaseSubobject, std::vector<BaseSubobject>,
3426 FullPathTy &FullPath,
3427 std::list<FullPathTy> &Paths) {
3429 Paths.push_back(FullPath);
3442 IntroducingObject, FullPath, Paths);
3443 FullPath.pop_back();
3449 FullPaths.remove_if([&](
const FullPathTy &SpecificPath) {
3450 for (
const FullPathTy &OtherPath : FullPaths) {
3451 if (&SpecificPath == &OtherPath)
3453 if (llvm::all_of(SpecificPath, [&](
const BaseSubobject &BSO) {
3454 return OtherPath.contains(BSO);
3465 const FullPathTy &FullPath) {
3473 assert(
Offset.getQuantity() == -1);
3477 assert(
Offset.getQuantity() != -1);
3483 return BS.getType()->getAsCXXRecordDecl() == Base;
3498 std::list<FullPathTy> &FullPaths) {
3500 if (FullPaths.empty())
3502 if (FullPaths.size() == 1)
3503 return &FullPaths.front();
3505 const FullPathTy *BestPath =
nullptr;
3506 typedef std::set<const CXXMethodDecl *> OverriderSetTy;
3507 OverriderSetTy LastOverrides;
3508 for (
const FullPathTy &SpecificPath : FullPaths) {
3509 assert(!SpecificPath.empty());
3510 OverriderSetTy CurrentOverrides;
3511 const CXXRecordDecl *TopLevelRD = SpecificPath.begin()->getBase();
3516 FinalOverriders Overriders(TopLevelRD,
CharUnits::Zero(), TopLevelRD);
3520 FinalOverriders::OverriderInfo OI =
3525 if (ComputeReturnAdjustmentBaseOffset(Context, OverridingMethod, MD)
3531 if (llvm::none_of(SpecificPath, [&](
const BaseSubobject &BSO) {
3532 return BSO.
getBase() == OverridingParent;
3535 CurrentOverrides.insert(OverridingMethod);
3537 OverriderSetTy NewOverrides =
3538 llvm::set_difference(CurrentOverrides, LastOverrides);
3539 if (NewOverrides.empty())
3541 OverriderSetTy MissingOverrides =
3542 llvm::set_difference(LastOverrides, CurrentOverrides);
3543 if (MissingOverrides.empty()) {
3545 BestPath = &SpecificPath;
3546 std::swap(CurrentOverrides, LastOverrides);
3551 const CXXMethodDecl *ConflictMD = *MissingOverrides.begin();
3562 return BestPath ? BestPath : &FullPaths.front();
3569 FullPathTy FullPath;
3570 std::list<FullPathTy> FullPaths;
3571 for (
const std::unique_ptr<VPtrInfo>& Info : Paths) {
3574 BaseSubobject(Info->IntroducingObject, Info->FullOffsetInMDC), FullPath,
3578 Info->PathToIntroducingObject.clear();
3579 if (
const FullPathTy *BestPath =
3582 Info->PathToIntroducingObject.push_back(BSO.getBase());
3599void MicrosoftVTableContext::computeVTableRelatedInformation(
3604 if (VFPtrLocations.count(RD))
3610 auto VFPtrs = std::make_unique<VPtrInfoVector>();
3611 computeVTablePaths(
false, RD, *VFPtrs);
3613 VFPtrLocations[RD] = std::move(VFPtrs);
3616 MethodVFTableLocationsTy NewMethodLocations;
3617 for (
const std::unique_ptr<VPtrInfo> &VFPtr : *VFPtrLocations[RD]) {
3618 VFTableBuilder Builder(*
this, RD, *VFPtr);
3620 VFTableIdTy id(RD, VFPtr->FullOffsetInMDC);
3621 assert(VFTableLayouts.count(
id) == 0);
3623 Builder.vtable_thunks_begin(), Builder.vtable_thunks_end());
3624 VFTableLayouts[id] = std::make_unique<VTableLayout>(
3626 EmptyAddressPointsMap);
3627 Thunks.insert(Builder.thunks_begin(), Builder.thunks_end());
3630 for (
const auto &Loc : Builder.vtable_locations()) {
3631 auto Insert = NewMethodLocations.insert(Loc);
3641 MethodVFTableLocations.insert(NewMethodLocations.begin(),
3642 NewMethodLocations.end());
3644 dumpMethodLocations(RD, NewMethodLocations, llvm::outs());
3647void MicrosoftVTableContext::dumpMethodLocations(
3648 const CXXRecordDecl *RD,
const MethodVFTableLocationsTy &NewMethods,
3652 std::map<MethodVFTableLocation, std::string> IndicesMap;
3653 bool HasNonzeroOffset =
false;
3655 for (
const auto &I : NewMethods) {
3656 const CXXMethodDecl *MD = cast<const CXXMethodDecl>(I.first.getDecl());
3662 if (isa<CXXDestructorDecl>(MD)) {
3663 IndicesMap[I.second] = MethodName +
" [scalar deleting]";
3665 IndicesMap[I.second] = MethodName;
3668 if (!I.second.VFPtrOffset.isZero() || I.second.VBTableIndex != 0)
3669 HasNonzeroOffset =
true;
3673 if (!IndicesMap.empty()) {
3674 Out <<
"VFTable indices for ";
3677 Out <<
"' (" << IndicesMap.size()
3678 << (IndicesMap.size() == 1 ?
" entry" :
" entries") <<
").\n";
3682 for (
const auto &I : IndicesMap) {
3683 CharUnits VFPtrOffset = I.first.VFPtrOffset;
3684 uint64_t VBIndex = I.first.VBTableIndex;
3685 if (HasNonzeroOffset &&
3686 (VFPtrOffset != LastVFPtrOffset || VBIndex != LastVBIndex)) {
3687 assert(VBIndex > LastVBIndex || VFPtrOffset > LastVFPtrOffset);
3688 Out <<
" -- accessible via ";
3690 Out <<
"vbtable index " << VBIndex <<
", ";
3691 Out <<
"vfptr at offset " << VFPtrOffset.
getQuantity() <<
" --\n";
3692 LastVFPtrOffset = VFPtrOffset;
3693 LastVBIndex = VBIndex;
3696 uint64_t VTableIndex = I.first.Index;
3697 const std::string &MethodName = I.second;
3698 Out << llvm::format(
"%4" PRIu64
" | ", VTableIndex) << MethodName <<
'\n';
3706const VirtualBaseInfo &MicrosoftVTableContext::computeVBTableRelatedInformation(
3713 std::unique_ptr<VirtualBaseInfo> &Entry = VBaseInfo[RD];
3716 Entry = std::make_unique<VirtualBaseInfo>();
3720 computeVTablePaths(
true, RD, VBI->
VBPtrPaths);
3728 computeVBTableRelatedInformation(VBPtrBase);
3736 for (
const auto &VB : RD->
vbases()) {
3737 const CXXRecordDecl *CurVBase = VB.getType()->getAsCXXRecordDecl();
3747 const VirtualBaseInfo &VBInfo = computeVBTableRelatedInformation(Derived);
3754 return computeVBTableRelatedInformation(RD).
VBPtrPaths;
3759 computeVTableRelatedInformation(RD);
3761 assert(VFPtrLocations.count(RD) &&
"Couldn't find vfptr locations");
3762 return *VFPtrLocations[RD];
3768 computeVTableRelatedInformation(RD);
3770 VFTableIdTy id(RD, VFPtrOffset);
3771 assert(VFTableLayouts.count(
id) &&
"Couldn't find a VFTable at this offset");
3772 return *VFTableLayouts[id];
3778 "Only use this method for virtual methods or dtors");
3779 if (isa<CXXDestructorDecl>(GD.
getDecl()))
3784 MethodVFTableLocationsTy::iterator I = MethodVFTableLocations.find(GD);
3785 if (I != MethodVFTableLocations.end())
3790 computeVTableRelatedInformation(RD);
3792 I = MethodVFTableLocations.find(GD);
3793 assert(I != MethodVFTableLocations.end() &&
"Did not find index!");
Defines the clang::ASTContext interface.
ASTImporterLookupTable & LT
static void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef< CounterExpression > Expressions, ArrayRef< CounterMappingRegion > Regions)
static Decl::Kind getKind(const Decl *D)
const NestedNameSpecifier * Specifier
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,...
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
const LangOptions & getLangOpts() const
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
DiagnosticsEngine & getDiagnostics() const
const TargetInfo & getTargetInfo() const
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
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.
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...
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 isPure() const
Whether this virtual function is pure, i.e.
QualType getReturnType() const
bool isDeleted() const
Whether this function has been deleted.
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
uint64_t getMethodVTableIndex(GlobalDecl GD)
Locate a virtual function in the vtable.
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)
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(IdentKind IK, const Decl *CurrentDecl)
@ PrettyFunctionNoVirtual
The same as PrettyFunction, except that the 'virtual' keyword is omitted for virtual member functions...
A (possibly-)qualified type.
QualType getCanonicalType() const
Base for LValueReferenceType and RValueReferenceType.
bool isMicrosoft() const
Is this ABI an MSVC-compatible ABI?
uint64_t getPointerWidth(LangAS AddrSpace) const
Return the width of pointers on this target, for the specified address space.
TargetCXXABI getCXXABI() const
Get the C++ ABI currently in use.
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
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.
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, APValue &Result)
@ Dtor_Complete
Complete object dtor.
@ Dtor_Deleting
Deleting dtor.
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...
CXXMethodDecl * Method
The overriding virtual method.
unsigned Subobject
The subobject in which the overriding virtual method resides.
const CXXRecordDecl * InVirtualSubobject
The virtual base class subobject of which this overridden virtual method is a part.
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.
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.
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::@181 Itanium
uint32_t VBPtrOffset
The offset (in bytes) of the vbptr, relative to the beginning of the derived class.
struct clang::ReturnAdjustment::VirtualAdjustment::@182 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::@183 Itanium
int32_t VtordispOffset
The offset of the vtordisp (in bytes), relative to the ECX.
int32_t VBOffsetOffset
The offset (in bytes) of the vbase offset in the vbtable.
struct clang::ThisAdjustment::VirtualAdjustment::@184 Microsoft
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...