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;
783 typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVTableIndicesTy;
799 bool MostDerivedClassIsVirtual;
810 const FinalOverriders Overriders;
814 llvm::DenseMap<const CXXRecordDecl *, VCallOffsetMap> VCallOffsetsForVBases;
818 VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
824 AddressPointsMapTy AddressPoints;
838 const uint64_t VTableIndex;
841 uint64_t VTableIndex)
842 : BaseOffset(BaseOffset),
843 BaseOffsetInLayoutClass(BaseOffsetInLayoutClass),
844 VTableIndex(VTableIndex) { }
852 typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy;
856 MethodInfoMapTy MethodInfoMap;
860 MethodVTableIndicesTy MethodVTableIndices;
862 typedef llvm::DenseMap<uint64_t, ThunkInfo> VTableThunksMapTy;
866 VTableThunksMapTy VTableThunks;
869 typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
880 void ComputeThisAdjustments();
882 typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy;
886 VisitedVirtualBasesSetTy PrimaryVirtualBases;
894 BaseOffset ComputeThisAdjustmentBaseOffset(
BaseSubobject Base,
903 FinalOverriders::OverriderInfo Overrider);
931 CharUnits FirstBaseOffsetInLayoutClass)
const;
939 PrimaryBasesSetVectorTy &PrimaryBases);
954 bool BaseIsMorallyVirtual,
955 bool BaseIsVirtualInLayoutClass,
963 void LayoutSecondaryVTables(
BaseSubobject Base,
bool BaseIsMorallyVirtual,
970 VisitedVirtualBasesSetTy &VBases);
975 VisitedVirtualBasesSetTy &VBases);
979 bool isBuildingConstructorVTable()
const {
980 return MostDerivedClass != LayoutClass;
991 bool MostDerivedClassIsVirtual,
993 : VTables(VTables), MostDerivedClass(MostDerivedClass),
994 MostDerivedClassOffset(MostDerivedClassOffset),
995 MostDerivedClassIsVirtual(MostDerivedClassIsVirtual),
997 Overriders(MostDerivedClass, MostDerivedClassOffset, LayoutClass) {
1003 dumpLayout(llvm::outs());
1006 uint64_t getNumThunks()
const {
1007 return Thunks.size();
1010 ThunksMapTy::const_iterator thunks_begin()
const {
1011 return Thunks.begin();
1014 ThunksMapTy::const_iterator thunks_end()
const {
1015 return Thunks.end();
1018 const VBaseOffsetOffsetsMapTy &getVBaseOffsetOffsets()
const {
1019 return VBaseOffsetOffsets;
1022 const AddressPointsMapTy &getAddressPoints()
const {
1023 return AddressPoints;
1026 MethodVTableIndicesTy::const_iterator vtable_indices_begin()
const {
1027 return MethodVTableIndices.begin();
1030 MethodVTableIndicesTy::const_iterator vtable_indices_end()
const {
1031 return MethodVTableIndices.end();
1036 AddressPointsMapTy::const_iterator address_points_begin()
const {
1037 return AddressPoints.begin();
1040 AddressPointsMapTy::const_iterator address_points_end()
const {
1041 return AddressPoints.end();
1044 VTableThunksMapTy::const_iterator vtable_thunks_begin()
const {
1045 return VTableThunks.begin();
1048 VTableThunksMapTy::const_iterator vtable_thunks_end()
const {
1049 return VTableThunks.end();
1053 void dumpLayout(raw_ostream&);
1056 void ItaniumVTableBuilder::AddThunk(
const CXXMethodDecl *MD,
1058 assert(!isBuildingConstructorVTable() &&
1059 "Can't add thunks for construction vtable");
1064 if (std::find(ThunksVector.begin(), ThunksVector.end(), Thunk) !=
1068 ThunksVector.push_back(Thunk);
1071 typedef llvm::SmallPtrSet<const CXXMethodDecl *, 8> OverriddenMethodsSetTy;
1077 template <
class VisitorTy>
1079 visitAllOverriddenMethods(
const CXXMethodDecl *MD, VisitorTy &Visitor) {
1080 assert(MD->
isVirtual() &&
"Method is not virtual!");
1085 if (!Visitor(OverriddenMD))
1087 visitAllOverriddenMethods(OverriddenMD, Visitor);
1096 auto OverriddenMethodsCollector = [&](
const CXXMethodDecl *MD) {
1098 return OverriddenMethods.insert(MD).second;
1100 visitAllOverriddenMethods(MD, OverriddenMethodsCollector);
1103 void ItaniumVTableBuilder::ComputeThisAdjustments() {
1106 for (
const auto &MI : MethodInfoMap) {
1108 const MethodInfo &MethodInfo = MI.second;
1111 uint64_t VTableIndex = MethodInfo.VTableIndex;
1112 if (Components[VTableIndex].
getKind() ==
1117 FinalOverriders::OverriderInfo Overrider =
1118 Overriders.getOverrider(MD, MethodInfo.BaseOffset);
1121 if (MethodInfo.BaseOffsetInLayoutClass == Overrider.Offset) {
1127 if (VTableThunks.lookup(VTableIndex).Return.isEmpty())
1132 ComputeThisAdjustment(MD, MethodInfo.BaseOffsetInLayoutClass, Overrider);
1138 VTableThunks[VTableIndex].This = ThisAdjustment;
1140 if (isa<CXXDestructorDecl>(MD)) {
1142 VTableThunks[VTableIndex + 1].This = ThisAdjustment;
1147 MethodInfoMap.clear();
1149 if (isBuildingConstructorVTable()) {
1154 for (
const auto &TI : VTableThunks) {
1159 switch (Component.
getKind()) {
1161 llvm_unreachable(
"Unexpected vtable component kind!");
1173 if (MD->
getParent() == MostDerivedClass)
1174 AddThunk(MD, Thunk);
1179 ItaniumVTableBuilder::ComputeReturnAdjustment(BaseOffset
Offset) {
1182 if (!Offset.isEmpty()) {
1183 if (Offset.VirtualBase) {
1185 if (Offset.DerivedClass == MostDerivedClass) {
1188 VBaseOffsetOffsets.lookup(Offset.VirtualBase).getQuantity();
1191 VTables.getVirtualBaseOffsetOffset(Offset.DerivedClass,
1192 Offset.VirtualBase).getQuantity();
1196 Adjustment.
NonVirtual = Offset.NonVirtualOffset.getQuantity();
1202 BaseOffset ItaniumVTableBuilder::ComputeThisAdjustmentBaseOffset(
1211 llvm_unreachable(
"Class must be derived from the passed in base class!");
1216 BaseOffset Offset = ComputeBaseOffset(Context, DerivedRD, Path);
1218 CharUnits OffsetToBaseSubobject = Offset.NonVirtualOffset;
1220 if (Offset.VirtualBase) {
1228 OffsetToBaseSubobject +=
1240 Offset.NonVirtualOffset = -Offset.NonVirtualOffset;
1245 return BaseOffset();
1250 FinalOverriders::OverriderInfo Overrider) {
1252 if (Overrider.Method->isPure())
1256 BaseOffsetInLayoutClass);
1258 BaseSubobject OverriderBaseSubobject(Overrider.Method->getParent(),
1262 BaseOffset Offset = ComputeThisAdjustmentBaseOffset(OverriddenBaseSubobject,
1263 OverriderBaseSubobject);
1264 if (Offset.isEmpty())
1269 if (Offset.VirtualBase) {
1271 VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[Offset.VirtualBase];
1273 if (VCallOffsets.empty()) {
1276 VCallAndVBaseOffsetBuilder
Builder(MostDerivedClass, MostDerivedClass,
1284 VCallOffsets = Builder.getVCallOffsets();
1288 VCallOffsets.getVCallOffsetOffset(MD).getQuantity();
1292 Adjustment.
NonVirtual = Offset.NonVirtualOffset.getQuantity();
1297 void ItaniumVTableBuilder::AddMethod(
const CXXMethodDecl *MD,
1300 assert(ReturnAdjustment.
isEmpty() &&
1301 "Destructor can't have return adjustment!");
1308 if (!ReturnAdjustment.
isEmpty())
1309 VTableThunks[Components.size()].Return = ReturnAdjustment;
1327 static bool OverridesIndirectMethodInBases(
1338 if (OverridesIndirectMethodInBases(OverriddenMD, Bases))
1345 bool ItaniumVTableBuilder::IsOverriderUsed(
1348 CharUnits FirstBaseOffsetInLayoutClass)
const {
1351 if (BaseOffsetInLayoutClass == FirstBaseOffsetInLayoutClass)
1360 if (Overrider->
getParent() == FirstBaseInPrimaryBaseChain)
1366 PrimaryBases.insert(RD);
1379 "Primary base should always be at offset 0!");
1386 if (LayoutClassLayout.getVBaseClassOffset(PrimaryBase) !=
1387 FirstBaseOffsetInLayoutClass) {
1393 "Primary base should always be at offset 0!");
1396 if (!PrimaryBases.insert(PrimaryBase))
1397 llvm_unreachable(
"Found a duplicate primary base!");
1404 return OverridesIndirectMethodInBases(Overrider, PrimaryBases);
1414 BasesSetVectorTy &Bases) {
1416 ComputeAllOverriddenMethods(MD, OverriddenMethods);
1419 llvm::make_range(Bases.rbegin(), Bases.rend())) {
1421 for (
const CXXMethodDecl *OverriddenMD : OverriddenMethods) {
1423 if (OverriddenMD->getParent() == PrimaryBase)
1424 return OverriddenMD;
1431 void ItaniumVTableBuilder::AddMethods(
1435 PrimaryBasesSetVectorTy &PrimaryBases) {
1450 CharUnits PrimaryBaseOffsetInLayoutClass;
1453 "Primary vbase should have a zero offset!");
1459 MostDerivedClassLayout.getVBaseClassOffset(PrimaryBase);
1464 PrimaryBaseOffsetInLayoutClass =
1468 "Primary base should have a zero offset!");
1471 PrimaryBaseOffsetInLayoutClass = BaseOffsetInLayoutClass;
1475 PrimaryBaseOffsetInLayoutClass, FirstBaseInPrimaryBaseChain,
1476 FirstBaseOffsetInLayoutClass, PrimaryBases);
1478 if (!PrimaryBases.insert(PrimaryBase))
1479 llvm_unreachable(
"Found a duplicate primary base!");
1485 NewVirtualFunctionsTy NewVirtualFunctions;
1488 for (
const auto *MD : RD->
methods()) {
1494 FinalOverriders::OverriderInfo Overrider =
1501 FindNearestOverriddenMethod(MD, PrimaryBases)) {
1502 if (ComputeReturnAdjustmentBaseOffset(Context, MD,
1503 OverriddenMD).isEmpty()) {
1506 assert(MethodInfoMap.count(OverriddenMD) &&
1507 "Did not find the overridden method!");
1508 MethodInfo &OverriddenMethodInfo = MethodInfoMap[OverriddenMD];
1510 MethodInfo MethodInfo(Base.
getBaseOffset(), BaseOffsetInLayoutClass,
1511 OverriddenMethodInfo.VTableIndex);
1513 assert(!MethodInfoMap.count(MD) &&
1514 "Should not have method info for this method yet!");
1516 MethodInfoMap.insert(std::make_pair(MD, MethodInfo));
1517 MethodInfoMap.erase(OverriddenMD);
1523 if (!isBuildingConstructorVTable() && OverriddenMD != MD) {
1526 ComputeThisAdjustment(OverriddenMD, BaseOffsetInLayoutClass,
1530 Overrider.Method->getParent() == MostDerivedClass) {
1535 BaseOffset ReturnAdjustmentOffset =
1536 ComputeReturnAdjustmentBaseOffset(Context, Overrider.Method, MD);
1537 ReturnAdjustment ReturnAdjustment =
1538 ComputeReturnAdjustment(ReturnAdjustmentOffset);
1541 AddThunk(Overrider.Method,
1542 ThunkInfo(ThisAdjustment, ReturnAdjustment));
1556 assert(!ImplicitVirtualDtor &&
1557 "Did already see an implicit virtual dtor!");
1558 ImplicitVirtualDtor = DD;
1563 NewVirtualFunctions.push_back(MD);
1566 if (ImplicitVirtualDtor)
1567 NewVirtualFunctions.push_back(ImplicitVirtualDtor);
1571 FinalOverriders::OverriderInfo Overrider =
1575 MethodInfo MethodInfo(Base.
getBaseOffset(), BaseOffsetInLayoutClass,
1578 assert(!MethodInfoMap.count(MD) &&
1579 "Should not have method info for this method yet!");
1580 MethodInfoMap.insert(std::make_pair(MD, MethodInfo));
1584 if (!IsOverriderUsed(OverriderMD, BaseOffsetInLayoutClass,
1585 FirstBaseInPrimaryBaseChain,
1586 FirstBaseOffsetInLayoutClass)) {
1593 BaseOffset ReturnAdjustmentOffset;
1594 if (!OverriderMD->
isPure()) {
1595 ReturnAdjustmentOffset =
1596 ComputeReturnAdjustmentBaseOffset(Context, OverriderMD, MD);
1599 ReturnAdjustment ReturnAdjustment =
1600 ComputeReturnAdjustment(ReturnAdjustmentOffset);
1602 AddMethod(Overrider.Method, ReturnAdjustment);
1606 void ItaniumVTableBuilder::LayoutVTable() {
1607 LayoutPrimaryAndSecondaryVTables(
BaseSubobject(MostDerivedClass,
1610 MostDerivedClassIsVirtual,
1611 MostDerivedClassOffset);
1613 VisitedVirtualBasesSetTy VBases;
1616 DeterminePrimaryVirtualBases(MostDerivedClass, MostDerivedClassOffset,
1620 LayoutVTablesForVirtualBases(MostDerivedClass, VBases);
1623 bool IsAppleKext = Context.
getLangOpts().AppleKext;
1628 void ItaniumVTableBuilder::LayoutPrimaryAndSecondaryVTables(
1630 bool BaseIsVirtualInLayoutClass,
CharUnits OffsetInLayoutClass) {
1633 unsigned VTableIndex = Components.size();
1634 VTableIndices.push_back(VTableIndex);
1637 VCallAndVBaseOffsetBuilder
Builder(MostDerivedClass, LayoutClass, &Overriders,
1638 Base, BaseIsVirtualInLayoutClass,
1639 OffsetInLayoutClass);
1640 Components.append(Builder.components_begin(), Builder.components_end());
1643 if (BaseIsVirtualInLayoutClass && !Builder.getVCallOffsets().empty()) {
1644 VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[Base.
getBase()];
1646 if (VCallOffsets.empty())
1647 VCallOffsets = Builder.getVCallOffsets();
1652 if (Base.
getBase() == MostDerivedClass)
1653 VBaseOffsetOffsets = Builder.getVBaseOffsetOffsets();
1656 CharUnits OffsetToTop = MostDerivedClassOffset - OffsetInLayoutClass;
1662 uint64_t AddressPoint = Components.size();
1665 PrimaryBasesSetVectorTy PrimaryBases;
1666 AddMethods(Base, OffsetInLayoutClass,
1667 Base.
getBase(), OffsetInLayoutClass,
1671 if (RD == MostDerivedClass) {
1672 assert(MethodVTableIndices.empty());
1673 for (
const auto &
I : MethodInfoMap) {
1675 const MethodInfo &MI =
I.second;
1678 = MI.VTableIndex - AddressPoint;
1680 = MI.VTableIndex + 1 - AddressPoint;
1682 MethodVTableIndices[MD] = MI.VTableIndex - AddressPoint;
1688 ComputeThisAdjustments();
1692 AddressPoints.insert(
1695 unsigned(VTableIndices.size() - 1),
1696 unsigned(AddressPoint - VTableIndex)}));
1711 OffsetInLayoutClass) {
1721 LayoutSecondaryVTables(Base, BaseIsMorallyVirtual, OffsetInLayoutClass);
1725 ItaniumVTableBuilder::LayoutSecondaryVTables(
BaseSubobject Base,
1726 bool BaseIsMorallyVirtual,
1737 for (
const auto &B : RD->
bases()) {
1742 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
1748 if (isBuildingConstructorVTable()) {
1754 if (!BaseIsMorallyVirtual && !BaseDecl->
getNumVBases())
1763 OffsetInLayoutClass + RelativeBaseOffset;
1767 if (BaseDecl == PrimaryBase) {
1769 BaseIsMorallyVirtual, BaseOffsetInLayoutClass);
1774 LayoutPrimaryAndSecondaryVTables(
1776 BaseIsMorallyVirtual,
1778 BaseOffsetInLayoutClass);
1782 void ItaniumVTableBuilder::DeterminePrimaryVirtualBases(
1784 VisitedVirtualBasesSetTy &VBases) {
1792 bool IsPrimaryVirtualBase =
true;
1794 if (isBuildingConstructorVTable()) {
1800 CharUnits PrimaryBaseOffsetInLayoutClass =
1805 if (PrimaryBaseOffsetInLayoutClass != OffsetInLayoutClass)
1806 IsPrimaryVirtualBase =
false;
1809 if (IsPrimaryVirtualBase)
1810 PrimaryVirtualBases.insert(PrimaryBase);
1815 for (
const auto &B : RD->
bases()) {
1816 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
1820 if (B.isVirtual()) {
1821 if (!VBases.insert(BaseDecl).second)
1827 BaseOffsetInLayoutClass =
1830 BaseOffsetInLayoutClass =
1834 DeterminePrimaryVirtualBases(BaseDecl, BaseOffsetInLayoutClass, VBases);
1838 void ItaniumVTableBuilder::LayoutVTablesForVirtualBases(
1839 const CXXRecordDecl *RD, VisitedVirtualBasesSetTy &VBases) {
1844 for (
const auto &B : RD->
bases()) {
1845 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
1850 !PrimaryVirtualBases.count(BaseDecl) &&
1851 VBases.insert(BaseDecl).second) {
1862 LayoutPrimaryAndSecondaryVTables(
1866 BaseOffsetInLayoutClass);
1872 LayoutVTablesForVirtualBases(BaseDecl, VBases);
1877 void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
1881 if (isBuildingConstructorVTable()) {
1882 Out <<
"Construction vtable for ('";
1885 Out << MostDerivedClassOffset.
getQuantity() <<
") in '";
1888 Out <<
"Vtable for '";
1891 Out <<
"' (" << Components.size() <<
" entries).\n";
1897 std::multimap<uint64_t, BaseSubobject> AddressPointsByIndex;
1898 for (
const auto &AP : AddressPoints) {
1901 VTableIndices[AP.second.VTableIndex] + AP.second.AddressPointIndex;
1903 AddressPointsByIndex.insert(std::make_pair(Index, Base));
1906 for (
unsigned I = 0,
E = Components.size();
I !=
E; ++
I) {
1909 Out << llvm::format(
"%4d | ",
I);
1914 switch (Component.
getKind()) {
1917 Out <<
"vcall_offset ("
1923 Out <<
"vbase_offset ("
1929 Out <<
"offset_to_top ("
1950 Out <<
" [deleted]";
1956 Out <<
"\n [return adjustment: ";
1961 Out <<
" vbase offset offset";
1969 Out <<
"\n [this adjustment: ";
1974 Out <<
" vcall offset offset";
1993 Out <<
"() [complete]";
1995 Out <<
"() [deleting]";
2004 Out <<
"\n [this adjustment: ";
2009 Out <<
" vcall offset offset";
2025 Out <<
"[unused] " << Str;
2036 if (AddressPointsByIndex.count(NextIndex)) {
2037 if (AddressPointsByIndex.count(NextIndex) == 1) {
2039 AddressPointsByIndex.find(NextIndex)->second;
2044 Out <<
") vtable address --\n";
2047 AddressPointsByIndex.lower_bound(NextIndex)->second.getBaseOffset();
2050 std::set<std::string> ClassNames;
2051 for (
const auto &
I :
2052 llvm::make_range(AddressPointsByIndex.equal_range(NextIndex))) {
2053 assert(
I.second.getBaseOffset() == BaseOffset &&
2054 "Invalid base offset!");
2056 ClassNames.insert(RD->getQualifiedNameAsString());
2059 for (
const std::string &
Name : ClassNames) {
2060 Out <<
" -- (" <<
Name;
2061 Out <<
", " << BaseOffset.
getQuantity() <<
") vtable address --\n";
2069 if (isBuildingConstructorVTable())
2076 std::map<std::string, CharUnits> ClassNamesAndOffsets;
2077 for (
const auto &
I : VBaseOffsetOffsets) {
2078 std::string ClassName =
I.first->getQualifiedNameAsString();
2080 ClassNamesAndOffsets.insert(std::make_pair(ClassName, OffsetOffset));
2083 Out <<
"Virtual base offset offsets for '";
2086 Out << ClassNamesAndOffsets.size();
2087 Out << (ClassNamesAndOffsets.size() == 1 ?
" entry" :
" entries") <<
").\n";
2089 for (
const auto &
I : ClassNamesAndOffsets)
2090 Out <<
" " <<
I.first <<
" | " <<
I.second.getQuantity() <<
'\n';
2095 if (!Thunks.empty()) {
2097 std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls;
2099 for (
const auto &
I : Thunks) {
2101 std::string MethodName =
2105 MethodNamesAndDecls.insert(std::make_pair(MethodName, MD));
2108 for (
const auto &
I : MethodNamesAndDecls) {
2109 const std::string &MethodName =
I.first;
2112 ThunkInfoVectorTy ThunksVector = Thunks[MD];
2113 std::sort(ThunksVector.begin(), ThunksVector.end(),
2115 assert(LHS.
Method ==
nullptr && RHS.Method ==
nullptr);
2116 return std::tie(LHS.
This, LHS.
Return) < std::tie(RHS.This, RHS.Return);
2119 Out <<
"Thunks for '" << MethodName <<
"' (" << ThunksVector.size();
2120 Out << (ThunksVector.size() == 1 ?
" entry" :
" entries") <<
").\n";
2122 for (
unsigned I = 0,
E = ThunksVector.size();
I !=
E; ++
I) {
2125 Out << llvm::format(
"%4d | ",
I);
2130 Out <<
" non-virtual";
2133 Out <<
" vbase offset offset";
2142 Out <<
"this adjustment: ";
2147 Out <<
" vcall offset offset";
2160 std::map<uint64_t, std::string> IndicesMap;
2162 for (
const auto *MD : MostDerivedClass->
methods()) {
2168 std::string MethodName =
2174 assert(MethodVTableIndices.count(GD));
2175 uint64_t VTableIndex = MethodVTableIndices[GD];
2176 IndicesMap[VTableIndex] = MethodName +
" [complete]";
2177 IndicesMap[VTableIndex + 1] = MethodName +
" [deleting]";
2179 assert(MethodVTableIndices.count(MD));
2180 IndicesMap[MethodVTableIndices[MD]] = MethodName;
2185 if (!IndicesMap.empty()) {
2186 Out <<
"VTable indices for '";
2188 Out <<
"' (" << IndicesMap.size() <<
" entries).\n";
2190 for (
const auto &
I : IndicesMap) {
2191 uint64_t VTableIndex =
I.first;
2192 const std::string &MethodName =
I.second;
2194 Out << llvm::format(
"%4" PRIu64
" | ", VTableIndex) << MethodName
2207 : VTableComponents(VTableComponents), VTableThunks(VTableThunks),
2208 AddressPoints(AddressPoints) {
2209 if (VTableIndices.size() <= 1)
2210 assert(VTableIndices.size() == 1 && VTableIndices[0] == 0);
2214 std::sort(this->VTableThunks.begin(), this->VTableThunks.end(),
2217 assert((LHS.first != RHS.first || LHS.second == RHS.second) &&
2218 "Different thunks should have unique indices!");
2219 return LHS.first < RHS.first;
2231 MethodVTableIndicesTy::iterator
I = MethodVTableIndices.find(GD);
2232 if (I != MethodVTableIndices.end())
2237 computeVTableRelatedInformation(RD);
2239 I = MethodVTableIndices.find(GD);
2240 assert(I != MethodVTableIndices.end() &&
"Did not find index!");
2247 ClassPairTy ClassPair(RD, VBase);
2249 VirtualBaseClassOffsetOffsetsMapTy::iterator
I =
2250 VirtualBaseClassOffsetOffsets.find(ClassPair);
2251 if (I != VirtualBaseClassOffsetOffsets.end())
2254 VCallAndVBaseOffsetBuilder
Builder(RD, RD,
nullptr,
2259 for (
const auto &I :
Builder.getVBaseOffsetOffsets()) {
2261 ClassPairTy ClassPair(RD, I.first);
2263 VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I.second));
2266 I = VirtualBaseClassOffsetOffsets.find(ClassPair);
2267 assert(I != VirtualBaseClassOffsetOffsets.end() &&
"Did not find index!");
2272 static std::unique_ptr<VTableLayout>
2275 VTableThunks(Builder.vtable_thunks_begin(), Builder.vtable_thunks_end());
2277 return llvm::make_unique<VTableLayout>(
2278 Builder.VTableIndices, Builder.vtable_components(), VTableThunks,
2279 Builder.getAddressPoints());
2283 ItaniumVTableContext::computeVTableRelatedInformation(
const CXXRecordDecl *RD) {
2284 std::unique_ptr<const VTableLayout> &Entry = VTableLayouts[RD];
2294 MethodVTableIndices.insert(
Builder.vtable_indices_begin(),
2295 Builder.vtable_indices_end());
2309 if (VirtualBaseClassOffsetOffsets.count(std::make_pair(RD, VBase)))
2312 for (
const auto &
I :
Builder.getVBaseOffsetOffsets()) {
2314 ClassPairTy ClassPair(RD,
I.first);
2316 VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair,
I.second));
2320 std::unique_ptr<VTableLayout>
2323 bool MostDerivedClassIsVirtual,
const CXXRecordDecl *LayoutClass) {
2324 ItaniumVTableBuilder
Builder(*
this, MostDerivedClass, MostDerivedClassOffset,
2325 MostDerivedClassIsVirtual, LayoutClass);
2373 class VFTableBuilder {
2377 typedef llvm::DenseMap<GlobalDecl, MethodVFTableLocation>
2378 MethodVFTableLocationsTy;
2380 typedef llvm::iterator_range<MethodVFTableLocationsTy::const_iterator>
2381 method_locations_range;
2399 const FinalOverriders Overriders;
2404 MethodVFTableLocationsTy MethodVFTableLocations;
2407 bool HasRTTIComponent =
false;
2414 const uint64_t VBTableIndex;
2417 const uint64_t VFTableIndex;
2428 MethodInfo(uint64_t VBTableIndex, uint64_t VFTableIndex,
2429 bool UsesExtraSlot =
false)
2430 : VBTableIndex(VBTableIndex), VFTableIndex(VFTableIndex),
2431 Shadowed(
false), UsesExtraSlot(UsesExtraSlot) {}
2434 : VBTableIndex(0), VFTableIndex(0), Shadowed(
false),
2435 UsesExtraSlot(
false) {}
2438 typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy;
2442 MethodInfoMapTy MethodInfoMap;
2444 typedef llvm::DenseMap<uint64_t, ThunkInfo> VTableThunksMapTy;
2448 VTableThunksMapTy VTableThunks;
2451 typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
2462 if (std::find(ThunksVector.begin(), ThunksVector.end(), Thunk) !=
2466 ThunksVector.push_back(Thunk);
2471 CharUnits ComputeThisOffset(FinalOverriders::OverriderInfo Overrider);
2473 void CalculateVtordispAdjustment(FinalOverriders::OverriderInfo Overrider,
2480 VTableThunks[Components.size()] = TI;
2485 "Destructor can't have return adjustment!");
2496 BasesSetVectorTy &VisitedBases);
2498 void LayoutVFTable() {
2500 if (HasRTTIComponent)
2503 BasesSetVectorTy VisitedBases;
2506 assert((HasRTTIComponent ? Components.size() - 1 : Components.size()) &&
2507 "vftable can't be empty");
2509 assert(MethodVFTableLocations.empty());
2510 for (
const auto &
I : MethodInfoMap) {
2512 const MethodInfo &MI =
I.second;
2515 if (MD->
getParent() != MostDerivedClass || MI.Shadowed)
2517 MethodVFTableLocation Loc(MI.VBTableIndex, WhichVFPtr.getVBaseWithVPtr(),
2518 WhichVFPtr.NonVirtualOffset, MI.VFTableIndex);
2522 MethodVFTableLocations[MD] = Loc;
2531 Context(MostDerivedClass->getASTContext()),
2532 MostDerivedClass(MostDerivedClass),
2533 MostDerivedClassLayout(
Context.getASTRecordLayout(MostDerivedClass)),
2535 Overriders(MostDerivedClass,
CharUnits(), MostDerivedClass) {
2542 HasRTTIComponent =
true;
2547 dumpLayout(llvm::outs());
2550 uint64_t getNumThunks()
const {
return Thunks.size(); }
2552 ThunksMapTy::const_iterator thunks_begin()
const {
return Thunks.begin(); }
2554 ThunksMapTy::const_iterator thunks_end()
const {
return Thunks.end(); }
2556 method_locations_range vtable_locations()
const {
2557 return method_locations_range(MethodVFTableLocations.begin(),
2558 MethodVFTableLocations.end());
2563 VTableThunksMapTy::const_iterator vtable_thunks_begin()
const {
2564 return VTableThunks.begin();
2567 VTableThunksMapTy::const_iterator vtable_thunks_end()
const {
2568 return VTableThunks.end();
2571 void dumpLayout(raw_ostream &);
2631 VFTableBuilder::ComputeThisOffset(FinalOverriders::OverriderInfo Overrider) {
2632 BasesSetVectorTy Bases;
2636 OverriddenMethodsSetTy VisitedOverriddenMethods;
2637 auto InitialOverriddenDefinitionCollector = [&](
2639 if (OverriddenMD->size_overridden_methods() == 0)
2640 Bases.insert(OverriddenMD->getParent());
2642 return VisitedOverriddenMethods.insert(OverriddenMD).second;
2644 visitAllOverriddenMethods(Overrider.Method,
2645 InitialOverriddenDefinitionCollector);
2650 if (Bases.size() == 0)
2651 return Overrider.Offset;
2654 Overrider.Method->getParent()->lookupInBases(
2670 CharUnits ThisOffset = Overrider.Offset;
2677 QualType CurTy = Element.Base->getType();
2682 if (Element.Base->isVirtual()) {
2693 LastVBaseOffset = ThisOffset =
2700 if (isa<CXXDestructorDecl>(Overrider.Method)) {
2701 if (LastVBaseOffset.
isZero()) {
2705 ThisOffset = Overrider.Offset;
2709 ThisOffset = LastVBaseOffset;
2713 if (Ret > ThisOffset || First) {
2719 assert(!First &&
"Method not found in the given subobject?");
2821 void VFTableBuilder::CalculateVtordispAdjustment(
2822 FinalOverriders::OverriderInfo Overrider,
CharUnits ThisOffset,
2825 MostDerivedClassLayout.getVBaseOffsetsMap();
2826 const ASTRecordLayout::VBaseOffsetsMapTy::const_iterator &VBaseMapEntry =
2827 VBaseMap.find(WhichVFPtr.getVBaseWithVPtr());
2828 assert(VBaseMapEntry != VBaseMap.end());
2832 if (!VBaseMapEntry->second.hasVtorDisp() ||
2833 Overrider.VirtualBase == WhichVFPtr.getVBaseWithVPtr())
2838 CharUnits OffsetOfVBaseWithVFPtr = VBaseMapEntry->second.VBaseOffset;
2840 (OffsetOfVBaseWithVFPtr - WhichVFPtr.FullOffsetInMDC).getQuantity() - 4;
2844 if (Overrider.Method->getParent() == MostDerivedClass ||
2845 !Overrider.VirtualBase)
2851 (OffsetOfVBaseWithVFPtr + WhichVFPtr.NonVirtualOffset -
2852 MostDerivedClassLayout.getVBPtrOffset()).getQuantity();
2857 TA.
NonVirtual = (ThisOffset - Overrider.Offset).getQuantity();
2871 typedef llvm::DenseMap<DeclarationName, unsigned> VisitedGroupIndicesTy;
2872 VisitedGroupIndicesTy VisitedGroupIndices;
2873 for (
const auto *D : RD->
decls()) {
2874 const auto *ND = dyn_cast<
NamedDecl>(D);
2877 VisitedGroupIndicesTy::iterator J;
2879 std::tie(J, Inserted) = VisitedGroupIndices.insert(
2880 std::make_pair(ND->getDeclName(), Groups.size()));
2882 Groups.push_back(MethodGroup());
2883 if (
const auto *MD = dyn_cast<CXXMethodDecl>(ND))
2888 for (
const MethodGroup &Group : Groups)
2889 VirtualMethods.append(Group.rbegin(), Group.rend());
2893 for (
const auto &B : RD->
bases()) {
2894 if (B.isVirtual() && B.getType()->getAsCXXRecordDecl() == Base)
2902 BasesSetVectorTy &VisitedBases) {
2912 const CXXRecordDecl *NextBase =
nullptr, *NextLastVBase = LastVBase;
2914 if (BaseDepth < WhichVFPtr.PathToIntroducingObject.size()) {
2915 NextBase = WhichVFPtr.PathToIntroducingObject[BaseDepth];
2917 NextLastVBase = NextBase;
2918 NextBaseOffset = MostDerivedClassLayout.getVBaseClassOffset(NextBase);
2925 "No primary virtual bases in this ABI");
2926 NextBase = PrimaryBase;
2931 AddMethods(
BaseSubobject(NextBase, NextBaseOffset), BaseDepth + 1,
2932 NextLastVBase, VisitedBases);
2933 if (!VisitedBases.insert(NextBase))
2934 llvm_unreachable(
"Found a duplicate primary base!");
2950 FinalOverriders::OverriderInfo FinalOverrider =
2952 const CXXMethodDecl *FinalOverriderMD = FinalOverrider.Method;
2954 FindNearestOverriddenMethod(MD, VisitedBases);
2957 bool ReturnAdjustingThunk =
false, ForceReturnAdjustmentMangling =
false;
2958 CharUnits ThisOffset = ComputeThisOffset(FinalOverrider);
2960 (ThisOffset - WhichVFPtr.FullOffsetInMDC).getQuantity();
2961 if ((OverriddenMD || FinalOverriderMD != MD) &&
2962 WhichVFPtr.getVBaseWithVPtr())
2963 CalculateVtordispAdjustment(FinalOverrider, ThisOffset,
2964 ThisAdjustmentOffset);
2969 MethodInfoMapTy::iterator OverriddenMDIterator =
2970 MethodInfoMap.find(OverriddenMD);
2973 if (OverriddenMDIterator == MethodInfoMap.end())
2976 MethodInfo &OverriddenMethodInfo = OverriddenMDIterator->second;
2983 ReturnAdjustingThunk = !ComputeReturnAdjustmentBaseOffset(
2984 Context, MD, OverriddenMD).isEmpty() ||
2985 OverriddenMethodInfo.UsesExtraSlot;
2987 if (!ReturnAdjustingThunk) {
2990 MethodInfo MI(OverriddenMethodInfo.VBTableIndex,
2991 OverriddenMethodInfo.VFTableIndex);
2992 MethodInfoMap.erase(OverriddenMDIterator);
2994 assert(!MethodInfoMap.count(MD) &&
2995 "Should not have method info for this method yet!");
2996 MethodInfoMap.insert(std::make_pair(MD, MI));
3002 OverriddenMethodInfo.Shadowed =
true;
3006 ForceReturnAdjustmentMangling =
3007 !(MD == FinalOverriderMD && ThisAdjustmentOffset.
isEmpty());
3008 }
else if (Base.
getBaseOffset() != WhichVFPtr.FullOffsetInMDC ||
3020 MethodInfo MI(VBIndex,
3021 HasRTTIComponent ? Components.size() - 1 : Components.size(),
3022 ReturnAdjustingThunk);
3024 assert(!MethodInfoMap.count(MD) &&
3025 "Should not have method info for this method yet!");
3026 MethodInfoMap.insert(std::make_pair(MD, MI));
3030 BaseOffset ReturnAdjustmentOffset;
3032 if (!FinalOverriderMD->
isPure()) {
3033 ReturnAdjustmentOffset =
3034 ComputeReturnAdjustmentBaseOffset(
Context, FinalOverriderMD, MD);
3036 if (!ReturnAdjustmentOffset.isEmpty()) {
3037 ForceReturnAdjustmentMangling =
true;
3039 ReturnAdjustmentOffset.NonVirtualOffset.getQuantity();
3040 if (ReturnAdjustmentOffset.VirtualBase) {
3047 ReturnAdjustmentOffset.VirtualBase);
3051 AddMethod(FinalOverriderMD,
3052 ThunkInfo(ThisAdjustmentOffset, ReturnAdjustment,
3053 ForceReturnAdjustmentMangling ? MD :
nullptr));
3059 llvm::make_range(Path.rbegin(), Path.rend())) {
3061 Elem->printQualifiedName(Out);
3067 bool ContinueFirstLine) {
3068 const ReturnAdjustment &R = TI.
Return;
3069 bool Multiline =
false;
3070 const char *LinePrefix =
"\n ";
3072 if (!ContinueFirstLine)
3074 Out <<
"[return adjustment (to type '"
3087 if (Multiline || !ContinueFirstLine)
3089 Out <<
"[this adjustment: ";
3097 Out << LinePrefix <<
" vboffset at "
3105 void VFTableBuilder::dumpLayout(raw_ostream &Out) {
3106 Out <<
"VFTable for ";
3110 Out <<
"' (" << Components.size()
3111 << (Components.size() == 1 ?
" entry" :
" entries") <<
").\n";
3113 for (
unsigned I = 0,
E = Components.size();
I !=
E; ++
I) {
3114 Out << llvm::format(
"%4d | ",
I);
3119 switch (Component.
getKind()) {
3137 Out <<
" [deleted]";
3150 Out <<
"() [scalar deleting]";
3158 "No return adjustment needed for destructors!");
3169 "Unexpected vftable component type %0 for component number %1");
3179 if (!Thunks.empty()) {
3181 std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls;
3183 for (
const auto &
I : Thunks) {
3188 MethodNamesAndDecls.insert(std::make_pair(MethodName, MD));
3191 for (
const auto &MethodNameAndDecl : MethodNamesAndDecls) {
3192 const std::string &MethodName = MethodNameAndDecl.first;
3195 ThunkInfoVectorTy ThunksVector = Thunks[MD];
3196 std::stable_sort(ThunksVector.begin(), ThunksVector.end(),
3200 return std::tie(LHS.
This, LHS.
Return) < std::tie(RHS.This, RHS.Return);
3203 Out <<
"Thunks for '" << MethodName <<
"' (" << ThunksVector.size();
3204 Out << (ThunksVector.size() == 1 ?
" entry" :
" entries") <<
").\n";
3206 for (
unsigned I = 0,
E = ThunksVector.size();
I !=
E; ++
I) {
3209 Out << llvm::format(
"%4d | ",
I);
3253 void MicrosoftVTableContext::computeVTablePaths(
bool ForVBTables,
3256 assert(Paths.empty());
3260 if (ForVBTables ? Layout.hasOwnVBPtr() : Layout.hasOwnVFPtr())
3261 Paths.push_back(llvm::make_unique<VPtrInfo>(RD));
3265 llvm::SmallPtrSet<const CXXRecordDecl*, 4> VBasesSeen;
3266 for (
const auto &B : RD->
bases()) {
3267 const CXXRecordDecl *Base = B.getType()->getAsCXXRecordDecl();
3268 if (B.isVirtual() && VBasesSeen.count(Base))
3277 for (
const std::unique_ptr<VPtrInfo> &BaseInfo : BasePaths) {
3284 auto P = llvm::make_unique<VPtrInfo>(*BaseInfo);
3288 if (
P->MangledPath.empty() ||
P->MangledPath.back() != Base)
3289 P->NextBaseToMangle = Base;
3294 if (
P->ObjectWithVPtr == Base &&
3295 Base == (ForVBTables ? Layout.getBaseSharingVBPtr()
3296 : Layout.getPrimaryBase()))
3297 P->ObjectWithVPtr = RD;
3302 P->ContainingVBases.push_back(Base);
3303 else if (
P->ContainingVBases.empty())
3304 P->NonVirtualOffset += Layout.getBaseClassOffset(Base);
3307 P->FullOffsetInMDC =
P->NonVirtualOffset;
3309 P->FullOffsetInMDC += Layout.getVBaseClassOffset(VB);
3311 Paths.push_back(std::move(
P));
3315 VBasesSeen.insert(Base);
3319 for (
const auto &VB : Base->
vbases())
3320 VBasesSeen.insert(VB.getType()->getAsCXXRecordDecl());
3325 bool Changed =
true;
3347 PathsSorted.reserve(Paths.size());
3348 for (
auto&
P : Paths)
3349 PathsSorted.push_back(*
P);
3350 std::sort(PathsSorted.begin(), PathsSorted.end(),
3354 bool Changed =
false;
3355 for (
size_t I = 0,
E = PathsSorted.size();
I !=
E;) {
3357 size_t BucketStart =
I;
3361 PathsSorted[BucketStart].
get().MangledPath ==
3362 PathsSorted[
I].get().MangledPath);
3365 if (
I - BucketStart > 1) {
3366 for (
size_t II = BucketStart; II !=
I; ++II)
3368 assert(Changed &&
"no paths were extended to fix ambiguity");
3377 typedef llvm::SetVector<BaseSubobject, std::vector<BaseSubobject>,
3387 FullPathTy &FullPath,
3388 std::list<FullPathTy> &Paths) {
3390 Paths.push_back(FullPath);
3397 const CXXRecordDecl *Base = BS.getType()->getAsCXXRecordDecl();
3403 IntroducingObject, FullPath, Paths);
3404 FullPath.pop_back();
3410 FullPaths.remove_if([&](
const FullPathTy &SpecificPath) {
3411 for (
const FullPathTy &OtherPath : FullPaths) {
3412 if (&SpecificPath == &OtherPath)
3414 if (std::all_of(SpecificPath.begin(), SpecificPath.end(),
3416 return OtherPath.count(BSO) != 0;
3427 const FullPathTy &FullPath) {
3448 : Offset + Layout.getBaseClassOffset(Base);
3460 std::list<FullPathTy> &FullPaths) {
3462 if (FullPaths.empty())
3464 if (FullPaths.size() == 1)
3465 return &FullPaths.front();
3467 const FullPathTy *BestPath =
nullptr;
3468 typedef std::set<const CXXMethodDecl *> OverriderSetTy;
3469 OverriderSetTy LastOverrides;
3470 for (
const FullPathTy &SpecificPath : FullPaths) {
3471 assert(!SpecificPath.empty());
3472 OverriderSetTy CurrentOverrides;
3473 const CXXRecordDecl *TopLevelRD = SpecificPath.begin()->getBase();
3478 FinalOverriders Overriders(TopLevelRD,
CharUnits::Zero(), TopLevelRD);
3482 FinalOverriders::OverriderInfo OI =
3487 if (ComputeReturnAdjustmentBaseOffset(Context, OverridingMethod, MD)
3493 if (std::none_of(SpecificPath.begin(), SpecificPath.end(),
3495 return BSO.getBase() == OverridingParent;
3498 CurrentOverrides.insert(OverridingMethod);
3500 OverriderSetTy NewOverrides =
3501 llvm::set_difference(CurrentOverrides, LastOverrides);
3502 if (NewOverrides.empty())
3504 OverriderSetTy MissingOverrides =
3505 llvm::set_difference(LastOverrides, CurrentOverrides);
3506 if (MissingOverrides.empty()) {
3508 BestPath = &SpecificPath;
3509 std::swap(CurrentOverrides, LastOverrides);
3514 const CXXMethodDecl *ConflictMD = *MissingOverrides.begin();
3525 return BestPath ? BestPath : &FullPaths.front();
3532 FullPathTy FullPath;
3533 std::list<FullPathTy> FullPaths;
3534 for (
const std::unique_ptr<VPtrInfo>& Info : Paths) {
3537 BaseSubobject(Info->IntroducingObject, Info->FullOffsetInMDC), FullPath,
3541 Info->PathToIntroducingObject.clear();
3542 if (
const FullPathTy *BestPath =
3545 Info->PathToIntroducingObject.push_back(BSO.getBase());
3550 void MicrosoftVTableContext::computeVTableRelatedInformation(
3555 if (VFPtrLocations.count(RD))
3562 computeVTablePaths(
false, RD, VFPtrs);
3564 VFPtrLocations[RD] = std::move(VFPtrs);
3567 MethodVFTableLocationsTy NewMethodLocations;
3568 for (
const std::unique_ptr<VPtrInfo> &VFPtr : VFPtrLocations[RD]) {
3569 VFTableBuilder
Builder(*
this, RD, *VFPtr);
3571 VFTableIdTy
id(RD, VFPtr->FullOffsetInMDC);
3572 assert(VFTableLayouts.count(
id) == 0);
3575 VFTableLayouts[
id] = llvm::make_unique<VTableLayout>(
3577 EmptyAddressPointsMap);
3580 for (
const auto &Loc :
Builder.vtable_locations()) {
3582 MethodVFTableLocation NewLoc = Loc.second;
3583 auto M = NewMethodLocations.find(GD);
3584 if (M == NewMethodLocations.end() || NewLoc < M->second)
3585 NewMethodLocations[GD] = NewLoc;
3589 MethodVFTableLocations.insert(NewMethodLocations.begin(),
3590 NewMethodLocations.end());
3592 dumpMethodLocations(RD, NewMethodLocations, llvm::outs());
3595 void MicrosoftVTableContext::dumpMethodLocations(
3596 const CXXRecordDecl *RD,
const MethodVFTableLocationsTy &NewMethods,
3600 std::map<MethodVFTableLocation, std::string> IndicesMap;
3601 bool HasNonzeroOffset =
false;
3603 for (
const auto &
I : NewMethods) {
3604 const CXXMethodDecl *MD = cast<const CXXMethodDecl>(
I.first.getDecl());
3610 if (isa<CXXDestructorDecl>(MD)) {
3611 IndicesMap[
I.second] = MethodName +
" [scalar deleting]";
3613 IndicesMap[
I.second] = MethodName;
3616 if (!
I.second.VFPtrOffset.isZero() ||
I.second.VBTableIndex != 0)
3617 HasNonzeroOffset =
true;
3621 if (!IndicesMap.empty()) {
3622 Out <<
"VFTable indices for ";
3625 Out <<
"' (" << IndicesMap.size()
3626 << (IndicesMap.size() == 1 ?
" entry" :
" entries") <<
").\n";
3629 uint64_t LastVBIndex = 0;
3630 for (
const auto &
I : IndicesMap) {
3632 uint64_t VBIndex =
I.first.VBTableIndex;
3633 if (HasNonzeroOffset &&
3634 (VFPtrOffset != LastVFPtrOffset || VBIndex != LastVBIndex)) {
3635 assert(VBIndex > LastVBIndex || VFPtrOffset > LastVFPtrOffset);
3636 Out <<
" -- accessible via ";
3638 Out <<
"vbtable index " << VBIndex <<
", ";
3639 Out <<
"vfptr at offset " << VFPtrOffset.
getQuantity() <<
" --\n";
3640 LastVFPtrOffset = VFPtrOffset;
3641 LastVBIndex = VBIndex;
3644 uint64_t VTableIndex =
I.first.Index;
3645 const std::string &MethodName =
I.second;
3646 Out << llvm::format(
"%4" PRIu64
" | ", VTableIndex) << MethodName <<
'\n';
3654 const VirtualBaseInfo &MicrosoftVTableContext::computeVBTableRelatedInformation(
3661 std::unique_ptr<VirtualBaseInfo> &Entry = VBaseInfo[RD];
3664 Entry = llvm::make_unique<VirtualBaseInfo>();
3668 computeVTablePaths(
true, RD, VBI->VBPtrPaths);
3676 computeVBTableRelatedInformation(VBPtrBase);
3683 unsigned VBTableIndex = 1 + VBI->VBTableIndices.size();
3684 for (
const auto &VB : RD->
vbases()) {
3685 const CXXRecordDecl *CurVBase = VB.getType()->getAsCXXRecordDecl();
3686 if (!VBI->VBTableIndices.count(CurVBase))
3687 VBI->VBTableIndices[CurVBase] = VBTableIndex++;
3695 const VirtualBaseInfo &VBInfo = computeVBTableRelatedInformation(Derived);
3702 return computeVBTableRelatedInformation(RD).
VBPtrPaths;
3707 computeVTableRelatedInformation(RD);
3709 assert(VFPtrLocations.count(RD) &&
"Couldn't find vfptr locations");
3710 return VFPtrLocations[RD];
3716 computeVTableRelatedInformation(RD);
3718 VFTableIdTy
id(RD, VFPtrOffset);
3719 assert(VFTableLayouts.count(
id) &&
"Couldn't find a VFTable at this offset");
3720 return *VFTableLayouts[
id];
3725 assert(cast<CXXMethodDecl>(GD.
getDecl())->isVirtual() &&
3726 "Only use this method for virtual methods or dtors");
3727 if (isa<CXXDestructorDecl>(GD.
getDecl()))
3730 MethodVFTableLocationsTy::iterator
I = MethodVFTableLocations.find(GD);
3731 if (I != MethodVFTableLocations.end())
3736 computeVTableRelatedInformation(RD);
3738 I = MethodVFTableLocations.find(GD);
3739 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.
struct clang::ThisAdjustment::VirtualAdjustment::@119 Microsoft
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.
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...
const NestedNameSpecifier * Specifier
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 std::unique_ptr< VTableLayout > CreateVTableLayout(const ItaniumVTableBuilder &Builder)
static VTableComponent MakeUnusedFunction(const CXXMethodDecl *MD)
static VTableComponent MakeVCallOffset(CharUnits Offset)
A this pointer adjustment.
const CXXMethodDecl * Method
Holds a pointer to the overridden method this thunk is for, if needed by the ABI to distinguish diffe...
int32_t VBOffsetOffset
The offset (in bytes) of the vbase offset in the vbtable.
method_iterator end_overridden_methods() const
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
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)
std::vector< const CXXMethodDecl * > OverriddenMethods
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...
const CXXRecordDecl * IntroducingObject
This is the class that introduced the vptr by declaring new virtual methods or virtual bases...
Concrete class used by the front-end to report problems and issues.
const VPtrInfoVector & getVFPtrOffsets(const CXXRecordDecl *RD)
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D...
base_class_iterator bases_begin()
static void removeRedundantPaths(std::list< FullPathTy > &FullPaths)
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
uint64_t getMethodVTableIndex(GlobalDecl GD)
Locate a virtual function in the vtable.
detail::InMemoryDirectory::const_iterator I
CharUnits getVirtualBaseOffsetOffset(const CXXRecordDecl *RD, const CXXRecordDecl *VBase)
Return the offset in chars (relative to the vtable address point) where the offset of the virtual bas...
static VTableComponent MakeDeletingDtor(const CXXDestructorDecl *DD)
DiagnosticsEngine & getDiagnostics() const
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.
static void findPathsToSubobject(ASTContext &Context, const ASTRecordLayout &MostDerivedLayout, const CXXRecordDecl *RD, CharUnits Offset, BaseSubobject IntroducingObject, FullPathTy &FullPath, std::list< FullPathTy > &Paths)
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
const CXXRecordDecl * getBaseSharingVBPtr() const
DeclContext * getParent()
getParent - Returns the containing DeclContext.
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...
struct clang::ThisAdjustment::VirtualAdjustment::@118 Itanium
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)
std::unique_ptr< VTableLayout > createConstructionVTableLayout(const CXXRecordDecl *MostDerivedClass, CharUnits MostDerivedClassOffset, bool MostDerivedClassIsVirtual, const CXXRecordDecl *LayoutClass)
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)
const CXXDestructorDecl * getDestructorDecl() const
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()))
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.
static bool extendPath(VPtrInfo &P)
The same as PrettyFunction, except that the 'virtual' keyword is omitted for virtual member functions...
DeclarationName - The name of a declaration.
CharUnits getVBaseOffset() const
A mapping from each virtual member function to its set of final overriders.
static CharUnits getOffsetOfFullPath(ASTContext &Context, const CXXRecordDecl *RD, const FullPathTy &FullPath)
int64_t VBaseOffsetOffset
The offset (in bytes), relative to the address point of the virtual base class offset.
detail::InMemoryDirectory::const_iterator E
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
VTableLayout(ArrayRef< size_t > VTableIndices, ArrayRef< VTableComponent > VTableComponents, ArrayRef< VTableThunkTy > VTableThunks, const AddressPointsMapTy &AddressPoints)
const T * getAs() const
Member-template getAs<specific type>'.
unsigned getTypeQuals() const
QualType getCanonicalType() const
struct clang::ReturnAdjustment::VirtualAdjustment::@116 Itanium
static const FullPathTy * selectBestPath(ASTContext &Context, const CXXRecordDecl *RD, const VPtrInfo &Info, std::list< FullPathTy > &FullPaths)
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.
llvm::DenseMap< BaseSubobject, AddressPointLocation > AddressPointsMapTy
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()
struct clang::ReturnAdjustment::VirtualAdjustment::@117 Microsoft
std::pair< uint64_t, ThunkInfo > VTableThunkTy
Defines the clang::TargetInfo interface.
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)