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 {
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) {
231 if (Element.Base->isVirtual()) {
233 QualType VBaseType = Element.Base->getType();
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 =
297 }
else if (isa<PointerType>(CanDerivedReturnType)) {
298 CanDerivedReturnType =
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 =
367 BaseOffset =
Base.getBaseOffset() + Offset;
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->isPureVirtual())
426 Offset = ComputeReturnAdjustmentBaseOffset(Context, Overrider.Method, MD);
428 if (!Offset.isEmpty()) {
429 Out <<
" [ret-adj: ";
430 if (Offset.VirtualBase) {
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 size_t NumComponentsAboveAddrPoint = 3;
670 NumComponentsAboveAddrPoint--;
671 int64_t OffsetIndex =
672 -(int64_t)(NumComponentsAboveAddrPoint + Components.size());
677 VTables.isRelativeLayout()
680 CharUnits OffsetOffset = OffsetWidth * OffsetIndex;
698 "Primary base should have a zero offset!");
705 for (
const auto *MD : RD->
methods()) {
710 CharUnits OffsetOffset = getCurrentOffsetOffset();
714 if (!VCallOffsets.AddVCallOffset(MD, OffsetOffset))
721 FinalOverriders::OverriderInfo Overrider =
722 Overriders->getOverrider(MD,
Base.getBaseOffset());
726 Offset = Overrider.Offset - VBaseOffset;
729 Components.push_back(
734 for (
const auto &B : RD->
bases()) {
738 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
739 if (BaseDecl == PrimaryBase)
752VCallAndVBaseOffsetBuilder::AddVBaseOffsets(
const CXXRecordDecl *RD,
758 for (
const auto &B : RD->
bases()) {
759 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
762 if (B.isVirtual() && VisitedVirtualBases.insert(BaseDecl).second) {
767 assert(!VBaseOffsetOffsets.count(BaseDecl) &&
768 "vbase offset offset already exists!");
770 CharUnits VBaseOffsetOffset = getCurrentOffsetOffset();
771 VBaseOffsetOffsets.insert(
772 std::make_pair(BaseDecl, VBaseOffsetOffset));
774 Components.push_back(
779 AddVBaseOffsets(BaseDecl, OffsetInLayoutClass);
784class ItaniumVTableBuilder {
789 PrimaryBasesSetVectorTy;
791 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits>
792 VBaseOffsetOffsetsMapTy;
796 typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVTableIndicesTy;
812 bool MostDerivedClassIsVirtual;
823 const FinalOverriders Overriders;
827 llvm::DenseMap<const CXXRecordDecl *, VCallOffsetMap> VCallOffsetsForVBases;
831 VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
837 AddressPointsMapTy AddressPoints;
851 const uint64_t VTableIndex;
854 uint64_t VTableIndex)
855 : BaseOffset(BaseOffset),
856 BaseOffsetInLayoutClass(BaseOffsetInLayoutClass),
857 VTableIndex(VTableIndex) { }
864 MethodInfo(MethodInfo
const&) =
default;
867 typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy;
871 MethodInfoMapTy MethodInfoMap;
875 MethodVTableIndicesTy MethodVTableIndices;
877 typedef llvm::DenseMap<uint64_t, ThunkInfo> VTableThunksMapTy;
881 VTableThunksMapTy VTableThunks;
884 typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
895 void ComputeThisAdjustments();
901 VisitedVirtualBasesSetTy PrimaryVirtualBases;
918 FinalOverriders::OverriderInfo Overrider);
946 CharUnits FirstBaseOffsetInLayoutClass)
const;
954 PrimaryBasesSetVectorTy &PrimaryBases);
969 bool BaseIsMorallyVirtual,
970 bool BaseIsVirtualInLayoutClass,
985 VisitedVirtualBasesSetTy &VBases);
990 VisitedVirtualBasesSetTy &VBases);
994 bool isBuildingConstructorVTable()
const {
995 return MostDerivedClass != LayoutClass;
1006 bool MostDerivedClassIsVirtual,
1008 : VTables(VTables), MostDerivedClass(MostDerivedClass),
1009 MostDerivedClassOffset(MostDerivedClassOffset),
1010 MostDerivedClassIsVirtual(MostDerivedClassIsVirtual),
1011 LayoutClass(LayoutClass), Context(MostDerivedClass->
getASTContext()),
1012 Overriders(MostDerivedClass, MostDerivedClassOffset, LayoutClass) {
1018 dumpLayout(llvm::outs());
1021 uint64_t getNumThunks()
const {
1022 return Thunks.size();
1025 ThunksMapTy::const_iterator thunks_begin()
const {
1026 return Thunks.begin();
1029 ThunksMapTy::const_iterator thunks_end()
const {
1030 return Thunks.end();
1033 const VBaseOffsetOffsetsMapTy &getVBaseOffsetOffsets()
const {
1034 return VBaseOffsetOffsets;
1037 const AddressPointsMapTy &getAddressPoints()
const {
1038 return AddressPoints;
1041 MethodVTableIndicesTy::const_iterator vtable_indices_begin()
const {
1042 return MethodVTableIndices.begin();
1045 MethodVTableIndicesTy::const_iterator vtable_indices_end()
const {
1046 return MethodVTableIndices.end();
1051 AddressPointsMapTy::const_iterator address_points_begin()
const {
1052 return AddressPoints.begin();
1055 AddressPointsMapTy::const_iterator address_points_end()
const {
1056 return AddressPoints.end();
1059 VTableThunksMapTy::const_iterator vtable_thunks_begin()
const {
1060 return VTableThunks.begin();
1063 VTableThunksMapTy::const_iterator vtable_thunks_end()
const {
1064 return VTableThunks.end();
1068 void dumpLayout(raw_ostream&);
1073 assert(!isBuildingConstructorVTable() &&
1074 "Can't add thunks for construction vtable");
1079 if (llvm::is_contained(ThunksVector, Thunk))
1082 ThunksVector.push_back(Thunk);
1091template <
class VisitorTy>
1093visitAllOverriddenMethods(
const CXXMethodDecl *MD, VisitorTy &Visitor) {
1097 if (!Visitor(OverriddenMD))
1099 visitAllOverriddenMethods(OverriddenMD, Visitor);
1107 OverriddenMethodsSetTy& OverriddenMethods) {
1108 auto OverriddenMethodsCollector = [&](
const CXXMethodDecl *MD) {
1110 return OverriddenMethods.insert(MD).second;
1112 visitAllOverriddenMethods(MD, OverriddenMethodsCollector);
1115void ItaniumVTableBuilder::ComputeThisAdjustments() {
1118 for (
const auto &MI : MethodInfoMap) {
1120 const MethodInfo &MethodInfo = MI.second;
1123 uint64_t VTableIndex = MethodInfo.VTableIndex;
1124 if (Components[VTableIndex].
getKind() ==
1129 FinalOverriders::OverriderInfo Overrider =
1130 Overriders.getOverrider(MD, MethodInfo.BaseOffset);
1133 if (MethodInfo.BaseOffsetInLayoutClass == Overrider.Offset) {
1139 if (VTableThunks.lookup(VTableIndex).Return.isEmpty())
1144 ComputeThisAdjustment(MD, MethodInfo.BaseOffsetInLayoutClass, Overrider);
1150 auto SetThisAdjustmentThunk = [&](uint64_t Idx) {
1172 if (!VTableThunks.count(Idx)) {
1173 const CXXMethodDecl *Method = VTables.findOriginalMethodInMap(MD);
1174 VTableThunks[Idx].Method = Method;
1180 SetThisAdjustmentThunk(VTableIndex);
1182 if (isa<CXXDestructorDecl>(MD)) {
1184 SetThisAdjustmentThunk(VTableIndex + 1);
1189 MethodInfoMap.clear();
1191 if (isBuildingConstructorVTable()) {
1196 for (
const auto &TI : VTableThunks) {
1201 switch (Component.
getKind()) {
1203 llvm_unreachable(
"Unexpected vtable component kind!");
1215 if (MD->
getParent() == MostDerivedClass)
1216 AddThunk(MD, Thunk);
1221ItaniumVTableBuilder::ComputeReturnAdjustment(BaseOffset Offset) {
1224 if (!Offset.isEmpty()) {
1225 if (Offset.VirtualBase) {
1227 if (Offset.DerivedClass == MostDerivedClass) {
1230 VBaseOffsetOffsets.lookup(Offset.VirtualBase).getQuantity();
1233 VTables.getVirtualBaseOffsetOffset(Offset.DerivedClass,
1234 Offset.VirtualBase).getQuantity();
1238 Adjustment.
NonVirtual = Offset.NonVirtualOffset.getQuantity();
1244BaseOffset ItaniumVTableBuilder::ComputeThisAdjustmentBaseOffset(
1253 llvm_unreachable(
"Class must be derived from the passed in base class!");
1258 BaseOffset Offset = ComputeBaseOffset(Context, DerivedRD,
Path);
1260 CharUnits OffsetToBaseSubobject = Offset.NonVirtualOffset;
1262 if (Offset.VirtualBase) {
1270 OffsetToBaseSubobject +=
1279 if (OffsetToBaseSubobject ==
Base.getBaseOffset()) {
1282 Offset.NonVirtualOffset = -Offset.NonVirtualOffset;
1287 return BaseOffset();
1292 FinalOverriders::OverriderInfo Overrider) {
1294 if (Overrider.Method->isPureVirtual())
1298 BaseOffsetInLayoutClass);
1300 BaseSubobject OverriderBaseSubobject(Overrider.Method->getParent(),
1304 BaseOffset Offset = ComputeThisAdjustmentBaseOffset(OverriddenBaseSubobject,
1305 OverriderBaseSubobject);
1306 if (Offset.isEmpty())
1311 if (Offset.VirtualBase) {
1313 VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[Offset.VirtualBase];
1315 if (VCallOffsets.empty()) {
1318 VCallAndVBaseOffsetBuilder Builder(
1319 VTables, MostDerivedClass, MostDerivedClass,
1326 VCallOffsets = Builder.getVCallOffsets();
1330 VCallOffsets.getVCallOffsetOffset(MD).getQuantity();
1334 Adjustment.
NonVirtual = Offset.NonVirtualOffset.getQuantity();
1339void ItaniumVTableBuilder::AddMethod(
const CXXMethodDecl *MD,
1343 "Destructor can't have return adjustment!");
1369static bool OverridesIndirectMethodInBases(
1377 if (OverridesIndirectMethodInBases(OverriddenMD, Bases))
1384bool ItaniumVTableBuilder::IsOverriderUsed(
1387 CharUnits FirstBaseOffsetInLayoutClass)
const {
1390 if (BaseOffsetInLayoutClass == FirstBaseOffsetInLayoutClass)
1399 if (Overrider->getParent() == FirstBaseInPrimaryBaseChain)
1405 PrimaryBases.insert(RD);
1418 "Primary base should always be at offset 0!");
1426 FirstBaseOffsetInLayoutClass) {
1432 "Primary base should always be at offset 0!");
1435 if (!PrimaryBases.insert(PrimaryBase))
1436 llvm_unreachable(
"Found a duplicate primary base!");
1443 return OverridesIndirectMethodInBases(Overrider, PrimaryBases);
1453 BasesSetVectorTy &Bases) {
1454 OverriddenMethodsSetTy OverriddenMethods;
1455 ComputeAllOverriddenMethods(MD, OverriddenMethods);
1457 for (
const CXXRecordDecl *PrimaryBase : llvm::reverse(Bases)) {
1459 for (
const CXXMethodDecl *OverriddenMD : OverriddenMethods) {
1461 if (OverriddenMD->getParent() == PrimaryBase)
1462 return OverriddenMD;
1469void ItaniumVTableBuilder::AddMethods(
1473 PrimaryBasesSetVectorTy &PrimaryBases) {
1488 CharUnits PrimaryBaseOffsetInLayoutClass;
1491 "Primary vbase should have a zero offset!");
1502 PrimaryBaseOffsetInLayoutClass =
1506 "Primary base should have a zero offset!");
1508 PrimaryBaseOffset =
Base.getBaseOffset();
1509 PrimaryBaseOffsetInLayoutClass = BaseOffsetInLayoutClass;
1513 PrimaryBaseOffsetInLayoutClass, FirstBaseInPrimaryBaseChain,
1514 FirstBaseOffsetInLayoutClass, PrimaryBases);
1516 if (!PrimaryBases.insert(PrimaryBase))
1517 llvm_unreachable(
"Found a duplicate primary base!");
1521 NewVirtualFunctionsTy NewVirtualFunctions;
1526 for (
const auto *MD : RD->
methods()) {
1527 if (!ItaniumVTableContext::hasVtableSlot(MD))
1532 FinalOverriders::OverriderInfo Overrider =
1533 Overriders.getOverrider(MD,
Base.getBaseOffset());
1539 FindNearestOverriddenMethod(MD, PrimaryBases)) {
1540 if (ComputeReturnAdjustmentBaseOffset(Context, MD,
1541 OverriddenMD).isEmpty()) {
1542 VTables.setOriginalMethod(MD, OverriddenMD);
1546 assert(MethodInfoMap.count(OverriddenMD) &&
1547 "Did not find the overridden method!");
1548 MethodInfo &OverriddenMethodInfo = MethodInfoMap[OverriddenMD];
1550 MethodInfo MethodInfo(
Base.getBaseOffset(), BaseOffsetInLayoutClass,
1551 OverriddenMethodInfo.VTableIndex);
1553 assert(!MethodInfoMap.count(MD) &&
1554 "Should not have method info for this method yet!");
1556 MethodInfoMap.insert(std::make_pair(MD, MethodInfo));
1557 MethodInfoMap.erase(OverriddenMD);
1563 if (!isBuildingConstructorVTable() && OverriddenMD != MD) {
1566 ComputeThisAdjustment(OverriddenMD, BaseOffsetInLayoutClass,
1570 Overrider.Method->getParent() == MostDerivedClass) {
1575 BaseOffset ReturnAdjustmentOffset =
1576 ComputeReturnAdjustmentBaseOffset(Context, Overrider.Method, MD);
1578 ComputeReturnAdjustment(ReturnAdjustmentOffset);
1581 AddThunk(Overrider.Method,
1583 OverriddenMD->getThisType().getTypePtr()));
1592 NewImplicitVirtualFunctions.push_back(MD);
1594 NewVirtualFunctions.push_back(MD);
1598 NewImplicitVirtualFunctions.begin(), NewImplicitVirtualFunctions.end(),
1602 if (A->isCopyAssignmentOperator() != B->isCopyAssignmentOperator())
1603 return A->isCopyAssignmentOperator();
1604 if (A->isMoveAssignmentOperator() != B->isMoveAssignmentOperator())
1605 return A->isMoveAssignmentOperator();
1606 if (isa<CXXDestructorDecl>(A) != isa<CXXDestructorDecl>(B))
1607 return isa<CXXDestructorDecl>(A);
1608 assert(A->getOverloadedOperator() == OO_EqualEqual &&
1609 B->getOverloadedOperator() == OO_EqualEqual &&
1610 "unexpected or duplicate implicit virtual function");
1615 NewVirtualFunctions.append(NewImplicitVirtualFunctions.begin(),
1616 NewImplicitVirtualFunctions.end());
1620 FinalOverriders::OverriderInfo Overrider =
1621 Overriders.getOverrider(MD,
Base.getBaseOffset());
1624 MethodInfo MethodInfo(
Base.getBaseOffset(), BaseOffsetInLayoutClass,
1627 assert(!MethodInfoMap.count(MD) &&
1628 "Should not have method info for this method yet!");
1629 MethodInfoMap.insert(std::make_pair(MD, MethodInfo));
1633 if (!IsOverriderUsed(OverriderMD, BaseOffsetInLayoutClass,
1634 FirstBaseInPrimaryBaseChain,
1635 FirstBaseOffsetInLayoutClass)) {
1642 BaseOffset ReturnAdjustmentOffset;
1644 ReturnAdjustmentOffset =
1645 ComputeReturnAdjustmentBaseOffset(Context, OverriderMD, MD);
1649 ComputeReturnAdjustment(ReturnAdjustmentOffset);
1656 VTableThunks[Components.size()].Method = MD;
1664void ItaniumVTableBuilder::LayoutVTable() {
1665 LayoutPrimaryAndSecondaryVTables(
BaseSubobject(MostDerivedClass,
1668 MostDerivedClassIsVirtual,
1669 MostDerivedClassOffset);
1671 VisitedVirtualBasesSetTy VBases;
1674 DeterminePrimaryVirtualBases(MostDerivedClass, MostDerivedClassOffset,
1678 LayoutVTablesForVirtualBases(MostDerivedClass, VBases);
1681 bool IsAppleKext = Context.
getLangOpts().AppleKext;
1686void ItaniumVTableBuilder::LayoutPrimaryAndSecondaryVTables(
1688 bool BaseIsVirtualInLayoutClass,
CharUnits OffsetInLayoutClass) {
1689 assert(
Base.getBase()->isDynamicClass() &&
"class does not have a vtable!");
1691 unsigned VTableIndex = Components.size();
1692 VTableIndices.push_back(VTableIndex);
1695 VCallAndVBaseOffsetBuilder Builder(
1696 VTables, MostDerivedClass, LayoutClass, &Overriders,
Base,
1697 BaseIsVirtualInLayoutClass, OffsetInLayoutClass);
1698 Components.append(Builder.components_begin(), Builder.components_end());
1701 if (BaseIsVirtualInLayoutClass && !Builder.getVCallOffsets().empty()) {
1702 VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[
Base.getBase()];
1704 if (VCallOffsets.empty())
1705 VCallOffsets = Builder.getVCallOffsets();
1710 if (
Base.getBase() == MostDerivedClass)
1711 VBaseOffsetOffsets = Builder.getVBaseOffsetOffsets();
1714 CharUnits OffsetToTop = MostDerivedClassOffset - OffsetInLayoutClass;
1721 uint64_t AddressPoint = Components.size();
1724 PrimaryBasesSetVectorTy PrimaryBases;
1725 AddMethods(
Base, OffsetInLayoutClass,
1726 Base.getBase(), OffsetInLayoutClass,
1730 if (RD == MostDerivedClass) {
1731 assert(MethodVTableIndices.empty());
1732 for (
const auto &I : MethodInfoMap) {
1734 const MethodInfo &MI = I.second;
1737 = MI.VTableIndex - AddressPoint;
1739 = MI.VTableIndex + 1 - AddressPoint;
1741 MethodVTableIndices[MD] = MI.VTableIndex - AddressPoint;
1747 ComputeThisAdjustments();
1751 AddressPoints.insert(
1754 unsigned(VTableIndices.size() - 1),
1755 unsigned(AddressPoint - VTableIndex)}));
1770 OffsetInLayoutClass) {
1780 LayoutSecondaryVTables(
Base, BaseIsMorallyVirtual, OffsetInLayoutClass);
1785 bool BaseIsMorallyVirtual,
1796 for (
const auto &B : RD->
bases()) {
1801 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
1807 if (isBuildingConstructorVTable()) {
1813 if (!BaseIsMorallyVirtual && !BaseDecl->
getNumVBases())
1819 CharUnits BaseOffset =
Base.getBaseOffset() + RelativeBaseOffset;
1822 OffsetInLayoutClass + RelativeBaseOffset;
1826 if (BaseDecl == PrimaryBase) {
1828 BaseIsMorallyVirtual, BaseOffsetInLayoutClass);
1833 LayoutPrimaryAndSecondaryVTables(
1835 BaseIsMorallyVirtual,
1837 BaseOffsetInLayoutClass);
1841void ItaniumVTableBuilder::DeterminePrimaryVirtualBases(
1843 VisitedVirtualBasesSetTy &VBases) {
1851 bool IsPrimaryVirtualBase =
true;
1853 if (isBuildingConstructorVTable()) {
1859 CharUnits PrimaryBaseOffsetInLayoutClass =
1864 if (PrimaryBaseOffsetInLayoutClass != OffsetInLayoutClass)
1865 IsPrimaryVirtualBase =
false;
1868 if (IsPrimaryVirtualBase)
1869 PrimaryVirtualBases.insert(PrimaryBase);
1874 for (
const auto &B : RD->
bases()) {
1875 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
1879 if (B.isVirtual()) {
1880 if (!VBases.insert(BaseDecl).second)
1886 BaseOffsetInLayoutClass =
1889 BaseOffsetInLayoutClass =
1893 DeterminePrimaryVirtualBases(BaseDecl, BaseOffsetInLayoutClass, VBases);
1897void ItaniumVTableBuilder::LayoutVTablesForVirtualBases(
1898 const CXXRecordDecl *RD, VisitedVirtualBasesSetTy &VBases) {
1903 for (
const auto &B : RD->
bases()) {
1904 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
1909 !PrimaryVirtualBases.count(BaseDecl) &&
1910 VBases.insert(BaseDecl).second) {
1921 LayoutPrimaryAndSecondaryVTables(
1925 BaseOffsetInLayoutClass);
1931 LayoutVTablesForVirtualBases(BaseDecl, VBases);
1935static void printThunkMethod(
const ThunkInfo &Info, raw_ostream &Out) {
1939 PredefinedIdentKind::PrettyFunctionNoVirtual, Info.
Method);
1940 Out <<
" method: " << Str;
1944void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
1948 Out <<
"Original map\n";
1950 for (
const auto &
P : VTables.getOriginalMethodMap()) {
1957 Out <<
" " << Str0 <<
" -> " << Str1 <<
"\n";
1960 if (isBuildingConstructorVTable()) {
1961 Out <<
"Construction vtable for ('";
1964 Out << MostDerivedClassOffset.
getQuantity() <<
") in '";
1967 Out <<
"Vtable for '";
1970 Out <<
"' (" << Components.size() <<
" entries).\n";
1976 std::multimap<uint64_t, BaseSubobject> AddressPointsByIndex;
1977 for (
const auto &AP : AddressPoints) {
1980 VTableIndices[AP.second.VTableIndex] + AP.second.AddressPointIndex;
1982 AddressPointsByIndex.insert(std::make_pair(Index,
Base));
1985 for (
unsigned I = 0,
E = Components.size(); I !=
E; ++I) {
1988 Out << llvm::format(
"%4d | ", I);
1993 switch (Component.
getKind()) {
1996 Out <<
"vcall_offset ("
2002 Out <<
"vbase_offset ("
2008 Out <<
"offset_to_top ("
2022 PredefinedIdentKind::PrettyFunctionNoVirtual, MD);
2028 Out <<
" [deleted]";
2030 ThunkInfo Thunk = VTableThunks.lookup(I);
2034 Out <<
"\n [return adjustment: ";
2039 Out <<
" vbase offset offset";
2043 printThunkMethod(Thunk, Out);
2048 Out <<
"\n [this adjustment: ";
2053 Out <<
" vcall offset offset";
2057 printThunkMethod(Thunk, Out);
2073 Out <<
"() [complete]";
2075 Out <<
"() [deleting]";
2080 ThunkInfo Thunk = VTableThunks.lookup(I);
2084 Out <<
"\n [this adjustment: ";
2089 Out <<
" vcall offset offset";
2094 printThunkMethod(Thunk, Out);
2104 PredefinedIdentKind::PrettyFunctionNoVirtual, MD);
2105 Out <<
"[unused] " << Str;
2115 uint64_t NextIndex = Index + 1;
2116 if (AddressPointsByIndex.count(NextIndex)) {
2117 if (AddressPointsByIndex.count(NextIndex) == 1) {
2119 AddressPointsByIndex.find(NextIndex)->second;
2122 Base.getBase()->printQualifiedName(Out);
2123 Out <<
", " <<
Base.getBaseOffset().getQuantity();
2124 Out <<
") vtable address --\n";
2127 AddressPointsByIndex.lower_bound(NextIndex)->second.getBaseOffset();
2130 std::set<std::string> ClassNames;
2131 for (
const auto &I :
2132 llvm::make_range(AddressPointsByIndex.equal_range(NextIndex))) {
2133 assert(I.second.getBaseOffset() == BaseOffset &&
2134 "Invalid base offset!");
2139 for (
const std::string &Name : ClassNames) {
2140 Out <<
" -- (" << Name;
2141 Out <<
", " << BaseOffset.
getQuantity() <<
") vtable address --\n";
2149 if (isBuildingConstructorVTable())
2156 std::map<std::string, CharUnits> ClassNamesAndOffsets;
2157 for (
const auto &I : VBaseOffsetOffsets) {
2158 std::string ClassName = I.first->getQualifiedNameAsString();
2160 ClassNamesAndOffsets.insert(std::make_pair(ClassName, OffsetOffset));
2163 Out <<
"Virtual base offset offsets for '";
2166 Out << ClassNamesAndOffsets.size();
2167 Out << (ClassNamesAndOffsets.size() == 1 ?
" entry" :
" entries") <<
").\n";
2169 for (
const auto &I : ClassNamesAndOffsets)
2170 Out <<
" " << I.first <<
" | " << I.second.getQuantity() <<
'\n';
2175 if (!Thunks.empty()) {
2177 std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls;
2179 for (
const auto &I : Thunks) {
2182 PredefinedIdentKind::PrettyFunctionNoVirtual, MD);
2184 MethodNamesAndDecls.insert(std::make_pair(MethodName, MD));
2187 for (
const auto &I : MethodNamesAndDecls) {
2188 const std::string &MethodName = I.first;
2191 ThunkInfoVectorTy ThunksVector = Thunks[MD];
2196 Out <<
"Thunks for '" << MethodName <<
"' (" << ThunksVector.size();
2197 Out << (ThunksVector.size() == 1 ?
" entry" :
" entries") <<
").\n";
2199 for (
unsigned I = 0,
E = ThunksVector.size(); I !=
E; ++I) {
2200 const ThunkInfo &Thunk = ThunksVector[I];
2202 Out << llvm::format(
"%4d | ", I);
2207 Out <<
" non-virtual";
2210 Out <<
" vbase offset offset";
2219 Out <<
"this adjustment: ";
2224 Out <<
" vcall offset offset";
2237 std::map<uint64_t, std::string> IndicesMap;
2239 for (
const auto *MD : MostDerivedClass->
methods()) {
2241 if (!ItaniumVTableContext::hasVtableSlot(MD))
2246 PredefinedIdentKind::PrettyFunctionNoVirtual, MD);
2250 assert(MethodVTableIndices.count(GD));
2251 uint64_t VTableIndex = MethodVTableIndices[GD];
2252 IndicesMap[VTableIndex] = MethodName +
" [complete]";
2253 IndicesMap[VTableIndex + 1] = MethodName +
" [deleting]";
2255 assert(MethodVTableIndices.count(MD));
2256 IndicesMap[MethodVTableIndices[MD]] = MethodName;
2261 if (!IndicesMap.empty()) {
2262 Out <<
"VTable indices for '";
2264 Out <<
"' (" << IndicesMap.size() <<
" entries).\n";
2266 for (
const auto &I : IndicesMap) {
2267 uint64_t VTableIndex = I.first;
2268 const std::string &MethodName = I.second;
2270 Out << llvm::format(
"%4" PRIu64
" | ", VTableIndex) << MethodName
2281 unsigned numVTables) {
2284 for (
auto it = addressPoints.begin(); it != addressPoints.end(); ++it) {
2285 const auto &addressPointLoc = it->second;
2286 unsigned vtableIndex = addressPointLoc.VTableIndex;
2287 unsigned addressPoint = addressPointLoc.AddressPointIndex;
2288 if (indexMap[vtableIndex]) {
2291 assert(indexMap[vtableIndex] == addressPoint &&
2292 "Every vtable index should have a unique address point. Found a "
2293 "vtable that has two different address points.");
2295 indexMap[vtableIndex] = addressPoint;
2310 : VTableComponents(VTableComponents), VTableThunks(VTableThunks),
2312 AddressPoints, VTableIndices.size())) {
2313 if (VTableIndices.size() <= 1)
2314 assert(VTableIndices.size() == 1 && VTableIndices[0] == 0);
2320 assert((LHS.first != RHS.first || LHS.second == RHS.second) &&
2321 "Different thunks should have unique indices!");
2322 return LHS.first < RHS.first;
2340 MethodVTableIndicesTy::iterator I = MethodVTableIndices.find(GD);
2341 if (I != MethodVTableIndices.end())
2346 computeVTableRelatedInformation(RD);
2348 I = MethodVTableIndices.find(GD);
2349 assert(I != MethodVTableIndices.end() &&
"Did not find index!");
2356 ClassPairTy ClassPair(RD, VBase);
2358 VirtualBaseClassOffsetOffsetsMapTy::iterator I =
2359 VirtualBaseClassOffsetOffsets.find(ClassPair);
2360 if (I != VirtualBaseClassOffsetOffsets.end())
2363 VCallAndVBaseOffsetBuilder Builder(*
this, RD, RD,
nullptr,
2368 for (
const auto &I : Builder.getVBaseOffsetOffsets()) {
2370 ClassPairTy ClassPair(RD, I.first);
2372 VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I.second));
2375 I = VirtualBaseClassOffsetOffsets.find(ClassPair);
2376 assert(I != VirtualBaseClassOffsetOffsets.end() &&
"Did not find index!");
2382 const auto *MD = cast<CXXMethodDecl>(GD.
getDecl());
2383 computeVTableRelatedInformation(MD->getParent());
2386 if (
const auto *DD = dyn_cast<CXXDestructorDecl>(OriginalMD))
2396 auto I = OriginalMethodMap.find(MD);
2400 if (I == OriginalMethodMap.end())
2410static std::unique_ptr<VTableLayout>
2413 VTableThunks(Builder.vtable_thunks_begin(), Builder.vtable_thunks_end());
2415 return std::make_unique<VTableLayout>(
2416 Builder.VTableIndices, Builder.vtable_components(), VTableThunks,
2417 Builder.getAddressPoints());
2421ItaniumVTableContext::computeVTableRelatedInformation(
const CXXRecordDecl *RD) {
2422 std::unique_ptr<const VTableLayout> &Entry = VTableLayouts[RD];
2432 MethodVTableIndices.insert(Builder.vtable_indices_begin(),
2433 Builder.vtable_indices_end());
2436 Thunks.insert(Builder.thunks_begin(), Builder.thunks_end());
2447 if (VirtualBaseClassOffsetOffsets.count(std::make_pair(RD, VBase)))
2450 for (
const auto &I : Builder.getVBaseOffsetOffsets()) {
2452 ClassPairTy ClassPair(RD, I.first);
2454 VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I.second));
2458std::unique_ptr<VTableLayout>
2461 bool MostDerivedClassIsVirtual,
const CXXRecordDecl *LayoutClass) {
2462 ItaniumVTableBuilder Builder(*
this, MostDerivedClass, MostDerivedClassOffset,
2463 MostDerivedClassIsVirtual, LayoutClass);
2511class VFTableBuilder {
2513 typedef llvm::DenseMap<GlobalDecl, MethodVFTableLocation>
2514 MethodVFTableLocationsTy;
2516 typedef llvm::iterator_range<MethodVFTableLocationsTy::const_iterator>
2517 method_locations_range;
2535 const FinalOverriders Overriders;
2540 MethodVFTableLocationsTy MethodVFTableLocations;
2543 bool HasRTTIComponent =
false;
2550 const uint64_t VBTableIndex;
2553 const uint64_t VFTableIndex;
2564 MethodInfo(uint64_t VBTableIndex, uint64_t VFTableIndex,
2565 bool UsesExtraSlot =
false)
2566 : VBTableIndex(VBTableIndex), VFTableIndex(VFTableIndex),
2567 Shadowed(
false), UsesExtraSlot(UsesExtraSlot) {}
2570 : VBTableIndex(0), VFTableIndex(0), Shadowed(
false),
2571 UsesExtraSlot(
false) {}
2574 typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy;
2578 MethodInfoMapTy MethodInfoMap;
2580 typedef llvm::DenseMap<uint64_t, ThunkInfo> VTableThunksMapTy;
2584 VTableThunksMapTy VTableThunks;
2587 typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
2598 if (llvm::is_contained(ThunksVector, Thunk))
2601 ThunksVector.push_back(Thunk);
2606 CharUnits ComputeThisOffset(FinalOverriders::OverriderInfo Overrider);
2608 void CalculateVtordispAdjustment(FinalOverriders::OverriderInfo Overrider,
2615 VTableThunks[Components.size()] = TI;
2620 "Destructor can't have return adjustment!");
2631 BasesSetVectorTy &VisitedBases);
2633 void LayoutVFTable() {
2635 if (HasRTTIComponent)
2638 BasesSetVectorTy VisitedBases;
2643 assert(!Components.empty() &&
"vftable can't be empty");
2645 assert(MethodVFTableLocations.empty());
2646 for (
const auto &I : MethodInfoMap) {
2648 const MethodInfo &MI = I.second;
2653 if (MD->
getParent() != MostDerivedClass || MI.Shadowed)
2660 MethodVFTableLocations[MD] =
Loc;
2669 Context(MostDerivedClass->getASTContext()),
2670 MostDerivedClass(MostDerivedClass),
2671 MostDerivedClassLayout(Context.getASTRecordLayout(MostDerivedClass)),
2673 Overriders(MostDerivedClass,
CharUnits(), MostDerivedClass) {
2680 HasRTTIComponent =
true;
2685 dumpLayout(llvm::outs());
2688 uint64_t getNumThunks()
const {
return Thunks.size(); }
2690 ThunksMapTy::const_iterator thunks_begin()
const {
return Thunks.begin(); }
2692 ThunksMapTy::const_iterator thunks_end()
const {
return Thunks.end(); }
2694 method_locations_range vtable_locations()
const {
2695 return method_locations_range(MethodVFTableLocations.begin(),
2696 MethodVFTableLocations.end());
2701 VTableThunksMapTy::const_iterator vtable_thunks_begin()
const {
2702 return VTableThunks.begin();
2705 VTableThunksMapTy::const_iterator vtable_thunks_end()
const {
2706 return VTableThunks.end();
2709 void dumpLayout(raw_ostream &);
2769VFTableBuilder::ComputeThisOffset(FinalOverriders::OverriderInfo Overrider) {
2770 BasesSetVectorTy Bases;
2774 OverriddenMethodsSetTy VisitedOverriddenMethods;
2775 auto InitialOverriddenDefinitionCollector = [&](
2777 if (OverriddenMD->size_overridden_methods() == 0)
2778 Bases.insert(OverriddenMD->getParent());
2780 return VisitedOverriddenMethods.insert(OverriddenMD).second;
2782 visitAllOverriddenMethods(Overrider.Method,
2783 InitialOverriddenDefinitionCollector);
2788 if (Bases.size() == 0)
2789 return Overrider.Offset;
2792 Overrider.Method->getParent()->lookupInBases(
2794 return Bases.count(
Specifier->getType()->getAsCXXRecordDecl());
2808 CharUnits ThisOffset = Overrider.Offset;
2815 QualType CurTy = Element.Base->getType();
2820 if (Element.Base->isVirtual()) {
2831 LastVBaseOffset = ThisOffset =
2838 if (isa<CXXDestructorDecl>(Overrider.Method)) {
2839 if (LastVBaseOffset.
isZero()) {
2843 ThisOffset = Overrider.Offset;
2847 ThisOffset = LastVBaseOffset;
2851 if (Ret > ThisOffset ||
First) {
2857 assert(!
First &&
"Method not found in the given subobject?");
2959void VFTableBuilder::CalculateVtordispAdjustment(
2960 FinalOverriders::OverriderInfo Overrider,
CharUnits ThisOffset,
2964 const ASTRecordLayout::VBaseOffsetsMapTy::const_iterator &VBaseMapEntry =
2966 assert(VBaseMapEntry != VBaseMap.end());
2970 if (!VBaseMapEntry->second.hasVtorDisp() ||
2976 CharUnits OffsetOfVBaseWithVFPtr = VBaseMapEntry->second.VBaseOffset;
2978 (OffsetOfVBaseWithVFPtr - WhichVFPtr.
FullOffsetInMDC).getQuantity() - 4;
2982 if (Overrider.Method->getParent() == MostDerivedClass ||
2983 !Overrider.VirtualBase)
2995 TA.
NonVirtual = (ThisOffset - Overrider.Offset).getQuantity();
3009 typedef llvm::DenseMap<DeclarationName, unsigned> VisitedGroupIndicesTy;
3010 VisitedGroupIndicesTy VisitedGroupIndices;
3011 for (
const auto *
D : RD->
decls()) {
3012 const auto *ND = dyn_cast<NamedDecl>(
D);
3015 VisitedGroupIndicesTy::iterator J;
3017 std::tie(J, Inserted) = VisitedGroupIndices.insert(
3018 std::make_pair(ND->getDeclName(), Groups.size()));
3020 Groups.push_back(MethodGroup());
3021 if (
const auto *MD = dyn_cast<CXXMethodDecl>(ND))
3026 for (
const MethodGroup &Group : Groups)
3027 VirtualMethods.append(Group.rbegin(), Group.rend());
3031 for (
const auto &B : RD->
bases()) {
3032 if (B.isVirtual() && B.getType()->getAsCXXRecordDecl() ==
Base)
3040 BasesSetVectorTy &VisitedBases) {
3050 const CXXRecordDecl *NextBase =
nullptr, *NextLastVBase = LastVBase;
3055 NextLastVBase = NextBase;
3063 "No primary virtual bases in this ABI");
3064 NextBase = PrimaryBase;
3065 NextBaseOffset =
Base.getBaseOffset();
3069 AddMethods(
BaseSubobject(NextBase, NextBaseOffset), BaseDepth + 1,
3070 NextLastVBase, VisitedBases);
3071 if (!VisitedBases.insert(NextBase))
3072 llvm_unreachable(
"Found a duplicate primary base!");
3088 FinalOverriders::OverriderInfo FinalOverrider =
3089 Overriders.getOverrider(MD,
Base.getBaseOffset());
3090 const CXXMethodDecl *FinalOverriderMD = FinalOverrider.Method;
3092 FindNearestOverriddenMethod(MD, VisitedBases);
3095 bool ReturnAdjustingThunk =
false, ForceReturnAdjustmentMangling =
false;
3096 CharUnits ThisOffset = ComputeThisOffset(FinalOverrider);
3099 if ((OverriddenMD || FinalOverriderMD != MD) &&
3101 CalculateVtordispAdjustment(FinalOverrider, ThisOffset,
3102 ThisAdjustmentOffset);
3110 MethodInfoMapTy::iterator OverriddenMDIterator =
3111 MethodInfoMap.find(OverriddenMD);
3114 if (OverriddenMDIterator == MethodInfoMap.end())
3117 MethodInfo &OverriddenMethodInfo = OverriddenMDIterator->second;
3119 VBIndex = OverriddenMethodInfo.VBTableIndex;
3126 ReturnAdjustingThunk = !ComputeReturnAdjustmentBaseOffset(
3127 Context, MD, OverriddenMD).isEmpty() ||
3128 OverriddenMethodInfo.UsesExtraSlot;
3130 if (!ReturnAdjustingThunk) {
3133 MethodInfo MI(VBIndex, OverriddenMethodInfo.VFTableIndex);
3134 MethodInfoMap.erase(OverriddenMDIterator);
3136 assert(!MethodInfoMap.count(MD) &&
3137 "Should not have method info for this method yet!");
3138 MethodInfoMap.insert(std::make_pair(MD, MI));
3144 OverriddenMethodInfo.Shadowed =
true;
3148 ForceReturnAdjustmentMangling =
3149 !(MD == FinalOverriderMD && ThisAdjustmentOffset.
isEmpty());
3160 MethodInfo MI(VBIndex,
3161 HasRTTIComponent ? Components.size() - 1 : Components.size(),
3162 ReturnAdjustingThunk);
3164 assert(!MethodInfoMap.count(MD) &&
3165 "Should not have method info for this method yet!");
3166 MethodInfoMap.insert(std::make_pair(MD, MI));
3170 BaseOffset ReturnAdjustmentOffset;
3173 ReturnAdjustmentOffset =
3174 ComputeReturnAdjustmentBaseOffset(Context, FinalOverriderMD, MD);
3176 if (!ReturnAdjustmentOffset.isEmpty()) {
3177 ForceReturnAdjustmentMangling =
true;
3179 ReturnAdjustmentOffset.NonVirtualOffset.getQuantity();
3180 if (ReturnAdjustmentOffset.VirtualBase) {
3187 ReturnAdjustmentOffset.VirtualBase);
3190 auto ThisType = (OverriddenMD ? OverriddenMD : MD)->getThisType().getTypePtr();
3191 AddMethod(FinalOverriderMD,
3193 ForceReturnAdjustmentMangling ? MD :
nullptr));
3200 Elem->printQualifiedName(Out);
3206 bool ContinueFirstLine) {
3208 bool Multiline =
false;
3209 const char *LinePrefix =
"\n ";
3211 if (!ContinueFirstLine)
3213 Out <<
"[return adjustment (to type '"
3225 if (Multiline || !ContinueFirstLine)
3227 Out <<
"[this adjustment: ";
3229 assert(
T.Virtual.Microsoft.VtordispOffset < 0);
3230 Out <<
"vtordisp at " <<
T.Virtual.Microsoft.VtordispOffset <<
", ";
3231 if (
T.Virtual.Microsoft.VBPtrOffset) {
3232 Out <<
"vbptr at " <<
T.Virtual.Microsoft.VBPtrOffset
3234 assert(
T.Virtual.Microsoft.VBOffsetOffset > 0);
3235 Out << LinePrefix <<
" vboffset at "
3236 <<
T.Virtual.Microsoft.VBOffsetOffset <<
" in the vbtable, ";
3239 Out <<
T.NonVirtual <<
" non-virtual]";
3243void VFTableBuilder::dumpLayout(raw_ostream &Out) {
3244 Out <<
"VFTable for ";
3248 Out <<
"' (" << Components.size()
3249 << (Components.size() == 1 ?
" entry" :
" entries") <<
").\n";
3251 for (
unsigned I = 0,
E = Components.size(); I !=
E; ++I) {
3252 Out << llvm::format(
"%4d | ", I);
3257 switch (Component.
getKind()) {
3275 Out <<
" [deleted]";
3277 ThunkInfo Thunk = VTableThunks.lookup(I);
3288 Out <<
"() [scalar deleting]";
3293 ThunkInfo Thunk = VTableThunks.lookup(I);
3296 "No return adjustment needed for destructors!");
3307 "Unexpected vftable component type %0 for component number %1");
3317 if (!Thunks.empty()) {
3319 std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls;
3321 for (
const auto &I : Thunks) {
3326 MethodNamesAndDecls.insert(std::make_pair(MethodName, MD));
3329 for (
const auto &MethodNameAndDecl : MethodNamesAndDecls) {
3330 const std::string &MethodName = MethodNameAndDecl.first;
3333 ThunkInfoVectorTy ThunksVector = Thunks[MD];
3334 llvm::stable_sort(ThunksVector, [](
const ThunkInfo &LHS,
3341 Out <<
"Thunks for '" << MethodName <<
"' (" << ThunksVector.size();
3342 Out << (ThunksVector.size() == 1 ?
" entry" :
" entries") <<
").\n";
3344 for (
unsigned I = 0,
E = ThunksVector.size(); I !=
E; ++I) {
3345 const ThunkInfo &Thunk = ThunksVector[I];
3347 Out << llvm::format(
"%4d | ", I);
3391void MicrosoftVTableContext::computeVTablePaths(
bool ForVBTables,
3394 assert(Paths.empty());
3399 Paths.push_back(std::make_unique<VPtrInfo>(RD));
3404 for (
const auto &B : RD->
bases()) {
3406 if (B.isVirtual() && VBasesSeen.count(
Base))
3409 if (!
Base->isDynamicClass())
3415 for (
const std::unique_ptr<VPtrInfo> &BaseInfo : BasePaths) {
3422 auto P = std::make_unique<VPtrInfo>(*BaseInfo);
3426 if (
P->MangledPath.empty() ||
P->MangledPath.back() !=
Base)
3427 P->NextBaseToMangle =
Base;
3432 if (
P->ObjectWithVPtr ==
Base &&
3435 P->ObjectWithVPtr = RD;
3440 P->ContainingVBases.push_back(
Base);
3441 else if (
P->ContainingVBases.empty())
3445 P->FullOffsetInMDC =
P->NonVirtualOffset;
3449 Paths.push_back(std::move(
P));
3453 VBasesSeen.insert(
Base);
3457 for (
const auto &VB :
Base->vbases())
3458 VBasesSeen.insert(VB.getType()->getAsCXXRecordDecl());
3469 if (
P.NextBaseToMangle) {
3470 P.MangledPath.push_back(
P.NextBaseToMangle);
3471 P.NextBaseToMangle =
nullptr;
3485 llvm::make_pointee_range(Paths));
3489 bool Changed =
false;
3490 for (
size_t I = 0,
E = PathsSorted.size(); I !=
E;) {
3492 size_t BucketStart = I;
3496 PathsSorted[BucketStart].get().MangledPath ==
3497 PathsSorted[I].get().MangledPath);
3500 if (I - BucketStart > 1) {
3501 for (
size_t II = BucketStart; II != I; ++II)
3503 assert(Changed &&
"no paths were extended to fix ambiguity");
3512typedef llvm::SetVector<BaseSubobject, std::vector<BaseSubobject>,
3513 llvm::DenseSet<BaseSubobject>> FullPathTy;
3522 FullPathTy &FullPath,
3523 std::list<FullPathTy> &Paths) {
3525 Paths.push_back(FullPath);
3538 IntroducingObject, FullPath, Paths);
3539 FullPath.pop_back();
3545 FullPaths.remove_if([&](
const FullPathTy &SpecificPath) {
3546 for (
const FullPathTy &OtherPath : FullPaths) {
3547 if (&SpecificPath == &OtherPath)
3549 if (llvm::all_of(SpecificPath, [&](
const BaseSubobject &BSO) {
3550 return OtherPath.contains(BSO);
3561 const FullPathTy &FullPath) {
3569 assert(Offset.getQuantity() == -1);
3573 assert(Offset.getQuantity() != -1);
3579 return BS.getType()->getAsCXXRecordDecl() == Base;
3594 std::list<FullPathTy> &FullPaths) {
3596 if (FullPaths.empty())
3598 if (FullPaths.size() == 1)
3599 return &FullPaths.front();
3601 const FullPathTy *BestPath =
nullptr;
3602 typedef std::set<const CXXMethodDecl *> OverriderSetTy;
3603 OverriderSetTy LastOverrides;
3604 for (
const FullPathTy &SpecificPath : FullPaths) {
3605 assert(!SpecificPath.empty());
3606 OverriderSetTy CurrentOverrides;
3607 const CXXRecordDecl *TopLevelRD = SpecificPath.begin()->getBase();
3612 FinalOverriders Overriders(TopLevelRD,
CharUnits::Zero(), TopLevelRD);
3616 FinalOverriders::OverriderInfo OI =
3621 if (ComputeReturnAdjustmentBaseOffset(Context, OverridingMethod, MD)
3627 if (llvm::none_of(SpecificPath, [&](
const BaseSubobject &BSO) {
3628 return BSO.
getBase() == OverridingParent;
3631 CurrentOverrides.insert(OverridingMethod);
3633 OverriderSetTy NewOverrides =
3634 llvm::set_difference(CurrentOverrides, LastOverrides);
3635 if (NewOverrides.empty())
3637 OverriderSetTy MissingOverrides =
3638 llvm::set_difference(LastOverrides, CurrentOverrides);
3639 if (MissingOverrides.empty()) {
3641 BestPath = &SpecificPath;
3642 std::swap(CurrentOverrides, LastOverrides);
3647 const CXXMethodDecl *ConflictMD = *MissingOverrides.begin();
3658 return BestPath ? BestPath : &FullPaths.front();
3665 FullPathTy FullPath;
3666 std::list<FullPathTy> FullPaths;
3667 for (
const std::unique_ptr<VPtrInfo>& Info : Paths) {
3670 BaseSubobject(Info->IntroducingObject, Info->FullOffsetInMDC), FullPath,
3674 Info->PathToIntroducingObject.clear();
3675 if (
const FullPathTy *BestPath =
3678 Info->PathToIntroducingObject.push_back(BSO.getBase());
3695void MicrosoftVTableContext::computeVTableRelatedInformation(
3700 if (VFPtrLocations.count(RD))
3706 auto VFPtrs = std::make_unique<VPtrInfoVector>();
3707 computeVTablePaths(
false, RD, *VFPtrs);
3709 VFPtrLocations[RD] = std::move(VFPtrs);
3712 MethodVFTableLocationsTy NewMethodLocations;
3713 for (
const std::unique_ptr<VPtrInfo> &VFPtr : *VFPtrLocations[RD]) {
3714 VFTableBuilder Builder(*
this, RD, *VFPtr);
3716 VFTableIdTy id(RD, VFPtr->FullOffsetInMDC);
3717 assert(VFTableLayouts.count(
id) == 0);
3719 Builder.vtable_thunks_begin(), Builder.vtable_thunks_end());
3720 VFTableLayouts[id] = std::make_unique<VTableLayout>(
3722 EmptyAddressPointsMap);
3723 Thunks.insert(Builder.thunks_begin(), Builder.thunks_end());
3726 for (
const auto &
Loc : Builder.vtable_locations()) {
3727 auto Insert = NewMethodLocations.insert(
Loc);
3737 MethodVFTableLocations.insert(NewMethodLocations.begin(),
3738 NewMethodLocations.end());
3740 dumpMethodLocations(RD, NewMethodLocations, llvm::outs());
3743void MicrosoftVTableContext::dumpMethodLocations(
3744 const CXXRecordDecl *RD,
const MethodVFTableLocationsTy &NewMethods,
3748 std::map<MethodVFTableLocation, std::string> IndicesMap;
3749 bool HasNonzeroOffset =
false;
3751 for (
const auto &I : NewMethods) {
3752 const CXXMethodDecl *MD = cast<const CXXMethodDecl>(I.first.getDecl());
3758 if (isa<CXXDestructorDecl>(MD)) {
3759 IndicesMap[I.second] = MethodName +
" [scalar deleting]";
3761 IndicesMap[I.second] = MethodName;
3764 if (!I.second.VFPtrOffset.isZero() || I.second.VBTableIndex != 0)
3765 HasNonzeroOffset =
true;
3769 if (!IndicesMap.empty()) {
3770 Out <<
"VFTable indices for ";
3773 Out <<
"' (" << IndicesMap.size()
3774 << (IndicesMap.size() == 1 ?
" entry" :
" entries") <<
").\n";
3778 for (
const auto &I : IndicesMap) {
3779 CharUnits VFPtrOffset = I.first.VFPtrOffset;
3780 uint64_t VBIndex = I.first.VBTableIndex;
3781 if (HasNonzeroOffset &&
3782 (VFPtrOffset != LastVFPtrOffset || VBIndex != LastVBIndex)) {
3783 assert(VBIndex > LastVBIndex || VFPtrOffset > LastVFPtrOffset);
3784 Out <<
" -- accessible via ";
3786 Out <<
"vbtable index " << VBIndex <<
", ";
3787 Out <<
"vfptr at offset " << VFPtrOffset.
getQuantity() <<
" --\n";
3788 LastVFPtrOffset = VFPtrOffset;
3789 LastVBIndex = VBIndex;
3792 uint64_t VTableIndex = I.first.Index;
3793 const std::string &MethodName = I.second;
3794 Out << llvm::format(
"%4" PRIu64
" | ", VTableIndex) << MethodName <<
'\n';
3802const VirtualBaseInfo &MicrosoftVTableContext::computeVBTableRelatedInformation(
3809 std::unique_ptr<VirtualBaseInfo> &Entry = VBaseInfo[RD];
3812 Entry = std::make_unique<VirtualBaseInfo>();
3816 computeVTablePaths(
true, RD, VBI->
VBPtrPaths);
3824 computeVBTableRelatedInformation(VBPtrBase);
3832 for (
const auto &VB : RD->
vbases()) {
3833 const CXXRecordDecl *CurVBase = VB.getType()->getAsCXXRecordDecl();
3843 const VirtualBaseInfo &VBInfo = computeVBTableRelatedInformation(Derived);
3850 return computeVBTableRelatedInformation(RD).
VBPtrPaths;
3855 computeVTableRelatedInformation(RD);
3857 assert(VFPtrLocations.count(RD) &&
"Couldn't find vfptr locations");
3858 return *VFPtrLocations[RD];
3864 computeVTableRelatedInformation(RD);
3866 VFTableIdTy id(RD, VFPtrOffset);
3867 assert(VFTableLayouts.count(
id) &&
"Couldn't find a VFTable at this offset");
3868 return *VFTableLayouts[id];
3874 "Only use this method for virtual methods or dtors");
3875 if (isa<CXXDestructorDecl>(GD.
getDecl()))
3880 MethodVFTableLocationsTy::iterator I = MethodVFTableLocations.find(GD);
3881 if (I != MethodVFTableLocations.end())
3886 computeVTableRelatedInformation(RD);
3888 I = MethodVFTableLocations.find(GD);
3889 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)
static QualType getPointeeType(const MemRegion *R)
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.
QualType getThisType() const
Return the type of the this pointer.
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 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.
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
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)
GlobalDecl findOriginalMethod(GlobalDecl GD)
Return the method that added the v-table slot that will be used to call the given method.
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.
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)
The JSON file list parser is used to communicate input to InstallAPI.
@ Dtor_Complete
Complete object dtor.
@ Dtor_Deleting
Deleting dtor.
const FunctionProtoType * T
@ 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 * 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...
uint32_t VBPtrOffset
The offset (in bytes) of the vbptr, relative to the beginning of the derived class.
int64_t VBaseOffsetOffset
The offset (in bytes), relative to the address point of the virtual base class offset.
struct clang::ReturnAdjustment::VirtualAdjustment::@189 Itanium
uint32_t VBIndex
Index of the virtual base in the vbtable.
struct clang::ReturnAdjustment::VirtualAdjustment::@190 Microsoft
int32_t VtordispOffset
The offset of the vtordisp (in bytes), relative to the ECX.
struct clang::ThisAdjustment::VirtualAdjustment::@192 Microsoft
int32_t VBOffsetOffset
The offset (in bytes) of the vbase offset in the vbtable.
struct clang::ThisAdjustment::VirtualAdjustment::@191 Itanium
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...