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;
219 static BaseOffset ComputeBaseOffset(
const ASTContext &Context,
224 unsigned NonVirtualStart = 0;
228 for (
int I = Path.size(), E = 0; I != E; --I) {
240 for (
unsigned I = NonVirtualStart, E = Path.size(); I != E; ++I) {
254 return BaseOffset(DerivedRD, VirtualBase, NonVirtualOffset);
258 static BaseOffset ComputeBaseOffset(
const ASTContext &Context,
265 llvm_unreachable(
"Class must be derived from the passed in base class!");
267 return ComputeBaseOffset(Context, DerivedRD, Paths.
front());
271 ComputeReturnAdjustmentBaseOffset(
ASTContext &Context,
283 assert(CanDerivedReturnType->getTypeClass() ==
284 CanBaseReturnType->getTypeClass() &&
285 "Types must have same type class!");
287 if (CanDerivedReturnType == CanBaseReturnType) {
292 if (isa<ReferenceType>(CanDerivedReturnType)) {
293 CanDerivedReturnType =
294 CanDerivedReturnType->getAs<
ReferenceType>()->getPointeeType();
297 }
else if (isa<PointerType>(CanDerivedReturnType)) {
298 CanDerivedReturnType =
299 CanDerivedReturnType->getAs<
PointerType>()->getPointeeType();
303 llvm_unreachable(
"Unexpected return type!");
309 if (CanDerivedReturnType.getUnqualifiedType() ==
316 cast<CXXRecordDecl>(cast<RecordType>(CanDerivedReturnType)->getDecl());
319 cast<CXXRecordDecl>(cast<RecordType>(CanBaseReturnType)->getDecl());
321 return ComputeBaseOffset(Context, BaseRD, DerivedRD);
327 SubobjectOffsetMapTy &SubobjectOffsets,
328 SubobjectOffsetMapTy &SubobjectLayoutClassOffsets,
329 SubobjectCountMapTy &SubobjectCounts) {
332 unsigned SubobjectNumber = 0;
334 SubobjectNumber = ++SubobjectCounts[RD];
337 assert(!SubobjectOffsets.count(std::make_pair(RD, SubobjectNumber))
338 &&
"Subobject offset already exists!");
339 assert(!SubobjectLayoutClassOffsets.count(std::make_pair(RD, SubobjectNumber))
340 &&
"Subobject offset already exists!");
342 SubobjectOffsets[std::make_pair(RD, SubobjectNumber)] = Base.
getBaseOffset();
343 SubobjectLayoutClassOffsets[std::make_pair(RD, SubobjectNumber)] =
347 for (
const auto &B : RD->
bases()) {
348 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
354 if (SubobjectOffsets.count(std::make_pair(BaseDecl, 0)))
360 BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
361 BaseOffsetInLayoutClass =
368 BaseOffsetInLayoutClass = OffsetInLayoutClass +
Offset;
372 B.isVirtual(), BaseOffsetInLayoutClass,
373 SubobjectOffsets, SubobjectLayoutClassOffsets,
379 VisitedVirtualBasesSetTy &VisitedVirtualBases) {
383 for (
const auto &B : RD->
bases()) {
384 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
392 if (!VisitedVirtualBases.insert(BaseDecl).second) {
397 BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
405 Out <<
"Final overriders for (";
411 for (
const auto *MD : RD->
methods()) {
412 if (!MD->isVirtual())
414 MD = MD->getCanonicalDecl();
416 OverriderInfo Overrider = getOverrider(MD, Base.
getBaseOffset());
419 MD->printQualifiedName(Out);
421 Overrider.Method->printQualifiedName(Out);
422 Out <<
", " << Overrider.Offset.getQuantity() <<
')';
425 if (!Overrider.Method->isPure())
426 Offset = ComputeReturnAdjustmentBaseOffset(Context, Overrider.Method, MD);
428 if (!Offset.isEmpty()) {
429 Out <<
" [ret-adj: ";
430 if (Offset.VirtualBase) {
431 Offset.VirtualBase->printQualifiedName(Out);
435 Out << Offset.NonVirtualOffset.getQuantity() <<
" nv]";
443 struct VCallOffsetMap {
445 typedef std::pair<const CXXMethodDecl *, CharUnits> MethodAndOffsetPairTy;
453 static bool MethodsCanShareVCallOffset(
const CXXMethodDecl *LHS,
467 bool empty()
const {
return Offsets.empty(); }
470 static bool HasSameVirtualSignature(
const CXXMethodDecl *LHS,
478 if (LT == RT)
return true;
488 bool VCallOffsetMap::MethodsCanShareVCallOffset(
const CXXMethodDecl *LHS,
490 assert(LHS->
isVirtual() &&
"LHS must be virtual!");
491 assert(RHS->
isVirtual() &&
"LHS must be virtual!");
494 if (isa<CXXDestructorDecl>(LHS))
495 return isa<CXXDestructorDecl>(RHS);
502 if (LHSName != RHSName)
506 return HasSameVirtualSignature(LHS, RHS);
512 for (
const auto &OffsetPair : Offsets) {
513 if (MethodsCanShareVCallOffset(OffsetPair.first, MD))
518 Offsets.push_back(MethodAndOffsetPairTy(MD, OffsetOffset));
524 for (
const auto &OffsetPair : Offsets) {
525 if (MethodsCanShareVCallOffset(OffsetPair.first, MD))
526 return OffsetPair.second;
529 llvm_unreachable(
"Should always find a vcall offset offset!");
533 class VCallAndVBaseOffsetBuilder {
535 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits>
536 VBaseOffsetOffsetsMapTy;
553 VTableComponentVectorTy Components;
556 llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBases;
559 VCallOffsetMap VCallOffsets;
564 VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
568 const FinalOverriders *Overriders;
572 void AddVCallAndVBaseOffsets(
BaseSubobject Base,
bool BaseIsVirtual,
584 CharUnits getCurrentOffsetOffset()
const;
587 VCallAndVBaseOffsetBuilder(
const CXXRecordDecl *MostDerivedClass,
589 const FinalOverriders *Overriders,
592 : MostDerivedClass(MostDerivedClass), LayoutClass(LayoutClass),
593 Context(MostDerivedClass->
getASTContext()), Overriders(Overriders) {
596 AddVCallAndVBaseOffsets(Base, BaseIsVirtual, OffsetInLayoutClass);
600 typedef VTableComponentVectorTy::const_reverse_iterator const_iterator;
601 const_iterator components_begin()
const {
return Components.rbegin(); }
602 const_iterator components_end()
const {
return Components.rend(); }
604 const VCallOffsetMap &getVCallOffsets()
const {
return VCallOffsets; }
605 const VBaseOffsetOffsetsMapTy &getVBaseOffsetOffsets()
const {
606 return VBaseOffsetOffsets;
611 VCallAndVBaseOffsetBuilder::AddVCallAndVBaseOffsets(
BaseSubobject Base,
631 if (PrimaryBaseIsVirtual) {
633 "Primary vbase should have a zero offset!");
639 MostDerivedClassLayout.getVBaseClassOffset(PrimaryBase);
642 "Primary base should have a zero offset!");
647 AddVCallAndVBaseOffsets(
649 PrimaryBaseIsVirtual, RealBaseOffset);
652 AddVBaseOffsets(Base.
getBase(), RealBaseOffset);
656 AddVCallOffsets(Base, RealBaseOffset);
659 CharUnits VCallAndVBaseOffsetBuilder::getCurrentOffsetOffset()
const {
664 int64_t OffsetIndex = -(int64_t)(3 + Components.size());
668 CharUnits OffsetOffset = PointerWidth * OffsetIndex;
672 void VCallAndVBaseOffsetBuilder::AddVCallOffsets(
BaseSubobject Base,
685 "Primary base should have a zero offset!");
692 for (
const auto *MD : RD->
methods()) {
697 CharUnits OffsetOffset = getCurrentOffsetOffset();
701 if (!VCallOffsets.AddVCallOffset(MD, OffsetOffset))
708 FinalOverriders::OverriderInfo Overrider =
713 Offset = Overrider.Offset - VBaseOffset;
716 Components.push_back(
721 for (
const auto &B : RD->
bases()) {
725 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
726 if (BaseDecl == PrimaryBase)
739 VCallAndVBaseOffsetBuilder::AddVBaseOffsets(
const CXXRecordDecl *RD,
745 for (
const auto &B : RD->
bases()) {
746 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
749 if (B.isVirtual() && VisitedVirtualBases.insert(BaseDecl).second) {
754 assert(!VBaseOffsetOffsets.count(BaseDecl) &&
755 "vbase offset offset already exists!");
757 CharUnits VBaseOffsetOffset = getCurrentOffsetOffset();
758 VBaseOffsetOffsets.insert(
759 std::make_pair(BaseDecl, VBaseOffsetOffset));
761 Components.push_back(
766 AddVBaseOffsets(BaseDecl, OffsetInLayoutClass);
771 class ItaniumVTableBuilder {
776 PrimaryBasesSetVectorTy;
778 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits>
779 VBaseOffsetOffsetsMapTy;
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),
996 LayoutClass(LayoutClass), Context(MostDerivedClass->
getASTContext()),
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!");
1083 if (!Visitor(OverriddenMD))
1085 visitAllOverriddenMethods(OverriddenMD, Visitor);
1093 OverriddenMethodsSetTy& OverriddenMethods) {
1094 auto OverriddenMethodsCollector = [&](
const CXXMethodDecl *MD) {
1096 return OverriddenMethods.insert(MD).second;
1098 visitAllOverriddenMethods(MD, OverriddenMethodsCollector);
1101 void ItaniumVTableBuilder::ComputeThisAdjustments() {
1104 for (
const auto &MI : MethodInfoMap) {
1106 const MethodInfo &MethodInfo = MI.second;
1109 uint64_t VTableIndex = MethodInfo.VTableIndex;
1110 if (Components[VTableIndex].
getKind() ==
1115 FinalOverriders::OverriderInfo Overrider =
1116 Overriders.getOverrider(MD, MethodInfo.BaseOffset);
1119 if (MethodInfo.BaseOffsetInLayoutClass == Overrider.Offset) {
1125 if (VTableThunks.lookup(VTableIndex).Return.isEmpty())
1130 ComputeThisAdjustment(MD, MethodInfo.BaseOffsetInLayoutClass, Overrider);
1136 VTableThunks[VTableIndex].This = ThisAdjustment;
1138 if (isa<CXXDestructorDecl>(MD)) {
1140 VTableThunks[VTableIndex + 1].This = ThisAdjustment;
1145 MethodInfoMap.clear();
1147 if (isBuildingConstructorVTable()) {
1152 for (
const auto &TI : VTableThunks) {
1157 switch (Component.
getKind()) {
1159 llvm_unreachable(
"Unexpected vtable component kind!");
1171 if (MD->
getParent() == MostDerivedClass)
1172 AddThunk(MD, Thunk);
1177 ItaniumVTableBuilder::ComputeReturnAdjustment(BaseOffset
Offset) {
1180 if (!Offset.isEmpty()) {
1181 if (Offset.VirtualBase) {
1183 if (Offset.DerivedClass == MostDerivedClass) {
1186 VBaseOffsetOffsets.lookup(Offset.VirtualBase).getQuantity();
1189 VTables.getVirtualBaseOffsetOffset(Offset.DerivedClass,
1190 Offset.VirtualBase).getQuantity();
1194 Adjustment.
NonVirtual = Offset.NonVirtualOffset.getQuantity();
1200 BaseOffset ItaniumVTableBuilder::ComputeThisAdjustmentBaseOffset(
1209 llvm_unreachable(
"Class must be derived from the passed in base class!");
1214 BaseOffset Offset = ComputeBaseOffset(Context, DerivedRD, Path);
1216 CharUnits OffsetToBaseSubobject = Offset.NonVirtualOffset;
1218 if (Offset.VirtualBase) {
1226 OffsetToBaseSubobject +=
1238 Offset.NonVirtualOffset = -Offset.NonVirtualOffset;
1243 return BaseOffset();
1248 FinalOverriders::OverriderInfo Overrider) {
1250 if (Overrider.Method->isPure())
1254 BaseOffsetInLayoutClass);
1256 BaseSubobject OverriderBaseSubobject(Overrider.Method->getParent(),
1260 BaseOffset Offset = ComputeThisAdjustmentBaseOffset(OverriddenBaseSubobject,
1261 OverriderBaseSubobject);
1262 if (Offset.isEmpty())
1267 if (Offset.VirtualBase) {
1269 VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[Offset.VirtualBase];
1271 if (VCallOffsets.empty()) {
1274 VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, MostDerivedClass,
1282 VCallOffsets = Builder.getVCallOffsets();
1286 VCallOffsets.getVCallOffsetOffset(MD).getQuantity();
1290 Adjustment.
NonVirtual = Offset.NonVirtualOffset.getQuantity();
1295 void ItaniumVTableBuilder::AddMethod(
const CXXMethodDecl *MD,
1298 assert(ReturnAdjustment.
isEmpty() &&
1299 "Destructor can't have return adjustment!");
1306 if (!ReturnAdjustment.
isEmpty())
1307 VTableThunks[Components.size()].Return = ReturnAdjustment;
1325 static bool OverridesIndirectMethodInBases(
1333 if (OverridesIndirectMethodInBases(OverriddenMD, Bases))
1340 bool ItaniumVTableBuilder::IsOverriderUsed(
1343 CharUnits FirstBaseOffsetInLayoutClass)
const {
1346 if (BaseOffsetInLayoutClass == FirstBaseOffsetInLayoutClass)
1355 if (Overrider->
getParent() == FirstBaseInPrimaryBaseChain)
1361 PrimaryBases.insert(RD);
1374 "Primary base should always be at offset 0!");
1381 if (LayoutClassLayout.getVBaseClassOffset(PrimaryBase) !=
1382 FirstBaseOffsetInLayoutClass) {
1388 "Primary base should always be at offset 0!");
1391 if (!PrimaryBases.insert(PrimaryBase))
1392 llvm_unreachable(
"Found a duplicate primary base!");
1399 return OverridesIndirectMethodInBases(Overrider, PrimaryBases);
1409 BasesSetVectorTy &Bases) {
1410 OverriddenMethodsSetTy OverriddenMethods;
1411 ComputeAllOverriddenMethods(MD, OverriddenMethods);
1414 llvm::make_range(Bases.rbegin(), Bases.rend())) {
1416 for (
const CXXMethodDecl *OverriddenMD : OverriddenMethods) {
1418 if (OverriddenMD->getParent() == PrimaryBase)
1419 return OverriddenMD;
1426 void ItaniumVTableBuilder::AddMethods(
1430 PrimaryBasesSetVectorTy &PrimaryBases) {
1445 CharUnits PrimaryBaseOffsetInLayoutClass;
1448 "Primary vbase should have a zero offset!");
1454 MostDerivedClassLayout.getVBaseClassOffset(PrimaryBase);
1459 PrimaryBaseOffsetInLayoutClass =
1463 "Primary base should have a zero offset!");
1466 PrimaryBaseOffsetInLayoutClass = BaseOffsetInLayoutClass;
1470 PrimaryBaseOffsetInLayoutClass, FirstBaseInPrimaryBaseChain,
1471 FirstBaseOffsetInLayoutClass, PrimaryBases);
1473 if (!PrimaryBases.insert(PrimaryBase))
1474 llvm_unreachable(
"Found a duplicate primary base!");
1480 NewVirtualFunctionsTy NewVirtualFunctions;
1483 for (
const auto *MD : RD->
methods()) {
1489 FinalOverriders::OverriderInfo Overrider =
1496 FindNearestOverriddenMethod(MD, PrimaryBases)) {
1497 if (ComputeReturnAdjustmentBaseOffset(Context, MD,
1498 OverriddenMD).isEmpty()) {
1501 assert(MethodInfoMap.count(OverriddenMD) &&
1502 "Did not find the overridden method!");
1503 MethodInfo &OverriddenMethodInfo = MethodInfoMap[OverriddenMD];
1505 MethodInfo MethodInfo(Base.
getBaseOffset(), BaseOffsetInLayoutClass,
1506 OverriddenMethodInfo.VTableIndex);
1508 assert(!MethodInfoMap.count(MD) &&
1509 "Should not have method info for this method yet!");
1511 MethodInfoMap.insert(std::make_pair(MD, MethodInfo));
1512 MethodInfoMap.erase(OverriddenMD);
1518 if (!isBuildingConstructorVTable() && OverriddenMD != MD) {
1521 ComputeThisAdjustment(OverriddenMD, BaseOffsetInLayoutClass,
1525 Overrider.Method->getParent() == MostDerivedClass) {
1530 BaseOffset ReturnAdjustmentOffset =
1531 ComputeReturnAdjustmentBaseOffset(Context, Overrider.Method, MD);
1532 ReturnAdjustment ReturnAdjustment =
1533 ComputeReturnAdjustment(ReturnAdjustmentOffset);
1536 AddThunk(Overrider.Method,
1537 ThunkInfo(ThisAdjustment, ReturnAdjustment));
1551 assert(!ImplicitVirtualDtor &&
1552 "Did already see an implicit virtual dtor!");
1553 ImplicitVirtualDtor = DD;
1558 NewVirtualFunctions.push_back(MD);
1561 if (ImplicitVirtualDtor)
1562 NewVirtualFunctions.push_back(ImplicitVirtualDtor);
1566 FinalOverriders::OverriderInfo Overrider =
1570 MethodInfo MethodInfo(Base.
getBaseOffset(), BaseOffsetInLayoutClass,
1573 assert(!MethodInfoMap.count(MD) &&
1574 "Should not have method info for this method yet!");
1575 MethodInfoMap.insert(std::make_pair(MD, MethodInfo));
1579 if (!IsOverriderUsed(OverriderMD, BaseOffsetInLayoutClass,
1580 FirstBaseInPrimaryBaseChain,
1581 FirstBaseOffsetInLayoutClass)) {
1588 BaseOffset ReturnAdjustmentOffset;
1589 if (!OverriderMD->
isPure()) {
1590 ReturnAdjustmentOffset =
1591 ComputeReturnAdjustmentBaseOffset(Context, OverriderMD, MD);
1594 ReturnAdjustment ReturnAdjustment =
1595 ComputeReturnAdjustment(ReturnAdjustmentOffset);
1597 AddMethod(Overrider.Method, ReturnAdjustment);
1601 void ItaniumVTableBuilder::LayoutVTable() {
1602 LayoutPrimaryAndSecondaryVTables(
BaseSubobject(MostDerivedClass,
1605 MostDerivedClassIsVirtual,
1606 MostDerivedClassOffset);
1608 VisitedVirtualBasesSetTy VBases;
1611 DeterminePrimaryVirtualBases(MostDerivedClass, MostDerivedClassOffset,
1615 LayoutVTablesForVirtualBases(MostDerivedClass, VBases);
1618 bool IsAppleKext = Context.
getLangOpts().AppleKext;
1623 void ItaniumVTableBuilder::LayoutPrimaryAndSecondaryVTables(
1625 bool BaseIsVirtualInLayoutClass,
CharUnits OffsetInLayoutClass) {
1628 unsigned VTableIndex = Components.size();
1629 VTableIndices.push_back(VTableIndex);
1632 VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, LayoutClass, &Overriders,
1633 Base, BaseIsVirtualInLayoutClass,
1634 OffsetInLayoutClass);
1635 Components.append(Builder.components_begin(), Builder.components_end());
1638 if (BaseIsVirtualInLayoutClass && !Builder.getVCallOffsets().empty()) {
1639 VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[Base.
getBase()];
1641 if (VCallOffsets.empty())
1642 VCallOffsets = Builder.getVCallOffsets();
1647 if (Base.
getBase() == MostDerivedClass)
1648 VBaseOffsetOffsets = Builder.getVBaseOffsetOffsets();
1651 CharUnits OffsetToTop = MostDerivedClassOffset - OffsetInLayoutClass;
1657 uint64_t AddressPoint = Components.size();
1660 PrimaryBasesSetVectorTy PrimaryBases;
1661 AddMethods(Base, OffsetInLayoutClass,
1662 Base.
getBase(), OffsetInLayoutClass,
1666 if (RD == MostDerivedClass) {
1667 assert(MethodVTableIndices.empty());
1668 for (
const auto &I : MethodInfoMap) {
1670 const MethodInfo &MI = I.second;
1673 = MI.VTableIndex - AddressPoint;
1675 = MI.VTableIndex + 1 - AddressPoint;
1677 MethodVTableIndices[MD] = MI.VTableIndex - AddressPoint;
1683 ComputeThisAdjustments();
1687 AddressPoints.insert(
1690 unsigned(VTableIndices.size() - 1),
1691 unsigned(AddressPoint - VTableIndex)}));
1706 OffsetInLayoutClass) {
1716 LayoutSecondaryVTables(Base, BaseIsMorallyVirtual, OffsetInLayoutClass);
1720 ItaniumVTableBuilder::LayoutSecondaryVTables(
BaseSubobject Base,
1721 bool BaseIsMorallyVirtual,
1732 for (
const auto &B : RD->
bases()) {
1737 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
1743 if (isBuildingConstructorVTable()) {
1749 if (!BaseIsMorallyVirtual && !BaseDecl->
getNumVBases())
1758 OffsetInLayoutClass + RelativeBaseOffset;
1762 if (BaseDecl == PrimaryBase) {
1764 BaseIsMorallyVirtual, BaseOffsetInLayoutClass);
1769 LayoutPrimaryAndSecondaryVTables(
1771 BaseIsMorallyVirtual,
1773 BaseOffsetInLayoutClass);
1777 void ItaniumVTableBuilder::DeterminePrimaryVirtualBases(
1779 VisitedVirtualBasesSetTy &VBases) {
1787 bool IsPrimaryVirtualBase =
true;
1789 if (isBuildingConstructorVTable()) {
1795 CharUnits PrimaryBaseOffsetInLayoutClass =
1800 if (PrimaryBaseOffsetInLayoutClass != OffsetInLayoutClass)
1801 IsPrimaryVirtualBase =
false;
1804 if (IsPrimaryVirtualBase)
1805 PrimaryVirtualBases.insert(PrimaryBase);
1810 for (
const auto &B : RD->
bases()) {
1811 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
1815 if (B.isVirtual()) {
1816 if (!VBases.insert(BaseDecl).second)
1822 BaseOffsetInLayoutClass =
1825 BaseOffsetInLayoutClass =
1829 DeterminePrimaryVirtualBases(BaseDecl, BaseOffsetInLayoutClass, VBases);
1833 void ItaniumVTableBuilder::LayoutVTablesForVirtualBases(
1834 const CXXRecordDecl *RD, VisitedVirtualBasesSetTy &VBases) {
1839 for (
const auto &B : RD->
bases()) {
1840 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
1845 !PrimaryVirtualBases.count(BaseDecl) &&
1846 VBases.insert(BaseDecl).second) {
1857 LayoutPrimaryAndSecondaryVTables(
1861 BaseOffsetInLayoutClass);
1867 LayoutVTablesForVirtualBases(BaseDecl, VBases);
1872 void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
1876 if (isBuildingConstructorVTable()) {
1877 Out <<
"Construction vtable for ('";
1880 Out << MostDerivedClassOffset.
getQuantity() <<
") in '";
1883 Out <<
"Vtable for '";
1886 Out <<
"' (" << Components.size() <<
" entries).\n";
1892 std::multimap<uint64_t, BaseSubobject> AddressPointsByIndex;
1893 for (
const auto &AP : AddressPoints) {
1896 VTableIndices[AP.second.VTableIndex] + AP.second.AddressPointIndex;
1898 AddressPointsByIndex.insert(std::make_pair(Index, Base));
1901 for (
unsigned I = 0, E = Components.size(); I != E; ++I) {
1904 Out << llvm::format(
"%4d | ", I);
1909 switch (Component.
getKind()) {
1912 Out <<
"vcall_offset (" 1918 Out <<
"vbase_offset (" 1924 Out <<
"offset_to_top (" 1945 Out <<
" [deleted]";
1947 ThunkInfo Thunk = VTableThunks.lookup(I);
1951 Out <<
"\n [return adjustment: ";
1956 Out <<
" vbase offset offset";
1964 Out <<
"\n [this adjustment: ";
1969 Out <<
" vcall offset offset";
1988 Out <<
"() [complete]";
1990 Out <<
"() [deleting]";
1995 ThunkInfo Thunk = VTableThunks.lookup(I);
1999 Out <<
"\n [this adjustment: ";
2004 Out <<
" vcall offset offset";
2020 Out <<
"[unused] " << Str;
2030 uint64_t NextIndex = Index + 1;
2031 if (AddressPointsByIndex.count(NextIndex)) {
2032 if (AddressPointsByIndex.count(NextIndex) == 1) {
2034 AddressPointsByIndex.find(NextIndex)->second;
2039 Out <<
") vtable address --\n";
2042 AddressPointsByIndex.lower_bound(NextIndex)->second.getBaseOffset();
2045 std::set<std::string> ClassNames;
2046 for (
const auto &I :
2047 llvm::make_range(AddressPointsByIndex.equal_range(NextIndex))) {
2048 assert(I.second.getBaseOffset() == BaseOffset &&
2049 "Invalid base offset!");
2051 ClassNames.insert(RD->getQualifiedNameAsString());
2054 for (
const std::string &Name : ClassNames) {
2055 Out <<
" -- (" << Name;
2056 Out <<
", " << BaseOffset.
getQuantity() <<
") vtable address --\n";
2064 if (isBuildingConstructorVTable())
2071 std::map<std::string, CharUnits> ClassNamesAndOffsets;
2072 for (
const auto &I : VBaseOffsetOffsets) {
2073 std::string ClassName = I.first->getQualifiedNameAsString();
2075 ClassNamesAndOffsets.insert(std::make_pair(ClassName, OffsetOffset));
2078 Out <<
"Virtual base offset offsets for '";
2081 Out << ClassNamesAndOffsets.size();
2082 Out << (ClassNamesAndOffsets.size() == 1 ?
" entry" :
" entries") <<
").\n";
2084 for (
const auto &I : ClassNamesAndOffsets)
2085 Out <<
" " << I.first <<
" | " << I.second.getQuantity() <<
'\n';
2090 if (!Thunks.empty()) {
2092 std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls;
2094 for (
const auto &I : Thunks) {
2096 std::string MethodName =
2100 MethodNamesAndDecls.insert(std::make_pair(MethodName, MD));
2103 for (
const auto &I : MethodNamesAndDecls) {
2104 const std::string &MethodName = I.first;
2107 ThunkInfoVectorTy ThunksVector = Thunks[MD];
2108 std::sort(ThunksVector.begin(), ThunksVector.end(),
2110 assert(LHS.
Method ==
nullptr && RHS.Method ==
nullptr);
2111 return std::tie(LHS.
This, LHS.
Return) < std::tie(RHS.This, RHS.Return);
2114 Out <<
"Thunks for '" << MethodName <<
"' (" << ThunksVector.size();
2115 Out << (ThunksVector.size() == 1 ?
" entry" :
" entries") <<
").\n";
2117 for (
unsigned I = 0, E = ThunksVector.size(); I != E; ++I) {
2118 const ThunkInfo &Thunk = ThunksVector[I];
2120 Out << llvm::format(
"%4d | ", I);
2125 Out <<
" non-virtual";
2128 Out <<
" vbase offset offset";
2137 Out <<
"this adjustment: ";
2142 Out <<
" vcall offset offset";
2155 std::map<uint64_t, std::string> IndicesMap;
2157 for (
const auto *MD : MostDerivedClass->
methods()) {
2163 std::string MethodName =
2169 assert(MethodVTableIndices.count(GD));
2170 uint64_t VTableIndex = MethodVTableIndices[GD];
2171 IndicesMap[VTableIndex] = MethodName +
" [complete]";
2172 IndicesMap[VTableIndex + 1] = MethodName +
" [deleting]";
2174 assert(MethodVTableIndices.count(MD));
2175 IndicesMap[MethodVTableIndices[MD]] = MethodName;
2180 if (!IndicesMap.empty()) {
2181 Out <<
"VTable indices for '";
2183 Out <<
"' (" << IndicesMap.size() <<
" entries).\n";
2185 for (
const auto &I : IndicesMap) {
2186 uint64_t VTableIndex = I.first;
2187 const std::string &MethodName = I.second;
2189 Out << llvm::format(
"%4" PRIu64
" | ", VTableIndex) << MethodName
2202 : VTableComponents(VTableComponents), VTableThunks(VTableThunks),
2203 AddressPoints(AddressPoints) {
2204 if (VTableIndices.size() <= 1)
2205 assert(VTableIndices.size() == 1 && VTableIndices[0] == 0);
2209 std::sort(this->VTableThunks.begin(), this->VTableThunks.end(),
2212 assert((LHS.first != RHS.first || LHS.second == RHS.second) &&
2213 "Different thunks should have unique indices!");
2214 return LHS.first < RHS.first;
2226 MethodVTableIndicesTy::iterator I = MethodVTableIndices.find(GD);
2227 if (I != MethodVTableIndices.end())
2232 computeVTableRelatedInformation(RD);
2234 I = MethodVTableIndices.find(GD);
2235 assert(I != MethodVTableIndices.end() &&
"Did not find index!");
2242 ClassPairTy ClassPair(RD, VBase);
2244 VirtualBaseClassOffsetOffsetsMapTy::iterator I =
2245 VirtualBaseClassOffsetOffsets.find(ClassPair);
2246 if (I != VirtualBaseClassOffsetOffsets.end())
2249 VCallAndVBaseOffsetBuilder Builder(RD, RD,
nullptr,
2254 for (
const auto &I : Builder.getVBaseOffsetOffsets()) {
2256 ClassPairTy ClassPair(RD, I.first);
2258 VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I.second));
2261 I = VirtualBaseClassOffsetOffsets.find(ClassPair);
2262 assert(I != VirtualBaseClassOffsetOffsets.end() &&
"Did not find index!");
2267 static std::unique_ptr<VTableLayout>
2270 VTableThunks(Builder.vtable_thunks_begin(), Builder.vtable_thunks_end());
2272 return llvm::make_unique<VTableLayout>(
2273 Builder.VTableIndices, Builder.vtable_components(), VTableThunks,
2274 Builder.getAddressPoints());
2278 ItaniumVTableContext::computeVTableRelatedInformation(
const CXXRecordDecl *RD) {
2279 std::unique_ptr<const VTableLayout> &Entry = VTableLayouts[RD];
2289 MethodVTableIndices.insert(Builder.vtable_indices_begin(),
2290 Builder.vtable_indices_end());
2293 Thunks.insert(Builder.thunks_begin(), Builder.thunks_end());
2304 if (VirtualBaseClassOffsetOffsets.count(std::make_pair(RD, VBase)))
2307 for (
const auto &I : Builder.getVBaseOffsetOffsets()) {
2309 ClassPairTy ClassPair(RD, I.first);
2311 VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I.second));
2315 std::unique_ptr<VTableLayout>
2318 bool MostDerivedClassIsVirtual,
const CXXRecordDecl *LayoutClass) {
2319 ItaniumVTableBuilder Builder(*
this, MostDerivedClass, MostDerivedClassOffset,
2320 MostDerivedClassIsVirtual, LayoutClass);
2368 class VFTableBuilder {
2372 typedef llvm::DenseMap<GlobalDecl, MethodVFTableLocation>
2373 MethodVFTableLocationsTy;
2375 typedef llvm::iterator_range<MethodVFTableLocationsTy::const_iterator>
2376 method_locations_range;
2394 const FinalOverriders Overriders;
2399 MethodVFTableLocationsTy MethodVFTableLocations;
2402 bool HasRTTIComponent =
false;
2409 const uint64_t VBTableIndex;
2412 const uint64_t VFTableIndex;
2423 MethodInfo(uint64_t VBTableIndex, uint64_t VFTableIndex,
2424 bool UsesExtraSlot =
false)
2425 : VBTableIndex(VBTableIndex), VFTableIndex(VFTableIndex),
2426 Shadowed(
false), UsesExtraSlot(UsesExtraSlot) {}
2429 : VBTableIndex(0), VFTableIndex(0), Shadowed(
false),
2430 UsesExtraSlot(
false) {}
2433 typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy;
2437 MethodInfoMapTy MethodInfoMap;
2439 typedef llvm::DenseMap<uint64_t, ThunkInfo> VTableThunksMapTy;
2443 VTableThunksMapTy VTableThunks;
2446 typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy>
ThunksMapTy;
2457 if (std::find(ThunksVector.begin(), ThunksVector.end(), Thunk) !=
2461 ThunksVector.push_back(Thunk);
2466 CharUnits ComputeThisOffset(FinalOverriders::OverriderInfo Overrider);
2468 void CalculateVtordispAdjustment(FinalOverriders::OverriderInfo Overrider,
2475 VTableThunks[Components.size()] = TI;
2480 "Destructor can't have return adjustment!");
2491 BasesSetVectorTy &VisitedBases);
2493 void LayoutVFTable() {
2495 if (HasRTTIComponent)
2498 BasesSetVectorTy VisitedBases;
2501 assert((HasRTTIComponent ? Components.size() - 1 : Components.size()) &&
2502 "vftable can't be empty");
2504 assert(MethodVFTableLocations.empty());
2505 for (
const auto &I : MethodInfoMap) {
2507 const MethodInfo &MI = I.second;
2510 if (MD->
getParent() != MostDerivedClass || MI.Shadowed)
2517 MethodVFTableLocations[MD] = Loc;
2527 MostDerivedClass(MostDerivedClass),
2530 Overriders(MostDerivedClass,
CharUnits(), MostDerivedClass) {
2537 HasRTTIComponent =
true;
2542 dumpLayout(llvm::outs());
2545 uint64_t getNumThunks()
const {
return Thunks.size(); }
2547 ThunksMapTy::const_iterator thunks_begin()
const {
return Thunks.begin(); }
2549 ThunksMapTy::const_iterator thunks_end()
const {
return Thunks.end(); }
2551 method_locations_range vtable_locations()
const {
2552 return method_locations_range(MethodVFTableLocations.begin(),
2553 MethodVFTableLocations.end());
2558 VTableThunksMapTy::const_iterator vtable_thunks_begin()
const {
2559 return VTableThunks.begin();
2562 VTableThunksMapTy::const_iterator vtable_thunks_end()
const {
2563 return VTableThunks.end();
2566 void dumpLayout(raw_ostream &);
2626 VFTableBuilder::ComputeThisOffset(FinalOverriders::OverriderInfo Overrider) {
2627 BasesSetVectorTy Bases;
2631 OverriddenMethodsSetTy VisitedOverriddenMethods;
2632 auto InitialOverriddenDefinitionCollector = [&](
2634 if (OverriddenMD->size_overridden_methods() == 0)
2635 Bases.insert(OverriddenMD->getParent());
2637 return VisitedOverriddenMethods.insert(OverriddenMD).second;
2639 visitAllOverriddenMethods(Overrider.Method,
2640 InitialOverriddenDefinitionCollector);
2645 if (Bases.size() == 0)
2646 return Overrider.Offset;
2649 Overrider.Method->getParent()->lookupInBases(
2665 CharUnits ThisOffset = Overrider.Offset;
2672 QualType CurTy = Element.Base->getType();
2677 if (Element.Base->isVirtual()) {
2688 LastVBaseOffset = ThisOffset =
2695 if (isa<CXXDestructorDecl>(Overrider.Method)) {
2696 if (LastVBaseOffset.
isZero()) {
2700 ThisOffset = Overrider.Offset;
2704 ThisOffset = LastVBaseOffset;
2708 if (Ret > ThisOffset || First) {
2714 assert(!First &&
"Method not found in the given subobject?");
2816 void VFTableBuilder::CalculateVtordispAdjustment(
2817 FinalOverriders::OverriderInfo Overrider,
CharUnits ThisOffset,
2820 MostDerivedClassLayout.getVBaseOffsetsMap();
2821 const ASTRecordLayout::VBaseOffsetsMapTy::const_iterator &VBaseMapEntry =
2822 VBaseMap.find(WhichVFPtr.getVBaseWithVPtr());
2823 assert(VBaseMapEntry != VBaseMap.end());
2827 if (!VBaseMapEntry->second.hasVtorDisp() ||
2828 Overrider.VirtualBase == WhichVFPtr.getVBaseWithVPtr())
2833 CharUnits OffsetOfVBaseWithVFPtr = VBaseMapEntry->second.VBaseOffset;
2835 (OffsetOfVBaseWithVFPtr - WhichVFPtr.FullOffsetInMDC).getQuantity() - 4;
2839 if (Overrider.Method->getParent() == MostDerivedClass ||
2840 !Overrider.VirtualBase)
2846 (OffsetOfVBaseWithVFPtr + WhichVFPtr.NonVirtualOffset -
2847 MostDerivedClassLayout.getVBPtrOffset()).getQuantity();
2850 VTables.getVBTableIndex(MostDerivedClass, Overrider.VirtualBase);
2852 TA.
NonVirtual = (ThisOffset - Overrider.Offset).getQuantity();
2866 typedef llvm::DenseMap<DeclarationName, unsigned> VisitedGroupIndicesTy;
2867 VisitedGroupIndicesTy VisitedGroupIndices;
2868 for (
const auto *D : RD->
decls()) {
2869 const auto *ND = dyn_cast<
NamedDecl>(D);
2872 VisitedGroupIndicesTy::iterator J;
2874 std::tie(J, Inserted) = VisitedGroupIndices.insert(
2875 std::make_pair(ND->getDeclName(), Groups.size()));
2877 Groups.push_back(MethodGroup());
2878 if (
const auto *MD = dyn_cast<CXXMethodDecl>(ND))
2879 if (MD->isVirtual())
2880 Groups[J->second].push_back(MD->getCanonicalDecl());
2883 for (
const MethodGroup &Group : Groups)
2884 VirtualMethods.append(Group.rbegin(), Group.rend());
2888 for (
const auto &B : RD->
bases()) {
2889 if (B.isVirtual() && B.getType()->getAsCXXRecordDecl() == Base)
2897 BasesSetVectorTy &VisitedBases) {
2907 const CXXRecordDecl *NextBase =
nullptr, *NextLastVBase = LastVBase;
2909 if (BaseDepth < WhichVFPtr.PathToIntroducingObject.size()) {
2910 NextBase = WhichVFPtr.PathToIntroducingObject[BaseDepth];
2912 NextLastVBase = NextBase;
2913 NextBaseOffset = MostDerivedClassLayout.getVBaseClassOffset(NextBase);
2920 "No primary virtual bases in this ABI");
2921 NextBase = PrimaryBase;
2926 AddMethods(
BaseSubobject(NextBase, NextBaseOffset), BaseDepth + 1,
2927 NextLastVBase, VisitedBases);
2928 if (!VisitedBases.insert(NextBase))
2929 llvm_unreachable(
"Found a duplicate primary base!");
2945 FinalOverriders::OverriderInfo FinalOverrider =
2947 const CXXMethodDecl *FinalOverriderMD = FinalOverrider.Method;
2949 FindNearestOverriddenMethod(MD, VisitedBases);
2952 bool ReturnAdjustingThunk =
false, ForceReturnAdjustmentMangling =
false;
2953 CharUnits ThisOffset = ComputeThisOffset(FinalOverrider);
2955 (ThisOffset - WhichVFPtr.FullOffsetInMDC).getQuantity();
2956 if ((OverriddenMD || FinalOverriderMD != MD) &&
2957 WhichVFPtr.getVBaseWithVPtr())
2958 CalculateVtordispAdjustment(FinalOverrider, ThisOffset,
2959 ThisAdjustmentOffset);
2962 LastVBase ? VTables.getVBTableIndex(MostDerivedClass, LastVBase) : 0;
2967 MethodInfoMapTy::iterator OverriddenMDIterator =
2968 MethodInfoMap.find(OverriddenMD);
2971 if (OverriddenMDIterator == MethodInfoMap.end())
2974 MethodInfo &OverriddenMethodInfo = OverriddenMDIterator->second;
2976 VBIndex = OverriddenMethodInfo.VBTableIndex;
2983 ReturnAdjustingThunk = !ComputeReturnAdjustmentBaseOffset(
2984 Context, MD, OverriddenMD).isEmpty() ||
2985 OverriddenMethodInfo.UsesExtraSlot;
2987 if (!ReturnAdjustingThunk) {
2990 MethodInfo MI(VBIndex, OverriddenMethodInfo.VFTableIndex);
2991 MethodInfoMap.erase(OverriddenMDIterator);
2993 assert(!MethodInfoMap.count(MD) &&
2994 "Should not have method info for this method yet!");
2995 MethodInfoMap.insert(std::make_pair(MD, MI));
3001 OverriddenMethodInfo.Shadowed =
true;
3005 ForceReturnAdjustmentMangling =
3006 !(MD == FinalOverriderMD && ThisAdjustmentOffset.
isEmpty());
3007 }
else if (Base.
getBaseOffset() != WhichVFPtr.FullOffsetInMDC ||
3008 MD->size_overridden_methods()) {
3017 MethodInfo MI(VBIndex,
3018 HasRTTIComponent ? Components.size() - 1 : Components.size(),
3019 ReturnAdjustingThunk);
3021 assert(!MethodInfoMap.count(MD) &&
3022 "Should not have method info for this method yet!");
3023 MethodInfoMap.insert(std::make_pair(MD, MI));
3027 BaseOffset ReturnAdjustmentOffset;
3029 if (!FinalOverriderMD->
isPure()) {
3030 ReturnAdjustmentOffset =
3031 ComputeReturnAdjustmentBaseOffset(Context, FinalOverriderMD, MD);
3033 if (!ReturnAdjustmentOffset.isEmpty()) {
3034 ForceReturnAdjustmentMangling =
true;
3036 ReturnAdjustmentOffset.NonVirtualOffset.getQuantity();
3037 if (ReturnAdjustmentOffset.VirtualBase) {
3043 VTables.getVBTableIndex(ReturnAdjustmentOffset.DerivedClass,
3044 ReturnAdjustmentOffset.VirtualBase);
3048 AddMethod(FinalOverriderMD,
3049 ThunkInfo(ThisAdjustmentOffset, ReturnAdjustment,
3050 ForceReturnAdjustmentMangling ? MD :
nullptr));
3056 llvm::make_range(Path.rbegin(), Path.rend())) {
3058 Elem->printQualifiedName(Out);
3064 bool ContinueFirstLine) {
3066 bool Multiline =
false;
3067 const char *LinePrefix =
"\n ";
3069 if (!ContinueFirstLine)
3071 Out <<
"[return adjustment (to type '" 3084 if (Multiline || !ContinueFirstLine)
3086 Out <<
"[this adjustment: ";
3094 Out << LinePrefix <<
" vboffset at " 3102 void VFTableBuilder::dumpLayout(raw_ostream &Out) {
3103 Out <<
"VFTable for ";
3106 MostDerivedClass->printQualifiedName(Out);
3107 Out <<
"' (" << Components.size()
3108 << (Components.size() == 1 ?
" entry" :
" entries") <<
").\n";
3110 for (
unsigned I = 0, E = Components.size(); I != E; ++I) {
3111 Out << llvm::format(
"%4d | ", I);
3116 switch (Component.
getKind()) {
3134 Out <<
" [deleted]";
3136 ThunkInfo Thunk = VTableThunks.lookup(I);
3147 Out <<
"() [scalar deleting]";
3152 ThunkInfo Thunk = VTableThunks.lookup(I);
3155 "No return adjustment needed for destructors!");
3166 "Unexpected vftable component type %0 for component number %1");
3167 Diags.
Report(MostDerivedClass->getLocation(), DiagID)
3178 std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls;
3180 for (
const auto &I :
Thunks) {
3185 MethodNamesAndDecls.insert(std::make_pair(MethodName, MD));
3188 for (
const auto &MethodNameAndDecl : MethodNamesAndDecls) {
3189 const std::string &MethodName = MethodNameAndDecl.first;
3193 std::stable_sort(ThunksVector.begin(), ThunksVector.end(),
3197 return std::tie(LHS.
This, LHS.
Return) < std::tie(RHS.This, RHS.Return);
3200 Out <<
"Thunks for '" << MethodName <<
"' (" << ThunksVector.size();
3201 Out << (ThunksVector.size() == 1 ?
" entry" :
" entries") <<
").\n";
3203 for (
unsigned I = 0, E = ThunksVector.size(); I != E; ++I) {
3204 const ThunkInfo &Thunk = ThunksVector[I];
3206 Out << llvm::format(
"%4d | ", I);
3250 void MicrosoftVTableContext::computeVTablePaths(
bool ForVBTables,
3253 assert(Paths.empty());
3257 if (ForVBTables ? Layout.hasOwnVBPtr() : Layout.hasOwnVFPtr())
3258 Paths.push_back(llvm::make_unique<VPtrInfo>(RD));
3262 llvm::SmallPtrSet<const CXXRecordDecl*, 4> VBasesSeen;
3263 for (
const auto &B : RD->
bases()) {
3264 const CXXRecordDecl *Base = B.getType()->getAsCXXRecordDecl();
3265 if (B.isVirtual() && VBasesSeen.count(Base))
3272 ForVBTables ? enumerateVBTables(Base) : getVFPtrOffsets(Base);
3274 for (
const std::unique_ptr<VPtrInfo> &BaseInfo : BasePaths) {
3281 auto P = llvm::make_unique<VPtrInfo>(*BaseInfo);
3285 if (
P->MangledPath.empty() ||
P->MangledPath.back() != Base)
3286 P->NextBaseToMangle = Base;
3291 if (
P->ObjectWithVPtr == Base &&
3292 Base == (ForVBTables ? Layout.getBaseSharingVBPtr()
3293 : Layout.getPrimaryBase()))
3294 P->ObjectWithVPtr = RD;
3299 P->ContainingVBases.push_back(Base);
3300 else if (
P->ContainingVBases.empty())
3301 P->NonVirtualOffset += Layout.getBaseClassOffset(Base);
3304 P->FullOffsetInMDC =
P->NonVirtualOffset;
3306 P->FullOffsetInMDC += Layout.getVBaseClassOffset(VB);
3308 Paths.push_back(std::move(
P));
3312 VBasesSeen.insert(Base);
3316 for (
const auto &VB : Base->
vbases())
3317 VBasesSeen.insert(VB.getType()->getAsCXXRecordDecl());
3322 bool Changed =
true;
3344 PathsSorted.reserve(Paths.size());
3345 for (
auto&
P : Paths)
3346 PathsSorted.push_back(*
P);
3347 std::sort(PathsSorted.begin(), PathsSorted.end(),
3351 bool Changed =
false;
3352 for (
size_t I = 0, E = PathsSorted.size(); I != E;) {
3354 size_t BucketStart = I;
3358 PathsSorted[BucketStart].
get().MangledPath ==
3359 PathsSorted[I].get().MangledPath);
3362 if (I - BucketStart > 1) {
3363 for (
size_t II = BucketStart; II != I; ++II)
3365 assert(Changed &&
"no paths were extended to fix ambiguity");
3374 typedef llvm::SetVector<BaseSubobject, std::vector<BaseSubobject>,
3384 FullPathTy &FullPath,
3385 std::list<FullPathTy> &Paths) {
3387 Paths.push_back(FullPath);
3394 const CXXRecordDecl *Base = BS.getType()->getAsCXXRecordDecl();
3400 IntroducingObject, FullPath, Paths);
3401 FullPath.pop_back();
3407 FullPaths.remove_if([&](
const FullPathTy &SpecificPath) {
3408 for (
const FullPathTy &OtherPath : FullPaths) {
3409 if (&SpecificPath == &OtherPath)
3411 if (std::all_of(SpecificPath.begin(), SpecificPath.end(),
3413 return OtherPath.count(BSO) != 0;
3424 const FullPathTy &FullPath) {
3445 : Offset + Layout.getBaseClassOffset(Base);
3457 std::list<FullPathTy> &FullPaths) {
3459 if (FullPaths.empty())
3461 if (FullPaths.size() == 1)
3462 return &FullPaths.front();
3464 const FullPathTy *BestPath =
nullptr;
3465 typedef std::set<const CXXMethodDecl *> OverriderSetTy;
3466 OverriderSetTy LastOverrides;
3467 for (
const FullPathTy &SpecificPath : FullPaths) {
3468 assert(!SpecificPath.empty());
3469 OverriderSetTy CurrentOverrides;
3470 const CXXRecordDecl *TopLevelRD = SpecificPath.begin()->getBase();
3475 FinalOverriders Overriders(TopLevelRD,
CharUnits::Zero(), TopLevelRD);
3477 if (!MD->isVirtual())
3479 FinalOverriders::OverriderInfo OI =
3480 Overriders.getOverrider(MD->getCanonicalDecl(), BaseOffset);
3484 if (ComputeReturnAdjustmentBaseOffset(Context, OverridingMethod, MD)
3490 if (std::none_of(SpecificPath.begin(), SpecificPath.end(),
3492 return BSO.getBase() == OverridingParent;
3495 CurrentOverrides.insert(OverridingMethod);
3497 OverriderSetTy NewOverrides =
3498 llvm::set_difference(CurrentOverrides, LastOverrides);
3499 if (NewOverrides.empty())
3501 OverriderSetTy MissingOverrides =
3502 llvm::set_difference(LastOverrides, CurrentOverrides);
3503 if (MissingOverrides.empty()) {
3505 BestPath = &SpecificPath;
3506 std::swap(CurrentOverrides, LastOverrides);
3511 const CXXMethodDecl *ConflictMD = *MissingOverrides.begin();
3522 return BestPath ? BestPath : &FullPaths.front();
3529 FullPathTy FullPath;
3530 std::list<FullPathTy> FullPaths;
3531 for (
const std::unique_ptr<VPtrInfo>& Info : Paths) {
3534 BaseSubobject(Info->IntroducingObject, Info->FullOffsetInMDC), FullPath,
3538 Info->PathToIntroducingObject.clear();
3539 if (
const FullPathTy *BestPath =
3542 Info->PathToIntroducingObject.push_back(BSO.getBase());
3547 void MicrosoftVTableContext::computeVTableRelatedInformation(
3552 if (VFPtrLocations.count(RD))
3559 computeVTablePaths(
false, RD, VFPtrs);
3561 VFPtrLocations[RD] = std::move(VFPtrs);
3564 MethodVFTableLocationsTy NewMethodLocations;
3565 for (
const std::unique_ptr<VPtrInfo> &VFPtr : VFPtrLocations[RD]) {
3566 VFTableBuilder Builder(*
this, RD, *VFPtr);
3568 VFTableIdTy
id(RD, VFPtr->FullOffsetInMDC);
3569 assert(VFTableLayouts.count(
id) == 0);
3571 Builder.vtable_thunks_begin(), Builder.vtable_thunks_end());
3572 VFTableLayouts[
id] = llvm::make_unique<VTableLayout>(
3574 EmptyAddressPointsMap);
3575 Thunks.insert(Builder.thunks_begin(), Builder.thunks_end());
3577 for (
const auto &Loc : Builder.vtable_locations()) {
3579 MethodVFTableLocation NewLoc = Loc.second;
3580 auto M = NewMethodLocations.find(GD);
3581 if (M == NewMethodLocations.end() || NewLoc < M->second)
3582 NewMethodLocations[GD] = NewLoc;
3586 MethodVFTableLocations.insert(NewMethodLocations.begin(),
3587 NewMethodLocations.end());
3589 dumpMethodLocations(RD, NewMethodLocations, llvm::outs());
3592 void MicrosoftVTableContext::dumpMethodLocations(
3593 const CXXRecordDecl *RD,
const MethodVFTableLocationsTy &NewMethods,
3597 std::map<MethodVFTableLocation, std::string> IndicesMap;
3598 bool HasNonzeroOffset =
false;
3600 for (
const auto &I : NewMethods) {
3601 const CXXMethodDecl *MD = cast<const CXXMethodDecl>(I.first.getDecl());
3607 if (isa<CXXDestructorDecl>(MD)) {
3608 IndicesMap[I.second] = MethodName +
" [scalar deleting]";
3610 IndicesMap[I.second] = MethodName;
3613 if (!I.second.VFPtrOffset.isZero() || I.second.VBTableIndex != 0)
3614 HasNonzeroOffset =
true;
3618 if (!IndicesMap.empty()) {
3619 Out <<
"VFTable indices for ";
3622 Out <<
"' (" << IndicesMap.size()
3623 << (IndicesMap.size() == 1 ?
" entry" :
" entries") <<
").\n";
3626 uint64_t LastVBIndex = 0;
3627 for (
const auto &I : IndicesMap) {
3628 CharUnits VFPtrOffset = I.first.VFPtrOffset;
3629 uint64_t VBIndex = I.first.VBTableIndex;
3630 if (HasNonzeroOffset &&
3631 (VFPtrOffset != LastVFPtrOffset || VBIndex != LastVBIndex)) {
3632 assert(VBIndex > LastVBIndex || VFPtrOffset > LastVFPtrOffset);
3633 Out <<
" -- accessible via ";
3635 Out <<
"vbtable index " << VBIndex <<
", ";
3636 Out <<
"vfptr at offset " << VFPtrOffset.
getQuantity() <<
" --\n";
3637 LastVFPtrOffset = VFPtrOffset;
3638 LastVBIndex = VBIndex;
3641 uint64_t VTableIndex = I.first.Index;
3642 const std::string &MethodName = I.second;
3643 Out << llvm::format(
"%4" PRIu64
" | ", VTableIndex) << MethodName <<
'\n';
3651 const VirtualBaseInfo &MicrosoftVTableContext::computeVBTableRelatedInformation(
3658 std::unique_ptr<VirtualBaseInfo> &Entry = VBaseInfo[RD];
3661 Entry = llvm::make_unique<VirtualBaseInfo>();
3665 computeVTablePaths(
true, RD, VBI->
VBPtrPaths);
3673 computeVBTableRelatedInformation(VBPtrBase);
3681 for (
const auto &VB : RD->
vbases()) {
3682 const CXXRecordDecl *CurVBase = VB.getType()->getAsCXXRecordDecl();
3692 const VirtualBaseInfo &VBInfo = computeVBTableRelatedInformation(Derived);
3699 return computeVBTableRelatedInformation(RD).VBPtrPaths;
3704 computeVTableRelatedInformation(RD);
3706 assert(VFPtrLocations.count(RD) &&
"Couldn't find vfptr locations");
3707 return VFPtrLocations[RD];
3713 computeVTableRelatedInformation(RD);
3715 VFTableIdTy
id(RD, VFPtrOffset);
3716 assert(VFTableLayouts.count(
id) &&
"Couldn't find a VFTable at this offset");
3717 return *VFTableLayouts[
id];
3722 assert(cast<CXXMethodDecl>(GD.
getDecl())->isVirtual() &&
3723 "Only use this method for virtual methods or dtors");
3724 if (isa<CXXDestructorDecl>(GD.
getDecl()))
3727 MethodVFTableLocationsTy::iterator I = MethodVFTableLocations.find(GD);
3728 if (I != MethodVFTableLocations.end())
3733 computeVTableRelatedInformation(RD);
3735 I = MethodVFTableLocations.find(GD);
3736 assert(I != MethodVFTableLocations.end() &&
"Did not find index!");
Defines the clang::ASTContext interface.
static std::string ComputeName(IdentType IT, const Decl *CurrentDecl)
struct clang::ThisAdjustment::VirtualAdjustment::@119 Microsoft
if(T->getSizeExpr()) TRY_TO(TraverseStmt(T -> getSizeExpr()))
PointerType - C99 6.7.5.1 - Pointer Declarators.
bool isPrimaryBaseVirtual() const
isPrimaryBaseVirtual - Get whether the primary base for this record is virtual or not...
A (possibly-)qualified type.
uint32_t VBPtrOffset
The offset (in bytes) of the vbptr, relative to the beginning of the derived class.
CXXDtorType getDtorType() const
ItaniumVTableContext(ASTContext &Context)
static VTableComponent MakeRTTI(const CXXRecordDecl *RD)
const CXXMethodDecl * getFunctionDecl() const
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D...
FunctionType - C99 6.7.5.3 - Function Declarators.
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
VPtrInfoVector VBPtrPaths
Information on all virtual base tables used when this record is the most derived class.
Decl - This represents one declaration (or definition), e.g.
bool isVirtual() const
Determines whether the base class is a virtual base class (or not).
int64_t NonVirtual
The non-virtual adjustment from the derived object to its nearest virtual base.
CanQual< T > getUnqualifiedType() const
Retrieve the unqualified form of this type.
DiagnosticsEngine & getDiagnostics() const
bool isDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is derived from the class Base.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
bool isZero() const
isZero - Test whether the quantity equals zero.
const TargetInfo & getTargetInfo() const
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)
const CXXMethodDecl * getUnusedFunctionDecl() const
QualType getReturnType() const
const T * getAs() const
Member-template getAs<specific type>'.
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
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...
CharUnits getBaseOffset() const
getBaseOffset - Returns the base class offset.
uint64_t getPointerWidth(unsigned AddrSpace) const
Return the width of pointers on this target, for the specified address space.
int32_t VBOffsetOffset
The offset (in bytes) of the vbase offset in the vbtable.
DeclarationName getDeclName() const
getDeclName - Get the actual, stored name of the declaration, which may be a special name...
TargetCXXABI getCXXABI() const
Get the C++ ABI currently in use.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
ArrayRef< QualType > getParamTypes() const
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...
CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const
getVBaseClassOffset - Get the offset, in chars, for the given base class.
The this pointer adjustment as well as an optional return adjustment for a thunk. ...
const CXXRecordDecl * NextBaseToMangle
The next base to push onto the mangled path if this path is ambiguous in a derived class...
unsigned getTypeQuals() const
~ItaniumVTableContext() override
The set of methods that override a given virtual method in each subobject where it occurs...
CharUnits - This is an opaque type for sizes expressed in character units.
llvm::DenseMap< const CXXMethodDecl *, ThunkInfoVectorTy > ThunksMapTy
~MicrosoftVTableContext() override
static void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef< CounterExpression > Expressions, ArrayRef< CounterMappingRegion > Regions)
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)
base_class_iterator bases_begin()
static void removeRedundantPaths(std::list< FullPathTy > &FullPaths)
uint64_t getMethodVTableIndex(GlobalDecl GD)
Locate a virtual function in the vtable.
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 bool setsIntersect(const llvm::SmallPtrSet< const CXXRecordDecl *, 4 > &A, ArrayRef< const CXXRecordDecl *> B)
static VTableComponent MakeDeletingDtor(const CXXDestructorDecl *DD)
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Represents a prototype with parameter type info, e.g.
bool isDynamicClass() const
union clang::ReturnAdjustment::VirtualAdjustment Virtual
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
static void GroupNewVirtualOverloads(const CXXRecordDecl *RD, SmallVector< const CXXMethodDecl *, 10 > &VirtualMethods)
SmallVector< ThunkInfo, 1 > ThunkInfoVectorTy
const FunctionProtoType * T
Kind getKind() const
Get the kind of this vtable component.
void getFinalOverriders(CXXFinalOverriderMap &FinaOverriders) const
Retrieve the final overriders for each virtual member function in the class hierarchy where this clas...
Represents a C++ destructor within a class.
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
overridden_method_range overridden_methods() const
CharUnits getOffsetToTop() const
CharUnits getVCallOffset() const
const CXXRecordDecl * getPrimaryBase() const
getPrimaryBase - Get the primary base for this record.
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)
const CXXRecordDecl * getBase() const
getBase - Returns the base class declaration.
bool isPolymorphic() const
Whether this class is polymorphic (C++ [class.virtual]), which means that the class contains or inher...
DeclContext * getParent()
getParent - Returns the containing DeclContext.
const CXXDestructorDecl * getDestructorDecl() const
Uniquely identifies a virtual method within a class hierarchy by the method itself and a class subobj...
CharUnits getVBPtrOffset() const
getVBPtrOffset - Get the offset for virtual base table pointer.
struct clang::ThisAdjustment::VirtualAdjustment::@118 Itanium
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.
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 ...
QualType getCanonicalType() const
static bool rebucketPaths(VPtrInfoVector &Paths)
std::unique_ptr< VTableLayout > createConstructionVTableLayout(const CXXRecordDecl *MostDerivedClass, CharUnits MostDerivedClassOffset, bool MostDerivedClassIsVirtual, const CXXRecordDecl *LayoutClass)
QualType getReturnType() const
bool isPure() const
Whether this virtual function is pure, i.e.
static void dumpMicrosoftThunkAdjustment(const ThunkInfo &TI, raw_ostream &Out, bool ContinueFirstLine)
ASTContext & getASTContext() const LLVM_READONLY
const Decl * getDecl() 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)
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. ...
const CXXRecordDecl * getRTTIDecl() const
CanProxy< U > getAs() const
Retrieve a canonical type pointer with a different static type, upcasting or downcasting as needed...
static VTableComponent MakeVBaseOffset(CharUnits Offset)
Represents an element in a path from a derived class to a base class.
Dataflow Directional Tag Classes.
ThisAdjustment This
The this pointer adjustment.
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.
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
const CXXRecordDecl * getParent() const
Returns the parent of this method declaration, which is the class in which this method is defined...
const CXXRecordDecl * getBaseSharingVBPtr() const
A mapping from each virtual member function to its set of final overriders.
static CharUnits getOffsetOfFullPath(ASTContext &Context, const CXXRecordDecl *RD, const FullPathTy &FullPath)
int64_t VBaseOffsetOffset
The offset (in bytes), relative to the address point of the virtual base class offset.
CharUnits NonVirtualOffset
IntroducingObject is at this offset from its containing complete object or virtual base...
base_class_iterator vbases_begin()
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 CXXRecordDecl * getVBaseWithVPtr() const
The vptr is stored inside the non-virtual component of this virtual base.
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.
Represents a base class of a C++ class.
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
llvm::DenseMap< BaseSubobject, AddressPointLocation > AddressPointsMapTy
Represents a C++ struct/union/class.
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
llvm::DenseMap< const CXXRecordDecl *, VBaseInfo > VBaseOffsetsMapTy
Defines the clang::TargetInfo interface.
bool isMicrosoft() const
Is this ABI an MSVC-compatible ABI?
A pointer to the deleting destructor.
static Decl::Kind getKind(const Decl *D)
static VTableComponent MakeFunction(const CXXMethodDecl *MD)
bool isDeleted() const
Whether this function has been deleted.
Holds information about the inheritance path to a virtual base or function table pointer.
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
uint32_t VBIndex
Index of the virtual base in the vbtable.
NamedDecl - This represents a decl with a name.
CharUnits getVBaseOffset() const
static void computeFullPathsForVFTables(ASTContext &Context, const CXXRecordDecl *RD, VPtrInfoVector &Paths)
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...
const LangOptions & getLangOpts() const
base_class_range vbases()
A pointer to the complete destructor.
An entry that is never used.
const MethodVFTableLocation & getMethodVFTableLocation(GlobalDecl GD)
SourceLocation getLocation() const
method_range methods() const
QualType getType() const
Retrieves the type of the base class.
static VTableComponent MakeOffsetToTop(CharUnits Offset)