20 #include "llvm/ADT/SetOperations.h"
21 #include "llvm/ADT/SmallPtrSet.h"
22 #include "llvm/Support/Format.h"
23 #include "llvm/Support/raw_ostream.h"
27 using namespace clang;
29 #define DUMP_OVERRIDERS 0
50 BaseOffset() : DerivedClass(
nullptr), VirtualBase(
nullptr),
54 : DerivedClass(DerivedClass), VirtualBase(VirtualBase),
55 NonVirtualOffset(NonVirtualOffset) { }
57 bool isEmpty()
const {
return NonVirtualOffset.
isZero() && !VirtualBase; }
62 class 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);
127 typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy;
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);
158 FinalOverriders::FinalOverriders(
const CXXRecordDecl *MostDerivedClass,
161 : MostDerivedClass(MostDerivedClass),
162 MostDerivedClassOffset(MostDerivedClassOffset), LayoutClass(LayoutClass),
163 Context(MostDerivedClass->getASTContext()),
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;
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);
258 static 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());
271 ComputeReturnAdjustmentBaseOffset(
ASTContext &Context,
283 assert(CanDerivedReturnType->getTypeClass() ==
284 CanBaseReturnType->getTypeClass() &&
285 "Types must have same type class!");
287 if (CanDerivedReturnType == CanBaseReturnType) {
292 if (isa<ReferenceType>(CanDerivedReturnType)) {
293 CanDerivedReturnType =
294 CanDerivedReturnType->getAs<
ReferenceType>()->getPointeeType();
297 }
else if (isa<PointerType>(CanDerivedReturnType)) {
298 CanDerivedReturnType =
299 CanDerivedReturnType->getAs<
PointerType>()->getPointeeType();
303 llvm_unreachable(
"Unexpected return type!");
309 if (CanDerivedReturnType.getUnqualifiedType() ==
316 cast<CXXRecordDecl>(cast<RecordType>(CanDerivedReturnType)->getDecl());
319 cast<CXXRecordDecl>(cast<RecordType>(CanBaseReturnType)->getDecl());
321 return ComputeBaseOffset(Context, BaseRD, DerivedRD);
327 SubobjectOffsetMapTy &SubobjectOffsets,
328 SubobjectOffsetMapTy &SubobjectLayoutClassOffsets,
329 SubobjectCountMapTy &SubobjectCounts) {
332 unsigned SubobjectNumber = 0;
334 SubobjectNumber = ++SubobjectCounts[RD];
337 assert(!SubobjectOffsets.count(std::make_pair(RD, SubobjectNumber))
338 &&
"Subobject offset already exists!");
339 assert(!SubobjectLayoutClassOffsets.count(std::make_pair(RD, SubobjectNumber))
340 &&
"Subobject offset already exists!");
342 SubobjectOffsets[std::make_pair(RD, SubobjectNumber)] = Base.
getBaseOffset();
343 SubobjectLayoutClassOffsets[std::make_pair(RD, SubobjectNumber)] =
347 for (
const auto &B : RD->
bases()) {
348 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
354 if (SubobjectOffsets.count(std::make_pair(BaseDecl, 0)))
360 BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
361 BaseOffsetInLayoutClass =
368 BaseOffsetInLayoutClass = OffsetInLayoutClass +
Offset;
372 B.isVirtual(), BaseOffsetInLayoutClass,
373 SubobjectOffsets, SubobjectLayoutClassOffsets,
379 VisitedVirtualBasesSetTy &VisitedVirtualBases) {
383 for (
const auto &B : RD->
bases()) {
384 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
392 if (!VisitedVirtualBases.insert(BaseDecl).second) {
397 BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
405 Out <<
"Final overriders for (";
411 for (
const auto *MD : RD->
methods()) {
412 if (!MD->isVirtual())
414 MD = MD->getCanonicalDecl();
416 OverriderInfo Overrider = getOverrider(MD, Base.
getBaseOffset());
419 MD->printQualifiedName(Out);
421 Overrider.Method->printQualifiedName(Out);
422 Out <<
", " << Overrider.Offset.getQuantity() <<
')';
425 if (!Overrider.Method->isPure())
426 Offset = ComputeReturnAdjustmentBaseOffset(Context, Overrider.Method, MD);
428 if (!Offset.isEmpty()) {
429 Out <<
" [ret-adj: ";
430 if (Offset.VirtualBase) {
431 Offset.VirtualBase->printQualifiedName(Out);
435 Out << Offset.NonVirtualOffset.getQuantity() <<
" nv]";
443 struct VCallOffsetMap {
445 typedef std::pair<const CXXMethodDecl *, CharUnits> MethodAndOffsetPairTy;
453 static bool MethodsCanShareVCallOffset(
const CXXMethodDecl *LHS,
467 bool empty()
const {
return Offsets.empty(); }
470 static bool HasSameVirtualSignature(
const CXXMethodDecl *LHS,
478 if (LT == RT)
return true;
488 bool VCallOffsetMap::MethodsCanShareVCallOffset(
const CXXMethodDecl *LHS,
490 assert(LHS->
isVirtual() &&
"LHS must be virtual!");
491 assert(RHS->
isVirtual() &&
"LHS must be virtual!");
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!");
533 class VCallAndVBaseOffsetBuilder {
535 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits>
536 VBaseOffsetOffsetsMapTy;
553 VTableComponentVectorTy Components;
556 llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBases;
559 VCallOffsetMap VCallOffsets;
564 VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
568 const FinalOverriders *Overriders;
572 void AddVCallAndVBaseOffsets(
BaseSubobject Base,
bool BaseIsVirtual,
584 CharUnits getCurrentOffsetOffset()
const;
587 VCallAndVBaseOffsetBuilder(
const CXXRecordDecl *MostDerivedClass,
589 const FinalOverriders *Overriders,
592 : MostDerivedClass(MostDerivedClass), LayoutClass(LayoutClass),
593 Context(MostDerivedClass->getASTContext()), Overriders(Overriders) {
596 AddVCallAndVBaseOffsets(Base, BaseIsVirtual, OffsetInLayoutClass);
600 typedef VTableComponentVectorTy::const_reverse_iterator const_iterator;
601 const_iterator components_begin()
const {
return Components.rbegin(); }
602 const_iterator components_end()
const {
return Components.rend(); }
604 const VCallOffsetMap &getVCallOffsets()
const {
return VCallOffsets; }
605 const VBaseOffsetOffsetsMapTy &getVBaseOffsetOffsets()
const {
606 return VBaseOffsetOffsets;
611 VCallAndVBaseOffsetBuilder::AddVCallAndVBaseOffsets(
BaseSubobject Base,
631 if (PrimaryBaseIsVirtual) {
633 "Primary vbase should have a zero offset!");
639 MostDerivedClassLayout.getVBaseClassOffset(PrimaryBase);
642 "Primary base should have a zero offset!");
647 AddVCallAndVBaseOffsets(
649 PrimaryBaseIsVirtual, RealBaseOffset);
652 AddVBaseOffsets(Base.
getBase(), RealBaseOffset);
656 AddVCallOffsets(Base, RealBaseOffset);
659 CharUnits VCallAndVBaseOffsetBuilder::getCurrentOffsetOffset()
const {
664 int64_t OffsetIndex = -(int64_t)(3 + Components.size());
668 CharUnits OffsetOffset = PointerWidth * OffsetIndex;
672 void VCallAndVBaseOffsetBuilder::AddVCallOffsets(
BaseSubobject Base,
685 "Primary base should have a zero offset!");
692 for (
const auto *MD : RD->
methods()) {
697 CharUnits OffsetOffset = getCurrentOffsetOffset();
701 if (!VCallOffsets.AddVCallOffset(MD, OffsetOffset))
708 FinalOverriders::OverriderInfo Overrider =
713 Offset = Overrider.Offset - VBaseOffset;
716 Components.push_back(
721 for (
const auto &B : RD->
bases()) {
725 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
726 if (BaseDecl == PrimaryBase)
739 VCallAndVBaseOffsetBuilder::AddVBaseOffsets(
const CXXRecordDecl *RD,
745 for (
const auto &B : RD->
bases()) {
746 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
749 if (B.isVirtual() && VisitedVirtualBases.insert(BaseDecl).second) {
754 assert(!VBaseOffsetOffsets.count(BaseDecl) &&
755 "vbase offset offset already exists!");
757 CharUnits VBaseOffsetOffset = getCurrentOffsetOffset();
758 VBaseOffsetOffsets.insert(
759 std::make_pair(BaseDecl, VBaseOffsetOffset));
761 Components.push_back(
766 AddVBaseOffsets(BaseDecl, OffsetInLayoutClass);
771 class ItaniumVTableBuilder {
776 PrimaryBasesSetVectorTy;
778 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits>
779 VBaseOffsetOffsetsMapTy;
781 typedef llvm::DenseMap<BaseSubobject, uint64_t>
784 typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVTableIndicesTy;
800 bool MostDerivedClassIsVirtual;
811 const FinalOverriders Overriders;
815 llvm::DenseMap<const CXXRecordDecl *, VCallOffsetMap> VCallOffsetsForVBases;
819 VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
825 AddressPointsMapTy AddressPoints;
839 const uint64_t VTableIndex;
842 uint64_t VTableIndex)
843 : BaseOffset(BaseOffset),
844 BaseOffsetInLayoutClass(BaseOffsetInLayoutClass),
845 VTableIndex(VTableIndex) { }
853 typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy;
857 MethodInfoMapTy MethodInfoMap;
861 MethodVTableIndicesTy MethodVTableIndices;
863 typedef llvm::DenseMap<uint64_t, ThunkInfo> VTableThunksMapTy;
867 VTableThunksMapTy VTableThunks;
870 typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
881 void ComputeThisAdjustments();
883 typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy;
887 VisitedVirtualBasesSetTy PrimaryVirtualBases;
895 BaseOffset ComputeThisAdjustmentBaseOffset(
BaseSubobject Base,
904 FinalOverriders::OverriderInfo Overrider);
932 CharUnits FirstBaseOffsetInLayoutClass)
const;
940 PrimaryBasesSetVectorTy &PrimaryBases);
955 bool BaseIsMorallyVirtual,
956 bool BaseIsVirtualInLayoutClass,
964 void LayoutSecondaryVTables(
BaseSubobject Base,
bool BaseIsMorallyVirtual,
971 VisitedVirtualBasesSetTy &VBases);
976 VisitedVirtualBasesSetTy &VBases);
980 bool isBuildingConstructorVTable()
const {
981 return MostDerivedClass != LayoutClass;
988 bool MostDerivedClassIsVirtual,
990 : VTables(VTables), MostDerivedClass(MostDerivedClass),
991 MostDerivedClassOffset(MostDerivedClassOffset),
992 MostDerivedClassIsVirtual(MostDerivedClassIsVirtual),
993 LayoutClass(LayoutClass),
Context(MostDerivedClass->getASTContext()),
994 Overriders(MostDerivedClass, MostDerivedClassOffset, LayoutClass) {
1000 dumpLayout(llvm::outs());
1003 uint64_t getNumThunks()
const {
1004 return Thunks.size();
1007 ThunksMapTy::const_iterator thunks_begin()
const {
1008 return Thunks.begin();
1011 ThunksMapTy::const_iterator thunks_end()
const {
1012 return Thunks.end();
1015 const VBaseOffsetOffsetsMapTy &getVBaseOffsetOffsets()
const {
1016 return VBaseOffsetOffsets;
1019 const AddressPointsMapTy &getAddressPoints()
const {
1020 return AddressPoints;
1023 MethodVTableIndicesTy::const_iterator vtable_indices_begin()
const {
1024 return MethodVTableIndices.begin();
1027 MethodVTableIndicesTy::const_iterator vtable_indices_end()
const {
1028 return MethodVTableIndices.end();
1033 uint64_t getNumVTableComponents()
const {
1034 return Components.size();
1038 return Components.begin();
1042 return Components.end();
1045 AddressPointsMapTy::const_iterator address_points_begin()
const {
1046 return AddressPoints.begin();
1049 AddressPointsMapTy::const_iterator address_points_end()
const {
1050 return AddressPoints.end();
1053 VTableThunksMapTy::const_iterator vtable_thunks_begin()
const {
1054 return VTableThunks.begin();
1057 VTableThunksMapTy::const_iterator vtable_thunks_end()
const {
1058 return VTableThunks.end();
1062 void dumpLayout(raw_ostream&);
1065 void ItaniumVTableBuilder::AddThunk(
const CXXMethodDecl *MD,
1067 assert(!isBuildingConstructorVTable() &&
1068 "Can't add thunks for construction vtable");
1073 if (std::find(ThunksVector.begin(), ThunksVector.end(), Thunk) !=
1077 ThunksVector.push_back(Thunk);
1080 typedef llvm::SmallPtrSet<const CXXMethodDecl *, 8> OverriddenMethodsSetTy;
1086 template <
class VisitorTy>
1088 visitAllOverriddenMethods(
const CXXMethodDecl *MD, VisitorTy &Visitor) {
1089 assert(MD->
isVirtual() &&
"Method is not virtual!");
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);
1112 void 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 VTableThunks[VTableIndex].This = ThisAdjustment;
1149 if (isa<CXXDestructorDecl>(MD)) {
1151 VTableThunks[VTableIndex + 1].This = ThisAdjustment;
1156 MethodInfoMap.clear();
1158 if (isBuildingConstructorVTable()) {
1163 for (
const auto &TI : VTableThunks) {
1168 switch (Component.
getKind()) {
1170 llvm_unreachable(
"Unexpected vtable component kind!");
1182 if (MD->
getParent() == MostDerivedClass)
1183 AddThunk(MD, Thunk);
1188 ItaniumVTableBuilder::ComputeReturnAdjustment(BaseOffset
Offset) {
1191 if (!Offset.isEmpty()) {
1192 if (Offset.VirtualBase) {
1194 if (Offset.DerivedClass == MostDerivedClass) {
1197 VBaseOffsetOffsets.lookup(Offset.VirtualBase).getQuantity();
1200 VTables.getVirtualBaseOffsetOffset(Offset.DerivedClass,
1201 Offset.VirtualBase).getQuantity();
1205 Adjustment.
NonVirtual = Offset.NonVirtualOffset.getQuantity();
1211 BaseOffset ItaniumVTableBuilder::ComputeThisAdjustmentBaseOffset(
1220 llvm_unreachable(
"Class must be derived from the passed in base class!");
1225 BaseOffset Offset = ComputeBaseOffset(Context, DerivedRD, Path);
1227 CharUnits OffsetToBaseSubobject = Offset.NonVirtualOffset;
1229 if (Offset.VirtualBase) {
1237 OffsetToBaseSubobject +=
1249 Offset.NonVirtualOffset = -Offset.NonVirtualOffset;
1254 return BaseOffset();
1259 FinalOverriders::OverriderInfo Overrider) {
1261 if (Overrider.Method->isPure())
1265 BaseOffsetInLayoutClass);
1267 BaseSubobject OverriderBaseSubobject(Overrider.Method->getParent(),
1271 BaseOffset Offset = ComputeThisAdjustmentBaseOffset(OverriddenBaseSubobject,
1272 OverriderBaseSubobject);
1273 if (Offset.isEmpty())
1278 if (Offset.VirtualBase) {
1280 VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[Offset.VirtualBase];
1282 if (VCallOffsets.empty()) {
1285 VCallAndVBaseOffsetBuilder
Builder(MostDerivedClass, MostDerivedClass,
1293 VCallOffsets = Builder.getVCallOffsets();
1297 VCallOffsets.getVCallOffsetOffset(MD).getQuantity();
1301 Adjustment.
NonVirtual = Offset.NonVirtualOffset.getQuantity();
1306 void ItaniumVTableBuilder::AddMethod(
const CXXMethodDecl *MD,
1309 assert(ReturnAdjustment.
isEmpty() &&
1310 "Destructor can't have return adjustment!");
1317 if (!ReturnAdjustment.
isEmpty())
1318 VTableThunks[Components.size()].Return = ReturnAdjustment;
1336 static bool OverridesIndirectMethodInBases(
1347 if (OverridesIndirectMethodInBases(OverriddenMD, Bases))
1354 bool ItaniumVTableBuilder::IsOverriderUsed(
1357 CharUnits FirstBaseOffsetInLayoutClass)
const {
1360 if (BaseOffsetInLayoutClass == FirstBaseOffsetInLayoutClass)
1369 if (Overrider->
getParent() == FirstBaseInPrimaryBaseChain)
1375 PrimaryBases.insert(RD);
1388 "Primary base should always be at offset 0!");
1395 if (LayoutClassLayout.getVBaseClassOffset(PrimaryBase) !=
1396 FirstBaseOffsetInLayoutClass) {
1402 "Primary base should always be at offset 0!");
1405 if (!PrimaryBases.insert(PrimaryBase))
1406 llvm_unreachable(
"Found a duplicate primary base!");
1413 return OverridesIndirectMethodInBases(Overrider, PrimaryBases);
1423 BasesSetVectorTy &Bases) {
1424 OverriddenMethodsSetTy OverriddenMethods;
1425 ComputeAllOverriddenMethods(MD, OverriddenMethods);
1428 llvm::make_range(Bases.rbegin(), Bases.rend())) {
1430 for (
const CXXMethodDecl *OverriddenMD : OverriddenMethods) {
1432 if (OverriddenMD->getParent() == PrimaryBase)
1433 return OverriddenMD;
1440 void ItaniumVTableBuilder::AddMethods(
1444 PrimaryBasesSetVectorTy &PrimaryBases) {
1459 CharUnits PrimaryBaseOffsetInLayoutClass;
1462 "Primary vbase should have a zero offset!");
1468 MostDerivedClassLayout.getVBaseClassOffset(PrimaryBase);
1473 PrimaryBaseOffsetInLayoutClass =
1477 "Primary base should have a zero offset!");
1480 PrimaryBaseOffsetInLayoutClass = BaseOffsetInLayoutClass;
1484 PrimaryBaseOffsetInLayoutClass, FirstBaseInPrimaryBaseChain,
1485 FirstBaseOffsetInLayoutClass, PrimaryBases);
1487 if (!PrimaryBases.insert(PrimaryBase))
1488 llvm_unreachable(
"Found a duplicate primary base!");
1494 NewVirtualFunctionsTy NewVirtualFunctions;
1497 for (
const auto *MD : RD->
methods()) {
1503 FinalOverriders::OverriderInfo Overrider =
1510 FindNearestOverriddenMethod(MD, PrimaryBases)) {
1511 if (ComputeReturnAdjustmentBaseOffset(Context, MD,
1512 OverriddenMD).isEmpty()) {
1515 assert(MethodInfoMap.count(OverriddenMD) &&
1516 "Did not find the overridden method!");
1517 MethodInfo &OverriddenMethodInfo = MethodInfoMap[OverriddenMD];
1519 MethodInfo MethodInfo(Base.
getBaseOffset(), BaseOffsetInLayoutClass,
1520 OverriddenMethodInfo.VTableIndex);
1522 assert(!MethodInfoMap.count(MD) &&
1523 "Should not have method info for this method yet!");
1525 MethodInfoMap.insert(std::make_pair(MD, MethodInfo));
1526 MethodInfoMap.erase(OverriddenMD);
1532 if (!isBuildingConstructorVTable() && OverriddenMD != MD) {
1535 ComputeThisAdjustment(OverriddenMD, BaseOffsetInLayoutClass,
1539 Overrider.Method->getParent() == MostDerivedClass) {
1544 BaseOffset ReturnAdjustmentOffset =
1545 ComputeReturnAdjustmentBaseOffset(Context, Overrider.Method, MD);
1546 ReturnAdjustment ReturnAdjustment =
1547 ComputeReturnAdjustment(ReturnAdjustmentOffset);
1550 AddThunk(Overrider.Method,
1551 ThunkInfo(ThisAdjustment, ReturnAdjustment));
1560 if (MD->isImplicit()) {
1565 assert(!ImplicitVirtualDtor &&
1566 "Did already see an implicit virtual dtor!");
1567 ImplicitVirtualDtor = DD;
1572 NewVirtualFunctions.push_back(MD);
1575 if (ImplicitVirtualDtor)
1576 NewVirtualFunctions.push_back(ImplicitVirtualDtor);
1580 FinalOverriders::OverriderInfo Overrider =
1584 MethodInfo MethodInfo(Base.
getBaseOffset(), BaseOffsetInLayoutClass,
1587 assert(!MethodInfoMap.count(MD) &&
1588 "Should not have method info for this method yet!");
1589 MethodInfoMap.insert(std::make_pair(MD, MethodInfo));
1593 if (!IsOverriderUsed(OverriderMD, BaseOffsetInLayoutClass,
1594 FirstBaseInPrimaryBaseChain,
1595 FirstBaseOffsetInLayoutClass)) {
1602 BaseOffset ReturnAdjustmentOffset;
1603 if (!OverriderMD->
isPure()) {
1604 ReturnAdjustmentOffset =
1605 ComputeReturnAdjustmentBaseOffset(Context, OverriderMD, MD);
1608 ReturnAdjustment ReturnAdjustment =
1609 ComputeReturnAdjustment(ReturnAdjustmentOffset);
1611 AddMethod(Overrider.Method, ReturnAdjustment);
1615 void ItaniumVTableBuilder::LayoutVTable() {
1616 LayoutPrimaryAndSecondaryVTables(
BaseSubobject(MostDerivedClass,
1619 MostDerivedClassIsVirtual,
1620 MostDerivedClassOffset);
1622 VisitedVirtualBasesSetTy VBases;
1625 DeterminePrimaryVirtualBases(MostDerivedClass, MostDerivedClassOffset,
1629 LayoutVTablesForVirtualBases(MostDerivedClass, VBases);
1632 bool IsAppleKext = Context.
getLangOpts().AppleKext;
1637 void ItaniumVTableBuilder::LayoutPrimaryAndSecondaryVTables(
1639 bool BaseIsVirtualInLayoutClass,
CharUnits OffsetInLayoutClass) {
1643 VCallAndVBaseOffsetBuilder
Builder(MostDerivedClass, LayoutClass, &Overriders,
1644 Base, BaseIsVirtualInLayoutClass,
1645 OffsetInLayoutClass);
1646 Components.append(Builder.components_begin(), Builder.components_end());
1649 if (BaseIsVirtualInLayoutClass && !Builder.getVCallOffsets().empty()) {
1650 VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[Base.
getBase()];
1652 if (VCallOffsets.empty())
1653 VCallOffsets = Builder.getVCallOffsets();
1658 if (Base.
getBase() == MostDerivedClass)
1659 VBaseOffsetOffsets = Builder.getVBaseOffsetOffsets();
1662 CharUnits OffsetToTop = MostDerivedClassOffset - OffsetInLayoutClass;
1668 uint64_t AddressPoint = Components.size();
1671 PrimaryBasesSetVectorTy PrimaryBases;
1672 AddMethods(Base, OffsetInLayoutClass,
1673 Base.
getBase(), OffsetInLayoutClass,
1677 if (RD == MostDerivedClass) {
1678 assert(MethodVTableIndices.empty());
1679 for (
const auto &
I : MethodInfoMap) {
1681 const MethodInfo &MI =
I.second;
1684 = MI.VTableIndex - AddressPoint;
1686 = MI.VTableIndex + 1 - AddressPoint;
1688 MethodVTableIndices[MD] = MI.VTableIndex - AddressPoint;
1694 ComputeThisAdjustments();
1698 AddressPoints.insert(std::make_pair(
1715 OffsetInLayoutClass) {
1725 LayoutSecondaryVTables(Base, BaseIsMorallyVirtual, OffsetInLayoutClass);
1729 ItaniumVTableBuilder::LayoutSecondaryVTables(
BaseSubobject Base,
1730 bool BaseIsMorallyVirtual,
1741 for (
const auto &B : RD->
bases()) {
1746 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
1752 if (isBuildingConstructorVTable()) {
1758 if (!BaseIsMorallyVirtual && !BaseDecl->
getNumVBases())
1767 OffsetInLayoutClass + RelativeBaseOffset;
1771 if (BaseDecl == PrimaryBase) {
1773 BaseIsMorallyVirtual, BaseOffsetInLayoutClass);
1778 LayoutPrimaryAndSecondaryVTables(
1780 BaseIsMorallyVirtual,
1782 BaseOffsetInLayoutClass);
1786 void ItaniumVTableBuilder::DeterminePrimaryVirtualBases(
1788 VisitedVirtualBasesSetTy &VBases) {
1796 bool IsPrimaryVirtualBase =
true;
1798 if (isBuildingConstructorVTable()) {
1804 CharUnits PrimaryBaseOffsetInLayoutClass =
1809 if (PrimaryBaseOffsetInLayoutClass != OffsetInLayoutClass)
1810 IsPrimaryVirtualBase =
false;
1813 if (IsPrimaryVirtualBase)
1814 PrimaryVirtualBases.insert(PrimaryBase);
1819 for (
const auto &B : RD->
bases()) {
1820 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
1824 if (B.isVirtual()) {
1825 if (!VBases.insert(BaseDecl).second)
1831 BaseOffsetInLayoutClass =
1834 BaseOffsetInLayoutClass =
1838 DeterminePrimaryVirtualBases(BaseDecl, BaseOffsetInLayoutClass, VBases);
1842 void ItaniumVTableBuilder::LayoutVTablesForVirtualBases(
1843 const CXXRecordDecl *RD, VisitedVirtualBasesSetTy &VBases) {
1848 for (
const auto &B : RD->
bases()) {
1849 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
1854 !PrimaryVirtualBases.count(BaseDecl) &&
1855 VBases.insert(BaseDecl).second) {
1866 LayoutPrimaryAndSecondaryVTables(
1870 BaseOffsetInLayoutClass);
1876 LayoutVTablesForVirtualBases(BaseDecl, VBases);
1881 void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
1885 if (isBuildingConstructorVTable()) {
1886 Out <<
"Construction vtable for ('";
1889 Out << MostDerivedClassOffset.
getQuantity() <<
") in '";
1892 Out <<
"Vtable for '";
1895 Out <<
"' (" << Components.size() <<
" entries).\n";
1901 std::multimap<uint64_t, BaseSubobject> AddressPointsByIndex;
1902 for (
const auto &AP : AddressPoints) {
1904 uint64_t Index = AP.second;
1906 AddressPointsByIndex.insert(std::make_pair(Index, Base));
1909 for (
unsigned I = 0,
E = Components.size();
I !=
E; ++
I) {
1912 Out << llvm::format(
"%4d | ",
I);
1917 switch (Component.
getKind()) {
1920 Out <<
"vcall_offset ("
1926 Out <<
"vbase_offset ("
1932 Out <<
"offset_to_top ("
1953 Out <<
" [deleted]";
1959 Out <<
"\n [return adjustment: ";
1964 Out <<
" vbase offset offset";
1972 Out <<
"\n [this adjustment: ";
1977 Out <<
" vcall offset offset";
1996 Out <<
"() [complete]";
1998 Out <<
"() [deleting]";
2007 Out <<
"\n [this adjustment: ";
2012 Out <<
" vcall offset offset";
2028 Out <<
"[unused] " << Str;
2039 if (AddressPointsByIndex.count(NextIndex)) {
2040 if (AddressPointsByIndex.count(NextIndex) == 1) {
2042 AddressPointsByIndex.find(NextIndex)->second;
2047 Out <<
") vtable address --\n";
2050 AddressPointsByIndex.lower_bound(NextIndex)->second.getBaseOffset();
2053 std::set<std::string> ClassNames;
2054 for (
const auto &
I :
2055 llvm::make_range(AddressPointsByIndex.equal_range(NextIndex))) {
2056 assert(
I.second.getBaseOffset() == BaseOffset &&
2057 "Invalid base offset!");
2059 ClassNames.insert(RD->getQualifiedNameAsString());
2062 for (
const std::string &
Name : ClassNames) {
2063 Out <<
" -- (" <<
Name;
2064 Out <<
", " << BaseOffset.
getQuantity() <<
") vtable address --\n";
2072 if (isBuildingConstructorVTable())
2079 std::map<std::string, CharUnits> ClassNamesAndOffsets;
2080 for (
const auto &
I : VBaseOffsetOffsets) {
2081 std::string ClassName =
I.first->getQualifiedNameAsString();
2083 ClassNamesAndOffsets.insert(std::make_pair(ClassName, OffsetOffset));
2086 Out <<
"Virtual base offset offsets for '";
2089 Out << ClassNamesAndOffsets.size();
2090 Out << (ClassNamesAndOffsets.size() == 1 ?
" entry" :
" entries") <<
").\n";
2092 for (
const auto &
I : ClassNamesAndOffsets)
2093 Out <<
" " <<
I.first <<
" | " <<
I.second.getQuantity() <<
'\n';
2098 if (!Thunks.empty()) {
2100 std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls;
2102 for (
const auto &
I : Thunks) {
2104 std::string MethodName =
2108 MethodNamesAndDecls.insert(std::make_pair(MethodName, MD));
2111 for (
const auto &
I : MethodNamesAndDecls) {
2112 const std::string &MethodName =
I.first;
2115 ThunkInfoVectorTy ThunksVector = Thunks[MD];
2116 std::sort(ThunksVector.begin(), ThunksVector.end(),
2118 assert(LHS.
Method ==
nullptr && RHS.Method ==
nullptr);
2119 return std::tie(LHS.
This, LHS.
Return) < std::tie(RHS.This, RHS.Return);
2122 Out <<
"Thunks for '" << MethodName <<
"' (" << ThunksVector.size();
2123 Out << (ThunksVector.size() == 1 ?
" entry" :
" entries") <<
").\n";
2125 for (
unsigned I = 0,
E = ThunksVector.size();
I !=
E; ++
I) {
2128 Out << llvm::format(
"%4d | ",
I);
2133 Out <<
" non-virtual";
2136 Out <<
" vbase offset offset";
2145 Out <<
"this adjustment: ";
2150 Out <<
" vcall offset offset";
2163 std::map<uint64_t, std::string> IndicesMap;
2165 for (
const auto *MD : MostDerivedClass->
methods()) {
2171 std::string MethodName =
2177 assert(MethodVTableIndices.count(GD));
2178 uint64_t VTableIndex = MethodVTableIndices[GD];
2179 IndicesMap[VTableIndex] = MethodName +
" [complete]";
2180 IndicesMap[VTableIndex + 1] = MethodName +
" [deleting]";
2182 assert(MethodVTableIndices.count(MD));
2183 IndicesMap[MethodVTableIndices[MD]] = MethodName;
2188 if (!IndicesMap.empty()) {
2189 Out <<
"VTable indices for '";
2191 Out <<
"' (" << IndicesMap.size() <<
" entries).\n";
2193 for (
const auto &
I : IndicesMap) {
2194 uint64_t VTableIndex =
I.first;
2195 const std::string &MethodName =
I.second;
2197 Out << llvm::format(
"%4" PRIu64
" | ", VTableIndex) << MethodName
2208 uint64_t NumVTableThunks,
2211 bool IsMicrosoftABI)
2212 : NumVTableComponents(NumVTableComponents),
2214 NumVTableThunks(NumVTableThunks),
2216 AddressPoints(AddressPoints),
2217 IsMicrosoftABI(IsMicrosoftABI) {
2218 std::copy(VTableComponents, VTableComponents+NumVTableComponents,
2219 this->VTableComponents.get());
2220 std::copy(VTableThunks, VTableThunks+NumVTableThunks,
2221 this->VTableThunks.get());
2222 std::sort(this->VTableThunks.get(),
2223 this->VTableThunks.get() + NumVTableThunks,
2226 assert((LHS.first != RHS.first || LHS.second == RHS.second) &&
2227 "Different thunks should have unique indices!");
2228 return LHS.first < RHS.first;
2238 llvm::DeleteContainerSeconds(VTableLayouts);
2243 if (I != MethodVTableIndices.end())
2248 computeVTableRelatedInformation(RD);
2250 I = MethodVTableIndices.find(GD);
2251 assert(I != MethodVTableIndices.end() &&
"Did not find index!");
2258 ClassPairTy ClassPair(RD, VBase);
2261 VirtualBaseClassOffsetOffsets.find(ClassPair);
2262 if (I != VirtualBaseClassOffsetOffsets.end())
2265 VCallAndVBaseOffsetBuilder
Builder(RD, RD,
nullptr,
2270 for (
const auto &I :
Builder.getVBaseOffsetOffsets()) {
2272 ClassPairTy ClassPair(RD, I.first);
2274 VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I.second));
2277 I = VirtualBaseClassOffsetOffsets.find(ClassPair);
2278 assert(I != VirtualBaseClassOffsetOffsets.end() &&
"Did not find index!");
2285 VTableThunks(Builder.vtable_thunks_begin(), Builder.vtable_thunks_end());
2287 return new VTableLayout(Builder.getNumVTableComponents(),
2288 Builder.vtable_component_begin(),
2289 VTableThunks.size(),
2290 VTableThunks.data(),
2291 Builder.getAddressPoints(),
2296 ItaniumVTableContext::computeVTableRelatedInformation(
const CXXRecordDecl *RD) {
2307 MethodVTableIndices.insert(
Builder.vtable_indices_begin(),
2308 Builder.vtable_indices_end());
2322 if (VirtualBaseClassOffsetOffsets.count(std::make_pair(RD, VBase)))
2325 for (
const auto &
I :
Builder.getVBaseOffsetOffsets()) {
2327 ClassPairTy ClassPair(RD,
I.first);
2329 VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair,
I.second));
2335 bool MostDerivedClassIsVirtual,
const CXXRecordDecl *LayoutClass) {
2336 ItaniumVTableBuilder
Builder(*
this, MostDerivedClass, MostDerivedClassOffset,
2337 MostDerivedClassIsVirtual, LayoutClass);
2385 class VFTableBuilder {
2389 typedef llvm::DenseMap<GlobalDecl, MethodVFTableLocation>
2390 MethodVFTableLocationsTy;
2392 typedef llvm::iterator_range<MethodVFTableLocationsTy::const_iterator>
2393 method_locations_range;
2411 const FinalOverriders Overriders;
2416 MethodVFTableLocationsTy MethodVFTableLocations;
2419 bool HasRTTIComponent =
false;
2426 const uint64_t VBTableIndex;
2429 const uint64_t VFTableIndex;
2440 MethodInfo(uint64_t VBTableIndex, uint64_t VFTableIndex,
2441 bool UsesExtraSlot =
false)
2442 : VBTableIndex(VBTableIndex), VFTableIndex(VFTableIndex),
2443 Shadowed(
false), UsesExtraSlot(UsesExtraSlot) {}
2446 : VBTableIndex(0), VFTableIndex(0), Shadowed(
false),
2447 UsesExtraSlot(
false) {}
2450 typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy;
2454 MethodInfoMapTy MethodInfoMap;
2456 typedef llvm::DenseMap<uint64_t, ThunkInfo> VTableThunksMapTy;
2460 VTableThunksMapTy VTableThunks;
2463 typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
2474 if (std::find(ThunksVector.begin(), ThunksVector.end(), Thunk) !=
2478 ThunksVector.push_back(Thunk);
2483 CharUnits ComputeThisOffset(FinalOverriders::OverriderInfo Overrider);
2485 void CalculateVtordispAdjustment(FinalOverriders::OverriderInfo Overrider,
2492 VTableThunks[Components.size()] = TI;
2497 "Destructor can't have return adjustment!");
2508 BasesSetVectorTy &VisitedBases);
2510 void LayoutVFTable() {
2512 if (HasRTTIComponent)
2515 BasesSetVectorTy VisitedBases;
2518 assert((HasRTTIComponent ? Components.size() - 1 : Components.size()) &&
2519 "vftable can't be empty");
2521 assert(MethodVFTableLocations.empty());
2522 for (
const auto &
I : MethodInfoMap) {
2524 const MethodInfo &MI =
I.second;
2527 if (MD->
getParent() != MostDerivedClass || MI.Shadowed)
2529 MethodVFTableLocation Loc(MI.VBTableIndex, WhichVFPtr.getVBaseWithVPtr(),
2530 WhichVFPtr.NonVirtualOffset, MI.VFTableIndex);
2534 MethodVFTableLocations[MD] = Loc;
2543 Context(MostDerivedClass->getASTContext()),
2544 MostDerivedClass(MostDerivedClass),
2545 MostDerivedClassLayout(
Context.getASTRecordLayout(MostDerivedClass)),
2547 Overriders(MostDerivedClass,
CharUnits(), MostDerivedClass) {
2554 HasRTTIComponent =
true;
2559 dumpLayout(llvm::outs());
2562 uint64_t getNumThunks()
const {
return Thunks.size(); }
2564 ThunksMapTy::const_iterator thunks_begin()
const {
return Thunks.begin(); }
2566 ThunksMapTy::const_iterator thunks_end()
const {
return Thunks.end(); }
2568 method_locations_range vtable_locations()
const {
2569 return method_locations_range(MethodVFTableLocations.begin(),
2570 MethodVFTableLocations.end());
2573 uint64_t getNumVTableComponents()
const {
return Components.size(); }
2576 return Components.begin();
2580 return Components.end();
2583 VTableThunksMapTy::const_iterator vtable_thunks_begin()
const {
2584 return VTableThunks.begin();
2587 VTableThunksMapTy::const_iterator vtable_thunks_end()
const {
2588 return VTableThunks.end();
2591 void dumpLayout(raw_ostream &);
2651 VFTableBuilder::ComputeThisOffset(FinalOverriders::OverriderInfo Overrider) {
2652 BasesSetVectorTy Bases;
2656 OverriddenMethodsSetTy VisitedOverriddenMethods;
2657 auto InitialOverriddenDefinitionCollector = [&](
2659 if (OverriddenMD->size_overridden_methods() == 0)
2660 Bases.insert(OverriddenMD->getParent());
2662 return VisitedOverriddenMethods.insert(OverriddenMD).second;
2664 visitAllOverriddenMethods(Overrider.Method,
2665 InitialOverriddenDefinitionCollector);
2670 if (Bases.size() == 0)
2671 return Overrider.Offset;
2674 Overrider.Method->getParent()->lookupInBases(
2690 CharUnits ThisOffset = Overrider.Offset;
2697 QualType CurTy = Element.Base->getType();
2702 if (Element.Base->isVirtual()) {
2713 LastVBaseOffset = ThisOffset =
2720 if (isa<CXXDestructorDecl>(Overrider.Method)) {
2721 if (LastVBaseOffset.
isZero()) {
2725 ThisOffset = Overrider.Offset;
2729 ThisOffset = LastVBaseOffset;
2733 if (Ret > ThisOffset || First) {
2739 assert(!First &&
"Method not found in the given subobject?");
2841 void VFTableBuilder::CalculateVtordispAdjustment(
2842 FinalOverriders::OverriderInfo Overrider,
CharUnits ThisOffset,
2845 MostDerivedClassLayout.getVBaseOffsetsMap();
2846 const ASTRecordLayout::VBaseOffsetsMapTy::const_iterator &VBaseMapEntry =
2847 VBaseMap.find(WhichVFPtr.getVBaseWithVPtr());
2848 assert(VBaseMapEntry != VBaseMap.end());
2852 if (!VBaseMapEntry->second.hasVtorDisp() ||
2853 Overrider.VirtualBase == WhichVFPtr.getVBaseWithVPtr())
2858 CharUnits OffsetOfVBaseWithVFPtr = VBaseMapEntry->second.VBaseOffset;
2860 (OffsetOfVBaseWithVFPtr - WhichVFPtr.FullOffsetInMDC).getQuantity() - 4;
2864 if (Overrider.Method->getParent() == MostDerivedClass ||
2865 !Overrider.VirtualBase)
2871 (OffsetOfVBaseWithVFPtr + WhichVFPtr.NonVirtualOffset -
2872 MostDerivedClassLayout.getVBPtrOffset()).getQuantity();
2877 TA.
NonVirtual = (ThisOffset - Overrider.Offset).getQuantity();
2891 typedef llvm::DenseMap<DeclarationName, unsigned> VisitedGroupIndicesTy;
2892 VisitedGroupIndicesTy VisitedGroupIndices;
2893 for (
const auto *D : RD->
decls()) {
2894 const auto *ND = dyn_cast<
NamedDecl>(D);
2899 std::tie(J, Inserted) = VisitedGroupIndices.insert(
2900 std::make_pair(ND->getDeclName(), Groups.size()));
2902 Groups.push_back(MethodGroup());
2903 if (
const auto *MD = dyn_cast<CXXMethodDecl>(ND))
2908 for (
const MethodGroup &Group : Groups)
2909 VirtualMethods.append(Group.rbegin(), Group.rend());
2913 for (
const auto &B : RD->
bases()) {
2914 if (B.isVirtual() && B.getType()->getAsCXXRecordDecl() == Base)
2922 BasesSetVectorTy &VisitedBases) {
2932 const CXXRecordDecl *NextBase =
nullptr, *NextLastVBase = LastVBase;
2934 if (BaseDepth < WhichVFPtr.PathToBaseWithVPtr.size()) {
2935 NextBase = WhichVFPtr.PathToBaseWithVPtr[BaseDepth];
2937 NextLastVBase = NextBase;
2938 NextBaseOffset = MostDerivedClassLayout.getVBaseClassOffset(NextBase);
2945 "No primary virtual bases in this ABI");
2946 NextBase = PrimaryBase;
2951 AddMethods(
BaseSubobject(NextBase, NextBaseOffset), BaseDepth + 1,
2952 NextLastVBase, VisitedBases);
2953 if (!VisitedBases.insert(NextBase))
2954 llvm_unreachable(
"Found a duplicate primary base!");
2970 FinalOverriders::OverriderInfo FinalOverrider =
2972 const CXXMethodDecl *FinalOverriderMD = FinalOverrider.Method;
2974 FindNearestOverriddenMethod(MD, VisitedBases);
2977 bool ReturnAdjustingThunk =
false, ForceReturnAdjustmentMangling =
false;
2978 CharUnits ThisOffset = ComputeThisOffset(FinalOverrider);
2980 (ThisOffset - WhichVFPtr.FullOffsetInMDC).getQuantity();
2981 if ((OverriddenMD || FinalOverriderMD != MD) &&
2982 WhichVFPtr.getVBaseWithVPtr())
2983 CalculateVtordispAdjustment(FinalOverrider, ThisOffset,
2984 ThisAdjustmentOffset);
2990 MethodInfoMap.find(OverriddenMD);
2993 if (OverriddenMDIterator == MethodInfoMap.end())
2996 MethodInfo &OverriddenMethodInfo = OverriddenMDIterator->second;
3003 ReturnAdjustingThunk = !ComputeReturnAdjustmentBaseOffset(
3004 Context, MD, OverriddenMD).isEmpty() ||
3005 OverriddenMethodInfo.UsesExtraSlot;
3007 if (!ReturnAdjustingThunk) {
3010 MethodInfo MI(OverriddenMethodInfo.VBTableIndex,
3011 OverriddenMethodInfo.VFTableIndex);
3012 MethodInfoMap.erase(OverriddenMDIterator);
3014 assert(!MethodInfoMap.count(MD) &&
3015 "Should not have method info for this method yet!");
3016 MethodInfoMap.insert(std::make_pair(MD, MI));
3022 OverriddenMethodInfo.Shadowed =
true;
3026 ForceReturnAdjustmentMangling =
3027 !(MD == FinalOverriderMD && ThisAdjustmentOffset.
isEmpty());
3028 }
else if (Base.
getBaseOffset() != WhichVFPtr.FullOffsetInMDC ||
3040 MethodInfo MI(VBIndex,
3041 HasRTTIComponent ? Components.size() - 1 : Components.size(),
3042 ReturnAdjustingThunk);
3044 assert(!MethodInfoMap.count(MD) &&
3045 "Should not have method info for this method yet!");
3046 MethodInfoMap.insert(std::make_pair(MD, MI));
3050 BaseOffset ReturnAdjustmentOffset;
3052 if (!FinalOverriderMD->
isPure()) {
3053 ReturnAdjustmentOffset =
3054 ComputeReturnAdjustmentBaseOffset(
Context, FinalOverriderMD, MD);
3056 if (!ReturnAdjustmentOffset.isEmpty()) {
3057 ForceReturnAdjustmentMangling =
true;
3059 ReturnAdjustmentOffset.NonVirtualOffset.getQuantity();
3060 if (ReturnAdjustmentOffset.VirtualBase) {
3067 ReturnAdjustmentOffset.VirtualBase);
3071 AddMethod(FinalOverriderMD,
3072 ThunkInfo(ThisAdjustmentOffset, ReturnAdjustment,
3073 ForceReturnAdjustmentMangling ? MD :
nullptr));
3079 llvm::make_range(Path.rbegin(), Path.rend())) {
3081 Elem->printQualifiedName(Out);
3087 bool ContinueFirstLine) {
3088 const ReturnAdjustment &R = TI.
Return;
3089 bool Multiline =
false;
3090 const char *LinePrefix =
"\n ";
3092 if (!ContinueFirstLine)
3094 Out <<
"[return adjustment (to type '"
3107 if (Multiline || !ContinueFirstLine)
3109 Out <<
"[this adjustment: ";
3117 Out << LinePrefix <<
" vboffset at "
3125 void VFTableBuilder::dumpLayout(raw_ostream &Out) {
3126 Out <<
"VFTable for ";
3130 Out <<
"' (" << Components.size()
3131 << (Components.size() == 1 ?
" entry" :
" entries") <<
").\n";
3133 for (
unsigned I = 0,
E = Components.size();
I !=
E; ++
I) {
3134 Out << llvm::format(
"%4d | ",
I);
3139 switch (Component.
getKind()) {
3157 Out <<
" [deleted]";
3170 Out <<
"() [scalar deleting]";
3178 "No return adjustment needed for destructors!");
3189 "Unexpected vftable component type %0 for component number %1");
3190 Diags.
Report(MostDerivedClass->getLocation(), DiagID)
3199 if (!Thunks.empty()) {
3201 std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls;
3203 for (
const auto &
I : Thunks) {
3208 MethodNamesAndDecls.insert(std::make_pair(MethodName, MD));
3211 for (
const auto &MethodNameAndDecl : MethodNamesAndDecls) {
3212 const std::string &MethodName = MethodNameAndDecl.first;
3215 ThunkInfoVectorTy ThunksVector = Thunks[MD];
3216 std::stable_sort(ThunksVector.begin(), ThunksVector.end(),
3220 return std::tie(LHS.
This, LHS.
Return) < std::tie(RHS.This, RHS.Return);
3223 Out <<
"Thunks for '" << MethodName <<
"' (" << ThunksVector.size();
3224 Out << (ThunksVector.size() == 1 ?
" entry" :
" entries") <<
").\n";
3226 for (
unsigned I = 0,
E = ThunksVector.size();
I !=
E; ++
I) {
3229 Out << llvm::format(
"%4d | ",
I);
3273 void MicrosoftVTableContext::computeVTablePaths(
bool ForVBTables,
3276 assert(Paths.empty());
3280 if (ForVBTables ? Layout.hasOwnVBPtr() : Layout.hasOwnVFPtr())
3285 llvm::SmallPtrSet<const CXXRecordDecl*, 4> VBasesSeen;
3286 for (
const auto &B : RD->
bases()) {
3287 const CXXRecordDecl *Base = B.getType()->getAsCXXRecordDecl();
3288 if (B.isVirtual() && VBasesSeen.count(Base))
3297 for (
VPtrInfo *BaseInfo : BasePaths) {
3315 Base == (ForVBTables ? Layout.getBaseSharingVBPtr()
3316 : Layout.getPrimaryBase()))
3335 VBasesSeen.insert(Base);
3339 for (
const auto &VB : Base->
vbases())
3340 VBasesSeen.insert(VB.getType()->getAsCXXRecordDecl());
3345 bool Changed =
true;
3367 std::sort(PathsSorted.begin(), PathsSorted.end(),
3371 bool Changed =
false;
3372 for (
size_t I = 0,
E = PathsSorted.size();
I !=
E;) {
3374 size_t BucketStart =
I;
3377 }
while (
I !=
E && PathsSorted[BucketStart]->MangledPath ==
3378 PathsSorted[
I]->MangledPath);
3381 if (
I - BucketStart > 1) {
3382 for (
size_t II = BucketStart; II !=
I; ++II)
3384 assert(Changed &&
"no paths were extended to fix ambiguity");
3391 for (
auto &P : VFPtrLocations)
3392 llvm::DeleteContainerPointers(*P.second);
3393 llvm::DeleteContainerSeconds(VFPtrLocations);
3394 llvm::DeleteContainerSeconds(VFTableLayouts);
3395 llvm::DeleteContainerSeconds(VBaseInfo);
3399 typedef llvm::SetVector<BaseSubobject, std::vector<BaseSubobject>,
3409 FullPathTy &FullPath,
3410 std::list<FullPathTy> &Paths) {
3412 Paths.push_back(FullPath);
3419 const CXXRecordDecl *Base = BS.getType()->getAsCXXRecordDecl();
3425 BaseWithVPtr, FullPath, Paths);
3426 FullPath.pop_back();
3432 FullPaths.remove_if([&](
const FullPathTy &SpecificPath) {
3433 for (
const FullPathTy &OtherPath : FullPaths) {
3434 if (&SpecificPath == &OtherPath)
3436 if (std::all_of(SpecificPath.begin(), SpecificPath.end(),
3438 return OtherPath.count(BSO) != 0;
3449 const FullPathTy &FullPath) {
3470 : Offset + Layout.getBaseClassOffset(Base);
3481 std::list<FullPathTy> &FullPaths) {
3483 if (FullPaths.empty())
3485 if (FullPaths.size() == 1)
3486 return &FullPaths.front();
3488 const FullPathTy *BestPath =
nullptr;
3489 typedef std::set<const CXXMethodDecl *> OverriderSetTy;
3490 OverriderSetTy LastOverrides;
3491 for (
const FullPathTy &SpecificPath : FullPaths) {
3492 assert(!SpecificPath.empty());
3493 OverriderSetTy CurrentOverrides;
3494 const CXXRecordDecl *TopLevelRD = SpecificPath.begin()->getBase();
3499 FinalOverriders Overriders(TopLevelRD,
CharUnits::Zero(), TopLevelRD);
3503 FinalOverriders::OverriderInfo OI =
3508 if (ComputeReturnAdjustmentBaseOffset(Context, OverridingMethod, MD)
3514 if (std::none_of(SpecificPath.begin(), SpecificPath.end(),
3516 return BSO.getBase() == OverridingParent;
3519 CurrentOverrides.insert(OverridingMethod);
3521 OverriderSetTy NewOverrides =
3522 llvm::set_difference(CurrentOverrides, LastOverrides);
3523 if (NewOverrides.empty())
3525 OverriderSetTy MissingOverrides =
3526 llvm::set_difference(LastOverrides, CurrentOverrides);
3527 if (MissingOverrides.empty()) {
3529 BestPath = &SpecificPath;
3530 std::swap(CurrentOverrides, LastOverrides);
3535 const CXXMethodDecl *ConflictMD = *MissingOverrides.begin();
3536 Diags.
Report(RD->getLocation(), diag::err_vftable_ambiguous_component)
3538 Diags.
Report(CovariantMD->getLocation(), diag::note_covariant_thunk)
3540 Diags.
Report(ConflictMD->getLocation(), diag::note_covariant_thunk)
3546 return BestPath ? BestPath : &FullPaths.front();
3553 FullPathTy FullPath;
3554 std::list<FullPathTy> FullPaths;
3558 BaseSubobject(Info->BaseWithVPtr, Info->FullOffsetInMDC), FullPath,
3562 Info->PathToBaseWithVPtr.clear();
3563 if (
const FullPathTy *BestPath =
3566 Info->PathToBaseWithVPtr.push_back(BSO.getBase());
3571 void MicrosoftVTableContext::computeVTableRelatedInformation(
3576 if (VFPtrLocations.count(RD))
3582 computeVTablePaths(
false, RD, *VFPtrs);
3584 VFPtrLocations[RD] = VFPtrs;
3586 MethodVFTableLocationsTy NewMethodLocations;
3587 for (
const VPtrInfo *VFPtr : *VFPtrs) {
3588 VFTableBuilder
Builder(*
this, RD, VFPtr);
3590 VFTableIdTy
id(RD, VFPtr->FullOffsetInMDC);
3591 assert(VFTableLayouts.count(
id) == 0);
3595 Builder.getNumVTableComponents(),
Builder.vtable_component_begin(),
3596 VTableThunks.size(), VTableThunks.data(), EmptyAddressPointsMap,
true);
3599 for (
const auto &Loc :
Builder.vtable_locations()) {
3601 MethodVFTableLocation NewLoc = Loc.second;
3602 auto M = NewMethodLocations.find(GD);
3603 if (M == NewMethodLocations.end() || NewLoc < M->second)
3604 NewMethodLocations[GD] = NewLoc;
3608 MethodVFTableLocations.insert(NewMethodLocations.begin(),
3609 NewMethodLocations.end());
3611 dumpMethodLocations(RD, NewMethodLocations, llvm::outs());
3614 void MicrosoftVTableContext::dumpMethodLocations(
3615 const CXXRecordDecl *RD,
const MethodVFTableLocationsTy &NewMethods,
3619 std::map<MethodVFTableLocation, std::string> IndicesMap;
3620 bool HasNonzeroOffset =
false;
3622 for (
const auto &
I : NewMethods) {
3623 const CXXMethodDecl *MD = cast<const CXXMethodDecl>(
I.first.getDecl());
3629 if (isa<CXXDestructorDecl>(MD)) {
3630 IndicesMap[
I.second] = MethodName +
" [scalar deleting]";
3632 IndicesMap[
I.second] = MethodName;
3635 if (!
I.second.VFPtrOffset.isZero() ||
I.second.VBTableIndex != 0)
3636 HasNonzeroOffset =
true;
3640 if (!IndicesMap.empty()) {
3641 Out <<
"VFTable indices for ";
3644 Out <<
"' (" << IndicesMap.size()
3645 << (IndicesMap.size() == 1 ?
" entry" :
" entries") <<
").\n";
3648 uint64_t LastVBIndex = 0;
3649 for (
const auto &
I : IndicesMap) {
3651 uint64_t VBIndex =
I.first.VBTableIndex;
3652 if (HasNonzeroOffset &&
3653 (VFPtrOffset != LastVFPtrOffset || VBIndex != LastVBIndex)) {
3654 assert(VBIndex > LastVBIndex || VFPtrOffset > LastVFPtrOffset);
3655 Out <<
" -- accessible via ";
3657 Out <<
"vbtable index " << VBIndex <<
", ";
3658 Out <<
"vfptr at offset " << VFPtrOffset.
getQuantity() <<
" --\n";
3659 LastVFPtrOffset = VFPtrOffset;
3660 LastVBIndex = VBIndex;
3663 uint64_t VTableIndex =
I.first.Index;
3664 const std::string &MethodName =
I.second;
3665 Out << llvm::format(
"%4" PRIu64
" | ", VTableIndex) << MethodName <<
'\n';
3673 const VirtualBaseInfo *MicrosoftVTableContext::computeVBTableRelatedInformation(
3686 computeVTablePaths(
true, RD, VBI->
VBPtrPaths);
3694 computeVBTableRelatedInformation(VBPtrBase);
3702 for (
const auto &VB : RD->
vbases()) {
3703 const CXXRecordDecl *CurVBase = VB.getType()->getAsCXXRecordDecl();
3713 const VirtualBaseInfo *VBInfo = computeVBTableRelatedInformation(Derived);
3720 return computeVBTableRelatedInformation(RD)->
VBPtrPaths;
3725 computeVTableRelatedInformation(RD);
3727 assert(VFPtrLocations.count(RD) &&
"Couldn't find vfptr locations");
3728 return *VFPtrLocations[RD];
3734 computeVTableRelatedInformation(RD);
3736 VFTableIdTy
id(RD, VFPtrOffset);
3737 assert(VFTableLayouts.count(
id) &&
"Couldn't find a VFTable at this offset");
3738 return *VFTableLayouts[
id];
3743 assert(cast<CXXMethodDecl>(GD.
getDecl())->isVirtual() &&
3744 "Only use this method for virtual methods or dtors");
3745 if (isa<CXXDestructorDecl>(GD.
getDecl()))
3749 if (I != MethodVFTableLocations.end())
3754 computeVTableRelatedInformation(RD);
3756 I = MethodVFTableLocations.find(GD);
3757 assert(I != MethodVFTableLocations.end() &&
"Did not find index!");
Defines the clang::ASTContext interface.
static std::string ComputeName(IdentType IT, const Decl *CurrentDecl)
bool isDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is derived from the class Base.
PointerType - C99 6.7.5.1 - Pointer Declarators.
A (possibly-)qualified type.
bool isVirtual() const
Determines whether the base class is a virtual base class (or not).
llvm::DenseMap< const CXXRecordDecl *, VBaseInfo > VBaseOffsetsMapTy
uint32_t VBPtrOffset
The offset (in bytes) of the vbptr, relative to the beginning of the derived class.
CharUnits getOffsetToTop() const
QualType getType() const
Retrieves the type of the base class.
VTableLayout * createConstructionVTableLayout(const CXXRecordDecl *MostDerivedClass, CharUnits MostDerivedClassOffset, bool MostDerivedClassIsVirtual, const CXXRecordDecl *LayoutClass)
method_range methods() const
ItaniumVTableContext(ASTContext &Context)
static VTableComponent MakeRTTI(const CXXRecordDecl *RD)
CanQual< T > getUnqualifiedType() const
Retrieve the unqualified form of this type.
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
FunctionType - C99 6.7.5.3 - Function Declarators.
VPtrInfoVector VBPtrPaths
Information on all virtual base tables used when this record is the most derived class.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
std::string getAsString() const
int64_t NonVirtual
The non-virtual adjustment from the derived object to its nearest virtual base.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const
getVBaseClassOffset - Get the offset, in chars, for the given base class.
bool isPrimaryBaseVirtual() const
isPrimaryBaseVirtual - Get whether the primary base for this record is virtual or not...
BasePath MangledPath
The bases from the inheritance path that got used to mangle the vbtable name.
Represents a path from a specific derived class (which is not represented as part of the path) to a p...
static const FullPathTy * selectBestPath(ASTContext &Context, const CXXRecordDecl *RD, VPtrInfo *Info, std::list< FullPathTy > &FullPaths)
static VTableComponent MakeUnusedFunction(const CXXMethodDecl *MD)
static VTableComponent MakeVCallOffset(CharUnits Offset)
A 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...
int32_t VBOffsetOffset
The offset (in bytes) of the vbase offset in the vbtable.
method_iterator end_overridden_methods() const
const CXXRecordDecl * getVBaseWithVPtr() const
The vptr is stored inside the non-virtual component of this virtual base.
class LLVM_ALIGNAS(8) DependentTemplateSpecializationType const IdentifierInfo * Name
Represents a template specialization type whose template cannot be resolved, e.g. ...
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
ArrayRef< QualType > getParamTypes() const
QualType getReturnType() const
VTableLayout(uint64_t NumVTableComponents, const VTableComponent *VTableComponents, uint64_t NumVTableThunks, const VTableThunkTy *VTableThunks, const AddressPointsMapTy &AddressPoints, bool IsMicrosoftABI)
struct clang::ReturnAdjustment::VirtualAdjustment::@111 Microsoft
bool isPure() const
Whether this virtual function is pure, i.e.
CXXMethodDecl * getCanonicalDecl() override
static VTableComponent MakeCompleteDtor(const CXXDestructorDecl *DD)
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
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...
The this pointer adjustment as well as an optional return adjustment for a thunk. ...
const Decl * getDecl() const
const CXXRecordDecl * NextBaseToMangle
The next base to push onto the mangled path if this path is ambiguous in a derived class...
static bool setsIntersect(const llvm::SmallPtrSet< const CXXRecordDecl *, 4 > &A, ArrayRef< const CXXRecordDecl * > B)
const CXXMethodDecl * getFunctionDecl() const
~ItaniumVTableContext() override
The set of methods that override a given virtual method in each subobject where it occurs...
const TargetInfo & getTargetInfo() const
const LangOptions & getLangOpts() const
CharUnits - This is an opaque type for sizes expressed in character units.
~MicrosoftVTableContext() override
static void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef< CounterExpression > Expressions, ArrayRef< CounterMappingRegion > Regions)
CanProxy< U > getAs() const
Retrieve a canonical type pointer with a different static type, upcasting or downcasting as needed...
CharUnits getVCallOffset() const
QualType getReturnType() const
const CXXRecordDecl * getParent() const
Returns the parent of this method declaration, which is the class in which this method is defined...
Concrete class used by the front-end to report problems and issues.
const VPtrInfoVector & getVFPtrOffsets(const CXXRecordDecl *RD)
static VTableLayout * CreateVTableLayout(const ItaniumVTableBuilder &Builder)
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D...
base_class_iterator bases_begin()
static void removeRedundantPaths(std::list< FullPathTy > &FullPaths)
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
uint64_t getMethodVTableIndex(GlobalDecl GD)
Locate a virtual function in the vtable.
detail::InMemoryDirectory::const_iterator I
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...
static VTableComponent MakeDeletingDtor(const CXXDestructorDecl *DD)
DiagnosticsEngine & getDiagnostics() const
BasePath ContainingVBases
The set of possibly indirect vbases that contain this vbtable.
struct clang::ReturnAdjustment::VirtualAdjustment::@110 Itanium
Represents a prototype with parameter type info, e.g.
union clang::ReturnAdjustment::VirtualAdjustment Virtual
const CXXMethodDecl *const * method_iterator
const CXXRecordDecl * getBase() const
getBase - Returns the base class declaration.
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
bool isDeleted() const
Whether this function has been deleted.
bool isMicrosoft() const
Is this ABI an MSVC-compatible ABI?
CXXDtorType getDtorType() const
static void GroupNewVirtualOverloads(const CXXRecordDecl *RD, SmallVector< const CXXMethodDecl *, 10 > &VirtualMethods)
Represents a C++ destructor within a class.
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
internal::Matcher< T > id(StringRef ID, const internal::BindableMatcher< T > &InnerMatcher)
If the provided matcher matches a node, binds the node to ID.
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
const CXXRecordDecl * getBaseSharingVBPtr() const
llvm::DenseMap< BaseSubobject, uint64_t > AddressPointsMapTy
DeclContext * getParent()
getParent - Returns the containing DeclContext.
SmallVector< VPtrInfo *, 2 > VPtrInfoVector
CharUnits getVBPtrOffset() const
getVBPtrOffset - Get the offset for virtual base table pointer.
Uniquely identifies a virtual method within a class hierarchy by the method itself and a class subobj...
DeclarationName getDeclName() const
getDeclName - Get the actual, stored name of the declaration, which may be a special name...
const CXXRecordDecl * ReusingBase
The vtable will hold all of the virtual bases or virtual methods of ReusingBase.
GlobalDecl - represents a global declaration.
static void PrintBasePath(const VPtrInfo::BasePath &Path, raw_ostream &Out)
int64_t NonVirtual
The non-virtual adjustment from the derived object to its nearest virtual base.
unsigned getVBTableIndex(const CXXRecordDecl *Derived, const CXXRecordDecl *VBase)
Returns the index of VBase in the vbtable of Derived.
const CXXBaseSpecifier * Base
The base specifier that states the link from a derived class to a base class, which will be followed ...
const CXXRecordDecl * getRTTIDecl() const
static bool rebucketPaths(VPtrInfoVector &Paths)
const TemplateArgument * iterator
method_iterator begin_overridden_methods() const
const CXXRecordDecl * getPrimaryBase() const
getPrimaryBase - Get the primary base for this record.
static void dumpMicrosoftThunkAdjustment(const ThunkInfo &TI, raw_ostream &Out, bool ContinueFirstLine)
unsigned size_overridden_methods() const
Represents a single component in a vtable.
Represents a static or instance method of a struct/union/class.
const VTableLayout & getVFTableLayout(const CXXRecordDecl *RD, CharUnits VFPtrOffset)
static void findPathsToSubobject(ASTContext &Context, const ASTRecordLayout &MostDerivedLayout, const CXXRecordDecl *RD, CharUnits Offset, BaseSubobject BaseWithVPtr, FullPathTy &FullPath, std::list< FullPathTy > &Paths)
const CXXDestructorDecl * getDestructorDecl() const
const CXXRecordDecl * BaseWithVPtr
The vptr is stored inside this subobject.
unsigned getCustomDiagID(Level L, const char(&FormatString)[N])
Return an ID for a diagnostic with the specified format string and level.
int64_t VCallOffsetOffset
The offset (in bytes), relative to the address point, of the virtual call offset. ...
struct clang::ThisAdjustment::VirtualAdjustment::@113 Microsoft
void printQualifiedName(raw_ostream &OS) const
printQualifiedName - Returns human-readable qualified name for declaration, like A::B::i, for i being member of namespace A::B.
bool isDynamicClass() const
static VTableComponent MakeVBaseOffset(CharUnits Offset)
Represents an element in a path from a derived class to a base class.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(T-> getSizeExpr()))
ThisAdjustment This
The this pointer adjustment.
struct clang::ThisAdjustment::VirtualAdjustment::@112 Itanium
bool isZero() const
isZero - Test whether the quantity equals zero.
const VPtrInfoVector & enumerateVBTables(const CXXRecordDecl *RD)
static bool isDirectVBase(const CXXRecordDecl *Base, const CXXRecordDecl *RD)
ThunksMapTy Thunks
Contains all thunks that a given method decl will need.
The same as PrettyFunction, except that the 'virtual' keyword is omitted for virtual member functions...
DeclarationName - The name of a declaration.
CharUnits getVBaseOffset() const
A mapping from each virtual member function to its set of final overriders.
static CharUnits getOffsetOfFullPath(ASTContext &Context, const CXXRecordDecl *RD, const FullPathTy &FullPath)
int64_t VBaseOffsetOffset
The offset (in bytes), relative to the address point of the virtual base class offset.
detail::InMemoryDirectory::const_iterator E
CharUnits NonVirtualOffset
BaseWithVPtr is at this offset from its containing complete object or virtual base.
base_class_iterator vbases_begin()
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
All virtual base related information about a given record decl.
union clang::ThisAdjustment::VirtualAdjustment Virtual
const T * getAs() const
Member-template getAs<specific type>'.
unsigned getTypeQuals() const
QualType getCanonicalType() const
Base for LValueReferenceType and RValueReferenceType.
ReturnAdjustment Return
The return adjustment.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Represents a base class of a C++ class.
uint64_t getPointerWidth(unsigned AddrSpace) const
Return the width of pointers on this target, for the specified address space.
Represents a C++ struct/union/class.
BoundNodesTreeBuilder *const Builder
TargetCXXABI getCXXABI() const
Get the C++ ABI currently in use.
int32_t VtordispOffset
The offset of the vtordisp (in bytes), relative to the ECX.
base_class_iterator bases_end()
std::pair< uint64_t, ThunkInfo > VTableThunkTy
Defines the clang::TargetInfo interface.
static bool extendPath(VPtrInfo *P)
CharUnits FullOffsetInMDC
Static offset from the top of the most derived class to this vfptr, including any virtual base offset...
A pointer to the deleting destructor.
static Decl::Kind getKind(const Decl *D)
static VTableComponent MakeFunction(const CXXMethodDecl *MD)
Holds information about the inheritance path to a virtual base or function table pointer.
Kind getKind() const
Get the kind of this vtable component.
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
CharUnits getBaseOffset() const
getBaseOffset - Returns the base class offset.
uint32_t VBIndex
Index of the virtual base in the vbtable.
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
const CXXMethodDecl * getUnusedFunctionDecl() const
NamedDecl - This represents a decl with a name.
static void computeFullPathsForVFTables(ASTContext &Context, const CXXRecordDecl *RD, VPtrInfoVector &Paths)
void getFinalOverriders(CXXFinalOverriderMap &FinaOverriders) const
Retrieve the final overriders for each virtual member function in the class hierarchy where this clas...
bool isPolymorphic() const
Whether this class is polymorphic (C++ [class.virtual]), which means that the class contains or inher...
const CXXRecordDecl * Class
The record decl of the class that the base is a base of.
int32_t VBPtrOffset
The offset of the vbptr of the derived class (in bytes), relative to the ECX after vtordisp adjustmen...
base_class_range vbases()
A pointer to the complete destructor.
An entry that is never used.
const MethodVFTableLocation & getMethodVFTableLocation(GlobalDecl GD)
static VTableComponent MakeOffsetToTop(CharUnits Offset)