19#include "llvm/ADT/SetOperations.h"
20#include "llvm/ADT/SetVector.h"
21#include "llvm/ADT/SmallPtrSet.h"
22#include "llvm/Support/Format.h"
23#include "llvm/Support/raw_ostream.h"
29#define DUMP_OVERRIDERS 0
50 BaseOffset() : DerivedClass(
nullptr),
VirtualBase(
nullptr),
55 NonVirtualOffset(NonVirtualOffset) { }
62class FinalOverriders {
65 struct OverriderInfo {
102 typedef std::pair<const CXXMethodDecl *, CharUnits> MethodBaseOffsetPairTy;
104 typedef llvm::DenseMap<MethodBaseOffsetPairTy,
105 OverriderInfo> OverridersMapTy;
109 OverridersMapTy OverridersMap;
114 typedef llvm::DenseMap<std::pair<const CXXRecordDecl *, unsigned>,
117 typedef llvm::DenseMap<const CXXRecordDecl *, unsigned> SubobjectCountMapTy;
123 SubobjectOffsetMapTy &SubobjectOffsets,
124 SubobjectOffsetMapTy &SubobjectLayoutClassOffsets,
125 SubobjectCountMapTy &SubobjectCounts);
132 VisitedVirtualBasesSetTy& VisitedVirtualBases);
143 assert(OverridersMap.count(std::make_pair(MD, BaseOffset)) &&
144 "Did not find overrider!");
146 return OverridersMap.lookup(std::make_pair(MD, BaseOffset));
151 VisitedVirtualBasesSetTy VisitedVirtualBases;
153 VisitedVirtualBases);
158FinalOverriders::FinalOverriders(
const CXXRecordDecl *MostDerivedClass,
161 : MostDerivedClass(MostDerivedClass),
162 MostDerivedClassOffset(MostDerivedClassOffset), LayoutClass(LayoutClass),
164 MostDerivedClassLayout(Context.getASTRecordLayout(MostDerivedClass)) {
167 SubobjectOffsetMapTy SubobjectOffsets;
168 SubobjectOffsetMapTy SubobjectLayoutClassOffsets;
169 SubobjectCountMapTy SubobjectCounts;
172 MostDerivedClassOffset,
173 SubobjectOffsets, SubobjectLayoutClassOffsets,
180 for (
const auto &Overrider : FinalOverriders) {
184 for (
const auto &M : Methods) {
185 unsigned SubobjectNumber = M.first;
186 assert(SubobjectOffsets.count(std::make_pair(MD->
getParent(),
188 "Did not find subobject offset!");
193 assert(M.second.size() == 1 &&
"Final overrider is not unique!");
197 assert(SubobjectLayoutClassOffsets.count(
198 std::make_pair(OverriderRD, Method.Subobject))
199 &&
"Did not find subobject offset!");
201 SubobjectLayoutClassOffsets[std::make_pair(OverriderRD,
204 OverriderInfo& Overrider = OverridersMap[std::make_pair(MD, BaseOffset)];
205 assert(!Overrider.Method &&
"Overrider should not exist yet!");
207 Overrider.Offset = OverriderOffset;
208 Overrider.Method = Method.Method;
209 Overrider.VirtualBase = Method.InVirtualSubobject;
219static BaseOffset ComputeBaseOffset(
const ASTContext &Context,
224 unsigned NonVirtualStart = 0;
228 for (
int I = Path.size(), E = 0; I != E; --I) {
240 for (
unsigned I = NonVirtualStart, E = Path.size(); I != E; ++I) {
254 return BaseOffset(DerivedRD,
VirtualBase, NonVirtualOffset);
258static BaseOffset ComputeBaseOffset(
const ASTContext &Context,
265 llvm_unreachable(
"Class must be derived from the passed in base class!");
267 return ComputeBaseOffset(Context, DerivedRD, Paths.
front());
271ComputeReturnAdjustmentBaseOffset(
ASTContext &Context,
281 Context.getCanonicalType(BaseFT->getReturnType());
283 assert(CanDerivedReturnType->getTypeClass() ==
284 CanBaseReturnType->getTypeClass() &&
285 "Types must have same type class!");
287 if (CanDerivedReturnType == CanBaseReturnType) {
293 CanDerivedReturnType =
298 CanDerivedReturnType =
303 llvm_unreachable(
"Unexpected return type!");
309 if (CanDerivedReturnType.getUnqualifiedType() ==
315 const auto *DerivedRD =
317 ->getDefinitionOrSelf();
322 return ComputeBaseOffset(Context, BaseRD, DerivedRD);
328 SubobjectOffsetMapTy &SubobjectOffsets,
329 SubobjectOffsetMapTy &SubobjectLayoutClassOffsets,
330 SubobjectCountMapTy &SubobjectCounts) {
333 unsigned SubobjectNumber = 0;
335 SubobjectNumber = ++SubobjectCounts[RD];
338 assert(!SubobjectOffsets.count(std::make_pair(RD, SubobjectNumber))
339 &&
"Subobject offset already exists!");
340 assert(!SubobjectLayoutClassOffsets.count(std::make_pair(RD, SubobjectNumber))
341 &&
"Subobject offset already exists!");
343 SubobjectOffsets[std::make_pair(RD, SubobjectNumber)] =
Base.getBaseOffset();
344 SubobjectLayoutClassOffsets[std::make_pair(RD, SubobjectNumber)] =
348 for (
const auto &B : RD->
bases()) {
349 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
355 if (SubobjectOffsets.count(std::make_pair(BaseDecl, 0)))
359 Context.getASTRecordLayout(LayoutClass);
362 BaseOffsetInLayoutClass =
368 BaseOffset =
Base.getBaseOffset() + Offset;
369 BaseOffsetInLayoutClass = OffsetInLayoutClass + Offset;
373 B.isVirtual(), BaseOffsetInLayoutClass,
374 SubobjectOffsets, SubobjectLayoutClassOffsets,
380 VisitedVirtualBasesSetTy &VisitedVirtualBases) {
384 for (
const auto &B : RD->
bases()) {
385 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
393 if (!VisitedVirtualBases.insert(BaseDecl).second) {
406 Out <<
"Final overriders for (";
409 Out <<
Base.getBaseOffset().getQuantity() <<
")\n";
412 for (
const auto *MD : RD->
methods()) {
415 MD = MD->getCanonicalDecl();
417 OverriderInfo Overrider = getOverrider(MD,
Base.getBaseOffset());
420 MD->printQualifiedName(Out);
422 Overrider.Method->printQualifiedName(Out);
423 Out <<
", " << Overrider.Offset.getQuantity() <<
')';
426 if (!Overrider.Method->isPureVirtual())
427 Offset = ComputeReturnAdjustmentBaseOffset(Context, Overrider.Method, MD);
429 if (!Offset.isEmpty()) {
430 Out <<
" [ret-adj: ";
431 if (Offset.VirtualBase) {
432 Offset.VirtualBase->printQualifiedName(Out);
436 Out << Offset.NonVirtualOffset.getQuantity() <<
" nv]";
444struct VCallOffsetMap {
446 typedef std::pair<const CXXMethodDecl *, CharUnits> MethodAndOffsetPairTy;
454 static bool MethodsCanShareVCallOffset(
const CXXMethodDecl *LHS,
468 bool empty()
const {
return Offsets.empty(); }
479 if (LT == RT)
return true;
489bool VCallOffsetMap::MethodsCanShareVCallOffset(
const CXXMethodDecl *LHS,
503 if (LHSName != RHSName)
507 return HasSameVirtualSignature(LHS, RHS);
513 for (
const auto &OffsetPair : Offsets) {
514 if (MethodsCanShareVCallOffset(OffsetPair.first, MD))
519 Offsets.push_back(MethodAndOffsetPairTy(MD, OffsetOffset));
525 for (
const auto &OffsetPair : Offsets) {
526 if (MethodsCanShareVCallOffset(OffsetPair.first, MD))
527 return OffsetPair.second;
530 llvm_unreachable(
"Should always find a vcall offset offset!");
534class VCallAndVBaseOffsetBuilder {
536 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits>
537 VBaseOffsetOffsetsMapTy;
554 VTableComponentVectorTy Components;
560 VCallOffsetMap VCallOffsets;
565 VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
569 const FinalOverriders *Overriders;
585 CharUnits getCurrentOffsetOffset()
const;
588 VCallAndVBaseOffsetBuilder(
const CXXRecordDecl *MostDerivedClass,
590 const FinalOverriders *Overriders,
593 : MostDerivedClass(MostDerivedClass), LayoutClass(LayoutClass),
594 Context(MostDerivedClass->
getASTContext()), Overriders(Overriders) {
597 AddVCallAndVBaseOffsets(
Base, BaseIsVirtual, OffsetInLayoutClass);
601 typedef VTableComponentVectorTy::const_reverse_iterator
const_iterator;
602 const_iterator components_begin()
const {
return Components.rbegin(); }
603 const_iterator components_end()
const {
return Components.rend(); }
605 const VCallOffsetMap &getVCallOffsets()
const {
return VCallOffsets; }
606 const VBaseOffsetOffsetsMapTy &getVBaseOffsetOffsets()
const {
607 return VBaseOffsetOffsets;
632 if (PrimaryBaseIsVirtual) {
634 "Primary vbase should have a zero offset!");
637 Context.getASTRecordLayout(MostDerivedClass);
643 "Primary base should have a zero offset!");
645 PrimaryBaseOffset =
Base.getBaseOffset();
648 AddVCallAndVBaseOffsets(
650 PrimaryBaseIsVirtual, RealBaseOffset);
653 AddVBaseOffsets(
Base.getBase(), RealBaseOffset);
657 AddVCallOffsets(
Base, RealBaseOffset);
660CharUnits VCallAndVBaseOffsetBuilder::getCurrentOffsetOffset()
const {
665 size_t NumComponentsAboveAddrPoint = 3;
666 if (Context.getLangOpts().OmitVTableRTTI)
667 NumComponentsAboveAddrPoint--;
668 int64_t OffsetIndex =
669 -(int64_t)(NumComponentsAboveAddrPoint + Components.size());
673 CharUnits OffsetWidth = Context.toCharUnitsFromBits(
674 Context.getLangOpts().RelativeCXXABIVTables
677 CharUnits OffsetOffset = OffsetWidth * OffsetIndex;
695 "Primary base should have a zero offset!");
702 for (
const auto *MD : RD->
methods()) {
707 CharUnits OffsetOffset = getCurrentOffsetOffset();
711 if (!VCallOffsets.AddVCallOffset(MD, OffsetOffset))
718 FinalOverriders::OverriderInfo Overrider =
719 Overriders->getOverrider(MD,
Base.getBaseOffset());
723 Offset = Overrider.Offset - VBaseOffset;
726 Components.push_back(
731 for (
const auto &B : RD->
bases()) {
735 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
736 if (BaseDecl == PrimaryBase)
749VCallAndVBaseOffsetBuilder::AddVBaseOffsets(
const CXXRecordDecl *RD,
752 Context.getASTRecordLayout(LayoutClass);
755 for (
const auto &B : RD->
bases()) {
756 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
759 if (B.isVirtual() && VisitedVirtualBases.insert(BaseDecl).second) {
764 assert(!VBaseOffsetOffsets.count(BaseDecl) &&
765 "vbase offset offset already exists!");
767 CharUnits VBaseOffsetOffset = getCurrentOffsetOffset();
768 VBaseOffsetOffsets.insert(
769 std::make_pair(BaseDecl, VBaseOffsetOffset));
771 Components.push_back(
776 AddVBaseOffsets(BaseDecl, OffsetInLayoutClass);
781class ItaniumVTableBuilder {
786 PrimaryBasesSetVectorTy;
788 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits>
789 VBaseOffsetOffsetsMapTy;
793 typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVTableIndicesTy;
809 bool MostDerivedClassIsVirtual;
820 const FinalOverriders Overriders;
824 llvm::DenseMap<const CXXRecordDecl *, VCallOffsetMap> VCallOffsetsForVBases;
828 VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
834 AddressPointsMapTy AddressPoints;
848 const uint64_t VTableIndex;
851 uint64_t VTableIndex)
852 : BaseOffset(BaseOffset),
853 BaseOffsetInLayoutClass(BaseOffsetInLayoutClass),
854 VTableIndex(VTableIndex) { }
861 MethodInfo(MethodInfo
const&) =
default;
864 typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy;
868 MethodInfoMapTy MethodInfoMap;
872 MethodVTableIndicesTy MethodVTableIndices;
874 typedef llvm::DenseMap<uint64_t, ThunkInfo> VTableThunksMapTy;
878 VTableThunksMapTy VTableThunks;
881 typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
892 void ComputeThisAdjustments();
898 VisitedVirtualBasesSetTy PrimaryVirtualBases;
915 FinalOverriders::OverriderInfo Overrider);
943 CharUnits FirstBaseOffsetInLayoutClass)
const;
951 PrimaryBasesSetVectorTy &PrimaryBases);
966 bool BaseIsMorallyVirtual,
967 bool BaseIsVirtualInLayoutClass,
982 VisitedVirtualBasesSetTy &VBases);
987 VisitedVirtualBasesSetTy &VBases);
991 bool isBuildingConstructorVTable()
const {
992 return MostDerivedClass != LayoutClass;
1003 bool MostDerivedClassIsVirtual,
1005 : VTables(VTables), MostDerivedClass(MostDerivedClass),
1006 MostDerivedClassOffset(MostDerivedClassOffset),
1007 MostDerivedClassIsVirtual(MostDerivedClassIsVirtual),
1008 LayoutClass(LayoutClass), Context(MostDerivedClass->
getASTContext()),
1009 Overriders(MostDerivedClass, MostDerivedClassOffset, LayoutClass) {
1010 assert(!Context.getTargetInfo().getCXXABI().isMicrosoft());
1014 if (Context.getLangOpts().DumpVTableLayouts)
1015 dumpLayout(llvm::outs());
1018 uint64_t getNumThunks()
const {
1019 return Thunks.size();
1022 ThunksMapTy::const_iterator thunks_begin()
const {
1023 return Thunks.begin();
1026 ThunksMapTy::const_iterator thunks_end()
const {
1027 return Thunks.end();
1030 const VBaseOffsetOffsetsMapTy &getVBaseOffsetOffsets()
const {
1031 return VBaseOffsetOffsets;
1034 const AddressPointsMapTy &getAddressPoints()
const {
1035 return AddressPoints;
1038 MethodVTableIndicesTy::const_iterator vtable_indices_begin()
const {
1039 return MethodVTableIndices.begin();
1042 MethodVTableIndicesTy::const_iterator vtable_indices_end()
const {
1043 return MethodVTableIndices.end();
1048 AddressPointsMapTy::const_iterator address_points_begin()
const {
1049 return AddressPoints.begin();
1052 AddressPointsMapTy::const_iterator address_points_end()
const {
1053 return AddressPoints.end();
1056 VTableThunksMapTy::const_iterator vtable_thunks_begin()
const {
1057 return VTableThunks.begin();
1060 VTableThunksMapTy::const_iterator vtable_thunks_end()
const {
1061 return VTableThunks.end();
1065 void dumpLayout(raw_ostream&);
1070 assert(!isBuildingConstructorVTable() &&
1071 "Can't add thunks for construction vtable");
1076 if (llvm::is_contained(ThunksVector, Thunk))
1079 ThunksVector.push_back(Thunk);
1088template <
class VisitorTy>
1090visitAllOverriddenMethods(
const CXXMethodDecl *MD, VisitorTy &Visitor) {
1094 if (!Visitor(OverriddenMD))
1096 visitAllOverriddenMethods(OverriddenMD, Visitor);
1104 OverriddenMethodsSetTy& OverriddenMethods) {
1105 auto OverriddenMethodsCollector = [&](
const CXXMethodDecl *MD) {
1107 return OverriddenMethods.insert(MD).second;
1109 visitAllOverriddenMethods(MD, OverriddenMethodsCollector);
1112void ItaniumVTableBuilder::ComputeThisAdjustments() {
1115 for (
const auto &MI : MethodInfoMap) {
1117 const MethodInfo &MethodInfo = MI.second;
1120 uint64_t VTableIndex = MethodInfo.VTableIndex;
1121 if (Components[VTableIndex].
getKind() ==
1126 FinalOverriders::OverriderInfo Overrider =
1127 Overriders.getOverrider(MD, MethodInfo.BaseOffset);
1130 if (MethodInfo.BaseOffsetInLayoutClass == Overrider.Offset) {
1136 if (VTableThunks.lookup(VTableIndex).Return.isEmpty())
1141 ComputeThisAdjustment(MD, MethodInfo.BaseOffsetInLayoutClass, Overrider);
1147 auto SetThisAdjustmentThunk = [&](uint64_t Idx) {
1169 auto [It, Inserted] = VTableThunks.try_emplace(Idx);
1172 It->second.Method = Method;
1178 SetThisAdjustmentThunk(VTableIndex);
1182 SetThisAdjustmentThunk(VTableIndex + 1);
1187 MethodInfoMap.clear();
1189 if (isBuildingConstructorVTable()) {
1194 for (
const auto &TI : VTableThunks) {
1199 switch (Component.
getKind()) {
1201 llvm_unreachable(
"Unexpected vtable component kind!");
1213 if (MD->
getParent() == MostDerivedClass)
1214 AddThunk(MD, Thunk);
1219ItaniumVTableBuilder::ComputeReturnAdjustment(BaseOffset Offset) {
1222 if (!Offset.isEmpty()) {
1223 if (Offset.VirtualBase) {
1225 if (Offset.DerivedClass == MostDerivedClass) {
1228 VBaseOffsetOffsets.lookup(Offset.VirtualBase).getQuantity();
1236 Adjustment.
NonVirtual = Offset.NonVirtualOffset.getQuantity();
1242BaseOffset ItaniumVTableBuilder::ComputeThisAdjustmentBaseOffset(
1251 llvm_unreachable(
"Class must be derived from the passed in base class!");
1256 BaseOffset Offset = ComputeBaseOffset(Context, DerivedRD, Path);
1258 CharUnits OffsetToBaseSubobject = Offset.NonVirtualOffset;
1260 if (Offset.VirtualBase) {
1264 Context.getASTRecordLayout(LayoutClass);
1268 OffsetToBaseSubobject +=
1277 if (OffsetToBaseSubobject ==
Base.getBaseOffset()) {
1280 Offset.NonVirtualOffset = -Offset.NonVirtualOffset;
1285 return BaseOffset();
1290 FinalOverriders::OverriderInfo Overrider) {
1296 BaseOffsetInLayoutClass);
1302 BaseOffset Offset = ComputeThisAdjustmentBaseOffset(OverriddenBaseSubobject,
1303 OverriderBaseSubobject);
1304 if (Offset.isEmpty())
1309 if (Offset.VirtualBase) {
1311 VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[Offset.VirtualBase];
1313 if (VCallOffsets.empty()) {
1316 VCallAndVBaseOffsetBuilder Builder(
1317 MostDerivedClass, MostDerivedClass,
1324 VCallOffsets = Builder.getVCallOffsets();
1328 VCallOffsets.getVCallOffsetOffset(MD).getQuantity();
1332 Adjustment.
NonVirtual = Offset.NonVirtualOffset.getQuantity();
1337void ItaniumVTableBuilder::AddMethod(
const CXXMethodDecl *MD,
1341 "Destructor can't have return adjustment!");
1367static bool OverridesIndirectMethodInBases(
1369 ItaniumVTableBuilder::PrimaryBasesSetVectorTy &Bases) {
1375 if (OverridesIndirectMethodInBases(OverriddenMD, Bases))
1382bool ItaniumVTableBuilder::IsOverriderUsed(
1385 CharUnits FirstBaseOffsetInLayoutClass)
const {
1388 if (BaseOffsetInLayoutClass == FirstBaseOffsetInLayoutClass)
1397 if (Overrider->getParent() == FirstBaseInPrimaryBaseChain)
1400 ItaniumVTableBuilder::PrimaryBasesSetVectorTy PrimaryBases;
1403 PrimaryBases.insert(RD);
1416 "Primary base should always be at offset 0!");
1419 Context.getASTRecordLayout(LayoutClass);
1424 FirstBaseOffsetInLayoutClass) {
1430 "Primary base should always be at offset 0!");
1433 if (!PrimaryBases.insert(PrimaryBase))
1434 llvm_unreachable(
"Found a duplicate primary base!");
1441 return OverridesIndirectMethodInBases(Overrider, PrimaryBases);
1451 BasesSetVectorTy &Bases) {
1452 OverriddenMethodsSetTy OverriddenMethods;
1453 ComputeAllOverriddenMethods(MD, OverriddenMethods);
1455 for (
const CXXRecordDecl *PrimaryBase : llvm::reverse(Bases)) {
1457 for (
const CXXMethodDecl *OverriddenMD : OverriddenMethods) {
1459 if (OverriddenMD->getParent() == PrimaryBase)
1460 return OverriddenMD;
1467void ItaniumVTableBuilder::AddMethods(
1471 PrimaryBasesSetVectorTy &PrimaryBases) {
1486 CharUnits PrimaryBaseOffsetInLayoutClass;
1489 "Primary vbase should have a zero offset!");
1492 Context.getASTRecordLayout(MostDerivedClass);
1498 Context.getASTRecordLayout(LayoutClass);
1500 PrimaryBaseOffsetInLayoutClass =
1504 "Primary base should have a zero offset!");
1506 PrimaryBaseOffset =
Base.getBaseOffset();
1507 PrimaryBaseOffsetInLayoutClass = BaseOffsetInLayoutClass;
1511 PrimaryBaseOffsetInLayoutClass, FirstBaseInPrimaryBaseChain,
1512 FirstBaseOffsetInLayoutClass, PrimaryBases);
1514 if (!PrimaryBases.insert(PrimaryBase))
1515 llvm_unreachable(
"Found a duplicate primary base!");
1519 NewVirtualFunctionsTy NewVirtualFunctions;
1524 for (
const auto *MD : RD->
methods()) {
1530 FinalOverriders::OverriderInfo Overrider =
1531 Overriders.getOverrider(MD,
Base.getBaseOffset());
1537 FindNearestOverriddenMethod(MD, PrimaryBases)) {
1538 if (ComputeReturnAdjustmentBaseOffset(Context, MD,
1539 OverriddenMD).isEmpty()) {
1544 assert(MethodInfoMap.count(OverriddenMD) &&
1545 "Did not find the overridden method!");
1546 MethodInfo &OverriddenMethodInfo = MethodInfoMap[OverriddenMD];
1548 MethodInfo MethodInfo(
Base.getBaseOffset(), BaseOffsetInLayoutClass,
1549 OverriddenMethodInfo.VTableIndex);
1551 assert(!MethodInfoMap.count(MD) &&
1552 "Should not have method info for this method yet!");
1554 MethodInfoMap.insert(std::make_pair(MD, MethodInfo));
1555 MethodInfoMap.erase(OverriddenMD);
1561 if (!isBuildingConstructorVTable() && OverriddenMD != MD) {
1564 ComputeThisAdjustment(OverriddenMD, BaseOffsetInLayoutClass,
1568 Overrider.Method->
getParent() == MostDerivedClass) {
1573 BaseOffset ReturnAdjustmentOffset =
1574 ComputeReturnAdjustmentBaseOffset(Context, Overrider.Method, MD);
1576 ComputeReturnAdjustment(ReturnAdjustmentOffset);
1579 AddThunk(Overrider.Method,
1581 OverriddenMD->getThisType().getTypePtr()));
1590 NewImplicitVirtualFunctions.push_back(MD);
1592 NewVirtualFunctions.push_back(MD);
1596 NewImplicitVirtualFunctions,
1608 "unexpected or duplicate implicit virtual function");
1613 NewVirtualFunctions.append(NewImplicitVirtualFunctions.begin(),
1614 NewImplicitVirtualFunctions.end());
1618 FinalOverriders::OverriderInfo Overrider =
1619 Overriders.getOverrider(MD,
Base.getBaseOffset());
1622 MethodInfo MethodInfo(
Base.getBaseOffset(), BaseOffsetInLayoutClass,
1625 assert(!MethodInfoMap.count(MD) &&
1626 "Should not have method info for this method yet!");
1627 MethodInfoMap.insert(std::make_pair(MD, MethodInfo));
1631 if (!IsOverriderUsed(OverriderMD, BaseOffsetInLayoutClass,
1632 FirstBaseInPrimaryBaseChain,
1633 FirstBaseOffsetInLayoutClass)) {
1640 BaseOffset ReturnAdjustmentOffset;
1642 ReturnAdjustmentOffset =
1643 ComputeReturnAdjustmentBaseOffset(Context, OverriderMD, MD);
1647 ComputeReturnAdjustment(ReturnAdjustmentOffset);
1654 auto &VTT = VTableThunks[Components.size()];
1663void ItaniumVTableBuilder::LayoutVTable() {
1664 LayoutPrimaryAndSecondaryVTables(
BaseSubobject(MostDerivedClass,
1667 MostDerivedClassIsVirtual,
1668 MostDerivedClassOffset);
1670 VisitedVirtualBasesSetTy VBases;
1673 DeterminePrimaryVirtualBases(MostDerivedClass, MostDerivedClassOffset,
1677 LayoutVTablesForVirtualBases(MostDerivedClass, VBases);
1680 bool IsAppleKext = Context.getLangOpts().AppleKext;
1685void ItaniumVTableBuilder::LayoutPrimaryAndSecondaryVTables(
1687 bool BaseIsVirtualInLayoutClass,
CharUnits OffsetInLayoutClass) {
1688 assert(
Base.getBase()->isDynamicClass() &&
"class does not have a vtable!");
1690 unsigned VTableIndex = Components.size();
1691 VTableIndices.push_back(VTableIndex);
1694 VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, LayoutClass, &Overriders,
1695 Base, BaseIsVirtualInLayoutClass,
1696 OffsetInLayoutClass);
1697 Components.append(Builder.components_begin(), Builder.components_end());
1700 if (BaseIsVirtualInLayoutClass && !Builder.getVCallOffsets().empty()) {
1701 VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[
Base.getBase()];
1703 if (VCallOffsets.empty())
1704 VCallOffsets = Builder.getVCallOffsets();
1709 if (
Base.getBase() == MostDerivedClass)
1710 VBaseOffsetOffsets = Builder.getVBaseOffsetOffsets();
1713 CharUnits OffsetToTop = MostDerivedClassOffset - OffsetInLayoutClass;
1717 if (!Context.getLangOpts().OmitVTableRTTI)
1720 uint64_t AddressPoint = Components.size();
1723 PrimaryBasesSetVectorTy PrimaryBases;
1724 AddMethods(
Base, OffsetInLayoutClass,
1725 Base.getBase(), OffsetInLayoutClass,
1729 if (RD == MostDerivedClass) {
1730 assert(MethodVTableIndices.empty());
1731 for (
const auto &I : MethodInfoMap) {
1733 const MethodInfo &MI = I.second;
1736 = MI.VTableIndex - AddressPoint;
1738 = MI.VTableIndex + 1 - AddressPoint;
1740 MethodVTableIndices[MD] = MI.VTableIndex - AddressPoint;
1746 ComputeThisAdjustments();
1750 AddressPoints.insert(
1753 unsigned(VTableIndices.size() - 1),
1754 unsigned(AddressPoint - VTableIndex)}));
1766 Context.getASTRecordLayout(LayoutClass);
1769 OffsetInLayoutClass) {
1779 LayoutSecondaryVTables(
Base, BaseIsMorallyVirtual, OffsetInLayoutClass);
1784 bool BaseIsMorallyVirtual,
1795 for (
const auto &B : RD->
bases()) {
1800 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
1806 if (isBuildingConstructorVTable()) {
1812 if (!BaseIsMorallyVirtual && !BaseDecl->
getNumVBases())
1818 CharUnits BaseOffset =
Base.getBaseOffset() + RelativeBaseOffset;
1821 OffsetInLayoutClass + RelativeBaseOffset;
1825 if (BaseDecl == PrimaryBase) {
1827 BaseIsMorallyVirtual, BaseOffsetInLayoutClass);
1832 LayoutPrimaryAndSecondaryVTables(
1834 BaseIsMorallyVirtual,
1836 BaseOffsetInLayoutClass);
1840void ItaniumVTableBuilder::DeterminePrimaryVirtualBases(
1842 VisitedVirtualBasesSetTy &VBases) {
1850 bool IsPrimaryVirtualBase =
true;
1852 if (isBuildingConstructorVTable()) {
1856 Context.getASTRecordLayout(LayoutClass);
1858 CharUnits PrimaryBaseOffsetInLayoutClass =
1863 if (PrimaryBaseOffsetInLayoutClass != OffsetInLayoutClass)
1864 IsPrimaryVirtualBase =
false;
1867 if (IsPrimaryVirtualBase)
1868 PrimaryVirtualBases.insert(PrimaryBase);
1873 for (
const auto &B : RD->
bases()) {
1874 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
1878 if (B.isVirtual()) {
1879 if (!VBases.insert(BaseDecl).second)
1883 Context.getASTRecordLayout(LayoutClass);
1885 BaseOffsetInLayoutClass =
1888 BaseOffsetInLayoutClass =
1892 DeterminePrimaryVirtualBases(BaseDecl, BaseOffsetInLayoutClass, VBases);
1896void ItaniumVTableBuilder::LayoutVTablesForVirtualBases(
1897 const CXXRecordDecl *RD, VisitedVirtualBasesSetTy &VBases) {
1902 for (
const auto &B : RD->
bases()) {
1903 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
1908 !PrimaryVirtualBases.count(BaseDecl) &&
1909 VBases.insert(BaseDecl).second) {
1911 Context.getASTRecordLayout(MostDerivedClass);
1916 Context.getASTRecordLayout(LayoutClass);
1920 LayoutPrimaryAndSecondaryVTables(
1924 BaseOffsetInLayoutClass);
1930 LayoutVTablesForVirtualBases(BaseDecl, VBases);
1934static void printThunkMethod(
const ThunkInfo &Info, raw_ostream &Out) {
1939 Out <<
" method: " << Str;
1943void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
1947 Out <<
"Original map\n";
1956 Out <<
" " << Str0 <<
" -> " << Str1 <<
"\n";
1959 if (isBuildingConstructorVTable()) {
1960 Out <<
"Construction vtable for ('";
1963 Out << MostDerivedClassOffset.
getQuantity() <<
") in '";
1966 Out <<
"Vtable for '";
1969 Out <<
"' (" << Components.size() <<
" entries).\n";
1975 std::multimap<uint64_t, BaseSubobject> AddressPointsByIndex;
1976 for (
const auto &AP : AddressPoints) {
1979 VTableIndices[AP.second.VTableIndex] + AP.second.AddressPointIndex;
1981 AddressPointsByIndex.insert(std::make_pair(Index,
Base));
1984 for (
unsigned I = 0, E = Components.size(); I != E; ++I) {
1987 Out << llvm::format(
"%4d | ", I);
1992 switch (Component.
getKind()) {
1995 Out <<
"vcall_offset ("
2001 Out <<
"vbase_offset ("
2007 Out <<
"offset_to_top ("
2027 Out <<
" [deleted]";
2029 ThunkInfo Thunk = VTableThunks.lookup(I);
2033 Out <<
"\n [return adjustment: ";
2038 Out <<
" vbase offset offset";
2042 printThunkMethod(Thunk, Out);
2047 Out <<
"\n [this adjustment: ";
2052 Out <<
" vcall offset offset";
2056 printThunkMethod(Thunk, Out);
2072 Out <<
"() [complete]";
2074 Out <<
"() [deleting]";
2079 ThunkInfo Thunk = VTableThunks.lookup(I);
2083 Out <<
"\n [this adjustment: ";
2088 Out <<
" vcall offset offset";
2093 printThunkMethod(Thunk, Out);
2104 Out <<
"[unused] " << Str;
2114 uint64_t NextIndex = Index + 1;
2115 if (
unsigned Count = AddressPointsByIndex.count(NextIndex)) {
2118 AddressPointsByIndex.find(NextIndex)->second;
2121 Base.getBase()->printQualifiedName(Out);
2122 Out <<
", " <<
Base.getBaseOffset().getQuantity();
2123 Out <<
") vtable address --\n";
2126 AddressPointsByIndex.lower_bound(NextIndex)->second.getBaseOffset();
2129 std::set<std::string> ClassNames;
2130 for (
const auto &I :
2131 llvm::make_range(AddressPointsByIndex.equal_range(NextIndex))) {
2132 assert(I.second.getBaseOffset() == BaseOffset &&
2133 "Invalid base offset!");
2138 for (
const std::string &Name : ClassNames) {
2139 Out <<
" -- (" << Name;
2140 Out <<
", " << BaseOffset.getQuantity() <<
") vtable address --\n";
2148 if (isBuildingConstructorVTable())
2155 std::map<std::string, CharUnits> ClassNamesAndOffsets;
2156 for (
const auto &I : VBaseOffsetOffsets) {
2157 std::string ClassName = I.first->getQualifiedNameAsString();
2159 ClassNamesAndOffsets.insert(std::make_pair(ClassName, OffsetOffset));
2162 Out <<
"Virtual base offset offsets for '";
2165 Out << ClassNamesAndOffsets.size();
2166 Out << (ClassNamesAndOffsets.size() == 1 ?
" entry" :
" entries") <<
").\n";
2168 for (
const auto &I : ClassNamesAndOffsets)
2169 Out <<
" " << I.first <<
" | " << I.second.getQuantity() <<
'\n';
2174 if (!Thunks.empty()) {
2176 std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls;
2178 for (
const auto &I : Thunks) {
2183 MethodNamesAndDecls.insert(std::make_pair(MethodName, MD));
2186 for (
const auto &I : MethodNamesAndDecls) {
2187 const std::string &MethodName = I.first;
2190 ThunkInfoVectorTy ThunksVector = Thunks[MD];
2195 Out <<
"Thunks for '" << MethodName <<
"' (" << ThunksVector.size();
2196 Out << (ThunksVector.size() == 1 ?
" entry" :
" entries") <<
").\n";
2198 for (
unsigned I = 0, E = ThunksVector.size(); I != E; ++I) {
2199 const ThunkInfo &Thunk = ThunksVector[I];
2201 Out << llvm::format(
"%4d | ", I);
2206 Out <<
" non-virtual";
2209 Out <<
" vbase offset offset";
2218 Out <<
"this adjustment: ";
2223 Out <<
" vcall offset offset";
2236 std::map<uint64_t, std::string> IndicesMap;
2238 for (
const auto *MD : MostDerivedClass->
methods()) {
2249 assert(MethodVTableIndices.count(GD));
2250 uint64_t VTableIndex = MethodVTableIndices[GD];
2251 IndicesMap[VTableIndex] = MethodName +
" [complete]";
2252 IndicesMap[VTableIndex + 1] = MethodName +
" [deleting]";
2254 assert(MethodVTableIndices.count(MD));
2255 IndicesMap[MethodVTableIndices[MD]] = MethodName;
2260 if (!IndicesMap.empty()) {
2261 Out <<
"VTable indices for '";
2263 Out <<
"' (" << IndicesMap.size() <<
" entries).\n";
2265 for (
const auto &I : IndicesMap) {
2266 uint64_t VTableIndex = I.first;
2267 const std::string &MethodName = I.second;
2269 Out << llvm::format(
"%4" PRIu64
" | ", VTableIndex) << MethodName
2280 unsigned numVTables) {
2283 for (
auto it = addressPoints.begin(); it != addressPoints.end(); ++it) {
2284 const auto &addressPointLoc = it->second;
2285 unsigned vtableIndex = addressPointLoc.VTableIndex;
2286 unsigned addressPoint = addressPointLoc.AddressPointIndex;
2287 if (indexMap[vtableIndex]) {
2290 assert(indexMap[vtableIndex] == addressPoint &&
2291 "Every vtable index should have a unique address point. Found a "
2292 "vtable that has two different address points.");
2294 indexMap[vtableIndex] = addressPoint;
2309 : VTableIndices(
std::move(VTableIndices)),
2310 VTableComponents(VTableComponents), VTableThunks(VTableThunks),
2311 AddressPoints(AddressPoints),
2312 AddressPointIndices(
2314 assert(!this->VTableIndices.empty() &&
2315 "VTableLayout requires at least one index.");
2316 assert(this->VTableIndices.front() == 0 &&
2317 "VTableLayout requires the first index is 0.");
2320 assert((LHS.first != RHS.first || LHS.second == RHS.second) &&
2321 "Different thunks should have unique indices!");
2322 return LHS.first < RHS.first;
2339 MethodVTableIndicesTy::iterator I = MethodVTableIndices.find(GD);
2340 if (I != MethodVTableIndices.end())
2345 computeVTableRelatedInformation(RD);
2347 I = MethodVTableIndices.find(GD);
2348 assert(I != MethodVTableIndices.end() &&
"Did not find index!");
2355 ClassPairTy ClassPair(RD, VBase);
2357 VirtualBaseClassOffsetOffsetsMapTy::iterator I =
2358 VirtualBaseClassOffsetOffsets.find(ClassPair);
2359 if (I != VirtualBaseClassOffsetOffsets.end())
2362 VCallAndVBaseOffsetBuilder Builder(RD, RD,
nullptr,
2367 for (
const auto &I : Builder.getVBaseOffsetOffsets()) {
2369 ClassPairTy ClassPair(RD, I.first);
2371 VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I.second));
2374 I = VirtualBaseClassOffsetOffsets.find(ClassPair);
2375 assert(I != VirtualBaseClassOffsetOffsets.end() &&
"Did not find index!");
2382 computeVTableRelatedInformation(MD->getParent());
2385 if (
const auto *DD = dyn_cast<CXXDestructorDecl>(OriginalMD))
2395 auto I = OriginalMethodMap.find(MD);
2399 if (I == OriginalMethodMap.end())
2409static std::unique_ptr<VTableLayout>
2412 VTableThunks(Builder.vtable_thunks_begin(), Builder.vtable_thunks_end());
2414 return std::make_unique<VTableLayout>(
2415 Builder.VTableIndices, Builder.vtable_components(), VTableThunks,
2416 Builder.getAddressPoints());
2420ItaniumVTableContext::computeVTableRelatedInformation(
const CXXRecordDecl *RD) {
2421 std::unique_ptr<const VTableLayout> &Entry = VTableLayouts[RD];
2431 MethodVTableIndices.insert(Builder.vtable_indices_begin(),
2432 Builder.vtable_indices_end());
2435 Thunks.insert(Builder.thunks_begin(), Builder.thunks_end());
2443 const CXXRecordDecl *VBase =
2446 if (VirtualBaseClassOffsetOffsets.count(std::make_pair(RD, VBase)))
2449 for (
const auto &I : Builder.getVBaseOffsetOffsets()) {
2451 ClassPairTy ClassPair(RD, I.first);
2453 VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I.second));
2457std::unique_ptr<VTableLayout>
2460 bool MostDerivedClassIsVirtual,
const CXXRecordDecl *LayoutClass) {
2461 ItaniumVTableBuilder Builder(*
this, MostDerivedClass, MostDerivedClassOffset,
2462 MostDerivedClassIsVirtual, LayoutClass);
2510class VFTableBuilder {
2512 typedef llvm::DenseMap<GlobalDecl, MethodVFTableLocation>
2513 MethodVFTableLocationsTy;
2515 typedef llvm::iterator_range<MethodVFTableLocationsTy::const_iterator>
2516 method_locations_range;
2534 const FinalOverriders Overriders;
2539 MethodVFTableLocationsTy MethodVFTableLocations;
2542 bool HasRTTIComponent =
false;
2549 const uint64_t VBTableIndex;
2552 const uint64_t VFTableIndex;
2563 MethodInfo(uint64_t VBTableIndex, uint64_t VFTableIndex,
2564 bool UsesExtraSlot =
false)
2565 : VBTableIndex(VBTableIndex), VFTableIndex(VFTableIndex),
2566 Shadowed(
false), UsesExtraSlot(UsesExtraSlot) {}
2569 : VBTableIndex(0), VFTableIndex(0), Shadowed(
false),
2570 UsesExtraSlot(
false) {}
2573 typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy;
2577 MethodInfoMapTy MethodInfoMap;
2579 typedef llvm::DenseMap<uint64_t, ThunkInfo> VTableThunksMapTy;
2583 VTableThunksMapTy VTableThunks;
2585 typedef SmallVector<ThunkInfo, 1> ThunkInfoVectorTy;
2586 typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
2593 void AddThunk(
const CXXMethodDecl *MD,
const ThunkInfo &Thunk) {
2594 SmallVector<ThunkInfo, 1> &ThunksVector = Thunks[MD];
2597 if (llvm::is_contained(ThunksVector, Thunk))
2600 ThunksVector.push_back(Thunk);
2605 CharUnits ComputeThisOffset(FinalOverriders::OverriderInfo Overrider);
2607 void CalculateVtordispAdjustment(FinalOverriders::OverriderInfo Overrider,
2608 CharUnits ThisOffset, ThisAdjustment &TA);
2612 void AddMethod(
const CXXMethodDecl *MD, ThunkInfo TI) {
2614 VTableThunks[Components.size()] = TI;
2617 if (
const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
2619 "Destructor can't have return adjustment!");
2628 void AddMethods(BaseSubobject Base,
unsigned BaseDepth,
2629 const CXXRecordDecl *LastVBase,
2630 BasesSetVectorTy &VisitedBases);
2632 void LayoutVFTable() {
2634 if (HasRTTIComponent)
2637 BasesSetVectorTy VisitedBases;
2638 AddMethods(BaseSubobject(MostDerivedClass,
CharUnits::Zero()), 0,
nullptr,
2642 assert(!Components.empty() &&
"vftable can't be empty");
2644 assert(MethodVFTableLocations.empty());
2645 for (
const auto &I : MethodInfoMap) {
2646 const CXXMethodDecl *MD = I.first;
2647 const MethodInfo &MI = I.second;
2652 if (MD->
getParent() != MostDerivedClass || MI.Shadowed)
2656 if (
const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
2662 MethodVFTableLocations[GlobalDecl(DD, DtorTy)] = Loc;
2664 MethodVFTableLocations[MD] = Loc;
2670 VFTableBuilder(MicrosoftVTableContext &VTables,
2671 const CXXRecordDecl *MostDerivedClass,
const VPtrInfo &Which)
2673 Context(MostDerivedClass->getASTContext()),
2674 MostDerivedClass(MostDerivedClass),
2675 MostDerivedClassLayout(Context.getASTRecordLayout(MostDerivedClass)),
2677 Overriders(MostDerivedClass, CharUnits(), MostDerivedClass) {
2684 HasRTTIComponent =
true;
2689 dumpLayout(llvm::outs());
2692 uint64_t getNumThunks()
const {
return Thunks.size(); }
2694 ThunksMapTy::const_iterator thunks_begin()
const {
return Thunks.begin(); }
2696 ThunksMapTy::const_iterator thunks_end()
const {
return Thunks.end(); }
2698 method_locations_range vtable_locations()
const {
2699 return method_locations_range(MethodVFTableLocations.begin(),
2700 MethodVFTableLocations.end());
2703 ArrayRef<VTableComponent> vtable_components()
const {
return Components; }
2705 VTableThunksMapTy::const_iterator vtable_thunks_begin()
const {
2706 return VTableThunks.begin();
2709 VTableThunksMapTy::const_iterator vtable_thunks_end()
const {
2710 return VTableThunks.end();
2713 void dumpLayout(raw_ostream &);
2773VFTableBuilder::ComputeThisOffset(FinalOverriders::OverriderInfo Overrider) {
2774 BasesSetVectorTy Bases;
2778 OverriddenMethodsSetTy VisitedOverriddenMethods;
2779 auto InitialOverriddenDefinitionCollector = [&](
2781 if (OverriddenMD->size_overridden_methods() == 0)
2782 Bases.insert(OverriddenMD->getParent());
2784 return VisitedOverriddenMethods.insert(OverriddenMD).second;
2786 visitAllOverriddenMethods(Overrider.Method,
2787 InitialOverriddenDefinitionCollector);
2792 if (Bases.size() == 0)
2793 return Overrider.Offset;
2798 return Bases.count(
Specifier->getType()->getAsCXXRecordDecl());
2812 CharUnits ThisOffset = Overrider.Offset;
2819 QualType CurTy = Element.Base->getType();
2824 if (Element.Base->isVirtual()) {
2835 LastVBaseOffset = ThisOffset =
2843 if (LastVBaseOffset.
isZero()) {
2847 ThisOffset = Overrider.Offset;
2851 ThisOffset = LastVBaseOffset;
2855 if (Ret > ThisOffset ||
First) {
2861 assert(!
First &&
"Method not found in the given subobject?");
2963void VFTableBuilder::CalculateVtordispAdjustment(
2964 FinalOverriders::OverriderInfo Overrider,
CharUnits ThisOffset,
2968 const ASTRecordLayout::VBaseOffsetsMapTy::const_iterator &VBaseMapEntry =
2970 assert(VBaseMapEntry != VBaseMap.end());
2974 if (!VBaseMapEntry->second.hasVtorDisp() ||
2980 CharUnits OffsetOfVBaseWithVFPtr = VBaseMapEntry->second.VBaseOffset;
2982 (OffsetOfVBaseWithVFPtr - WhichVFPtr.
FullOffsetInMDC).getQuantity() - 4;
2986 if (Overrider.Method->
getParent() == MostDerivedClass ||
2987 !Overrider.VirtualBase)
2999 TA.
NonVirtual = (ThisOffset - Overrider.Offset).getQuantity();
3013 typedef llvm::DenseMap<DeclarationName, unsigned> VisitedGroupIndicesTy;
3014 VisitedGroupIndicesTy VisitedGroupIndices;
3015 for (
const auto *D : RD->
decls()) {
3016 const auto *ND = dyn_cast<NamedDecl>(D);
3019 VisitedGroupIndicesTy::iterator J;
3021 std::tie(J, Inserted) = VisitedGroupIndices.insert(
3022 std::make_pair(ND->getDeclName(), Groups.size()));
3024 Groups.push_back(MethodGroup());
3025 if (
const auto *MD = dyn_cast<CXXMethodDecl>(ND))
3030 for (
const MethodGroup &Group : Groups)
3031 VirtualMethods.append(Group.rbegin(), Group.rend());
3035 for (
const auto &B : RD->
bases()) {
3036 if (B.isVirtual() && B.getType()->getAsCXXRecordDecl() ==
Base)
3042void VFTableBuilder::AddMethods(
BaseSubobject Base,
unsigned BaseDepth,
3044 BasesSetVectorTy &VisitedBases) {
3054 const CXXRecordDecl *NextBase =
nullptr, *NextLastVBase = LastVBase;
3059 NextLastVBase = NextBase;
3067 "No primary virtual bases in this ABI");
3068 NextBase = PrimaryBase;
3069 NextBaseOffset =
Base.getBaseOffset();
3073 AddMethods(
BaseSubobject(NextBase, NextBaseOffset), BaseDepth + 1,
3074 NextLastVBase, VisitedBases);
3075 if (!VisitedBases.insert(NextBase))
3076 llvm_unreachable(
"Found a duplicate primary base!");
3092 FinalOverriders::OverriderInfo FinalOverrider =
3093 Overriders.getOverrider(MD,
Base.getBaseOffset());
3094 const CXXMethodDecl *FinalOverriderMD = FinalOverrider.Method;
3096 FindNearestOverriddenMethod(MD, VisitedBases);
3099 bool ReturnAdjustingThunk =
false, ForceReturnAdjustmentMangling =
false;
3100 CharUnits ThisOffset = ComputeThisOffset(FinalOverrider);
3103 if ((OverriddenMD || FinalOverriderMD != MD) &&
3105 CalculateVtordispAdjustment(FinalOverrider, ThisOffset,
3106 ThisAdjustmentOffset);
3114 MethodInfoMapTy::iterator OverriddenMDIterator =
3115 MethodInfoMap.find(OverriddenMD);
3118 if (OverriddenMDIterator == MethodInfoMap.end())
3121 MethodInfo &OverriddenMethodInfo = OverriddenMDIterator->second;
3123 VBIndex = OverriddenMethodInfo.VBTableIndex;
3130 ReturnAdjustingThunk = !ComputeReturnAdjustmentBaseOffset(
3131 Context, MD, OverriddenMD).isEmpty() ||
3132 OverriddenMethodInfo.UsesExtraSlot;
3134 if (!ReturnAdjustingThunk) {
3137 MethodInfo MI(VBIndex, OverriddenMethodInfo.VFTableIndex);
3138 MethodInfoMap.erase(OverriddenMDIterator);
3140 assert(!MethodInfoMap.count(MD) &&
3141 "Should not have method info for this method yet!");
3142 MethodInfoMap.insert(std::make_pair(MD, MI));
3148 OverriddenMethodInfo.Shadowed =
true;
3152 ForceReturnAdjustmentMangling =
3153 !(MD == FinalOverriderMD && ThisAdjustmentOffset.
isEmpty());
3164 MethodInfo MI(VBIndex,
3165 HasRTTIComponent ? Components.size() - 1 : Components.size(),
3166 ReturnAdjustingThunk);
3168 assert(!MethodInfoMap.count(MD) &&
3169 "Should not have method info for this method yet!");
3170 MethodInfoMap.insert(std::make_pair(MD, MI));
3174 BaseOffset ReturnAdjustmentOffset;
3177 ReturnAdjustmentOffset =
3178 ComputeReturnAdjustmentBaseOffset(Context, FinalOverriderMD, MD);
3180 if (!ReturnAdjustmentOffset.isEmpty()) {
3181 ForceReturnAdjustmentMangling =
true;
3183 ReturnAdjustmentOffset.NonVirtualOffset.
getQuantity();
3184 if (ReturnAdjustmentOffset.VirtualBase) {
3191 ReturnAdjustmentOffset.VirtualBase);
3194 auto ThisType = (OverriddenMD ? OverriddenMD : MD)->getThisType().getTypePtr();
3195 AddMethod(FinalOverriderMD,
3197 ForceReturnAdjustmentMangling ? MD :
nullptr));
3204 Elem->printQualifiedName(Out);
3210 bool ContinueFirstLine) {
3212 bool Multiline =
false;
3213 const char *LinePrefix =
"\n ";
3214 if (!R.isEmpty() || TI.
Method) {
3215 if (!ContinueFirstLine)
3217 Out <<
"[return adjustment (to type '"
3219 if (R.Virtual.Microsoft.VBPtrOffset)
3220 Out <<
"vbptr at offset " << R.Virtual.Microsoft.VBPtrOffset <<
", ";
3221 if (R.Virtual.Microsoft.VBIndex)
3222 Out <<
"vbase #" << R.Virtual.Microsoft.VBIndex <<
", ";
3223 Out << R.NonVirtual <<
" non-virtual]";
3229 if (Multiline || !ContinueFirstLine)
3231 Out <<
"[this adjustment: ";
3233 assert(T.Virtual.Microsoft.VtordispOffset < 0);
3234 Out <<
"vtordisp at " << T.Virtual.Microsoft.VtordispOffset <<
", ";
3235 if (T.Virtual.Microsoft.VBPtrOffset) {
3236 Out <<
"vbptr at " << T.Virtual.Microsoft.VBPtrOffset
3238 assert(T.Virtual.Microsoft.VBOffsetOffset > 0);
3239 Out << LinePrefix <<
" vboffset at "
3240 << T.Virtual.Microsoft.VBOffsetOffset <<
" in the vbtable, ";
3243 Out << T.NonVirtual <<
" non-virtual]";
3247void VFTableBuilder::dumpLayout(raw_ostream &Out) {
3248 Out <<
"VFTable for ";
3252 Out <<
"' (" << Components.size()
3253 << (Components.size() == 1 ?
" entry" :
" entries") <<
").\n";
3255 for (
unsigned I = 0, E = Components.size(); I != E; ++I) {
3256 Out << llvm::format(
"%4d | ", I);
3261 switch (Component.
getKind()) {
3279 Out <<
" [deleted]";
3281 ThunkInfo Thunk = VTableThunks.lookup(I);
3294 Out <<
"() [vector deleting]";
3296 Out <<
"() [scalar deleting]";
3301 ThunkInfo Thunk = VTableThunks.lookup(I);
3304 "No return adjustment needed for destructors!");
3314 diag::err_unexpected_vftable_component)
3323 if (!Thunks.empty()) {
3325 std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls;
3327 for (
const auto &I : Thunks) {
3332 MethodNamesAndDecls.insert(std::make_pair(MethodName, MD));
3335 for (
const auto &MethodNameAndDecl : MethodNamesAndDecls) {
3336 const std::string &MethodName = MethodNameAndDecl.first;
3339 ThunkInfoVectorTy ThunksVector = Thunks[MD];
3340 llvm::stable_sort(ThunksVector, [](
const ThunkInfo &LHS,
3347 Out <<
"Thunks for '" << MethodName <<
"' (" << ThunksVector.size();
3348 Out << (ThunksVector.size() == 1 ?
" entry" :
" entries") <<
").\n";
3350 for (
unsigned I = 0, E = ThunksVector.size(); I != E; ++I) {
3351 const ThunkInfo &Thunk = ThunksVector[I];
3353 Out << llvm::format(
"%4d | ", I);
3397void MicrosoftVTableContext::computeVTablePaths(
bool ForVBTables,
3400 assert(Paths.empty());
3401 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
3405 Paths.push_back(std::make_unique<VPtrInfo>(RD));
3409 llvm::SmallPtrSet<const CXXRecordDecl*, 4> VBasesSeen;
3410 for (
const auto &B : RD->
bases()) {
3411 const CXXRecordDecl *
Base = B.getType()->getAsCXXRecordDecl();
3412 if (B.isVirtual() && VBasesSeen.count(Base))
3415 if (!
Base->isDynamicClass())
3421 for (
const std::unique_ptr<VPtrInfo> &BaseInfo : BasePaths) {
3428 auto P = std::make_unique<VPtrInfo>(*BaseInfo);
3432 if (P->MangledPath.empty() || P->MangledPath.back() != Base)
3433 P->NextBaseToMangle =
Base;
3438 if (P->ObjectWithVPtr == Base &&
3441 P->ObjectWithVPtr = RD;
3446 P->ContainingVBases.push_back(Base);
3447 else if (P->ContainingVBases.empty())
3451 P->FullOffsetInMDC = P->NonVirtualOffset;
3452 if (
const CXXRecordDecl *VB = P->getVBaseWithVPtr())
3455 Paths.push_back(std::move(P));
3459 VBasesSeen.insert(Base);
3463 for (
const auto &VB :
Base->vbases())
3464 VBasesSeen.insert(VB.getType()->getAsCXXRecordDecl());
3491 llvm::make_pointee_range(Paths));
3495 bool Changed =
false;
3496 for (
size_t I = 0, E = PathsSorted.size(); I != E;) {
3498 size_t BucketStart = I;
3502 PathsSorted[BucketStart].get().MangledPath ==
3503 PathsSorted[I].get().MangledPath);
3506 if (I - BucketStart > 1) {
3507 for (
size_t II = BucketStart; II != I; ++II)
3509 assert(Changed &&
"no paths were extended to fix ambiguity");
3518typedef llvm::SetVector<BaseSubobject, std::vector<BaseSubobject>,
3519 llvm::DenseSet<BaseSubobject>> FullPathTy;
3528 FullPathTy &FullPath,
3529 std::list<FullPathTy> &Paths) {
3531 Paths.push_back(FullPath);
3544 IntroducingObject, FullPath, Paths);
3545 FullPath.pop_back();
3551 FullPaths.remove_if([&](
const FullPathTy &SpecificPath) {
3552 for (
const FullPathTy &OtherPath : FullPaths) {
3553 if (&SpecificPath == &OtherPath)
3555 if (llvm::all_of(SpecificPath, [&](
const BaseSubobject &BSO) {
3556 return OtherPath.contains(BSO);
3567 const FullPathTy &FullPath) {
3569 Context.getASTRecordLayout(RD);
3575 assert(Offset.getQuantity() == -1);
3579 assert(Offset.getQuantity() != -1);
3585 return BS.getType()->getAsCXXRecordDecl() == Base;
3600 std::list<FullPathTy> &FullPaths) {
3602 if (FullPaths.empty())
3604 if (FullPaths.size() == 1)
3605 return &FullPaths.front();
3607 const FullPathTy *BestPath =
nullptr;
3608 typedef std::set<const CXXMethodDecl *> OverriderSetTy;
3609 OverriderSetTy LastOverrides;
3610 for (
const FullPathTy &SpecificPath : FullPaths) {
3611 assert(!SpecificPath.empty());
3612 OverriderSetTy CurrentOverrides;
3613 const CXXRecordDecl *TopLevelRD = SpecificPath.begin()->getBase();
3618 FinalOverriders Overriders(TopLevelRD,
CharUnits::Zero(), TopLevelRD);
3622 FinalOverriders::OverriderInfo OI =
3627 if (ComputeReturnAdjustmentBaseOffset(Context, OverridingMethod, MD)
3633 if (llvm::none_of(SpecificPath, [&](
const BaseSubobject &BSO) {
3634 return BSO.
getBase() == OverridingParent;
3637 CurrentOverrides.insert(OverridingMethod);
3639 OverriderSetTy NewOverrides =
3640 llvm::set_difference(CurrentOverrides, LastOverrides);
3641 if (NewOverrides.empty())
3643 OverriderSetTy MissingOverrides =
3644 llvm::set_difference(LastOverrides, CurrentOverrides);
3645 if (MissingOverrides.empty()) {
3647 BestPath = &SpecificPath;
3648 std::swap(CurrentOverrides, LastOverrides);
3653 const CXXMethodDecl *ConflictMD = *MissingOverrides.begin();
3664 return BestPath ? BestPath : &FullPaths.front();
3670 const ASTRecordLayout &MostDerivedLayout = Context.getASTRecordLayout(RD);
3671 FullPathTy FullPath;
3672 std::list<FullPathTy> FullPaths;
3673 for (
const std::unique_ptr<VPtrInfo>& Info : Paths) {
3676 BaseSubobject(Info->IntroducingObject, Info->FullOffsetInMDC), FullPath,
3680 Info->PathToIntroducingObject.clear();
3681 if (
const FullPathTy *BestPath =
3684 Info->PathToIntroducingObject.push_back(BSO.getBase());
3701void MicrosoftVTableContext::computeVTableRelatedInformation(
3706 if (VFPtrLocations.count(RD))
3712 auto VFPtrs = std::make_unique<VPtrInfoVector>();
3713 computeVTablePaths(
false, RD, *VFPtrs);
3715 VFPtrLocations[RD] = std::move(VFPtrs);
3718 MethodVFTableLocationsTy NewMethodLocations;
3719 for (
const std::unique_ptr<VPtrInfo> &VFPtr : *VFPtrLocations[RD]) {
3720 VFTableBuilder Builder(*
this, RD, *VFPtr);
3722 VFTableIdTy id(RD, VFPtr->FullOffsetInMDC);
3723 assert(VFTableLayouts.count(
id) == 0);
3724 SmallVector<VTableLayout::VTableThunkTy, 1> VTableThunks(
3725 Builder.vtable_thunks_begin(), Builder.vtable_thunks_end());
3726 VFTableLayouts[id] = std::make_unique<VTableLayout>(
3728 VTableThunks, EmptyAddressPointsMap);
3729 Thunks.insert(Builder.thunks_begin(), Builder.thunks_end());
3731 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
3732 for (
const auto &Loc : Builder.vtable_locations()) {
3733 auto Insert = NewMethodLocations.insert(Loc);
3735 const MethodVFTableLocation &NewLoc = Loc.second;
3736 MethodVFTableLocation &OldLoc =
Insert.first->second;
3743 MethodVFTableLocations.insert_range(NewMethodLocations);
3744 if (Context.getLangOpts().DumpVTableLayouts)
3745 dumpMethodLocations(RD, NewMethodLocations, llvm::outs());
3748void MicrosoftVTableContext::dumpMethodLocations(
3749 const CXXRecordDecl *RD,
const MethodVFTableLocationsTy &NewMethods,
3753 std::map<MethodVFTableLocation, std::string> IndicesMap;
3754 bool HasNonzeroOffset =
false;
3756 for (
const auto &I : NewMethods) {
3764 IndicesMap[I.second] = MethodName +
" [vector deleting]";
3766 IndicesMap[I.second] = MethodName;
3769 if (!I.second.VFPtrOffset.isZero() || I.second.VBTableIndex != 0)
3770 HasNonzeroOffset =
true;
3774 if (!IndicesMap.empty()) {
3775 Out <<
"VFTable indices for ";
3778 Out <<
"' (" << IndicesMap.size()
3779 << (IndicesMap.size() == 1 ?
" entry" :
" entries") <<
").\n";
3783 for (
const auto &I : IndicesMap) {
3784 CharUnits VFPtrOffset = I.first.VFPtrOffset;
3785 uint64_t VBIndex = I.first.VBTableIndex;
3786 if (HasNonzeroOffset &&
3787 (VFPtrOffset != LastVFPtrOffset || VBIndex != LastVBIndex)) {
3788 assert(VBIndex > LastVBIndex || VFPtrOffset > LastVFPtrOffset);
3789 Out <<
" -- accessible via ";
3791 Out <<
"vbtable index " << VBIndex <<
", ";
3792 Out <<
"vfptr at offset " << VFPtrOffset.
getQuantity() <<
" --\n";
3793 LastVFPtrOffset = VFPtrOffset;
3794 LastVBIndex = VBIndex;
3797 uint64_t VTableIndex = I.first.Index;
3798 const std::string &MethodName = I.second;
3799 Out << llvm::format(
"%4" PRIu64
" | ", VTableIndex) << MethodName <<
'\n';
3807const VirtualBaseInfo &MicrosoftVTableContext::computeVBTableRelatedInformation(
3809 VirtualBaseInfo *VBI;
3814 std::unique_ptr<VirtualBaseInfo> &Entry = VBaseInfo[RD];
3817 Entry = std::make_unique<VirtualBaseInfo>();
3821 computeVTablePaths(
true, RD, VBI->
VBPtrPaths);
3824 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
3828 const VirtualBaseInfo &BaseInfo =
3829 computeVBTableRelatedInformation(VBPtrBase);
3836 for (
const auto &VB : RD->
vbases()) {
3837 const CXXRecordDecl *CurVBase = VB.getType()->getAsCXXRecordDecl();
3838 if (VBI->
VBTableIndices.try_emplace(CurVBase, VBTableIndex).second)
3847 const VirtualBaseInfo &VBInfo = computeVBTableRelatedInformation(Derived);
3854 return computeVBTableRelatedInformation(RD).VBPtrPaths;
3859 computeVTableRelatedInformation(RD);
3861 assert(VFPtrLocations.count(RD) &&
"Couldn't find vfptr locations");
3862 return *VFPtrLocations[RD];
3868 computeVTableRelatedInformation(RD);
3870 VFTableIdTy id(RD, VFPtrOffset);
3871 assert(VFTableLayouts.count(
id) &&
"Couldn't find a VFTable at this offset");
3872 return *VFTableLayouts[id];
3878 "Only use this method for virtual methods or dtors");
3885 MethodVFTableLocationsTy::iterator I = MethodVFTableLocations.find(GD);
3886 if (I != MethodVFTableLocations.end())
3891 computeVTableRelatedInformation(RD);
3893 I = MethodVFTableLocations.find(GD);
3894 assert(I != MethodVFTableLocations.end() &&
"Did not find index!");
Defines the clang::ASTContext interface.
static void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef< CounterExpression > Expressions, ArrayRef< CounterMappingRegion > Regions)
static Decl::Kind getKind(const Decl *D)
static QualType getPointeeType(const MemRegion *R)
static void findPathsToSubobject(ASTContext &Context, const ASTRecordLayout &MostDerivedLayout, const CXXRecordDecl *RD, CharUnits Offset, BaseSubobject IntroducingObject, FullPathTy &FullPath, std::list< FullPathTy > &Paths)
static const FullPathTy * selectBestPath(ASTContext &Context, const CXXRecordDecl *RD, const VPtrInfo &Info, std::list< FullPathTy > &FullPaths)
static CharUnits getOffsetOfFullPath(ASTContext &Context, const CXXRecordDecl *RD, const FullPathTy &FullPath)
static void removeRedundantPaths(std::list< FullPathTy > &FullPaths)
static std::unique_ptr< VTableLayout > CreateVTableLayout(const ItaniumVTableBuilder &Builder)
static bool vfptrIsEarlierInMDC(const ASTRecordLayout &Layout, const MethodVFTableLocation &LHS, const MethodVFTableLocation &RHS)
static bool isDirectVBase(const CXXRecordDecl *Base, const CXXRecordDecl *RD)
static void PrintBasePath(const VPtrInfo::BasePath &Path, raw_ostream &Out)
static VTableLayout::AddressPointsIndexMapTy MakeAddressPointIndices(const VTableLayout::AddressPointsMapTy &addressPoints, unsigned numVTables)
static bool rebucketPaths(VPtrInfoVector &Paths)
static bool extendPath(VPtrInfo &P)
static void dumpMicrosoftThunkAdjustment(const ThunkInfo &TI, raw_ostream &Out, bool ContinueFirstLine)
static void GroupNewVirtualOverloads(const CXXRecordDecl *RD, SmallVector< const CXXMethodDecl *, 10 > &VirtualMethods)
static void computeFullPathsForVFTables(ASTContext &Context, const CXXRecordDecl *RD, VPtrInfoVector &Paths)
static bool setsIntersect(const llvm::SmallPtrSet< const CXXRecordDecl *, 4 > &A, ArrayRef< const CXXRecordDecl * > B)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
const LangOptions & getLangOpts() const
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
DiagnosticsEngine & getDiagnostics() const
const TargetInfo & getTargetInfo() const
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
bool hasOwnVFPtr() const
hasOwnVFPtr - Does this class provide its own virtual-function table pointer, rather than inheriting ...
const CXXRecordDecl * getBaseSharingVBPtr() const
bool hasOwnVBPtr() const
hasOwnVBPtr - Does this class provide its own virtual-base table pointer, rather than inheriting one ...
llvm::DenseMap< const CXXRecordDecl *, VBaseInfo > VBaseOffsetsMapTy
CharUnits getVBPtrOffset() const
getVBPtrOffset - Get the offset for virtual base table pointer.
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const
getVBaseClassOffset - Get the offset, in chars, for the given base class.
const VBaseOffsetsMapTy & getVBaseOffsetsMap() const
const CXXRecordDecl * getPrimaryBase() const
getPrimaryBase - Get the primary base for this record.
bool isPrimaryBaseVirtual() const
isPrimaryBaseVirtual - Get whether the primary base for this record is virtual or not.
const CXXRecordDecl * getBase() const
getBase - Returns the base class declaration.
CharUnits getBaseOffset() const
getBaseOffset - Returns the base class offset.
Represents a path from a specific derived class (which is not represented as part of the path) to a p...
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
Represents a base class of a C++ class.
bool isVirtual() const
Determines whether the base class is a virtual base class (or not).
QualType getType() const
Retrieves the type of the base class.
Represents a C++ destructor within a class.
A mapping from each virtual member function to its set of final overriders.
Represents a static or instance method of a struct/union/class.
overridden_method_range overridden_methods() const
unsigned size_overridden_methods() const
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
QualType getThisType() const
Return the type of the this pointer.
bool isMoveAssignmentOperator() const
Determine whether this is a move assignment operator.
bool isCopyAssignmentOperator() const
Determine whether this is a copy-assignment operator, regardless of whether it was declared implicitl...
CXXMethodDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Represents a C++ struct/union/class.
base_class_iterator bases_end()
method_range methods() const
bool isPolymorphic() const
Whether this class is polymorphic (C++ [class.virtual]), which means that the class contains or inher...
bool lookupInBases(BaseMatchesCallback BaseMatches, CXXBasePaths &Paths, bool LookupInDependent=false) const
Look for entities within the base classes of this C++ class, transitively searching all base class su...
base_class_iterator bases_begin()
base_class_range vbases()
base_class_iterator vbases_begin()
bool isDynamicClass() const
void getFinalOverriders(CXXFinalOverriderMap &FinaOverriders) const
Retrieve the final overriders for each virtual member function in the class hierarchy where this clas...
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
bool isDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is derived from the class Base.
CanQual< T > getUnqualifiedType() const
Retrieve the unqualified form of this type.
CanProxy< U > getAs() const
Retrieve a canonical type pointer with a different static type, upcasting or downcasting as needed.
CharUnits - This is an opaque type for sizes expressed in character units.
bool isZero() const
isZero - Test whether the quantity equals zero.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
DeclContext * getParent()
getParent - Returns the containing DeclContext.
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
Decl - This represents one declaration (or definition), e.g.
ASTContext & getASTContext() const LLVM_READONLY
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
SourceLocation getLocation() const
The name of a declaration.
Concrete class used by the front-end to report problems and issues.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
bool isImmediateFunction() const
QualType getReturnType() const
bool isDeleted() const
Whether this function has been deleted.
bool isPureVirtual() const
Whether this virtual function is pure, i.e.
OverloadedOperatorKind getOverloadedOperator() const
getOverloadedOperator - Which C++ overloaded operator this function represents, if any.
Represents a prototype with parameter type info, e.g.
Qualifiers getMethodQuals() const
ArrayRef< QualType > getParamTypes() const
FunctionType - C99 6.7.5.3 - Function Declarators.
QualType getReturnType() const
GlobalDecl - represents a global declaration.
GlobalDecl getCanonicalDecl() const
CXXDtorType getDtorType() const
const Decl * getDecl() const
const CXXMethodDecl * findOriginalMethodInMap(const CXXMethodDecl *MD) const
const OriginalMethodMapTy & getOriginalMethodMap()
This method is reserved for the implementation and shouldn't be used directly.
uint64_t getMethodVTableIndex(GlobalDecl GD)
Locate a virtual function in the vtable.
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...
GlobalDecl findOriginalMethod(GlobalDecl GD)
Return the method that added the v-table slot that will be used to call the given method.
void setOriginalMethod(const CXXMethodDecl *Key, const CXXMethodDecl *Val)
ItaniumVTableContext(ASTContext &Context)
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.
virtual bool emitVectorDeletingDtors(const LangOptions &) const
Controls whether to emit MSVC vector deleting destructors.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
const T * castAs() const
Member-template castAs<specific type>.
Represents a single component in a vtable.
static VTableComponent MakeCompleteDtor(const CXXDestructorDecl *DD)
static VTableComponent MakeRTTI(const CXXRecordDecl *RD)
const CXXMethodDecl * getUnusedFunctionDecl() const
static VTableComponent MakeOffsetToTop(CharUnits Offset)
CharUnits getVBaseOffset() const
static VTableComponent MakeUnusedFunction(const CXXMethodDecl *MD)
Kind getKind() const
Get the kind of this vtable component.
static VTableComponent MakeFunction(const CXXMethodDecl *MD)
@ CK_DeletingDtorPointer
A pointer to the deleting destructor.
@ CK_UnusedFunctionPointer
An entry that is never used.
@ CK_CompleteDtorPointer
A pointer to the complete destructor.
static VTableComponent MakeVBaseOffset(CharUnits Offset)
const CXXRecordDecl * getRTTIDecl() const
static VTableComponent MakeDeletingDtor(const CXXDestructorDecl *DD)
CharUnits getOffsetToTop() const
const CXXMethodDecl * getFunctionDecl() const
static VTableComponent MakeVCallOffset(CharUnits Offset)
CharUnits getVCallOffset() const
const CXXDestructorDecl * getDestructorDecl() const
VTableContextBase(bool MS)
static bool hasVtableSlot(const CXXMethodDecl *MD)
Determine whether this function should be assigned a vtable slot.
ThunksMapTy Thunks
Contains all thunks that a given method decl will need.
llvm::SmallVector< std::size_t > VTableIndicesTy
VTableLayout(VTableIndicesTy VTableIndices, ArrayRef< VTableComponent > VTableComponents, ArrayRef< VTableThunkTy > VTableThunks, const AddressPointsMapTy &AddressPoints)
llvm::SmallVector< unsigned, 4 > AddressPointsIndexMapTy
llvm::DenseMap< BaseSubobject, AddressPointLocation > AddressPointsMapTy
std::pair< uint64_t, ThunkInfo > VTableThunkTy
Defines the clang::TargetInfo interface.
PRESERVE_NONE bool Ret(InterpState &S, CodePtr &PC)
The JSON file list parser is used to communicate input to InstallAPI.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool isa(CodeGen::Address addr)
SmallVector< std::unique_ptr< VPtrInfo >, 2 > VPtrInfoVector
CXXDtorType
C++ destructor types.
@ Dtor_VectorDeleting
Vector deleting dtor.
@ Dtor_Complete
Complete object dtor.
@ Dtor_Deleting
Deleting dtor.
for(const auto &A :T->param_types())
U cast(CodeGen::Address addr)
@ PrettyFunctionNoVirtual
The same as PrettyFunction, except that the 'virtual' keyword is omitted for virtual member functions...
Represents an element in a path from a derived class to a base class.
const CXXRecordDecl * Class
The record decl of the class that the base is a base of.
const CXXBaseSpecifier * Base
The base specifier that states the link from a derived class to a base class, which will be followed ...
const CXXRecordDecl * VBase
If nonnull, holds the last vbase which contains the vfptr that the method definition is adjusted to.
CharUnits VFPtrOffset
This is the offset of the vfptr from the start of the last vbase, or the complete type if there are n...
union clang::ReturnAdjustment::VirtualAdjustment Virtual
int64_t NonVirtual
The non-virtual adjustment from the derived object to its nearest virtual base.
A this pointer adjustment.
union clang::ThisAdjustment::VirtualAdjustment Virtual
int64_t NonVirtual
The non-virtual adjustment from the derived object to its nearest virtual base.
The this pointer adjustment as well as an optional return adjustment for a thunk.
ThisAdjustment This
The this pointer adjustment.
const CXXMethodDecl * Method
Holds a pointer to the overridden method this thunk is for, if needed by the ABI to distinguish diffe...
ReturnAdjustment Return
The return adjustment.
Uniquely identifies a virtual method within a class hierarchy by the method itself and a class subobj...
Holds information about the inheritance path to a virtual base or function table pointer.
CharUnits NonVirtualOffset
IntroducingObject is at this offset from its containing complete object or virtual base.
CharUnits FullOffsetInMDC
Static offset from the top of the most derived class to this vfptr, including any virtual base offset...
const CXXRecordDecl * getVBaseWithVPtr() const
The vptr is stored inside the non-virtual component of this virtual base.
SmallVector< const CXXRecordDecl *, 1 > BasePath
const CXXRecordDecl * IntroducingObject
This is the class that introduced the vptr by declaring new virtual methods or virtual bases.
BasePath MangledPath
The bases from the inheritance path that got used to mangle the vbtable name.
const CXXRecordDecl * NextBaseToMangle
The next base to push onto the mangled path if this path is ambiguous in a derived class.
BasePath PathToIntroducingObject
This holds the base classes path from the complete type to the first base with the given vfptr offset...
All virtual base related information about a given record decl.
VPtrInfoVector VBPtrPaths
Information on all virtual base tables used when this record is the most derived class.
llvm::DenseMap< const CXXRecordDecl *, unsigned > VBTableIndices
A map from virtual base to vbtable index for doing a conversion from the the derived class to the a b...
struct clang::ReturnAdjustment::VirtualAdjustment::@103031170252120233124322035264172076254313213024 Itanium
uint32_t VBPtrOffset
The offset (in bytes) of the vbptr, relative to the beginning of the derived class.
struct clang::ReturnAdjustment::VirtualAdjustment::@167242364125115315334113104006210160165266060257 Microsoft
int64_t VBaseOffsetOffset
The offset (in bytes), relative to the address point of the virtual base class offset.
uint32_t VBIndex
Index of the virtual base in the vbtable.
struct clang::ThisAdjustment::VirtualAdjustment::@106065375072164260365214033034320247050276346205 Itanium
int32_t VtordispOffset
The offset of the vtordisp (in bytes), relative to the ECX.
struct clang::ThisAdjustment::VirtualAdjustment::@312251255113040203233347230177110330127151157305 Microsoft
int32_t VBOffsetOffset
The offset (in bytes) of the vbase offset in the vbtable.
int64_t VCallOffsetOffset
The offset (in bytes), relative to the address point, of the virtual call offset.
int32_t VBPtrOffset
The offset of the vbptr of the derived class (in bytes), relative to the ECX after vtordisp adjustmen...