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 llvm::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 llvm::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;
2227 MethodVTableIndicesTy::iterator I = MethodVTableIndices.find(GD);
2228 if (I != MethodVTableIndices.end())
2233 computeVTableRelatedInformation(RD);
2235 I = MethodVTableIndices.find(GD);
2236 assert(I != MethodVTableIndices.end() &&
"Did not find index!");
2243 ClassPairTy ClassPair(RD, VBase);
2245 VirtualBaseClassOffsetOffsetsMapTy::iterator I =
2246 VirtualBaseClassOffsetOffsets.find(ClassPair);
2247 if (I != VirtualBaseClassOffsetOffsets.end())
2250 VCallAndVBaseOffsetBuilder Builder(RD, RD,
nullptr,
2255 for (
const auto &I : Builder.getVBaseOffsetOffsets()) {
2257 ClassPairTy ClassPair(RD, I.first);
2259 VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I.second));
2262 I = VirtualBaseClassOffsetOffsets.find(ClassPair);
2263 assert(I != VirtualBaseClassOffsetOffsets.end() &&
"Did not find index!");
2268 static std::unique_ptr<VTableLayout>
2271 VTableThunks(Builder.vtable_thunks_begin(), Builder.vtable_thunks_end());
2273 return llvm::make_unique<VTableLayout>(
2274 Builder.VTableIndices, Builder.vtable_components(), VTableThunks,
2275 Builder.getAddressPoints());
2279 ItaniumVTableContext::computeVTableRelatedInformation(
const CXXRecordDecl *RD) {
2280 std::unique_ptr<const VTableLayout> &Entry = VTableLayouts[RD];
2290 MethodVTableIndices.insert(Builder.vtable_indices_begin(),
2291 Builder.vtable_indices_end());
2294 Thunks.insert(Builder.thunks_begin(), Builder.thunks_end());
2305 if (VirtualBaseClassOffsetOffsets.count(std::make_pair(RD, VBase)))
2308 for (
const auto &I : Builder.getVBaseOffsetOffsets()) {
2310 ClassPairTy ClassPair(RD, I.first);
2312 VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I.second));
2316 std::unique_ptr<VTableLayout>
2319 bool MostDerivedClassIsVirtual,
const CXXRecordDecl *LayoutClass) {
2320 ItaniumVTableBuilder Builder(*
this, MostDerivedClass, MostDerivedClassOffset,
2321 MostDerivedClassIsVirtual, LayoutClass);
2369 class VFTableBuilder {
2371 typedef llvm::DenseMap<GlobalDecl, MethodVFTableLocation>
2372 MethodVFTableLocationsTy;
2374 typedef llvm::iterator_range<MethodVFTableLocationsTy::const_iterator>
2375 method_locations_range;
2393 const FinalOverriders Overriders;
2398 MethodVFTableLocationsTy MethodVFTableLocations;
2401 bool HasRTTIComponent =
false;
2408 const uint64_t VBTableIndex;
2411 const uint64_t VFTableIndex;
2422 MethodInfo(uint64_t VBTableIndex, uint64_t VFTableIndex,
2423 bool UsesExtraSlot =
false)
2424 : VBTableIndex(VBTableIndex), VFTableIndex(VFTableIndex),
2425 Shadowed(
false), UsesExtraSlot(UsesExtraSlot) {}
2428 : VBTableIndex(0), VFTableIndex(0), Shadowed(
false),
2429 UsesExtraSlot(
false) {}
2432 typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy;
2436 MethodInfoMapTy MethodInfoMap;
2438 typedef llvm::DenseMap<uint64_t, ThunkInfo> VTableThunksMapTy;
2442 VTableThunksMapTy VTableThunks;
2445 typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy>
ThunksMapTy;
2456 if (std::find(ThunksVector.begin(), ThunksVector.end(), Thunk) !=
2460 ThunksVector.push_back(Thunk);
2465 CharUnits ComputeThisOffset(FinalOverriders::OverriderInfo Overrider);
2467 void CalculateVtordispAdjustment(FinalOverriders::OverriderInfo Overrider,
2474 VTableThunks[Components.size()] = TI;
2479 "Destructor can't have return adjustment!");
2490 BasesSetVectorTy &VisitedBases);
2492 void LayoutVFTable() {
2494 if (HasRTTIComponent)
2497 BasesSetVectorTy VisitedBases;
2500 assert((HasRTTIComponent ? Components.size() - 1 : Components.size()) &&
2501 "vftable can't be empty");
2503 assert(MethodVFTableLocations.empty());
2504 for (
const auto &I : MethodInfoMap) {
2506 const MethodInfo &MI = I.second;
2511 if (MD->
getParent() != MostDerivedClass || MI.Shadowed)
2518 MethodVFTableLocations[MD] = Loc;
2528 MostDerivedClass(MostDerivedClass),
2531 Overriders(MostDerivedClass,
CharUnits(), MostDerivedClass) {
2538 HasRTTIComponent =
true;
2543 dumpLayout(llvm::outs());
2546 uint64_t getNumThunks()
const {
return Thunks.size(); }
2548 ThunksMapTy::const_iterator thunks_begin()
const {
return Thunks.begin(); }
2550 ThunksMapTy::const_iterator thunks_end()
const {
return Thunks.end(); }
2552 method_locations_range vtable_locations()
const {
2553 return method_locations_range(MethodVFTableLocations.begin(),
2554 MethodVFTableLocations.end());
2559 VTableThunksMapTy::const_iterator vtable_thunks_begin()
const {
2560 return VTableThunks.begin();
2563 VTableThunksMapTy::const_iterator vtable_thunks_end()
const {
2564 return VTableThunks.end();
2567 void dumpLayout(raw_ostream &);
2627 VFTableBuilder::ComputeThisOffset(FinalOverriders::OverriderInfo Overrider) {
2628 BasesSetVectorTy Bases;
2632 OverriddenMethodsSetTy VisitedOverriddenMethods;
2633 auto InitialOverriddenDefinitionCollector = [&](
2635 if (OverriddenMD->size_overridden_methods() == 0)
2636 Bases.insert(OverriddenMD->getParent());
2638 return VisitedOverriddenMethods.insert(OverriddenMD).second;
2640 visitAllOverriddenMethods(Overrider.Method,
2641 InitialOverriddenDefinitionCollector);
2646 if (Bases.size() == 0)
2647 return Overrider.Offset;
2650 Overrider.Method->getParent()->lookupInBases(
2666 CharUnits ThisOffset = Overrider.Offset;
2673 QualType CurTy = Element.Base->getType();
2678 if (Element.Base->isVirtual()) {
2689 LastVBaseOffset = ThisOffset =
2696 if (isa<CXXDestructorDecl>(Overrider.Method)) {
2697 if (LastVBaseOffset.
isZero()) {
2701 ThisOffset = Overrider.Offset;
2705 ThisOffset = LastVBaseOffset;
2709 if (Ret > ThisOffset || First) {
2715 assert(!First &&
"Method not found in the given subobject?");
2817 void VFTableBuilder::CalculateVtordispAdjustment(
2818 FinalOverriders::OverriderInfo Overrider,
CharUnits ThisOffset,
2821 MostDerivedClassLayout.getVBaseOffsetsMap();
2822 const ASTRecordLayout::VBaseOffsetsMapTy::const_iterator &VBaseMapEntry =
2823 VBaseMap.find(WhichVFPtr.getVBaseWithVPtr());
2824 assert(VBaseMapEntry != VBaseMap.end());
2828 if (!VBaseMapEntry->second.hasVtorDisp() ||
2829 Overrider.VirtualBase == WhichVFPtr.getVBaseWithVPtr())
2834 CharUnits OffsetOfVBaseWithVFPtr = VBaseMapEntry->second.VBaseOffset;
2836 (OffsetOfVBaseWithVFPtr - WhichVFPtr.FullOffsetInMDC).getQuantity() - 4;
2840 if (Overrider.Method->getParent() == MostDerivedClass ||
2841 !Overrider.VirtualBase)
2847 (OffsetOfVBaseWithVFPtr + WhichVFPtr.NonVirtualOffset -
2848 MostDerivedClassLayout.getVBPtrOffset()).getQuantity();
2851 VTables.getVBTableIndex(MostDerivedClass, Overrider.VirtualBase);
2853 TA.
NonVirtual = (ThisOffset - Overrider.Offset).getQuantity();
2867 typedef llvm::DenseMap<DeclarationName, unsigned> VisitedGroupIndicesTy;
2868 VisitedGroupIndicesTy VisitedGroupIndices;
2869 for (
const auto *D : RD->
decls()) {
2870 const auto *ND = dyn_cast<
NamedDecl>(D);
2873 VisitedGroupIndicesTy::iterator J;
2875 std::tie(J, Inserted) = VisitedGroupIndices.insert(
2876 std::make_pair(ND->getDeclName(), Groups.size()));
2878 Groups.push_back(MethodGroup());
2879 if (
const auto *MD = dyn_cast<CXXMethodDecl>(ND))
2880 if (MD->isVirtual())
2881 Groups[J->second].push_back(MD->getCanonicalDecl());
2884 for (
const MethodGroup &Group : Groups)
2885 VirtualMethods.append(Group.rbegin(), Group.rend());
2889 for (
const auto &B : RD->
bases()) {
2890 if (B.isVirtual() && B.getType()->getAsCXXRecordDecl() == Base)
2898 BasesSetVectorTy &VisitedBases) {
2908 const CXXRecordDecl *NextBase =
nullptr, *NextLastVBase = LastVBase;
2910 if (BaseDepth < WhichVFPtr.PathToIntroducingObject.size()) {
2911 NextBase = WhichVFPtr.PathToIntroducingObject[BaseDepth];
2913 NextLastVBase = NextBase;
2914 NextBaseOffset = MostDerivedClassLayout.getVBaseClassOffset(NextBase);
2921 "No primary virtual bases in this ABI");
2922 NextBase = PrimaryBase;
2927 AddMethods(
BaseSubobject(NextBase, NextBaseOffset), BaseDepth + 1,
2928 NextLastVBase, VisitedBases);
2929 if (!VisitedBases.insert(NextBase))
2930 llvm_unreachable(
"Found a duplicate primary base!");
2946 FinalOverriders::OverriderInfo FinalOverrider =
2948 const CXXMethodDecl *FinalOverriderMD = FinalOverrider.Method;
2950 FindNearestOverriddenMethod(MD, VisitedBases);
2953 bool ReturnAdjustingThunk =
false, ForceReturnAdjustmentMangling =
false;
2954 CharUnits ThisOffset = ComputeThisOffset(FinalOverrider);
2956 (ThisOffset - WhichVFPtr.FullOffsetInMDC).getQuantity();
2957 if ((OverriddenMD || FinalOverriderMD != MD) &&
2958 WhichVFPtr.getVBaseWithVPtr())
2959 CalculateVtordispAdjustment(FinalOverrider, ThisOffset,
2960 ThisAdjustmentOffset);
2963 LastVBase ? VTables.getVBTableIndex(MostDerivedClass, LastVBase) : 0;
2968 MethodInfoMapTy::iterator OverriddenMDIterator =
2969 MethodInfoMap.find(OverriddenMD);
2972 if (OverriddenMDIterator == MethodInfoMap.end())
2975 MethodInfo &OverriddenMethodInfo = OverriddenMDIterator->second;
2977 VBIndex = OverriddenMethodInfo.VBTableIndex;
2984 ReturnAdjustingThunk = !ComputeReturnAdjustmentBaseOffset(
2985 Context, MD, OverriddenMD).isEmpty() ||
2986 OverriddenMethodInfo.UsesExtraSlot;
2988 if (!ReturnAdjustingThunk) {
2991 MethodInfo MI(VBIndex, 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 ||
3009 MD->size_overridden_methods()) {
3018 MethodInfo MI(VBIndex,
3019 HasRTTIComponent ? Components.size() - 1 : Components.size(),
3020 ReturnAdjustingThunk);
3022 assert(!MethodInfoMap.count(MD) &&
3023 "Should not have method info for this method yet!");
3024 MethodInfoMap.insert(std::make_pair(MD, MI));
3028 BaseOffset ReturnAdjustmentOffset;
3030 if (!FinalOverriderMD->
isPure()) {
3031 ReturnAdjustmentOffset =
3032 ComputeReturnAdjustmentBaseOffset(Context, FinalOverriderMD, MD);
3034 if (!ReturnAdjustmentOffset.isEmpty()) {
3035 ForceReturnAdjustmentMangling =
true;
3037 ReturnAdjustmentOffset.NonVirtualOffset.getQuantity();
3038 if (ReturnAdjustmentOffset.VirtualBase) {
3044 VTables.getVBTableIndex(ReturnAdjustmentOffset.DerivedClass,
3045 ReturnAdjustmentOffset.VirtualBase);
3049 AddMethod(FinalOverriderMD,
3050 ThunkInfo(ThisAdjustmentOffset, ReturnAdjustment,
3051 ForceReturnAdjustmentMangling ? MD :
nullptr));
3057 llvm::make_range(Path.rbegin(), Path.rend())) {
3059 Elem->printQualifiedName(Out);
3065 bool ContinueFirstLine) {
3067 bool Multiline =
false;
3068 const char *LinePrefix =
"\n ";
3070 if (!ContinueFirstLine)
3072 Out <<
"[return adjustment (to type '" 3085 if (Multiline || !ContinueFirstLine)
3087 Out <<
"[this adjustment: ";
3095 Out << LinePrefix <<
" vboffset at " 3103 void VFTableBuilder::dumpLayout(raw_ostream &Out) {
3104 Out <<
"VFTable for ";
3107 MostDerivedClass->printQualifiedName(Out);
3108 Out <<
"' (" << Components.size()
3109 << (Components.size() == 1 ?
" entry" :
" entries") <<
").\n";
3111 for (
unsigned I = 0, E = Components.size(); I != E; ++I) {
3112 Out << llvm::format(
"%4d | ", I);
3117 switch (Component.
getKind()) {
3135 Out <<
" [deleted]";
3137 ThunkInfo Thunk = VTableThunks.lookup(I);
3148 Out <<
"() [scalar deleting]";
3153 ThunkInfo Thunk = VTableThunks.lookup(I);
3156 "No return adjustment needed for destructors!");
3167 "Unexpected vftable component type %0 for component number %1");
3168 Diags.
Report(MostDerivedClass->getLocation(), DiagID)
3179 std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls;
3181 for (
const auto &I :
Thunks) {
3186 MethodNamesAndDecls.insert(std::make_pair(MethodName, MD));
3189 for (
const auto &MethodNameAndDecl : MethodNamesAndDecls) {
3190 const std::string &MethodName = MethodNameAndDecl.first;
3194 std::stable_sort(ThunksVector.begin(), ThunksVector.end(),
3198 return std::tie(LHS.
This, LHS.
Return) < std::tie(RHS.This, RHS.Return);
3201 Out <<
"Thunks for '" << MethodName <<
"' (" << ThunksVector.size();
3202 Out << (ThunksVector.size() == 1 ?
" entry" :
" entries") <<
").\n";
3204 for (
unsigned I = 0, E = ThunksVector.size(); I != E; ++I) {
3205 const ThunkInfo &Thunk = ThunksVector[I];
3207 Out << llvm::format(
"%4d | ", I);
3251 void MicrosoftVTableContext::computeVTablePaths(
bool ForVBTables,
3254 assert(Paths.empty());
3258 if (ForVBTables ? Layout.hasOwnVBPtr() : Layout.hasOwnVFPtr())
3259 Paths.push_back(llvm::make_unique<VPtrInfo>(RD));
3263 llvm::SmallPtrSet<const CXXRecordDecl*, 4> VBasesSeen;
3264 for (
const auto &B : RD->
bases()) {
3265 const CXXRecordDecl *Base = B.getType()->getAsCXXRecordDecl();
3266 if (B.isVirtual() && VBasesSeen.count(Base))
3273 ForVBTables ? enumerateVBTables(Base) : getVFPtrOffsets(Base);
3275 for (
const std::unique_ptr<VPtrInfo> &BaseInfo : BasePaths) {
3282 auto P = llvm::make_unique<VPtrInfo>(*BaseInfo);
3286 if (
P->MangledPath.empty() ||
P->MangledPath.back() != Base)
3287 P->NextBaseToMangle = Base;
3292 if (
P->ObjectWithVPtr == Base &&
3293 Base == (ForVBTables ? Layout.getBaseSharingVBPtr()
3294 : Layout.getPrimaryBase()))
3295 P->ObjectWithVPtr = RD;
3300 P->ContainingVBases.push_back(Base);
3301 else if (
P->ContainingVBases.empty())
3302 P->NonVirtualOffset += Layout.getBaseClassOffset(Base);
3305 P->FullOffsetInMDC =
P->NonVirtualOffset;
3307 P->FullOffsetInMDC += Layout.getVBaseClassOffset(VB);
3309 Paths.push_back(std::move(
P));
3313 VBasesSeen.insert(Base);
3317 for (
const auto &VB : Base->
vbases())
3318 VBasesSeen.insert(VB.getType()->getAsCXXRecordDecl());
3323 bool Changed =
true;
3345 PathsSorted.reserve(Paths.size());
3346 for (
auto&
P : Paths)
3347 PathsSorted.push_back(*
P);
3348 llvm::sort(PathsSorted.begin(), PathsSorted.end(),
3352 bool Changed =
false;
3353 for (
size_t I = 0, E = PathsSorted.size(); I != E;) {
3355 size_t BucketStart = I;
3359 PathsSorted[BucketStart].
get().MangledPath ==
3360 PathsSorted[I].get().MangledPath);
3363 if (I - BucketStart > 1) {
3364 for (
size_t II = BucketStart; II != I; ++II)
3366 assert(Changed &&
"no paths were extended to fix ambiguity");
3375 typedef llvm::SetVector<BaseSubobject, std::vector<BaseSubobject>,
3385 FullPathTy &FullPath,
3386 std::list<FullPathTy> &Paths) {
3388 Paths.push_back(FullPath);
3395 const CXXRecordDecl *Base = BS.getType()->getAsCXXRecordDecl();
3401 IntroducingObject, FullPath, Paths);
3402 FullPath.pop_back();
3408 FullPaths.remove_if([&](
const FullPathTy &SpecificPath) {
3409 for (
const FullPathTy &OtherPath : FullPaths) {
3410 if (&SpecificPath == &OtherPath)
3412 if (std::all_of(SpecificPath.begin(), SpecificPath.end(),
3414 return OtherPath.count(BSO) != 0;
3425 const FullPathTy &FullPath) {
3446 : Offset + Layout.getBaseClassOffset(Base);
3458 std::list<FullPathTy> &FullPaths) {
3460 if (FullPaths.empty())
3462 if (FullPaths.size() == 1)
3463 return &FullPaths.front();
3465 const FullPathTy *BestPath =
nullptr;
3466 typedef std::set<const CXXMethodDecl *> OverriderSetTy;
3467 OverriderSetTy LastOverrides;
3468 for (
const FullPathTy &SpecificPath : FullPaths) {
3469 assert(!SpecificPath.empty());
3470 OverriderSetTy CurrentOverrides;
3471 const CXXRecordDecl *TopLevelRD = SpecificPath.begin()->getBase();
3476 FinalOverriders Overriders(TopLevelRD,
CharUnits::Zero(), TopLevelRD);
3478 if (!MD->isVirtual())
3480 FinalOverriders::OverriderInfo OI =
3481 Overriders.getOverrider(MD->getCanonicalDecl(), BaseOffset);
3485 if (ComputeReturnAdjustmentBaseOffset(Context, OverridingMethod, MD)
3491 if (std::none_of(SpecificPath.begin(), SpecificPath.end(),
3493 return BSO.getBase() == OverridingParent;
3496 CurrentOverrides.insert(OverridingMethod);
3498 OverriderSetTy NewOverrides =
3499 llvm::set_difference(CurrentOverrides, LastOverrides);
3500 if (NewOverrides.empty())
3502 OverriderSetTy MissingOverrides =
3503 llvm::set_difference(LastOverrides, CurrentOverrides);
3504 if (MissingOverrides.empty()) {
3506 BestPath = &SpecificPath;
3507 std::swap(CurrentOverrides, LastOverrides);
3512 const CXXMethodDecl *ConflictMD = *MissingOverrides.begin();
3523 return BestPath ? BestPath : &FullPaths.front();
3530 FullPathTy FullPath;
3531 std::list<FullPathTy> FullPaths;
3532 for (
const std::unique_ptr<VPtrInfo>& Info : Paths) {
3535 BaseSubobject(Info->IntroducingObject, Info->FullOffsetInMDC), FullPath,
3539 Info->PathToIntroducingObject.clear();
3540 if (
const FullPathTy *BestPath =
3543 Info->PathToIntroducingObject.push_back(BSO.getBase());
3560 void MicrosoftVTableContext::computeVTableRelatedInformation(
3565 if (VFPtrLocations.count(RD))
3571 auto VFPtrs = llvm::make_unique<VPtrInfoVector>();
3572 computeVTablePaths(
false, RD, *VFPtrs);
3574 VFPtrLocations[RD] = std::move(VFPtrs);
3577 MethodVFTableLocationsTy NewMethodLocations;
3578 for (
const std::unique_ptr<VPtrInfo> &VFPtr : *VFPtrLocations[RD]) {
3579 VFTableBuilder Builder(*
this, RD, *VFPtr);
3581 VFTableIdTy
id(RD, VFPtr->FullOffsetInMDC);
3582 assert(VFTableLayouts.count(
id) == 0);
3584 Builder.vtable_thunks_begin(), Builder.vtable_thunks_end());
3585 VFTableLayouts[
id] = llvm::make_unique<VTableLayout>(
3587 EmptyAddressPointsMap);
3588 Thunks.insert(Builder.thunks_begin(), Builder.thunks_end());
3591 for (
const auto &Loc : Builder.vtable_locations()) {
3592 auto Insert = NewMethodLocations.insert(Loc);
3602 MethodVFTableLocations.insert(NewMethodLocations.begin(),
3603 NewMethodLocations.end());
3605 dumpMethodLocations(RD, NewMethodLocations, llvm::outs());
3608 void MicrosoftVTableContext::dumpMethodLocations(
3609 const CXXRecordDecl *RD,
const MethodVFTableLocationsTy &NewMethods,
3613 std::map<MethodVFTableLocation, std::string> IndicesMap;
3614 bool HasNonzeroOffset =
false;
3616 for (
const auto &I : NewMethods) {
3617 const CXXMethodDecl *MD = cast<const CXXMethodDecl>(I.first.getDecl());
3623 if (isa<CXXDestructorDecl>(MD)) {
3624 IndicesMap[I.second] = MethodName +
" [scalar deleting]";
3626 IndicesMap[I.second] = MethodName;
3629 if (!I.second.VFPtrOffset.isZero() || I.second.VBTableIndex != 0)
3630 HasNonzeroOffset =
true;
3634 if (!IndicesMap.empty()) {
3635 Out <<
"VFTable indices for ";
3638 Out <<
"' (" << IndicesMap.size()
3639 << (IndicesMap.size() == 1 ?
" entry" :
" entries") <<
").\n";
3642 uint64_t LastVBIndex = 0;
3643 for (
const auto &I : IndicesMap) {
3644 CharUnits VFPtrOffset = I.first.VFPtrOffset;
3645 uint64_t VBIndex = I.first.VBTableIndex;
3646 if (HasNonzeroOffset &&
3647 (VFPtrOffset != LastVFPtrOffset || VBIndex != LastVBIndex)) {
3648 assert(VBIndex > LastVBIndex || VFPtrOffset > LastVFPtrOffset);
3649 Out <<
" -- accessible via ";
3651 Out <<
"vbtable index " << VBIndex <<
", ";
3652 Out <<
"vfptr at offset " << VFPtrOffset.
getQuantity() <<
" --\n";
3653 LastVFPtrOffset = VFPtrOffset;
3654 LastVBIndex = VBIndex;
3657 uint64_t VTableIndex = I.first.Index;
3658 const std::string &MethodName = I.second;
3659 Out << llvm::format(
"%4" PRIu64
" | ", VTableIndex) << MethodName <<
'\n';
3667 const VirtualBaseInfo &MicrosoftVTableContext::computeVBTableRelatedInformation(
3674 std::unique_ptr<VirtualBaseInfo> &Entry = VBaseInfo[RD];
3677 Entry = llvm::make_unique<VirtualBaseInfo>();
3681 computeVTablePaths(
true, RD, VBI->
VBPtrPaths);
3689 computeVBTableRelatedInformation(VBPtrBase);
3697 for (
const auto &VB : RD->
vbases()) {
3698 const CXXRecordDecl *CurVBase = VB.getType()->getAsCXXRecordDecl();
3708 const VirtualBaseInfo &VBInfo = computeVBTableRelatedInformation(Derived);
3715 return computeVBTableRelatedInformation(RD).VBPtrPaths;
3720 computeVTableRelatedInformation(RD);
3722 assert(VFPtrLocations.count(RD) &&
"Couldn't find vfptr locations");
3723 return *VFPtrLocations[RD];
3729 computeVTableRelatedInformation(RD);
3731 VFTableIdTy
id(RD, VFPtrOffset);
3732 assert(VFTableLayouts.count(
id) &&
"Couldn't find a VFTable at this offset");
3733 return *VFTableLayouts[
id];
3738 assert(cast<CXXMethodDecl>(GD.
getDecl())->isVirtual() &&
3739 "Only use this method for virtual methods or dtors");
3740 if (isa<CXXDestructorDecl>(GD.
getDecl()))
3745 MethodVFTableLocationsTy::iterator I = MethodVFTableLocations.find(GD);
3746 if (I != MethodVFTableLocations.end())
3749 const CXXRecordDecl *RD = cast<CXXMethodDecl>(GD.getDecl())->getParent();
3751 computeVTableRelatedInformation(RD);
3753 I = MethodVFTableLocations.find(GD);
3754 assert(I != MethodVFTableLocations.end() &&
"Did not find index!");
Defines the clang::ASTContext interface.
static std::string ComputeName(IdentType IT, const Decl *CurrentDecl)
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.
CharUnits VFPtrOffset
This is the offset of the vfptr from the start of the last vbase, or the complete type if there are n...
bool isVirtual() const
Determines whether the base class is a virtual base class (or not).
GlobalDecl getCanonicalDecl() const
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 CXXRecordDecl * VBase
If nonnull, holds the last vbase which contains the vfptr that the method definition is adjusted to...
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
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)
struct clang::ReturnAdjustment::VirtualAdjustment::@117 Itanium
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
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::ReturnAdjustment::VirtualAdjustment::@118 Microsoft
void printQualifiedName(raw_ostream &OS) const
Returns a human-readable qualified name for this declaration, like A::B::i, for i being member of nam...
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
static bool vfptrIsEarlierInMDC(const ASTRecordLayout &Layout, const MethodVFTableLocation &LHS, const MethodVFTableLocation &RHS)
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.
struct clang::ThisAdjustment::VirtualAdjustment::@120 Microsoft
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.
struct clang::ThisAdjustment::VirtualAdjustment::@119 Itanium
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.
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()
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)
MethodVFTableLocation getMethodVFTableLocation(GlobalDecl GD)
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.
This represents a decl that may have 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.
SourceLocation getLocation() const
method_range methods() const
QualType getType() const
Retrieves the type of the base class.
static VTableComponent MakeOffsetToTop(CharUnits Offset)