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),
167 SubobjectOffsetMapTy SubobjectOffsets;
168 SubobjectOffsetMapTy SubobjectLayoutClassOffsets;
169 SubobjectCountMapTy SubobjectCounts;
172 MostDerivedClassOffset,
173 SubobjectOffsets, SubobjectLayoutClassOffsets,
180 for (CXXFinalOverriderMap::const_iterator I = FinalOverriders.begin(),
181 E = FinalOverriders.end(); I != E; ++I) {
186 E = Methods.
end(); I != E; ++I) {
187 unsigned SubobjectNumber = I->first;
188 assert(SubobjectOffsets.count(std::make_pair(MD->
getParent(),
190 "Did not find subobject offset!");
195 assert(I->second.size() == 1 &&
"Final overrider is not unique!");
199 assert(SubobjectLayoutClassOffsets.count(
200 std::make_pair(OverriderRD, Method.Subobject))
201 &&
"Did not find subobject offset!");
203 SubobjectLayoutClassOffsets[std::make_pair(OverriderRD,
206 OverriderInfo& Overrider = OverridersMap[std::make_pair(MD, BaseOffset)];
207 assert(!Overrider.Method &&
"Overrider should not exist yet!");
209 Overrider.Offset = OverriderOffset;
210 Overrider.Method = Method.Method;
211 Overrider.VirtualBase = Method.InVirtualSubobject;
226 unsigned NonVirtualStart = 0;
230 for (
int I = Path.size(), E = 0; I != E; --I) {
242 for (
unsigned I = NonVirtualStart, E = Path.size(); I != E; ++I) {
256 return BaseOffset(DerivedRD, VirtualBase, NonVirtualOffset);
260 static BaseOffset ComputeBaseOffset(
const ASTContext &Context,
267 llvm_unreachable(
"Class must be derived from the passed in base class!");
269 return ComputeBaseOffset(Context, DerivedRD, Paths.
front());
273 ComputeReturnAdjustmentBaseOffset(
ASTContext &Context,
285 assert(CanDerivedReturnType->getTypeClass() ==
286 CanBaseReturnType->getTypeClass() &&
287 "Types must have same type class!");
289 if (CanDerivedReturnType == CanBaseReturnType) {
294 if (isa<ReferenceType>(CanDerivedReturnType)) {
295 CanDerivedReturnType =
296 CanDerivedReturnType->getAs<
ReferenceType>()->getPointeeType();
299 }
else if (isa<PointerType>(CanDerivedReturnType)) {
300 CanDerivedReturnType =
301 CanDerivedReturnType->getAs<
PointerType>()->getPointeeType();
305 llvm_unreachable(
"Unexpected return type!");
311 if (CanDerivedReturnType.getUnqualifiedType() ==
318 cast<CXXRecordDecl>(cast<RecordType>(CanDerivedReturnType)->getDecl());
321 cast<CXXRecordDecl>(cast<RecordType>(CanBaseReturnType)->getDecl());
323 return ComputeBaseOffset(Context, BaseRD, DerivedRD);
329 SubobjectOffsetMapTy &SubobjectOffsets,
330 SubobjectOffsetMapTy &SubobjectLayoutClassOffsets,
331 SubobjectCountMapTy &SubobjectCounts) {
334 unsigned SubobjectNumber = 0;
336 SubobjectNumber = ++SubobjectCounts[RD];
339 assert(!SubobjectOffsets.count(std::make_pair(RD, SubobjectNumber))
340 &&
"Subobject offset already exists!");
341 assert(!SubobjectLayoutClassOffsets.count(std::make_pair(RD, SubobjectNumber))
342 &&
"Subobject offset already exists!");
344 SubobjectOffsets[std::make_pair(RD, SubobjectNumber)] = Base.
getBaseOffset();
345 SubobjectLayoutClassOffsets[std::make_pair(RD, SubobjectNumber)] =
349 for (
const auto &B : RD->
bases()) {
350 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
356 if (SubobjectOffsets.count(std::make_pair(BaseDecl, 0)))
362 BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
363 BaseOffsetInLayoutClass =
370 BaseOffsetInLayoutClass = OffsetInLayoutClass +
Offset;
374 B.isVirtual(), BaseOffsetInLayoutClass,
375 SubobjectOffsets, SubobjectLayoutClassOffsets,
381 VisitedVirtualBasesSetTy &VisitedVirtualBases) {
385 for (
const auto &B : RD->
bases()) {
386 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
394 if (!VisitedVirtualBases.insert(BaseDecl).second) {
399 BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
407 Out <<
"Final overriders for (";
413 for (
const auto *MD : RD->
methods()) {
414 if (!MD->isVirtual())
416 MD = MD->getCanonicalDecl();
418 OverriderInfo Overrider = getOverrider(MD, Base.
getBaseOffset());
421 MD->printQualifiedName(Out);
423 Overrider.Method->printQualifiedName(Out);
424 Out <<
", " << Overrider.Offset.getQuantity() <<
')';
427 if (!Overrider.Method->isPure())
428 Offset = ComputeReturnAdjustmentBaseOffset(Context, Overrider.Method, MD);
430 if (!Offset.isEmpty()) {
431 Out <<
" [ret-adj: ";
432 if (Offset.VirtualBase) {
433 Offset.VirtualBase->printQualifiedName(Out);
437 Out << Offset.NonVirtualOffset.getQuantity() <<
" nv]";
445 struct VCallOffsetMap {
447 typedef std::pair<const CXXMethodDecl *, CharUnits> MethodAndOffsetPairTy;
455 static bool MethodsCanShareVCallOffset(
const CXXMethodDecl *LHS,
469 bool empty()
const {
return Offsets.empty(); }
472 static bool HasSameVirtualSignature(
const CXXMethodDecl *LHS,
480 if (LT == RT)
return true;
488 for (
unsigned I = 0, E = LT->
getNumParams(); I != E; ++I)
494 bool VCallOffsetMap::MethodsCanShareVCallOffset(
const CXXMethodDecl *LHS,
496 assert(LHS->
isVirtual() &&
"LHS must be virtual!");
497 assert(RHS->
isVirtual() &&
"LHS must be virtual!");
500 if (isa<CXXDestructorDecl>(LHS))
501 return isa<CXXDestructorDecl>(RHS);
508 if (LHSName != RHSName)
512 return HasSameVirtualSignature(LHS, RHS);
518 for (
unsigned I = 0, E = Offsets.size(); I != E; ++I) {
519 if (MethodsCanShareVCallOffset(Offsets[I].first, MD))
524 Offsets.push_back(MethodAndOffsetPairTy(MD, OffsetOffset));
530 for (
unsigned I = 0, E = Offsets.size(); I != E; ++I) {
531 if (MethodsCanShareVCallOffset(Offsets[I].first, MD))
532 return Offsets[I].second;
535 llvm_unreachable(
"Should always find a vcall offset offset!");
539 class VCallAndVBaseOffsetBuilder {
541 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits>
542 VBaseOffsetOffsetsMapTy;
559 VTableComponentVectorTy Components;
562 llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBases;
565 VCallOffsetMap VCallOffsets;
570 VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
574 const FinalOverriders *Overriders;
578 void AddVCallAndVBaseOffsets(
BaseSubobject Base,
bool BaseIsVirtual,
590 CharUnits getCurrentOffsetOffset()
const;
593 VCallAndVBaseOffsetBuilder(
const CXXRecordDecl *MostDerivedClass,
595 const FinalOverriders *Overriders,
598 : MostDerivedClass(MostDerivedClass), LayoutClass(LayoutClass),
602 AddVCallAndVBaseOffsets(Base, BaseIsVirtual, OffsetInLayoutClass);
606 typedef VTableComponentVectorTy::const_reverse_iterator const_iterator;
607 const_iterator components_begin()
const {
return Components.rbegin(); }
608 const_iterator components_end()
const {
return Components.rend(); }
610 const VCallOffsetMap &getVCallOffsets()
const {
return VCallOffsets; }
611 const VBaseOffsetOffsetsMapTy &getVBaseOffsetOffsets()
const {
612 return VBaseOffsetOffsets;
617 VCallAndVBaseOffsetBuilder::AddVCallAndVBaseOffsets(
BaseSubobject Base,
637 if (PrimaryBaseIsVirtual) {
639 "Primary vbase should have a zero offset!");
645 MostDerivedClassLayout.getVBaseClassOffset(PrimaryBase);
648 "Primary base should have a zero offset!");
653 AddVCallAndVBaseOffsets(
655 PrimaryBaseIsVirtual, RealBaseOffset);
658 AddVBaseOffsets(Base.
getBase(), RealBaseOffset);
662 AddVCallOffsets(Base, RealBaseOffset);
665 CharUnits VCallAndVBaseOffsetBuilder::getCurrentOffsetOffset()
const {
670 int64_t OffsetIndex = -(int64_t)(3 + Components.size());
674 CharUnits OffsetOffset = PointerWidth * OffsetIndex;
678 void VCallAndVBaseOffsetBuilder::AddVCallOffsets(
BaseSubobject Base,
691 "Primary base should have a zero offset!");
698 for (
const auto *MD : RD->
methods()) {
703 CharUnits OffsetOffset = getCurrentOffsetOffset();
707 if (!VCallOffsets.AddVCallOffset(MD, OffsetOffset))
714 FinalOverriders::OverriderInfo Overrider =
719 Offset = Overrider.Offset - VBaseOffset;
722 Components.push_back(
727 for (
const auto &B : RD->
bases()) {
731 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
732 if (BaseDecl == PrimaryBase)
745 VCallAndVBaseOffsetBuilder::AddVBaseOffsets(
const CXXRecordDecl *RD,
751 for (
const auto &B : RD->
bases()) {
752 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
755 if (B.isVirtual() && VisitedVirtualBases.insert(BaseDecl).second) {
760 assert(!VBaseOffsetOffsets.count(BaseDecl) &&
761 "vbase offset offset already exists!");
763 CharUnits VBaseOffsetOffset = getCurrentOffsetOffset();
764 VBaseOffsetOffsets.insert(
765 std::make_pair(BaseDecl, VBaseOffsetOffset));
767 Components.push_back(
772 AddVBaseOffsets(BaseDecl, OffsetInLayoutClass);
777 class ItaniumVTableBuilder {
782 PrimaryBasesSetVectorTy;
784 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits>
785 VBaseOffsetOffsetsMapTy;
787 typedef llvm::DenseMap<BaseSubobject, uint64_t>
790 typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVTableIndicesTy;
806 bool MostDerivedClassIsVirtual;
817 const FinalOverriders Overriders;
821 llvm::DenseMap<const CXXRecordDecl *, VCallOffsetMap> VCallOffsetsForVBases;
825 VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
831 AddressPointsMapTy AddressPoints;
845 const uint64_t VTableIndex;
848 uint64_t VTableIndex)
849 : BaseOffset(BaseOffset),
850 BaseOffsetInLayoutClass(BaseOffsetInLayoutClass),
851 VTableIndex(VTableIndex) { }
859 typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy;
863 MethodInfoMapTy MethodInfoMap;
867 MethodVTableIndicesTy MethodVTableIndices;
869 typedef llvm::DenseMap<uint64_t, ThunkInfo> VTableThunksMapTy;
873 VTableThunksMapTy VTableThunks;
876 typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
887 void ComputeThisAdjustments();
889 typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy;
893 VisitedVirtualBasesSetTy PrimaryVirtualBases;
901 BaseOffset ComputeThisAdjustmentBaseOffset(
BaseSubobject Base,
910 FinalOverriders::OverriderInfo Overrider);
938 CharUnits FirstBaseOffsetInLayoutClass)
const;
946 PrimaryBasesSetVectorTy &PrimaryBases);
961 bool BaseIsMorallyVirtual,
962 bool BaseIsVirtualInLayoutClass,
970 void LayoutSecondaryVTables(
BaseSubobject Base,
bool BaseIsMorallyVirtual,
977 VisitedVirtualBasesSetTy &VBases);
982 VisitedVirtualBasesSetTy &VBases);
986 bool isBuildingConstructorVTable()
const {
987 return MostDerivedClass != LayoutClass;
994 bool MostDerivedClassIsVirtual,
996 : VTables(VTables), MostDerivedClass(MostDerivedClass),
997 MostDerivedClassOffset(MostDerivedClassOffset),
998 MostDerivedClassIsVirtual(MostDerivedClassIsVirtual),
1000 Overriders(MostDerivedClass, MostDerivedClassOffset, LayoutClass) {
1006 dumpLayout(llvm::outs());
1009 uint64_t getNumThunks()
const {
1010 return Thunks.size();
1013 ThunksMapTy::const_iterator thunks_begin()
const {
1014 return Thunks.begin();
1017 ThunksMapTy::const_iterator thunks_end()
const {
1018 return Thunks.end();
1021 const VBaseOffsetOffsetsMapTy &getVBaseOffsetOffsets()
const {
1022 return VBaseOffsetOffsets;
1025 const AddressPointsMapTy &getAddressPoints()
const {
1026 return AddressPoints;
1029 MethodVTableIndicesTy::const_iterator vtable_indices_begin()
const {
1030 return MethodVTableIndices.begin();
1033 MethodVTableIndicesTy::const_iterator vtable_indices_end()
const {
1034 return MethodVTableIndices.end();
1039 uint64_t getNumVTableComponents()
const {
1040 return Components.size();
1044 return Components.begin();
1048 return Components.end();
1051 AddressPointsMapTy::const_iterator address_points_begin()
const {
1052 return AddressPoints.begin();
1055 AddressPointsMapTy::const_iterator address_points_end()
const {
1056 return AddressPoints.end();
1059 VTableThunksMapTy::const_iterator vtable_thunks_begin()
const {
1060 return VTableThunks.begin();
1063 VTableThunksMapTy::const_iterator vtable_thunks_end()
const {
1064 return VTableThunks.end();
1068 void dumpLayout(raw_ostream&);
1071 void ItaniumVTableBuilder::AddThunk(
const CXXMethodDecl *MD,
1073 assert(!isBuildingConstructorVTable() &&
1074 "Can't add thunks for construction vtable");
1079 if (std::find(ThunksVector.begin(), ThunksVector.end(), Thunk) !=
1083 ThunksVector.push_back(Thunk);
1086 typedef llvm::SmallPtrSet<const CXXMethodDecl *, 8> OverriddenMethodsSetTy;
1092 template <
class VisitorTy>
1094 visitAllOverriddenMethods(
const CXXMethodDecl *MD, VisitorTy &Visitor) {
1095 assert(MD->
isVirtual() &&
"Method is not virtual!");
1100 if (!Visitor.visit(OverriddenMD))
1102 visitAllOverriddenMethods(OverriddenMD, Visitor);
1107 struct OverriddenMethodsCollector {
1108 OverriddenMethodsSetTy *Methods;
1112 return Methods->insert(MD).second;
1121 OverriddenMethodsSetTy& OverriddenMethods) {
1122 OverriddenMethodsCollector Collector = { &OverriddenMethods };
1123 visitAllOverriddenMethods(MD, Collector);
1126 void ItaniumVTableBuilder::ComputeThisAdjustments() {
1129 for (MethodInfoMapTy::const_iterator I = MethodInfoMap.begin(),
1130 E = MethodInfoMap.end(); I != E; ++I) {
1132 const MethodInfo &MethodInfo = I->second;
1135 uint64_t VTableIndex = MethodInfo.VTableIndex;
1136 if (Components[VTableIndex].
getKind() ==
1141 FinalOverriders::OverriderInfo Overrider =
1142 Overriders.getOverrider(MD, MethodInfo.BaseOffset);
1145 if (MethodInfo.BaseOffsetInLayoutClass == Overrider.Offset) {
1151 if (VTableThunks.lookup(VTableIndex).Return.isEmpty())
1156 ComputeThisAdjustment(MD, MethodInfo.BaseOffsetInLayoutClass, Overrider);
1162 VTableThunks[VTableIndex].This = ThisAdjustment;
1164 if (isa<CXXDestructorDecl>(MD)) {
1166 VTableThunks[VTableIndex + 1].This = ThisAdjustment;
1171 MethodInfoMap.clear();
1173 if (isBuildingConstructorVTable()) {
1178 for (VTableThunksMapTy::const_iterator I = VTableThunks.begin(),
1179 E = VTableThunks.end(); I != E; ++I) {
1184 switch (Component.
getKind()) {
1186 llvm_unreachable(
"Unexpected vtable component kind!");
1198 if (MD->
getParent() == MostDerivedClass)
1199 AddThunk(MD, Thunk);
1204 ItaniumVTableBuilder::ComputeReturnAdjustment(BaseOffset
Offset) {
1207 if (!Offset.isEmpty()) {
1208 if (Offset.VirtualBase) {
1210 if (Offset.DerivedClass == MostDerivedClass) {
1213 VBaseOffsetOffsets.lookup(Offset.VirtualBase).getQuantity();
1216 VTables.getVirtualBaseOffsetOffset(Offset.DerivedClass,
1217 Offset.VirtualBase).getQuantity();
1221 Adjustment.
NonVirtual = Offset.NonVirtualOffset.getQuantity();
1227 BaseOffset ItaniumVTableBuilder::ComputeThisAdjustmentBaseOffset(
1236 llvm_unreachable(
"Class must be derived from the passed in base class!");
1242 BaseOffset Offset = ComputeBaseOffset(Context, DerivedRD, *I);
1244 CharUnits OffsetToBaseSubobject = Offset.NonVirtualOffset;
1246 if (Offset.VirtualBase) {
1254 OffsetToBaseSubobject +=
1266 Offset.NonVirtualOffset = -Offset.NonVirtualOffset;
1271 return BaseOffset();
1276 FinalOverriders::OverriderInfo Overrider) {
1278 if (Overrider.Method->isPure())
1282 BaseOffsetInLayoutClass);
1284 BaseSubobject OverriderBaseSubobject(Overrider.Method->getParent(),
1288 BaseOffset Offset = ComputeThisAdjustmentBaseOffset(OverriddenBaseSubobject,
1289 OverriderBaseSubobject);
1290 if (Offset.isEmpty())
1295 if (Offset.VirtualBase) {
1297 VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[Offset.VirtualBase];
1299 if (VCallOffsets.empty()) {
1302 VCallAndVBaseOffsetBuilder
Builder(MostDerivedClass, MostDerivedClass,
1310 VCallOffsets = Builder.getVCallOffsets();
1314 VCallOffsets.getVCallOffsetOffset(MD).getQuantity();
1318 Adjustment.
NonVirtual = Offset.NonVirtualOffset.getQuantity();
1323 void ItaniumVTableBuilder::AddMethod(
const CXXMethodDecl *MD,
1326 assert(ReturnAdjustment.
isEmpty() &&
1327 "Destructor can't have return adjustment!");
1334 if (!ReturnAdjustment.
isEmpty())
1335 VTableThunks[Components.size()].Return = ReturnAdjustment;
1353 static bool OverridesIndirectMethodInBases(
1364 if (OverridesIndirectMethodInBases(OverriddenMD, Bases))
1371 bool ItaniumVTableBuilder::IsOverriderUsed(
1374 CharUnits FirstBaseOffsetInLayoutClass)
const {
1377 if (BaseOffsetInLayoutClass == FirstBaseOffsetInLayoutClass)
1386 if (Overrider->
getParent() == FirstBaseInPrimaryBaseChain)
1392 PrimaryBases.insert(RD);
1405 "Primary base should always be at offset 0!");
1412 if (LayoutClassLayout.getVBaseClassOffset(PrimaryBase) !=
1413 FirstBaseOffsetInLayoutClass) {
1419 "Primary base should always be at offset 0!");
1422 if (!PrimaryBases.insert(PrimaryBase))
1423 llvm_unreachable(
"Found a duplicate primary base!");
1430 return OverridesIndirectMethodInBases(Overrider, PrimaryBases);
1440 BasesSetVectorTy &Bases) {
1441 OverriddenMethodsSetTy OverriddenMethods;
1442 ComputeAllOverriddenMethods(MD, OverriddenMethods);
1444 for (
int I = Bases.size(), E = 0; I != E; --I) {
1448 for (OverriddenMethodsSetTy::const_iterator I = OverriddenMethods.begin(),
1449 E = OverriddenMethods.end(); I != E; ++I) {
1453 if (OverriddenMD->
getParent() == PrimaryBase)
1454 return OverriddenMD;
1461 void ItaniumVTableBuilder::AddMethods(
1465 PrimaryBasesSetVectorTy &PrimaryBases) {
1480 CharUnits PrimaryBaseOffsetInLayoutClass;
1483 "Primary vbase should have a zero offset!");
1489 MostDerivedClassLayout.getVBaseClassOffset(PrimaryBase);
1494 PrimaryBaseOffsetInLayoutClass =
1498 "Primary base should have a zero offset!");
1501 PrimaryBaseOffsetInLayoutClass = BaseOffsetInLayoutClass;
1505 PrimaryBaseOffsetInLayoutClass, FirstBaseInPrimaryBaseChain,
1506 FirstBaseOffsetInLayoutClass, PrimaryBases);
1508 if (!PrimaryBases.insert(PrimaryBase))
1509 llvm_unreachable(
"Found a duplicate primary base!");
1515 NewVirtualFunctionsTy NewVirtualFunctions;
1518 for (
const auto *MD : RD->
methods()) {
1524 FinalOverriders::OverriderInfo Overrider =
1531 FindNearestOverriddenMethod(MD, PrimaryBases)) {
1532 if (ComputeReturnAdjustmentBaseOffset(Context, MD,
1533 OverriddenMD).isEmpty()) {
1536 assert(MethodInfoMap.count(OverriddenMD) &&
1537 "Did not find the overridden method!");
1538 MethodInfo &OverriddenMethodInfo = MethodInfoMap[OverriddenMD];
1540 MethodInfo MethodInfo(Base.
getBaseOffset(), BaseOffsetInLayoutClass,
1541 OverriddenMethodInfo.VTableIndex);
1543 assert(!MethodInfoMap.count(MD) &&
1544 "Should not have method info for this method yet!");
1546 MethodInfoMap.insert(std::make_pair(MD, MethodInfo));
1547 MethodInfoMap.erase(OverriddenMD);
1553 if (!isBuildingConstructorVTable() && OverriddenMD != MD) {
1556 ComputeThisAdjustment(OverriddenMD, BaseOffsetInLayoutClass,
1560 Overrider.Method->getParent() == MostDerivedClass) {
1565 BaseOffset ReturnAdjustmentOffset =
1566 ComputeReturnAdjustmentBaseOffset(Context, Overrider.Method, MD);
1567 ReturnAdjustment ReturnAdjustment =
1568 ComputeReturnAdjustment(ReturnAdjustmentOffset);
1571 AddThunk(Overrider.Method,
1572 ThunkInfo(ThisAdjustment, ReturnAdjustment));
1586 assert(!ImplicitVirtualDtor &&
1587 "Did already see an implicit virtual dtor!");
1588 ImplicitVirtualDtor = DD;
1593 NewVirtualFunctions.push_back(MD);
1596 if (ImplicitVirtualDtor)
1597 NewVirtualFunctions.push_back(ImplicitVirtualDtor);
1599 for (NewVirtualFunctionsTy::const_iterator I = NewVirtualFunctions.begin(),
1600 E = NewVirtualFunctions.end(); I != E; ++I) {
1604 FinalOverriders::OverriderInfo Overrider =
1608 MethodInfo MethodInfo(Base.
getBaseOffset(), BaseOffsetInLayoutClass,
1611 assert(!MethodInfoMap.count(MD) &&
1612 "Should not have method info for this method yet!");
1613 MethodInfoMap.insert(std::make_pair(MD, MethodInfo));
1617 if (!IsOverriderUsed(OverriderMD, BaseOffsetInLayoutClass,
1618 FirstBaseInPrimaryBaseChain,
1619 FirstBaseOffsetInLayoutClass)) {
1626 BaseOffset ReturnAdjustmentOffset;
1627 if (!OverriderMD->
isPure()) {
1628 ReturnAdjustmentOffset =
1629 ComputeReturnAdjustmentBaseOffset(Context, OverriderMD, MD);
1632 ReturnAdjustment ReturnAdjustment =
1633 ComputeReturnAdjustment(ReturnAdjustmentOffset);
1635 AddMethod(Overrider.Method, ReturnAdjustment);
1639 void ItaniumVTableBuilder::LayoutVTable() {
1640 LayoutPrimaryAndSecondaryVTables(
BaseSubobject(MostDerivedClass,
1643 MostDerivedClassIsVirtual,
1644 MostDerivedClassOffset);
1646 VisitedVirtualBasesSetTy VBases;
1649 DeterminePrimaryVirtualBases(MostDerivedClass, MostDerivedClassOffset,
1653 LayoutVTablesForVirtualBases(MostDerivedClass, VBases);
1656 bool IsAppleKext = Context.
getLangOpts().AppleKext;
1661 void ItaniumVTableBuilder::LayoutPrimaryAndSecondaryVTables(
1663 bool BaseIsVirtualInLayoutClass,
CharUnits OffsetInLayoutClass) {
1667 VCallAndVBaseOffsetBuilder
Builder(MostDerivedClass, LayoutClass, &Overriders,
1668 Base, BaseIsVirtualInLayoutClass,
1669 OffsetInLayoutClass);
1670 Components.append(Builder.components_begin(), Builder.components_end());
1673 if (BaseIsVirtualInLayoutClass && !Builder.getVCallOffsets().empty()) {
1674 VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[Base.
getBase()];
1676 if (VCallOffsets.empty())
1677 VCallOffsets = Builder.getVCallOffsets();
1682 if (Base.
getBase() == MostDerivedClass)
1683 VBaseOffsetOffsets = Builder.getVBaseOffsetOffsets();
1686 CharUnits OffsetToTop = MostDerivedClassOffset - OffsetInLayoutClass;
1692 uint64_t AddressPoint = Components.size();
1695 PrimaryBasesSetVectorTy PrimaryBases;
1696 AddMethods(Base, OffsetInLayoutClass,
1697 Base.
getBase(), OffsetInLayoutClass,
1701 if (RD == MostDerivedClass) {
1702 assert(MethodVTableIndices.empty());
1703 for (MethodInfoMapTy::const_iterator I = MethodInfoMap.begin(),
1704 E = MethodInfoMap.end(); I != E; ++I) {
1706 const MethodInfo &MI = I->second;
1709 = MI.VTableIndex - AddressPoint;
1711 = MI.VTableIndex + 1 - AddressPoint;
1713 MethodVTableIndices[MD] = MI.VTableIndex - AddressPoint;
1719 ComputeThisAdjustments();
1723 AddressPoints.insert(std::make_pair(
1740 OffsetInLayoutClass) {
1750 LayoutSecondaryVTables(Base, BaseIsMorallyVirtual, OffsetInLayoutClass);
1754 ItaniumVTableBuilder::LayoutSecondaryVTables(
BaseSubobject Base,
1755 bool BaseIsMorallyVirtual,
1766 for (
const auto &B : RD->
bases()) {
1771 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
1777 if (isBuildingConstructorVTable()) {
1783 if (!BaseIsMorallyVirtual && !BaseDecl->
getNumVBases())
1792 OffsetInLayoutClass + RelativeBaseOffset;
1796 if (BaseDecl == PrimaryBase) {
1798 BaseIsMorallyVirtual, BaseOffsetInLayoutClass);
1803 LayoutPrimaryAndSecondaryVTables(
1805 BaseIsMorallyVirtual,
1807 BaseOffsetInLayoutClass);
1811 void ItaniumVTableBuilder::DeterminePrimaryVirtualBases(
1813 VisitedVirtualBasesSetTy &VBases) {
1821 bool IsPrimaryVirtualBase =
true;
1823 if (isBuildingConstructorVTable()) {
1829 CharUnits PrimaryBaseOffsetInLayoutClass =
1834 if (PrimaryBaseOffsetInLayoutClass != OffsetInLayoutClass)
1835 IsPrimaryVirtualBase =
false;
1838 if (IsPrimaryVirtualBase)
1839 PrimaryVirtualBases.insert(PrimaryBase);
1844 for (
const auto &B : RD->
bases()) {
1845 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
1849 if (B.isVirtual()) {
1850 if (!VBases.insert(BaseDecl).second)
1856 BaseOffsetInLayoutClass =
1859 BaseOffsetInLayoutClass =
1863 DeterminePrimaryVirtualBases(BaseDecl, BaseOffsetInLayoutClass, VBases);
1867 void ItaniumVTableBuilder::LayoutVTablesForVirtualBases(
1868 const CXXRecordDecl *RD, VisitedVirtualBasesSetTy &VBases) {
1873 for (
const auto &B : RD->
bases()) {
1874 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
1879 !PrimaryVirtualBases.count(BaseDecl) &&
1880 VBases.insert(BaseDecl).second) {
1891 LayoutPrimaryAndSecondaryVTables(
1895 BaseOffsetInLayoutClass);
1901 LayoutVTablesForVirtualBases(BaseDecl, VBases);
1906 void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
1910 if (isBuildingConstructorVTable()) {
1911 Out <<
"Construction vtable for ('";
1914 Out << MostDerivedClassOffset.
getQuantity() <<
") in '";
1917 Out <<
"Vtable for '";
1920 Out <<
"' (" << Components.size() <<
" entries).\n";
1926 std::multimap<uint64_t, BaseSubobject> AddressPointsByIndex;
1927 for (AddressPointsMapTy::const_iterator I = AddressPoints.begin(),
1928 E = AddressPoints.end(); I != E; ++I) {
1930 uint64_t Index = I->second;
1932 AddressPointsByIndex.insert(std::make_pair(Index, Base));
1935 for (
unsigned I = 0, E = Components.size(); I != E; ++I) {
1938 Out << llvm::format(
"%4d | ", I);
1943 switch (Component.
getKind()) {
1946 Out <<
"vcall_offset ("
1952 Out <<
"vbase_offset ("
1958 Out <<
"offset_to_top ("
1979 Out <<
" [deleted]";
1981 ThunkInfo Thunk = VTableThunks.lookup(I);
1985 Out <<
"\n [return adjustment: ";
1990 Out <<
" vbase offset offset";
1998 Out <<
"\n [this adjustment: ";
2003 Out <<
" vcall offset offset";
2022 Out <<
"() [complete]";
2024 Out <<
"() [deleting]";
2029 ThunkInfo Thunk = VTableThunks.lookup(I);
2033 Out <<
"\n [this adjustment: ";
2038 Out <<
" vcall offset offset";
2054 Out <<
"[unused] " << Str;
2065 if (AddressPointsByIndex.count(NextIndex)) {
2066 if (AddressPointsByIndex.count(NextIndex) == 1) {
2068 AddressPointsByIndex.find(NextIndex)->second;
2073 Out <<
") vtable address --\n";
2076 AddressPointsByIndex.lower_bound(NextIndex)->second.getBaseOffset();
2079 std::set<std::string> ClassNames;
2080 for (std::multimap<uint64_t, BaseSubobject>::const_iterator I =
2081 AddressPointsByIndex.lower_bound(NextIndex), E =
2082 AddressPointsByIndex.upper_bound(NextIndex); I != E; ++I) {
2083 assert(I->second.getBaseOffset() == BaseOffset &&
2084 "Invalid base offset!");
2086 ClassNames.insert(RD->getQualifiedNameAsString());
2089 for (std::set<std::string>::const_iterator I = ClassNames.begin(),
2090 E = ClassNames.end(); I != E; ++I) {
2091 Out <<
" -- (" << *I;
2092 Out <<
", " << BaseOffset.
getQuantity() <<
") vtable address --\n";
2100 if (isBuildingConstructorVTable())
2107 std::map<std::string, CharUnits> ClassNamesAndOffsets;
2108 for (VBaseOffsetOffsetsMapTy::const_iterator I = VBaseOffsetOffsets.begin(),
2109 E = VBaseOffsetOffsets.end(); I != E; ++I) {
2110 std::string ClassName = I->first->getQualifiedNameAsString();
2112 ClassNamesAndOffsets.insert(
2113 std::make_pair(ClassName, OffsetOffset));
2116 Out <<
"Virtual base offset offsets for '";
2119 Out << ClassNamesAndOffsets.size();
2120 Out << (ClassNamesAndOffsets.size() == 1 ?
" entry" :
" entries") <<
").\n";
2122 for (std::map<std::string, CharUnits>::const_iterator I =
2123 ClassNamesAndOffsets.begin(), E = ClassNamesAndOffsets.end();
2125 Out <<
" " << I->first <<
" | " << I->second.getQuantity() <<
'\n';
2130 if (!Thunks.empty()) {
2132 std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls;
2134 for (ThunksMapTy::const_iterator I = Thunks.begin(), E = Thunks.end();
2137 std::string MethodName =
2141 MethodNamesAndDecls.insert(std::make_pair(MethodName, MD));
2144 for (std::map<std::string, const CXXMethodDecl *>::const_iterator I =
2145 MethodNamesAndDecls.begin(), E = MethodNamesAndDecls.end();
2147 const std::string &MethodName = I->first;
2150 ThunkInfoVectorTy ThunksVector = Thunks[MD];
2151 std::sort(ThunksVector.begin(), ThunksVector.end(),
2153 assert(LHS.
Method ==
nullptr && RHS.Method ==
nullptr);
2154 return std::tie(LHS.
This, LHS.
Return) < std::tie(RHS.This, RHS.Return);
2157 Out <<
"Thunks for '" << MethodName <<
"' (" << ThunksVector.size();
2158 Out << (ThunksVector.size() == 1 ?
" entry" :
" entries") <<
").\n";
2160 for (
unsigned I = 0, E = ThunksVector.size(); I != E; ++I) {
2161 const ThunkInfo &Thunk = ThunksVector[I];
2163 Out << llvm::format(
"%4d | ", I);
2168 Out <<
" non-virtual";
2171 Out <<
" vbase offset offset";
2180 Out <<
"this adjustment: ";
2185 Out <<
" vcall offset offset";
2198 std::map<uint64_t, std::string> IndicesMap;
2200 for (
const auto *MD : MostDerivedClass->
methods()) {
2206 std::string MethodName =
2212 assert(MethodVTableIndices.count(GD));
2213 uint64_t VTableIndex = MethodVTableIndices[GD];
2214 IndicesMap[VTableIndex] = MethodName +
" [complete]";
2215 IndicesMap[VTableIndex + 1] = MethodName +
" [deleting]";
2217 assert(MethodVTableIndices.count(MD));
2218 IndicesMap[MethodVTableIndices[MD]] = MethodName;
2223 if (!IndicesMap.empty()) {
2224 Out <<
"VTable indices for '";
2226 Out <<
"' (" << IndicesMap.size() <<
" entries).\n";
2228 for (std::map<uint64_t, std::string>::const_iterator I = IndicesMap.begin(),
2229 E = IndicesMap.end(); I != E; ++I) {
2230 uint64_t VTableIndex = I->first;
2231 const std::string &MethodName = I->second;
2233 Out << llvm::format(
"%4" PRIu64
" | ", VTableIndex) << MethodName
2244 uint64_t NumVTableThunks,
2247 bool IsMicrosoftABI)
2248 : NumVTableComponents(NumVTableComponents),
2250 NumVTableThunks(NumVTableThunks),
2252 AddressPoints(AddressPoints),
2253 IsMicrosoftABI(IsMicrosoftABI) {
2254 std::copy(VTableComponents, VTableComponents+NumVTableComponents,
2255 this->VTableComponents.get());
2256 std::copy(VTableThunks, VTableThunks+NumVTableThunks,
2257 this->VTableThunks.get());
2258 std::sort(this->VTableThunks.get(),
2259 this->VTableThunks.get() + NumVTableThunks,
2262 assert((LHS.first != RHS.first || LHS.second == RHS.second) &&
2263 "Different thunks should have unique indices!");
2264 return LHS.first < RHS.first;
2274 llvm::DeleteContainerSeconds(VTableLayouts);
2278 MethodVTableIndicesTy::iterator I = MethodVTableIndices.find(GD);
2279 if (I != MethodVTableIndices.end())
2284 computeVTableRelatedInformation(RD);
2286 I = MethodVTableIndices.find(GD);
2287 assert(I != MethodVTableIndices.end() &&
"Did not find index!");
2294 ClassPairTy ClassPair(RD, VBase);
2296 VirtualBaseClassOffsetOffsetsMapTy::iterator I =
2297 VirtualBaseClassOffsetOffsets.find(ClassPair);
2298 if (I != VirtualBaseClassOffsetOffsets.end())
2301 VCallAndVBaseOffsetBuilder
Builder(RD, RD,
nullptr,
2306 for (VCallAndVBaseOffsetBuilder::VBaseOffsetOffsetsMapTy::const_iterator I =
2307 Builder.getVBaseOffsetOffsets().begin(),
2308 E =
Builder.getVBaseOffsetOffsets().end(); I != E; ++I) {
2310 ClassPairTy ClassPair(RD, I->first);
2312 VirtualBaseClassOffsetOffsets.insert(
2313 std::make_pair(ClassPair, I->second));
2316 I = VirtualBaseClassOffsetOffsets.find(ClassPair);
2317 assert(I != VirtualBaseClassOffsetOffsets.end() &&
"Did not find index!");
2324 VTableThunks(Builder.vtable_thunks_begin(), Builder.vtable_thunks_end());
2326 return new VTableLayout(Builder.getNumVTableComponents(),
2327 Builder.vtable_component_begin(),
2328 VTableThunks.size(),
2329 VTableThunks.data(),
2330 Builder.getAddressPoints(),
2335 ItaniumVTableContext::computeVTableRelatedInformation(
const CXXRecordDecl *RD) {
2346 MethodVTableIndices.insert(
Builder.vtable_indices_begin(),
2347 Builder.vtable_indices_end());
2361 if (VirtualBaseClassOffsetOffsets.count(std::make_pair(RD, VBase)))
2364 for (ItaniumVTableBuilder::VBaseOffsetOffsetsMapTy::const_iterator
2365 I =
Builder.getVBaseOffsetOffsets().begin(),
2366 E =
Builder.getVBaseOffsetOffsets().end();
2369 ClassPairTy ClassPair(RD, I->first);
2371 VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I->second));
2377 bool MostDerivedClassIsVirtual,
const CXXRecordDecl *LayoutClass) {
2378 ItaniumVTableBuilder
Builder(*
this, MostDerivedClass, MostDerivedClassOffset,
2379 MostDerivedClassIsVirtual, LayoutClass);
2427 class VFTableBuilder {
2431 typedef llvm::DenseMap<GlobalDecl, MethodVFTableLocation>
2432 MethodVFTableLocationsTy;
2434 typedef llvm::iterator_range<MethodVFTableLocationsTy::const_iterator>
2435 method_locations_range;
2453 const FinalOverriders Overriders;
2458 MethodVFTableLocationsTy MethodVFTableLocations;
2461 bool HasRTTIComponent;
2468 const uint64_t VBTableIndex;
2471 const uint64_t VFTableIndex;
2482 MethodInfo(uint64_t VBTableIndex, uint64_t VFTableIndex,
2483 bool UsesExtraSlot =
false)
2484 : VBTableIndex(VBTableIndex), VFTableIndex(VFTableIndex),
2485 Shadowed(
false), UsesExtraSlot(UsesExtraSlot) {}
2488 : VBTableIndex(0), VFTableIndex(0), Shadowed(
false),
2489 UsesExtraSlot(
false) {}
2492 typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy;
2496 MethodInfoMapTy MethodInfoMap;
2498 typedef llvm::DenseMap<uint64_t, ThunkInfo> VTableThunksMapTy;
2502 VTableThunksMapTy VTableThunks;
2505 typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
2516 if (std::find(ThunksVector.begin(), ThunksVector.end(), Thunk) !=
2520 ThunksVector.push_back(Thunk);
2525 CharUnits ComputeThisOffset(FinalOverriders::OverriderInfo Overrider);
2527 void CalculateVtordispAdjustment(FinalOverriders::OverriderInfo Overrider,
2534 VTableThunks[Components.size()] = TI;
2539 "Destructor can't have return adjustment!");
2550 BasesSetVectorTy &VisitedBases);
2552 void LayoutVFTable() {
2554 if (HasRTTIComponent)
2557 BasesSetVectorTy VisitedBases;
2560 assert((HasRTTIComponent ? Components.size() - 1 : Components.size()) &&
2561 "vftable can't be empty");
2563 assert(MethodVFTableLocations.empty());
2564 for (MethodInfoMapTy::const_iterator I = MethodInfoMap.begin(),
2565 E = MethodInfoMap.end(); I != E; ++I) {
2567 const MethodInfo &MI = I->second;
2570 if (MD->
getParent() != MostDerivedClass || MI.Shadowed)
2572 MethodVFTableLocation Loc(MI.VBTableIndex, WhichVFPtr.getVBaseWithVPtr(),
2573 WhichVFPtr.NonVirtualOffset, MI.VFTableIndex);
2577 MethodVFTableLocations[MD] = Loc;
2586 Context(MostDerivedClass->getASTContext()),
2587 MostDerivedClass(MostDerivedClass),
2588 MostDerivedClassLayout(
Context.getASTRecordLayout(MostDerivedClass)),
2590 Overriders(MostDerivedClass,
CharUnits(), MostDerivedClass) {
2594 !MostDerivedClass->
hasAttr<DLLImportAttr>() &&
2601 dumpLayout(llvm::outs());
2604 uint64_t getNumThunks()
const {
return Thunks.size(); }
2606 ThunksMapTy::const_iterator thunks_begin()
const {
return Thunks.begin(); }
2608 ThunksMapTy::const_iterator thunks_end()
const {
return Thunks.end(); }
2610 method_locations_range vtable_locations()
const {
2611 return method_locations_range(MethodVFTableLocations.begin(),
2612 MethodVFTableLocations.end());
2615 uint64_t getNumVTableComponents()
const {
return Components.size(); }
2618 return Components.begin();
2622 return Components.end();
2625 VTableThunksMapTy::const_iterator vtable_thunks_begin()
const {
2626 return VTableThunks.begin();
2629 VTableThunksMapTy::const_iterator vtable_thunks_end()
const {
2630 return VTableThunks.end();
2633 void dumpLayout(raw_ostream &);
2638 struct InitialOverriddenDefinitionCollector {
2639 BasesSetVectorTy Bases;
2640 OverriddenMethodsSetTy VisitedOverriddenMethods;
2644 Bases.insert(OverriddenMD->
getParent());
2646 return VisitedOverriddenMethods.insert(OverriddenMD).second;
2654 BasesSetVectorTy *Bases = (BasesSetVectorTy *)BasesSet;
2713 VFTableBuilder::ComputeThisOffset(FinalOverriders::OverriderInfo Overrider) {
2714 InitialOverriddenDefinitionCollector Collector;
2715 visitAllOverriddenMethods(Overrider.Method, Collector);
2719 if (Collector.Bases.size() == 0)
2720 return Overrider.Offset;
2723 Overrider.Method->getParent()->lookupInBases(
BaseInSet, &Collector.Bases,
2738 CharUnits ThisOffset = Overrider.Offset;
2744 for (
int J = 0, F = Path.size(); J != F; ++J) {
2762 LastVBaseOffset = ThisOffset =
2769 if (isa<CXXDestructorDecl>(Overrider.Method)) {
2770 if (LastVBaseOffset.
isZero()) {
2774 ThisOffset = Overrider.Offset;
2778 ThisOffset = LastVBaseOffset;
2782 if (Ret > ThisOffset || First) {
2788 assert(!First &&
"Method not found in the given subobject?");
2890 void VFTableBuilder::CalculateVtordispAdjustment(
2891 FinalOverriders::OverriderInfo Overrider,
CharUnits ThisOffset,
2894 MostDerivedClassLayout.getVBaseOffsetsMap();
2895 const ASTRecordLayout::VBaseOffsetsMapTy::const_iterator &VBaseMapEntry =
2896 VBaseMap.find(WhichVFPtr.getVBaseWithVPtr());
2897 assert(VBaseMapEntry != VBaseMap.end());
2901 if (!VBaseMapEntry->second.hasVtorDisp() ||
2902 Overrider.VirtualBase == WhichVFPtr.getVBaseWithVPtr())
2907 CharUnits OffsetOfVBaseWithVFPtr = VBaseMapEntry->second.VBaseOffset;
2909 (OffsetOfVBaseWithVFPtr - WhichVFPtr.FullOffsetInMDC).getQuantity() - 4;
2913 if (Overrider.Method->getParent() == MostDerivedClass ||
2914 !Overrider.VirtualBase)
2920 (OffsetOfVBaseWithVFPtr + WhichVFPtr.NonVirtualOffset -
2921 MostDerivedClassLayout.getVBPtrOffset()).getQuantity();
2926 TA.
NonVirtual = (ThisOffset - Overrider.Offset).getQuantity();
2939 typedef llvm::DenseMap<DeclarationName, unsigned> VisitedGroupIndicesTy;
2940 VisitedGroupIndicesTy VisitedGroupIndices;
2941 for (
const auto *MD : RD->
methods()) {
2943 VisitedGroupIndicesTy::iterator J;
2945 std::tie(J, Inserted) = VisitedGroupIndices.insert(
2946 std::make_pair(MD->
getDeclName(), Groups.size()));
2948 Groups.push_back(MethodGroup());
2950 Groups[J->second].push_back(MD);
2953 for (
unsigned I = 0, E = Groups.size(); I != E; ++I)
2954 VirtualMethods.append(Groups[I].rbegin(), Groups[I].rend());
2958 for (
const auto &B : RD->
bases()) {
2959 if (B.isVirtual() && B.getType()->getAsCXXRecordDecl() == Base)
2967 BasesSetVectorTy &VisitedBases) {
2977 const CXXRecordDecl *NextBase =
nullptr, *NextLastVBase = LastVBase;
2979 if (BaseDepth < WhichVFPtr.PathToBaseWithVPtr.size()) {
2980 NextBase = WhichVFPtr.PathToBaseWithVPtr[BaseDepth];
2982 NextLastVBase = NextBase;
2983 NextBaseOffset = MostDerivedClassLayout.getVBaseClassOffset(NextBase);
2990 "No primary virtual bases in this ABI");
2991 NextBase = PrimaryBase;
2996 AddMethods(
BaseSubobject(NextBase, NextBaseOffset), BaseDepth + 1,
2997 NextLastVBase, VisitedBases);
2998 if (!VisitedBases.insert(NextBase))
2999 llvm_unreachable(
"Found a duplicate primary base!");
3014 for (
unsigned I = 0, E = VirtualMethods.size(); I != E; ++I) {
3017 FinalOverriders::OverriderInfo FinalOverrider =
3019 const CXXMethodDecl *FinalOverriderMD = FinalOverrider.Method;
3021 FindNearestOverriddenMethod(MD, VisitedBases);
3024 bool ReturnAdjustingThunk =
false, ForceReturnAdjustmentMangling =
false;
3025 CharUnits ThisOffset = ComputeThisOffset(FinalOverrider);
3027 (ThisOffset - WhichVFPtr.FullOffsetInMDC).getQuantity();
3028 if ((OverriddenMD || FinalOverriderMD != MD) &&
3029 WhichVFPtr.getVBaseWithVPtr())
3030 CalculateVtordispAdjustment(FinalOverrider, ThisOffset,
3031 ThisAdjustmentOffset);
3036 MethodInfoMapTy::iterator OverriddenMDIterator =
3037 MethodInfoMap.find(OverriddenMD);
3040 if (OverriddenMDIterator == MethodInfoMap.end())
3043 MethodInfo &OverriddenMethodInfo = OverriddenMDIterator->second;
3050 ReturnAdjustingThunk = !ComputeReturnAdjustmentBaseOffset(
3051 Context, MD, OverriddenMD).isEmpty() ||
3052 OverriddenMethodInfo.UsesExtraSlot;
3054 if (!ReturnAdjustingThunk) {
3057 MethodInfo MI(OverriddenMethodInfo.VBTableIndex,
3058 OverriddenMethodInfo.VFTableIndex);
3059 MethodInfoMap.erase(OverriddenMDIterator);
3061 assert(!MethodInfoMap.count(MD) &&
3062 "Should not have method info for this method yet!");
3063 MethodInfoMap.insert(std::make_pair(MD, MI));
3069 OverriddenMethodInfo.Shadowed =
true;
3073 ForceReturnAdjustmentMangling =
3074 !(MD == FinalOverriderMD && ThisAdjustmentOffset.
isEmpty());
3075 }
else if (Base.
getBaseOffset() != WhichVFPtr.FullOffsetInMDC ||
3087 MethodInfo MI(VBIndex,
3088 HasRTTIComponent ? Components.size() - 1 : Components.size(),
3089 ReturnAdjustingThunk);
3091 assert(!MethodInfoMap.count(MD) &&
3092 "Should not have method info for this method yet!");
3093 MethodInfoMap.insert(std::make_pair(MD, MI));
3097 BaseOffset ReturnAdjustmentOffset;
3099 if (!FinalOverriderMD->
isPure()) {
3100 ReturnAdjustmentOffset =
3101 ComputeReturnAdjustmentBaseOffset(
Context, FinalOverriderMD, MD);
3103 if (!ReturnAdjustmentOffset.isEmpty()) {
3104 ForceReturnAdjustmentMangling =
true;
3106 ReturnAdjustmentOffset.NonVirtualOffset.getQuantity();
3107 if (ReturnAdjustmentOffset.VirtualBase) {
3114 ReturnAdjustmentOffset.VirtualBase);
3118 AddMethod(FinalOverriderMD,
3119 ThunkInfo(ThisAdjustmentOffset, ReturnAdjustment,
3120 ForceReturnAdjustmentMangling ? MD :
nullptr));
3125 for (VPtrInfo::BasePath::const_reverse_iterator I = Path.rbegin(),
3126 E = Path.rend(); I != E; ++I) {
3128 (*I)->printQualifiedName(Out);
3134 bool ContinueFirstLine) {
3135 const ReturnAdjustment &R = TI.
Return;
3136 bool Multiline =
false;
3137 const char *LinePrefix =
"\n ";
3139 if (!ContinueFirstLine)
3141 Out <<
"[return adjustment (to type '"
3154 if (Multiline || !ContinueFirstLine)
3156 Out <<
"[this adjustment: ";
3164 Out << LinePrefix <<
" vboffset at "
3172 void VFTableBuilder::dumpLayout(raw_ostream &Out) {
3173 Out <<
"VFTable for ";
3177 Out <<
"' (" << Components.size()
3178 << (Components.size() == 1 ?
" entry" :
" entries") <<
").\n";
3180 for (
unsigned I = 0, E = Components.size(); I != E; ++I) {
3181 Out << llvm::format(
"%4d | ", I);
3186 switch (Component.
getKind()) {
3204 Out <<
" [deleted]";
3206 ThunkInfo Thunk = VTableThunks.lookup(I);
3217 Out <<
"() [scalar deleting]";
3222 ThunkInfo Thunk = VTableThunks.lookup(I);
3225 "No return adjustment needed for destructors!");
3236 "Unexpected vftable component type %0 for component number %1");
3246 if (!Thunks.empty()) {
3248 std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls;
3250 for (ThunksMapTy::const_iterator I = Thunks.begin(), E = Thunks.end();
3256 MethodNamesAndDecls.insert(std::make_pair(MethodName, MD));
3259 for (std::map<std::string, const CXXMethodDecl *>::const_iterator
3260 I = MethodNamesAndDecls.begin(),
3261 E = MethodNamesAndDecls.end();
3263 const std::string &MethodName = I->first;
3266 ThunkInfoVectorTy ThunksVector = Thunks[MD];
3267 std::stable_sort(ThunksVector.begin(), ThunksVector.end(),
3271 return std::tie(LHS.
This, LHS.
Return) < std::tie(RHS.This, RHS.Return);
3274 Out <<
"Thunks for '" << MethodName <<
"' (" << ThunksVector.size();
3275 Out << (ThunksVector.size() == 1 ?
" entry" :
" entries") <<
").\n";
3277 for (
unsigned I = 0, E = ThunksVector.size(); I != E; ++I) {
3278 const ThunkInfo &Thunk = ThunksVector[I];
3280 Out << llvm::format(
"%4d | ", I);
3325 void MicrosoftVTableContext::computeVTablePaths(
bool ForVBTables,
3328 assert(Paths.empty());
3332 if (ForVBTables ? Layout.hasOwnVBPtr() : Layout.hasOwnVFPtr())
3337 llvm::SmallPtrSet<const CXXRecordDecl*, 4> VBasesSeen;
3338 for (
const auto &B : RD->
bases()) {
3339 const CXXRecordDecl *Base = B.getType()->getAsCXXRecordDecl();
3340 if (B.isVirtual() && VBasesSeen.count(Base))
3349 for (
VPtrInfo *BaseInfo : BasePaths) {
3367 Base == (ForVBTables ? Layout.getBaseSharingVBPtr()
3368 : Layout.getPrimaryBase()))
3387 VBasesSeen.insert(Base);
3391 for (
const auto &VB : Base->
vbases())
3392 VBasesSeen.insert(VB.getType()->getAsCXXRecordDecl());
3397 bool Changed =
true;
3419 std::sort(PathsSorted.begin(), PathsSorted.end(),
3423 bool Changed =
false;
3424 for (
size_t I = 0, E = PathsSorted.size(); I != E;) {
3426 size_t BucketStart = I;
3429 }
while (I != E && PathsSorted[BucketStart]->MangledPath ==
3430 PathsSorted[I]->MangledPath);
3433 if (I - BucketStart > 1) {
3434 for (
size_t II = BucketStart; II != I; ++II)
3436 assert(Changed &&
"no paths were extended to fix ambiguity");
3443 for (
auto &P : VFPtrLocations)
3444 llvm::DeleteContainerPointers(*P.second);
3445 llvm::DeleteContainerSeconds(VFPtrLocations);
3446 llvm::DeleteContainerSeconds(VFTableLayouts);
3447 llvm::DeleteContainerSeconds(VBaseInfo);
3451 typedef llvm::SetVector<BaseSubobject, std::vector<BaseSubobject>,
3461 FullPathTy &FullPath,
3462 std::list<FullPathTy> &Paths) {
3464 Paths.push_back(FullPath);
3471 const CXXRecordDecl *Base = BS.getType()->getAsCXXRecordDecl();
3477 BaseWithVPtr, FullPath, Paths);
3478 FullPath.pop_back();
3484 FullPaths.remove_if([&](
const FullPathTy &SpecificPath) {
3485 for (
const FullPathTy &OtherPath : FullPaths) {
3486 if (&SpecificPath == &OtherPath)
3488 if (std::all_of(SpecificPath.begin(), SpecificPath.end(),
3490 return OtherPath.count(BSO) != 0;
3501 const FullPathTy &FullPath) {
3522 : Offset + Layout.getBaseClassOffset(Base);
3533 std::list<FullPathTy> &FullPaths) {
3535 if (FullPaths.empty())
3537 if (FullPaths.size() == 1)
3538 return &FullPaths.front();
3540 const FullPathTy *BestPath =
nullptr;
3541 typedef std::set<const CXXMethodDecl *> OverriderSetTy;
3542 OverriderSetTy LastOverrides;
3543 for (
const FullPathTy &SpecificPath : FullPaths) {
3544 assert(!SpecificPath.empty());
3545 OverriderSetTy CurrentOverrides;
3546 const CXXRecordDecl *TopLevelRD = SpecificPath.begin()->getBase();
3551 FinalOverriders Overriders(TopLevelRD,
CharUnits::Zero(), TopLevelRD);
3555 FinalOverriders::OverriderInfo OI =
3560 if (ComputeReturnAdjustmentBaseOffset(Context, OverridingMethod, MD)
3566 if (std::none_of(SpecificPath.begin(), SpecificPath.end(),
3568 return BSO.getBase() == OverridingParent;
3571 CurrentOverrides.insert(OverridingMethod);
3573 OverriderSetTy NewOverrides =
3574 llvm::set_difference(CurrentOverrides, LastOverrides);
3575 if (NewOverrides.empty())
3577 OverriderSetTy MissingOverrides =
3578 llvm::set_difference(LastOverrides, CurrentOverrides);
3579 if (MissingOverrides.empty()) {
3581 BestPath = &SpecificPath;
3582 std::swap(CurrentOverrides, LastOverrides);
3587 const CXXMethodDecl *ConflictMD = *MissingOverrides.begin();
3598 return BestPath ? BestPath : &FullPaths.front();
3605 FullPathTy FullPath;
3606 std::list<FullPathTy> FullPaths;
3610 BaseSubobject(Info->BaseWithVPtr, Info->FullOffsetInMDC), FullPath,
3614 Info->PathToBaseWithVPtr.clear();
3615 if (
const FullPathTy *BestPath =
3618 Info->PathToBaseWithVPtr.push_back(BSO.getBase());
3623 void MicrosoftVTableContext::computeVTableRelatedInformation(
3628 if (VFPtrLocations.count(RD))
3634 computeVTablePaths(
false, RD, *VFPtrs);
3636 VFPtrLocations[RD] = VFPtrs;
3638 MethodVFTableLocationsTy NewMethodLocations;
3639 for (VPtrInfoVector::iterator I = VFPtrs->begin(), E = VFPtrs->end();
3641 VFTableBuilder
Builder(*
this, RD, *I);
3643 VFTableIdTy
id(RD, (*I)->FullOffsetInMDC);
3644 assert(VFTableLayouts.count(
id) == 0);
3648 Builder.getNumVTableComponents(),
Builder.vtable_component_begin(),
3649 VTableThunks.size(), VTableThunks.data(), EmptyAddressPointsMap,
true);
3652 for (
const auto &Loc :
Builder.vtable_locations()) {
3654 MethodVFTableLocation NewLoc = Loc.second;
3655 auto M = NewMethodLocations.find(GD);
3656 if (M == NewMethodLocations.end() || NewLoc < M->second)
3657 NewMethodLocations[GD] = NewLoc;
3661 MethodVFTableLocations.insert(NewMethodLocations.begin(),
3662 NewMethodLocations.end());
3664 dumpMethodLocations(RD, NewMethodLocations, llvm::outs());
3667 void MicrosoftVTableContext::dumpMethodLocations(
3668 const CXXRecordDecl *RD,
const MethodVFTableLocationsTy &NewMethods,
3672 std::map<MethodVFTableLocation, std::string> IndicesMap;
3673 bool HasNonzeroOffset =
false;
3675 for (MethodVFTableLocationsTy::const_iterator I = NewMethods.begin(),
3676 E = NewMethods.end(); I != E; ++I) {
3677 const CXXMethodDecl *MD = cast<const CXXMethodDecl>(I->first.getDecl());
3683 if (isa<CXXDestructorDecl>(MD)) {
3684 IndicesMap[I->second] = MethodName +
" [scalar deleting]";
3686 IndicesMap[I->second] = MethodName;
3689 if (!I->second.VFPtrOffset.isZero() || I->second.VBTableIndex != 0)
3690 HasNonzeroOffset =
true;
3694 if (!IndicesMap.empty()) {
3695 Out <<
"VFTable indices for ";
3698 Out <<
"' (" << IndicesMap.size()
3699 << (IndicesMap.size() == 1 ?
" entry" :
" entries") <<
").\n";
3702 uint64_t LastVBIndex = 0;
3703 for (std::map<MethodVFTableLocation, std::string>::const_iterator
3704 I = IndicesMap.begin(),
3705 E = IndicesMap.end();
3707 CharUnits VFPtrOffset = I->first.VFPtrOffset;
3708 uint64_t VBIndex = I->first.VBTableIndex;
3709 if (HasNonzeroOffset &&
3710 (VFPtrOffset != LastVFPtrOffset || VBIndex != LastVBIndex)) {
3711 assert(VBIndex > LastVBIndex || VFPtrOffset > LastVFPtrOffset);
3712 Out <<
" -- accessible via ";
3714 Out <<
"vbtable index " << VBIndex <<
", ";
3715 Out <<
"vfptr at offset " << VFPtrOffset.
getQuantity() <<
" --\n";
3716 LastVFPtrOffset = VFPtrOffset;
3717 LastVBIndex = VBIndex;
3720 uint64_t VTableIndex = I->first.Index;
3721 const std::string &MethodName = I->second;
3722 Out << llvm::format(
"%4" PRIu64
" | ", VTableIndex) << MethodName <<
'\n';
3730 const VirtualBaseInfo *MicrosoftVTableContext::computeVBTableRelatedInformation(
3743 computeVTablePaths(
true, RD, VBI->
VBPtrPaths);
3751 computeVBTableRelatedInformation(VBPtrBase);
3759 for (
const auto &VB : RD->
vbases()) {
3760 const CXXRecordDecl *CurVBase = VB.getType()->getAsCXXRecordDecl();
3770 const VirtualBaseInfo *VBInfo = computeVBTableRelatedInformation(Derived);
3777 return computeVBTableRelatedInformation(RD)->
VBPtrPaths;
3782 computeVTableRelatedInformation(RD);
3784 assert(VFPtrLocations.count(RD) &&
"Couldn't find vfptr locations");
3785 return *VFPtrLocations[RD];
3791 computeVTableRelatedInformation(RD);
3793 VFTableIdTy
id(RD, VFPtrOffset);
3794 assert(VFTableLayouts.count(
id) &&
"Couldn't find a VFTable at this offset");
3795 return *VFTableLayouts[
id];
3800 assert(cast<CXXMethodDecl>(GD.
getDecl())->isVirtual() &&
3801 "Only use this method for virtual methods or dtors");
3802 if (isa<CXXDestructorDecl>(GD.
getDecl()))
3805 MethodVFTableLocationsTy::iterator I = MethodVFTableLocations.find(GD);
3806 if (I != MethodVFTableLocations.end())
3811 computeVTableRelatedInformation(RD);
3813 I = MethodVFTableLocations.find(GD);
3814 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.
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.
VPtrInfoVector VBPtrPaths
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
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.
MapType::const_iterator const_iterator
const CXXMethodDecl * Method
Holds a pointer to the overridden method this thunk is for, if needed by the ABI to distinguish diffe...
std::list< CXXBasePath >::const_iterator const_paths_iterator
static bool BaseInSet(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, void *BasesSet)
unsigned getNumParams() const
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.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
QualType getReturnType() const
VTableLayout(uint64_t NumVTableComponents, const VTableComponent *VTableComponents, uint64_t NumVTableThunks, const VTableThunkTy *VTableThunks, const AddressPointsMapTy &AddressPoints, bool IsMicrosoftABI)
CXXMethodDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
static VTableComponent MakeCompleteDtor(const CXXDestructorDecl *DD)
struct clang::ReturnAdjustment::VirtualAdjustment::@113 Itanium
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
llvm::DenseMap< const CXXRecordDecl *, unsigned > VBTableIndices
The this pointer adjustment as well as an optional return adjustment for a thunk. ...
const Decl * getDecl() const
const CXXRecordDecl * NextBaseToMangle
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
~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
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.
CharUnits getVirtualBaseOffsetOffset(const CXXRecordDecl *RD, const CXXRecordDecl *VBase)
static VTableComponent MakeDeletingDtor(const CXXDestructorDecl *DD)
DiagnosticsEngine & getDiagnostics() const
BasePath ContainingVBases
QualType getParamType(unsigned i) const
union clang::ReturnAdjustment::VirtualAdjustment Virtual
const CXXMethodDecl *const * method_iterator
struct clang::ThisAdjustment::VirtualAdjustment::@115 Itanium
const CXXRecordDecl * getBase() const
getBase - Returns the base class declaration.
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
Uniquely identifies a virtual method within a class hierarchy by the method itself and a class subobj...
DeclarationName getDeclName() const
const CXXRecordDecl * ReusingBase
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. VBase must be a morally virtual base 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)
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)
struct clang::ReturnAdjustment::VirtualAdjustment::@114 Microsoft
ASTContext & getASTContext() const LLVM_READONLY
unsigned size_overridden_methods() const
Represents a single component in a vtable.
Represents a static or instance method of a struct/union/class.
struct clang::ThisAdjustment::VirtualAdjustment::@116 Microsoft
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. ...
void printQualifiedName(raw_ostream &OS) const
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()))
TemplateSpecializationKind getTemplateSpecializationKind() const
Determine whether this particular class is a specialization or instantiation of a class template or m...
ThisAdjustment This
The this pointer adjustment.
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...
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.
CharUnits NonVirtualOffset
base_class_iterator vbases_begin()
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
union clang::ThisAdjustment::VirtualAdjustment Virtual
unsigned getTypeQuals() const
QualType getCanonicalType() const
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
A pointer to the deleting destructor.
static Decl::Kind getKind(const Decl *D)
static VTableComponent MakeFunction(const CXXMethodDecl *MD)
Kind getKind() const
Get the kind of this vtable component.
CharUnits getBaseOffset() const
getBaseOffset - Returns the base class offset.
uint32_t VBIndex
Index of the virtual base in the vbtable.
SourceLocation getLocation() const
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
const CXXMethodDecl * getUnusedFunctionDecl() const
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
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.
std::list< CXXBasePath >::iterator paths_iterator
const MethodVFTableLocation & getMethodVFTableLocation(GlobalDecl GD)
static VTableComponent MakeOffsetToTop(CharUnits Offset)