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 (
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),
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),
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));
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;
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) {
2551 !MostDerivedClass->
hasAttr<DLLImportAttr>() &&
2558 dumpLayout(llvm::outs());
2561 uint64_t getNumThunks()
const {
return Thunks.size(); }
2563 ThunksMapTy::const_iterator thunks_begin()
const {
return Thunks.begin(); }
2565 ThunksMapTy::const_iterator thunks_end()
const {
return Thunks.end(); }
2567 method_locations_range vtable_locations()
const {
2568 return method_locations_range(MethodVFTableLocations.begin(),
2569 MethodVFTableLocations.end());
2572 uint64_t getNumVTableComponents()
const {
return Components.size(); }
2575 return Components.begin();
2579 return Components.end();
2582 VTableThunksMapTy::const_iterator vtable_thunks_begin()
const {
2583 return VTableThunks.begin();
2586 VTableThunksMapTy::const_iterator vtable_thunks_end()
const {
2587 return VTableThunks.end();
2590 void dumpLayout(raw_ostream &);
2650 VFTableBuilder::ComputeThisOffset(FinalOverriders::OverriderInfo Overrider) {
2651 BasesSetVectorTy Bases;
2655 OverriddenMethodsSetTy VisitedOverriddenMethods;
2656 auto InitialOverriddenDefinitionCollector = [&](
2658 if (OverriddenMD->size_overridden_methods() == 0)
2659 Bases.insert(OverriddenMD->getParent());
2661 return VisitedOverriddenMethods.insert(OverriddenMD).second;
2663 visitAllOverriddenMethods(Overrider.Method,
2664 InitialOverriddenDefinitionCollector);
2669 if (Bases.size() == 0)
2670 return Overrider.Offset;
2673 Overrider.Method->getParent()->lookupInBases(
2689 CharUnits ThisOffset = Overrider.Offset;
2696 QualType CurTy = Element.Base->getType();
2701 if (Element.Base->isVirtual()) {
2712 LastVBaseOffset = ThisOffset =
2719 if (isa<CXXDestructorDecl>(Overrider.Method)) {
2720 if (LastVBaseOffset.
isZero()) {
2724 ThisOffset = Overrider.Offset;
2728 ThisOffset = LastVBaseOffset;
2732 if (Ret > ThisOffset || First) {
2738 assert(!First &&
"Method not found in the given subobject?");
2840 void VFTableBuilder::CalculateVtordispAdjustment(
2841 FinalOverriders::OverriderInfo Overrider,
CharUnits ThisOffset,
2844 MostDerivedClassLayout.getVBaseOffsetsMap();
2845 const ASTRecordLayout::VBaseOffsetsMapTy::const_iterator &VBaseMapEntry =
2846 VBaseMap.find(WhichVFPtr.getVBaseWithVPtr());
2847 assert(VBaseMapEntry != VBaseMap.end());
2851 if (!VBaseMapEntry->second.hasVtorDisp() ||
2852 Overrider.VirtualBase == WhichVFPtr.getVBaseWithVPtr())
2857 CharUnits OffsetOfVBaseWithVFPtr = VBaseMapEntry->second.VBaseOffset;
2859 (OffsetOfVBaseWithVFPtr - WhichVFPtr.FullOffsetInMDC).getQuantity() - 4;
2863 if (Overrider.Method->getParent() == MostDerivedClass ||
2864 !Overrider.VirtualBase)
2870 (OffsetOfVBaseWithVFPtr + WhichVFPtr.NonVirtualOffset -
2871 MostDerivedClassLayout.getVBPtrOffset()).getQuantity();
2876 TA.
NonVirtual = (ThisOffset - Overrider.Offset).getQuantity();
2890 typedef llvm::DenseMap<DeclarationName, unsigned> VisitedGroupIndicesTy;
2891 VisitedGroupIndicesTy VisitedGroupIndices;
2892 for (
const auto *D : RD->
decls()) {
2893 const auto *ND = dyn_cast<
NamedDecl>(D);
2898 std::tie(J, Inserted) = VisitedGroupIndices.insert(
2899 std::make_pair(ND->getDeclName(), Groups.size()));
2901 Groups.push_back(MethodGroup());
2902 if (
const auto *MD = dyn_cast<CXXMethodDecl>(ND))
2907 for (
const MethodGroup &Group : Groups)
2908 VirtualMethods.append(Group.rbegin(), Group.rend());
2912 for (
const auto &B : RD->
bases()) {
2913 if (B.isVirtual() && B.getType()->getAsCXXRecordDecl() == Base)
2921 BasesSetVectorTy &VisitedBases) {
2931 const CXXRecordDecl *NextBase =
nullptr, *NextLastVBase = LastVBase;
2933 if (BaseDepth < WhichVFPtr.PathToBaseWithVPtr.size()) {
2934 NextBase = WhichVFPtr.PathToBaseWithVPtr[BaseDepth];
2936 NextLastVBase = NextBase;
2937 NextBaseOffset = MostDerivedClassLayout.getVBaseClassOffset(NextBase);
2944 "No primary virtual bases in this ABI");
2945 NextBase = PrimaryBase;
2950 AddMethods(
BaseSubobject(NextBase, NextBaseOffset), BaseDepth + 1,
2951 NextLastVBase, VisitedBases);
2952 if (!VisitedBases.insert(NextBase))
2953 llvm_unreachable(
"Found a duplicate primary base!");
2969 FinalOverriders::OverriderInfo FinalOverrider =
2971 const CXXMethodDecl *FinalOverriderMD = FinalOverrider.Method;
2973 FindNearestOverriddenMethod(MD, VisitedBases);
2976 bool ReturnAdjustingThunk =
false, ForceReturnAdjustmentMangling =
false;
2977 CharUnits ThisOffset = ComputeThisOffset(FinalOverrider);
2979 (ThisOffset - WhichVFPtr.FullOffsetInMDC).getQuantity();
2980 if ((OverriddenMD || FinalOverriderMD != MD) &&
2981 WhichVFPtr.getVBaseWithVPtr())
2982 CalculateVtordispAdjustment(FinalOverrider, ThisOffset,
2983 ThisAdjustmentOffset);
2989 MethodInfoMap.find(OverriddenMD);
2992 if (OverriddenMDIterator == MethodInfoMap.end())
2995 MethodInfo &OverriddenMethodInfo = OverriddenMDIterator->second;
3002 ReturnAdjustingThunk = !ComputeReturnAdjustmentBaseOffset(
3003 Context, MD, OverriddenMD).isEmpty() ||
3004 OverriddenMethodInfo.UsesExtraSlot;
3006 if (!ReturnAdjustingThunk) {
3009 MethodInfo MI(OverriddenMethodInfo.VBTableIndex,
3010 OverriddenMethodInfo.VFTableIndex);
3011 MethodInfoMap.erase(OverriddenMDIterator);
3013 assert(!MethodInfoMap.count(MD) &&
3014 "Should not have method info for this method yet!");
3015 MethodInfoMap.insert(std::make_pair(MD, MI));
3021 OverriddenMethodInfo.Shadowed =
true;
3025 ForceReturnAdjustmentMangling =
3026 !(MD == FinalOverriderMD && ThisAdjustmentOffset.
isEmpty());
3027 }
else if (Base.
getBaseOffset() != WhichVFPtr.FullOffsetInMDC ||
3039 MethodInfo MI(VBIndex,
3040 HasRTTIComponent ? Components.size() - 1 : Components.size(),
3041 ReturnAdjustingThunk);
3043 assert(!MethodInfoMap.count(MD) &&
3044 "Should not have method info for this method yet!");
3045 MethodInfoMap.insert(std::make_pair(MD, MI));
3049 BaseOffset ReturnAdjustmentOffset;
3051 if (!FinalOverriderMD->
isPure()) {
3052 ReturnAdjustmentOffset =
3053 ComputeReturnAdjustmentBaseOffset(
Context, FinalOverriderMD, MD);
3055 if (!ReturnAdjustmentOffset.isEmpty()) {
3056 ForceReturnAdjustmentMangling =
true;
3058 ReturnAdjustmentOffset.NonVirtualOffset.getQuantity();
3059 if (ReturnAdjustmentOffset.VirtualBase) {
3066 ReturnAdjustmentOffset.VirtualBase);
3070 AddMethod(FinalOverriderMD,
3071 ThunkInfo(ThisAdjustmentOffset, ReturnAdjustment,
3072 ForceReturnAdjustmentMangling ? MD :
nullptr));
3078 llvm::make_range(Path.rbegin(), Path.rend())) {
3080 Elem->printQualifiedName(Out);
3086 bool ContinueFirstLine) {
3087 const ReturnAdjustment &R = TI.
Return;
3088 bool Multiline =
false;
3089 const char *LinePrefix =
"\n ";
3091 if (!ContinueFirstLine)
3093 Out <<
"[return adjustment (to type '"
3106 if (Multiline || !ContinueFirstLine)
3108 Out <<
"[this adjustment: ";
3116 Out << LinePrefix <<
" vboffset at "
3124 void VFTableBuilder::dumpLayout(raw_ostream &Out) {
3125 Out <<
"VFTable for ";
3129 Out <<
"' (" << Components.size()
3130 << (Components.size() == 1 ?
" entry" :
" entries") <<
").\n";
3132 for (
unsigned I = 0,
E = Components.size();
I !=
E; ++
I) {
3133 Out << llvm::format(
"%4d | ",
I);
3138 switch (Component.
getKind()) {
3156 Out <<
" [deleted]";
3169 Out <<
"() [scalar deleting]";
3177 "No return adjustment needed for destructors!");
3188 "Unexpected vftable component type %0 for component number %1");
3198 if (!Thunks.empty()) {
3200 std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls;
3202 for (
const auto &
I : Thunks) {
3207 MethodNamesAndDecls.insert(std::make_pair(MethodName, MD));
3210 for (
const auto &MethodNameAndDecl : MethodNamesAndDecls) {
3211 const std::string &MethodName = MethodNameAndDecl.first;
3214 ThunkInfoVectorTy ThunksVector = Thunks[MD];
3215 std::stable_sort(ThunksVector.begin(), ThunksVector.end(),
3219 return std::tie(LHS.
This, LHS.
Return) < std::tie(RHS.This, RHS.Return);
3222 Out <<
"Thunks for '" << MethodName <<
"' (" << ThunksVector.size();
3223 Out << (ThunksVector.size() == 1 ?
" entry" :
" entries") <<
").\n";
3225 for (
unsigned I = 0,
E = ThunksVector.size();
I !=
E; ++
I) {
3228 Out << llvm::format(
"%4d | ",
I);
3272 void MicrosoftVTableContext::computeVTablePaths(
bool ForVBTables,
3275 assert(Paths.empty());
3279 if (ForVBTables ? Layout.hasOwnVBPtr() : Layout.hasOwnVFPtr())
3284 llvm::SmallPtrSet<const CXXRecordDecl*, 4> VBasesSeen;
3285 for (
const auto &B : RD->
bases()) {
3286 const CXXRecordDecl *Base = B.getType()->getAsCXXRecordDecl();
3287 if (B.isVirtual() && VBasesSeen.count(Base))
3296 for (
VPtrInfo *BaseInfo : BasePaths) {
3314 Base == (ForVBTables ? Layout.getBaseSharingVBPtr()
3315 : Layout.getPrimaryBase()))
3334 VBasesSeen.insert(Base);
3338 for (
const auto &VB : Base->
vbases())
3339 VBasesSeen.insert(VB.getType()->getAsCXXRecordDecl());
3344 bool Changed =
true;
3366 std::sort(PathsSorted.begin(), PathsSorted.end(),
3370 bool Changed =
false;
3371 for (
size_t I = 0,
E = PathsSorted.size();
I !=
E;) {
3373 size_t BucketStart =
I;
3376 }
while (
I !=
E && PathsSorted[BucketStart]->MangledPath ==
3377 PathsSorted[
I]->MangledPath);
3380 if (
I - BucketStart > 1) {
3381 for (
size_t II = BucketStart; II !=
I; ++II)
3383 assert(Changed &&
"no paths were extended to fix ambiguity");
3390 for (
auto &P : VFPtrLocations)
3391 llvm::DeleteContainerPointers(*P.second);
3392 llvm::DeleteContainerSeconds(VFPtrLocations);
3393 llvm::DeleteContainerSeconds(VFTableLayouts);
3394 llvm::DeleteContainerSeconds(VBaseInfo);
3398 typedef llvm::SetVector<BaseSubobject, std::vector<BaseSubobject>,
3408 FullPathTy &FullPath,
3409 std::list<FullPathTy> &Paths) {
3411 Paths.push_back(FullPath);
3418 const CXXRecordDecl *Base = BS.getType()->getAsCXXRecordDecl();
3424 BaseWithVPtr, FullPath, Paths);
3425 FullPath.pop_back();
3431 FullPaths.remove_if([&](
const FullPathTy &SpecificPath) {
3432 for (
const FullPathTy &OtherPath : FullPaths) {
3433 if (&SpecificPath == &OtherPath)
3435 if (std::all_of(SpecificPath.begin(), SpecificPath.end(),
3437 return OtherPath.count(BSO) != 0;
3448 const FullPathTy &FullPath) {
3469 : Offset + Layout.getBaseClassOffset(Base);
3480 std::list<FullPathTy> &FullPaths) {
3482 if (FullPaths.empty())
3484 if (FullPaths.size() == 1)
3485 return &FullPaths.front();
3487 const FullPathTy *BestPath =
nullptr;
3488 typedef std::set<const CXXMethodDecl *> OverriderSetTy;
3489 OverriderSetTy LastOverrides;
3490 for (
const FullPathTy &SpecificPath : FullPaths) {
3491 assert(!SpecificPath.empty());
3492 OverriderSetTy CurrentOverrides;
3493 const CXXRecordDecl *TopLevelRD = SpecificPath.begin()->getBase();
3498 FinalOverriders Overriders(TopLevelRD,
CharUnits::Zero(), TopLevelRD);
3502 FinalOverriders::OverriderInfo OI =
3507 if (ComputeReturnAdjustmentBaseOffset(Context, OverridingMethod, MD)
3513 if (std::none_of(SpecificPath.begin(), SpecificPath.end(),
3515 return BSO.getBase() == OverridingParent;
3518 CurrentOverrides.insert(OverridingMethod);
3520 OverriderSetTy NewOverrides =
3521 llvm::set_difference(CurrentOverrides, LastOverrides);
3522 if (NewOverrides.empty())
3524 OverriderSetTy MissingOverrides =
3525 llvm::set_difference(LastOverrides, CurrentOverrides);
3526 if (MissingOverrides.empty()) {
3528 BestPath = &SpecificPath;
3529 std::swap(CurrentOverrides, LastOverrides);
3534 const CXXMethodDecl *ConflictMD = *MissingOverrides.begin();
3545 return BestPath ? BestPath : &FullPaths.front();
3552 FullPathTy FullPath;
3553 std::list<FullPathTy> FullPaths;
3557 BaseSubobject(Info->BaseWithVPtr, Info->FullOffsetInMDC), FullPath,
3561 Info->PathToBaseWithVPtr.clear();
3562 if (
const FullPathTy *BestPath =
3565 Info->PathToBaseWithVPtr.push_back(BSO.getBase());
3570 void MicrosoftVTableContext::computeVTableRelatedInformation(
3575 if (VFPtrLocations.count(RD))
3581 computeVTablePaths(
false, RD, *VFPtrs);
3583 VFPtrLocations[RD] = VFPtrs;
3585 MethodVFTableLocationsTy NewMethodLocations;
3586 for (
const VPtrInfo *VFPtr : *VFPtrs) {
3587 VFTableBuilder
Builder(*
this, RD, VFPtr);
3589 VFTableIdTy
id(RD, VFPtr->FullOffsetInMDC);
3590 assert(VFTableLayouts.count(
id) == 0);
3594 Builder.getNumVTableComponents(),
Builder.vtable_component_begin(),
3595 VTableThunks.size(), VTableThunks.data(), EmptyAddressPointsMap,
true);
3598 for (
const auto &Loc :
Builder.vtable_locations()) {
3600 MethodVFTableLocation NewLoc = Loc.second;
3601 auto M = NewMethodLocations.find(GD);
3602 if (M == NewMethodLocations.end() || NewLoc < M->second)
3603 NewMethodLocations[GD] = NewLoc;
3607 MethodVFTableLocations.insert(NewMethodLocations.begin(),
3608 NewMethodLocations.end());
3610 dumpMethodLocations(RD, NewMethodLocations, llvm::outs());
3613 void MicrosoftVTableContext::dumpMethodLocations(
3614 const CXXRecordDecl *RD,
const MethodVFTableLocationsTy &NewMethods,
3618 std::map<MethodVFTableLocation, std::string> IndicesMap;
3619 bool HasNonzeroOffset =
false;
3621 for (
const auto &
I : NewMethods) {
3622 const CXXMethodDecl *MD = cast<const CXXMethodDecl>(
I.first.getDecl());
3628 if (isa<CXXDestructorDecl>(MD)) {
3629 IndicesMap[
I.second] = MethodName +
" [scalar deleting]";
3631 IndicesMap[
I.second] = MethodName;
3634 if (!
I.second.VFPtrOffset.isZero() ||
I.second.VBTableIndex != 0)
3635 HasNonzeroOffset =
true;
3639 if (!IndicesMap.empty()) {
3640 Out <<
"VFTable indices for ";
3643 Out <<
"' (" << IndicesMap.size()
3644 << (IndicesMap.size() == 1 ?
" entry" :
" entries") <<
").\n";
3647 uint64_t LastVBIndex = 0;
3648 for (
const auto &
I : IndicesMap) {
3650 uint64_t VBIndex =
I.first.VBTableIndex;
3651 if (HasNonzeroOffset &&
3652 (VFPtrOffset != LastVFPtrOffset || VBIndex != LastVBIndex)) {
3653 assert(VBIndex > LastVBIndex || VFPtrOffset > LastVFPtrOffset);
3654 Out <<
" -- accessible via ";
3656 Out <<
"vbtable index " << VBIndex <<
", ";
3657 Out <<
"vfptr at offset " << VFPtrOffset.
getQuantity() <<
" --\n";
3658 LastVFPtrOffset = VFPtrOffset;
3659 LastVBIndex = VBIndex;
3662 uint64_t VTableIndex =
I.first.Index;
3663 const std::string &MethodName =
I.second;
3664 Out << llvm::format(
"%4" PRIu64
" | ", VTableIndex) << MethodName <<
'\n';
3672 const VirtualBaseInfo *MicrosoftVTableContext::computeVBTableRelatedInformation(
3685 computeVTablePaths(
true, RD, VBI->
VBPtrPaths);
3693 computeVBTableRelatedInformation(VBPtrBase);
3701 for (
const auto &VB : RD->
vbases()) {
3702 const CXXRecordDecl *CurVBase = VB.getType()->getAsCXXRecordDecl();
3712 const VirtualBaseInfo *VBInfo = computeVBTableRelatedInformation(Derived);
3719 return computeVBTableRelatedInformation(RD)->
VBPtrPaths;
3724 computeVTableRelatedInformation(RD);
3726 assert(VFPtrLocations.count(RD) &&
"Couldn't find vfptr locations");
3727 return *VFPtrLocations[RD];
3733 computeVTableRelatedInformation(RD);
3735 VFTableIdTy
id(RD, VFPtrOffset);
3736 assert(VFTableLayouts.count(
id) &&
"Couldn't find a VFTable at this offset");
3737 return *VFTableLayouts[
id];
3742 assert(cast<CXXMethodDecl>(GD.
getDecl())->isVirtual() &&
3743 "Only use this method for virtual methods or dtors");
3744 if (isa<CXXDestructorDecl>(GD.
getDecl()))
3748 if (I != MethodVFTableLocations.end())
3753 computeVTableRelatedInformation(RD);
3755 I = MethodVFTableLocations.find(GD);
3756 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.
Decl - This represents one declaration (or definition), e.g.
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)
struct clang::ThisAdjustment::VirtualAdjustment::@114 Microsoft
static VTableComponent MakeVCallOffset(CharUnits Offset)
A this pointer adjustment.
struct clang::ReturnAdjustment::VirtualAdjustment::@112 Microsoft
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)
bool isPure() const
Whether this virtual function is pure, i.e.
CXXMethodDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
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
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
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.
struct clang::ThisAdjustment::VirtualAdjustment::@113 Itanium
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.
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)
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.
const VTableLayout & getVFTableLayout(const CXXRecordDecl *RD, CharUnits VFPtrOffset)
struct clang::ReturnAdjustment::VirtualAdjustment::@111 Itanium
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
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()))
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...
This template specialization was instantiated from a template due to an explicit instantiation declar...
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.
SourceLocation getLocation() const
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)