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];
2109 assert(LHS.
Method ==
nullptr && RHS.
Method ==
nullptr);
2113 Out <<
"Thunks for '" << MethodName <<
"' (" << ThunksVector.size();
2114 Out << (ThunksVector.size() == 1 ?
" entry" :
" entries") <<
").\n";
2116 for (
unsigned I = 0, E = ThunksVector.size(); I != E; ++I) {
2117 const ThunkInfo &Thunk = ThunksVector[I];
2119 Out << llvm::format(
"%4d | ", I);
2124 Out <<
" non-virtual";
2127 Out <<
" vbase offset offset";
2136 Out <<
"this adjustment: ";
2141 Out <<
" vcall offset offset";
2154 std::map<uint64_t, std::string> IndicesMap;
2156 for (
const auto *MD : MostDerivedClass->
methods()) {
2162 std::string MethodName =
2168 assert(MethodVTableIndices.count(GD));
2169 uint64_t VTableIndex = MethodVTableIndices[GD];
2170 IndicesMap[VTableIndex] = MethodName +
" [complete]";
2171 IndicesMap[VTableIndex + 1] = MethodName +
" [deleting]";
2173 assert(MethodVTableIndices.count(MD));
2174 IndicesMap[MethodVTableIndices[MD]] = MethodName;
2179 if (!IndicesMap.empty()) {
2180 Out <<
"VTable indices for '";
2182 Out <<
"' (" << IndicesMap.size() <<
" entries).\n";
2184 for (
const auto &I : IndicesMap) {
2185 uint64_t VTableIndex = I.first;
2186 const std::string &MethodName = I.second;
2188 Out << llvm::format(
"%4" PRIu64
" | ", VTableIndex) << MethodName
2201 : VTableComponents(VTableComponents), VTableThunks(VTableThunks),
2202 AddressPoints(AddressPoints) {
2203 if (VTableIndices.size() <= 1)
2204 assert(VTableIndices.size() == 1 && VTableIndices[0] == 0);
2210 assert((LHS.first != RHS.first || LHS.second == RHS.second) &&
2211 "Different thunks should have unique indices!");
2212 return LHS.first < RHS.first;
2225 MethodVTableIndicesTy::iterator I = MethodVTableIndices.find(GD);
2226 if (I != MethodVTableIndices.end())
2231 computeVTableRelatedInformation(RD);
2233 I = MethodVTableIndices.find(GD);
2234 assert(I != MethodVTableIndices.end() &&
"Did not find index!");
2241 ClassPairTy ClassPair(RD, VBase);
2243 VirtualBaseClassOffsetOffsetsMapTy::iterator I =
2244 VirtualBaseClassOffsetOffsets.find(ClassPair);
2245 if (I != VirtualBaseClassOffsetOffsets.end())
2248 VCallAndVBaseOffsetBuilder Builder(RD, RD,
nullptr,
2253 for (
const auto &I : Builder.getVBaseOffsetOffsets()) {
2255 ClassPairTy ClassPair(RD, I.first);
2257 VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I.second));
2260 I = VirtualBaseClassOffsetOffsets.find(ClassPair);
2261 assert(I != VirtualBaseClassOffsetOffsets.end() &&
"Did not find index!");
2266 static std::unique_ptr<VTableLayout>
2269 VTableThunks(Builder.vtable_thunks_begin(), Builder.vtable_thunks_end());
2271 return llvm::make_unique<VTableLayout>(
2272 Builder.VTableIndices, Builder.vtable_components(), VTableThunks,
2273 Builder.getAddressPoints());
2277 ItaniumVTableContext::computeVTableRelatedInformation(
const CXXRecordDecl *RD) {
2278 std::unique_ptr<const VTableLayout> &Entry = VTableLayouts[RD];
2288 MethodVTableIndices.insert(Builder.vtable_indices_begin(),
2289 Builder.vtable_indices_end());
2292 Thunks.insert(Builder.thunks_begin(), Builder.thunks_end());
2303 if (VirtualBaseClassOffsetOffsets.count(std::make_pair(RD, VBase)))
2306 for (
const auto &I : Builder.getVBaseOffsetOffsets()) {
2308 ClassPairTy ClassPair(RD, I.first);
2310 VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I.second));
2314 std::unique_ptr<VTableLayout>
2317 bool MostDerivedClassIsVirtual,
const CXXRecordDecl *LayoutClass) {
2318 ItaniumVTableBuilder Builder(*
this, MostDerivedClass, MostDerivedClassOffset,
2319 MostDerivedClassIsVirtual, LayoutClass);
2367 class VFTableBuilder {
2369 typedef llvm::DenseMap<GlobalDecl, MethodVFTableLocation>
2370 MethodVFTableLocationsTy;
2372 typedef llvm::iterator_range<MethodVFTableLocationsTy::const_iterator>
2373 method_locations_range;
2391 const FinalOverriders Overriders;
2396 MethodVFTableLocationsTy MethodVFTableLocations;
2399 bool HasRTTIComponent =
false;
2406 const uint64_t VBTableIndex;
2409 const uint64_t VFTableIndex;
2420 MethodInfo(uint64_t VBTableIndex, uint64_t VFTableIndex,
2421 bool UsesExtraSlot =
false)
2422 : VBTableIndex(VBTableIndex), VFTableIndex(VFTableIndex),
2423 Shadowed(
false), UsesExtraSlot(UsesExtraSlot) {}
2426 : VBTableIndex(0), VFTableIndex(0), Shadowed(
false),
2427 UsesExtraSlot(
false) {}
2430 typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy;
2434 MethodInfoMapTy MethodInfoMap;
2436 typedef llvm::DenseMap<uint64_t, ThunkInfo> VTableThunksMapTy;
2440 VTableThunksMapTy VTableThunks;
2443 typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy>
ThunksMapTy;
2454 if (std::find(ThunksVector.begin(), ThunksVector.end(), Thunk) !=
2458 ThunksVector.push_back(Thunk);
2463 CharUnits ComputeThisOffset(FinalOverriders::OverriderInfo Overrider);
2465 void CalculateVtordispAdjustment(FinalOverriders::OverriderInfo Overrider,
2472 VTableThunks[Components.size()] = TI;
2477 "Destructor can't have return adjustment!");
2488 BasesSetVectorTy &VisitedBases);
2490 void LayoutVFTable() {
2492 if (HasRTTIComponent)
2495 BasesSetVectorTy VisitedBases;
2498 assert((HasRTTIComponent ? Components.size() - 1 : Components.size()) &&
2499 "vftable can't be empty");
2501 assert(MethodVFTableLocations.empty());
2502 for (
const auto &I : MethodInfoMap) {
2504 const MethodInfo &MI = I.second;
2509 if (MD->
getParent() != MostDerivedClass || MI.Shadowed)
2516 MethodVFTableLocations[MD] = Loc;
2526 MostDerivedClass(MostDerivedClass),
2529 Overriders(MostDerivedClass,
CharUnits(), MostDerivedClass) {
2536 HasRTTIComponent =
true;
2541 dumpLayout(llvm::outs());
2544 uint64_t getNumThunks()
const {
return Thunks.size(); }
2546 ThunksMapTy::const_iterator thunks_begin()
const {
return Thunks.begin(); }
2548 ThunksMapTy::const_iterator thunks_end()
const {
return Thunks.end(); }
2550 method_locations_range vtable_locations()
const {
2551 return method_locations_range(MethodVFTableLocations.begin(),
2552 MethodVFTableLocations.end());
2557 VTableThunksMapTy::const_iterator vtable_thunks_begin()
const {
2558 return VTableThunks.begin();
2561 VTableThunksMapTy::const_iterator vtable_thunks_end()
const {
2562 return VTableThunks.end();
2565 void dumpLayout(raw_ostream &);
2625 VFTableBuilder::ComputeThisOffset(FinalOverriders::OverriderInfo Overrider) {
2626 BasesSetVectorTy Bases;
2630 OverriddenMethodsSetTy VisitedOverriddenMethods;
2631 auto InitialOverriddenDefinitionCollector = [&](
2633 if (OverriddenMD->size_overridden_methods() == 0)
2634 Bases.insert(OverriddenMD->getParent());
2636 return VisitedOverriddenMethods.insert(OverriddenMD).second;
2638 visitAllOverriddenMethods(Overrider.Method,
2639 InitialOverriddenDefinitionCollector);
2644 if (Bases.size() == 0)
2645 return Overrider.Offset;
2648 Overrider.Method->getParent()->lookupInBases(
2664 CharUnits ThisOffset = Overrider.Offset;
2671 QualType CurTy = Element.Base->getType();
2676 if (Element.Base->isVirtual()) {
2687 LastVBaseOffset = ThisOffset =
2694 if (isa<CXXDestructorDecl>(Overrider.Method)) {
2695 if (LastVBaseOffset.
isZero()) {
2699 ThisOffset = Overrider.Offset;
2703 ThisOffset = LastVBaseOffset;
2707 if (Ret > ThisOffset || First) {
2713 assert(!First &&
"Method not found in the given subobject?");
2815 void VFTableBuilder::CalculateVtordispAdjustment(
2816 FinalOverriders::OverriderInfo Overrider,
CharUnits ThisOffset,
2819 MostDerivedClassLayout.getVBaseOffsetsMap();
2820 const ASTRecordLayout::VBaseOffsetsMapTy::const_iterator &VBaseMapEntry =
2821 VBaseMap.find(WhichVFPtr.getVBaseWithVPtr());
2822 assert(VBaseMapEntry != VBaseMap.end());
2826 if (!VBaseMapEntry->second.hasVtorDisp() ||
2827 Overrider.VirtualBase == WhichVFPtr.getVBaseWithVPtr())
2832 CharUnits OffsetOfVBaseWithVFPtr = VBaseMapEntry->second.VBaseOffset;
2834 (OffsetOfVBaseWithVFPtr - WhichVFPtr.FullOffsetInMDC).getQuantity() - 4;
2838 if (Overrider.Method->getParent() == MostDerivedClass ||
2839 !Overrider.VirtualBase)
2845 (OffsetOfVBaseWithVFPtr + WhichVFPtr.NonVirtualOffset -
2846 MostDerivedClassLayout.getVBPtrOffset()).getQuantity();
2849 VTables.getVBTableIndex(MostDerivedClass, Overrider.VirtualBase);
2851 TA.
NonVirtual = (ThisOffset - Overrider.Offset).getQuantity();
2865 typedef llvm::DenseMap<DeclarationName, unsigned> VisitedGroupIndicesTy;
2866 VisitedGroupIndicesTy VisitedGroupIndices;
2867 for (
const auto *D : RD->
decls()) {
2868 const auto *ND = dyn_cast<
NamedDecl>(D);
2871 VisitedGroupIndicesTy::iterator J;
2873 std::tie(J, Inserted) = VisitedGroupIndices.insert(
2874 std::make_pair(ND->getDeclName(), Groups.size()));
2876 Groups.push_back(MethodGroup());
2877 if (
const auto *MD = dyn_cast<CXXMethodDecl>(ND))
2878 if (MD->isVirtual())
2879 Groups[J->second].push_back(MD->getCanonicalDecl());
2882 for (
const MethodGroup &Group : Groups)
2883 VirtualMethods.append(Group.rbegin(), Group.rend());
2887 for (
const auto &B : RD->
bases()) {
2888 if (B.isVirtual() && B.getType()->getAsCXXRecordDecl() == Base)
2896 BasesSetVectorTy &VisitedBases) {
2906 const CXXRecordDecl *NextBase =
nullptr, *NextLastVBase = LastVBase;
2908 if (BaseDepth < WhichVFPtr.PathToIntroducingObject.size()) {
2909 NextBase = WhichVFPtr.PathToIntroducingObject[BaseDepth];
2911 NextLastVBase = NextBase;
2912 NextBaseOffset = MostDerivedClassLayout.getVBaseClassOffset(NextBase);
2919 "No primary virtual bases in this ABI");
2920 NextBase = PrimaryBase;
2925 AddMethods(
BaseSubobject(NextBase, NextBaseOffset), BaseDepth + 1,
2926 NextLastVBase, VisitedBases);
2927 if (!VisitedBases.insert(NextBase))
2928 llvm_unreachable(
"Found a duplicate primary base!");
2944 FinalOverriders::OverriderInfo FinalOverrider =
2946 const CXXMethodDecl *FinalOverriderMD = FinalOverrider.Method;
2948 FindNearestOverriddenMethod(MD, VisitedBases);
2951 bool ReturnAdjustingThunk =
false, ForceReturnAdjustmentMangling =
false;
2952 CharUnits ThisOffset = ComputeThisOffset(FinalOverrider);
2954 (ThisOffset - WhichVFPtr.FullOffsetInMDC).getQuantity();
2955 if ((OverriddenMD || FinalOverriderMD != MD) &&
2956 WhichVFPtr.getVBaseWithVPtr())
2957 CalculateVtordispAdjustment(FinalOverrider, ThisOffset,
2958 ThisAdjustmentOffset);
2961 LastVBase ? VTables.getVBTableIndex(MostDerivedClass, LastVBase) : 0;
2966 MethodInfoMapTy::iterator OverriddenMDIterator =
2967 MethodInfoMap.find(OverriddenMD);
2970 if (OverriddenMDIterator == MethodInfoMap.end())
2973 MethodInfo &OverriddenMethodInfo = OverriddenMDIterator->second;
2975 VBIndex = OverriddenMethodInfo.VBTableIndex;
2982 ReturnAdjustingThunk = !ComputeReturnAdjustmentBaseOffset(
2983 Context, MD, OverriddenMD).isEmpty() ||
2984 OverriddenMethodInfo.UsesExtraSlot;
2986 if (!ReturnAdjustingThunk) {
2989 MethodInfo MI(VBIndex, OverriddenMethodInfo.VFTableIndex);
2990 MethodInfoMap.erase(OverriddenMDIterator);
2992 assert(!MethodInfoMap.count(MD) &&
2993 "Should not have method info for this method yet!");
2994 MethodInfoMap.insert(std::make_pair(MD, MI));
3000 OverriddenMethodInfo.Shadowed =
true;
3004 ForceReturnAdjustmentMangling =
3005 !(MD == FinalOverriderMD && ThisAdjustmentOffset.
isEmpty());
3006 }
else if (Base.
getBaseOffset() != WhichVFPtr.FullOffsetInMDC ||
3007 MD->size_overridden_methods()) {
3016 MethodInfo MI(VBIndex,
3017 HasRTTIComponent ? Components.size() - 1 : Components.size(),
3018 ReturnAdjustingThunk);
3020 assert(!MethodInfoMap.count(MD) &&
3021 "Should not have method info for this method yet!");
3022 MethodInfoMap.insert(std::make_pair(MD, MI));
3026 BaseOffset ReturnAdjustmentOffset;
3028 if (!FinalOverriderMD->
isPure()) {
3029 ReturnAdjustmentOffset =
3030 ComputeReturnAdjustmentBaseOffset(Context, FinalOverriderMD, MD);
3032 if (!ReturnAdjustmentOffset.isEmpty()) {
3033 ForceReturnAdjustmentMangling =
true;
3035 ReturnAdjustmentOffset.NonVirtualOffset.getQuantity();
3036 if (ReturnAdjustmentOffset.VirtualBase) {
3042 VTables.getVBTableIndex(ReturnAdjustmentOffset.DerivedClass,
3043 ReturnAdjustmentOffset.VirtualBase);
3047 AddMethod(FinalOverriderMD,
3048 ThunkInfo(ThisAdjustmentOffset, ReturnAdjustment,
3049 ForceReturnAdjustmentMangling ? MD :
nullptr));
3055 llvm::make_range(Path.rbegin(), Path.rend())) {
3057 Elem->printQualifiedName(Out);
3063 bool ContinueFirstLine) {
3065 bool Multiline =
false;
3066 const char *LinePrefix =
"\n ";
3068 if (!ContinueFirstLine)
3070 Out <<
"[return adjustment (to type '" 3083 if (Multiline || !ContinueFirstLine)
3085 Out <<
"[this adjustment: ";
3093 Out << LinePrefix <<
" vboffset at " 3101 void VFTableBuilder::dumpLayout(raw_ostream &Out) {
3102 Out <<
"VFTable for ";
3105 MostDerivedClass->printQualifiedName(Out);
3106 Out <<
"' (" << Components.size()
3107 << (Components.size() == 1 ?
" entry" :
" entries") <<
").\n";
3109 for (
unsigned I = 0, E = Components.size(); I != E; ++I) {
3110 Out << llvm::format(
"%4d | ", I);
3115 switch (Component.
getKind()) {
3133 Out <<
" [deleted]";
3135 ThunkInfo Thunk = VTableThunks.lookup(I);
3146 Out <<
"() [scalar deleting]";
3151 ThunkInfo Thunk = VTableThunks.lookup(I);
3154 "No return adjustment needed for destructors!");
3165 "Unexpected vftable component type %0 for component number %1");
3166 Diags.
Report(MostDerivedClass->getLocation(), DiagID)
3177 std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls;
3179 for (
const auto &I :
Thunks) {
3184 MethodNamesAndDecls.insert(std::make_pair(MethodName, MD));
3187 for (
const auto &MethodNameAndDecl : MethodNamesAndDecls) {
3188 const std::string &MethodName = MethodNameAndDecl.first;
3192 std::stable_sort(ThunksVector.begin(), ThunksVector.end(),
3196 return std::tie(LHS.
This, LHS.
Return) < std::tie(RHS.This, RHS.Return);
3199 Out <<
"Thunks for '" << MethodName <<
"' (" << ThunksVector.size();
3200 Out << (ThunksVector.size() == 1 ?
" entry" :
" entries") <<
").\n";
3202 for (
unsigned I = 0, E = ThunksVector.size(); I != E; ++I) {
3203 const ThunkInfo &Thunk = ThunksVector[I];
3205 Out << llvm::format(
"%4d | ", I);
3249 void MicrosoftVTableContext::computeVTablePaths(
bool ForVBTables,
3252 assert(Paths.empty());
3256 if (ForVBTables ? Layout.hasOwnVBPtr() : Layout.hasOwnVFPtr())
3257 Paths.push_back(llvm::make_unique<VPtrInfo>(RD));
3261 llvm::SmallPtrSet<const CXXRecordDecl*, 4> VBasesSeen;
3262 for (
const auto &B : RD->
bases()) {
3263 const CXXRecordDecl *Base = B.getType()->getAsCXXRecordDecl();
3264 if (B.isVirtual() && VBasesSeen.count(Base))
3271 ForVBTables ? enumerateVBTables(Base) : getVFPtrOffsets(Base);
3273 for (
const std::unique_ptr<VPtrInfo> &BaseInfo : BasePaths) {
3280 auto P = llvm::make_unique<VPtrInfo>(*BaseInfo);
3284 if (
P->MangledPath.empty() ||
P->MangledPath.back() != Base)
3285 P->NextBaseToMangle = Base;
3290 if (
P->ObjectWithVPtr == Base &&
3291 Base == (ForVBTables ? Layout.getBaseSharingVBPtr()
3292 : Layout.getPrimaryBase()))
3293 P->ObjectWithVPtr = RD;
3298 P->ContainingVBases.push_back(Base);
3299 else if (
P->ContainingVBases.empty())
3300 P->NonVirtualOffset += Layout.getBaseClassOffset(Base);
3303 P->FullOffsetInMDC =
P->NonVirtualOffset;
3305 P->FullOffsetInMDC += Layout.getVBaseClassOffset(VB);
3307 Paths.push_back(std::move(
P));
3311 VBasesSeen.insert(Base);
3315 for (
const auto &VB : Base->
vbases())
3316 VBasesSeen.insert(VB.getType()->getAsCXXRecordDecl());
3321 bool Changed =
true;
3343 PathsSorted.reserve(Paths.size());
3344 for (
auto&
P : Paths)
3345 PathsSorted.push_back(*
P);
3349 bool Changed =
false;
3350 for (
size_t I = 0, E = PathsSorted.size(); I != E;) {
3352 size_t BucketStart = I;
3356 PathsSorted[BucketStart].
get().MangledPath ==
3357 PathsSorted[I].get().MangledPath);
3360 if (I - BucketStart > 1) {
3361 for (
size_t II = BucketStart; II != I; ++II)
3363 assert(Changed &&
"no paths were extended to fix ambiguity");
3372 typedef llvm::SetVector<BaseSubobject, std::vector<BaseSubobject>,
3382 FullPathTy &FullPath,
3383 std::list<FullPathTy> &Paths) {
3385 Paths.push_back(FullPath);
3392 const CXXRecordDecl *Base = BS.getType()->getAsCXXRecordDecl();
3398 IntroducingObject, FullPath, Paths);
3399 FullPath.pop_back();
3405 FullPaths.remove_if([&](
const FullPathTy &SpecificPath) {
3406 for (
const FullPathTy &OtherPath : FullPaths) {
3407 if (&SpecificPath == &OtherPath)
3409 if (llvm::all_of(SpecificPath, [&](
const BaseSubobject &BSO) {
3410 return OtherPath.count(BSO) != 0;
3421 const FullPathTy &FullPath) {
3442 : Offset + Layout.getBaseClassOffset(Base);
3454 std::list<FullPathTy> &FullPaths) {
3456 if (FullPaths.empty())
3458 if (FullPaths.size() == 1)
3459 return &FullPaths.front();
3461 const FullPathTy *BestPath =
nullptr;
3462 typedef std::set<const CXXMethodDecl *> OverriderSetTy;
3463 OverriderSetTy LastOverrides;
3464 for (
const FullPathTy &SpecificPath : FullPaths) {
3465 assert(!SpecificPath.empty());
3466 OverriderSetTy CurrentOverrides;
3467 const CXXRecordDecl *TopLevelRD = SpecificPath.begin()->getBase();
3472 FinalOverriders Overriders(TopLevelRD,
CharUnits::Zero(), TopLevelRD);
3474 if (!MD->isVirtual())
3476 FinalOverriders::OverriderInfo OI =
3477 Overriders.getOverrider(MD->getCanonicalDecl(), BaseOffset);
3481 if (ComputeReturnAdjustmentBaseOffset(Context, OverridingMethod, MD)
3487 if (llvm::none_of(SpecificPath, [&](
const BaseSubobject &BSO) {
3488 return BSO.
getBase() == OverridingParent;
3491 CurrentOverrides.insert(OverridingMethod);
3493 OverriderSetTy NewOverrides =
3494 llvm::set_difference(CurrentOverrides, LastOverrides);
3495 if (NewOverrides.empty())
3497 OverriderSetTy MissingOverrides =
3498 llvm::set_difference(LastOverrides, CurrentOverrides);
3499 if (MissingOverrides.empty()) {
3501 BestPath = &SpecificPath;
3502 std::swap(CurrentOverrides, LastOverrides);
3507 const CXXMethodDecl *ConflictMD = *MissingOverrides.begin();
3518 return BestPath ? BestPath : &FullPaths.front();
3525 FullPathTy FullPath;
3526 std::list<FullPathTy> FullPaths;
3527 for (
const std::unique_ptr<VPtrInfo>& Info : Paths) {
3530 BaseSubobject(Info->IntroducingObject, Info->FullOffsetInMDC), FullPath,
3534 Info->PathToIntroducingObject.clear();
3535 if (
const FullPathTy *BestPath =
3538 Info->PathToIntroducingObject.push_back(BSO.getBase());
3555 void MicrosoftVTableContext::computeVTableRelatedInformation(
3560 if (VFPtrLocations.count(RD))
3566 auto VFPtrs = llvm::make_unique<VPtrInfoVector>();
3567 computeVTablePaths(
false, RD, *VFPtrs);
3569 VFPtrLocations[RD] = std::move(VFPtrs);
3572 MethodVFTableLocationsTy NewMethodLocations;
3573 for (
const std::unique_ptr<VPtrInfo> &VFPtr : *VFPtrLocations[RD]) {
3574 VFTableBuilder Builder(*
this, RD, *VFPtr);
3576 VFTableIdTy
id(RD, VFPtr->FullOffsetInMDC);
3577 assert(VFTableLayouts.count(
id) == 0);
3579 Builder.vtable_thunks_begin(), Builder.vtable_thunks_end());
3580 VFTableLayouts[
id] = llvm::make_unique<VTableLayout>(
3582 EmptyAddressPointsMap);
3583 Thunks.insert(Builder.thunks_begin(), Builder.thunks_end());
3586 for (
const auto &Loc : Builder.vtable_locations()) {
3587 auto Insert = NewMethodLocations.insert(Loc);
3597 MethodVFTableLocations.insert(NewMethodLocations.begin(),
3598 NewMethodLocations.end());
3600 dumpMethodLocations(RD, NewMethodLocations, llvm::outs());
3603 void MicrosoftVTableContext::dumpMethodLocations(
3604 const CXXRecordDecl *RD,
const MethodVFTableLocationsTy &NewMethods,
3608 std::map<MethodVFTableLocation, std::string> IndicesMap;
3609 bool HasNonzeroOffset =
false;
3611 for (
const auto &I : NewMethods) {
3612 const CXXMethodDecl *MD = cast<const CXXMethodDecl>(I.first.getDecl());
3618 if (isa<CXXDestructorDecl>(MD)) {
3619 IndicesMap[I.second] = MethodName +
" [scalar deleting]";
3621 IndicesMap[I.second] = MethodName;
3624 if (!I.second.VFPtrOffset.isZero() || I.second.VBTableIndex != 0)
3625 HasNonzeroOffset =
true;
3629 if (!IndicesMap.empty()) {
3630 Out <<
"VFTable indices for ";
3633 Out <<
"' (" << IndicesMap.size()
3634 << (IndicesMap.size() == 1 ?
" entry" :
" entries") <<
").\n";
3637 uint64_t LastVBIndex = 0;
3638 for (
const auto &I : IndicesMap) {
3639 CharUnits VFPtrOffset = I.first.VFPtrOffset;
3640 uint64_t VBIndex = I.first.VBTableIndex;
3641 if (HasNonzeroOffset &&
3642 (VFPtrOffset != LastVFPtrOffset || VBIndex != LastVBIndex)) {
3643 assert(VBIndex > LastVBIndex || VFPtrOffset > LastVFPtrOffset);
3644 Out <<
" -- accessible via ";
3646 Out <<
"vbtable index " << VBIndex <<
", ";
3647 Out <<
"vfptr at offset " << VFPtrOffset.
getQuantity() <<
" --\n";
3648 LastVFPtrOffset = VFPtrOffset;
3649 LastVBIndex = VBIndex;
3652 uint64_t VTableIndex = I.first.Index;
3653 const std::string &MethodName = I.second;
3654 Out << llvm::format(
"%4" PRIu64
" | ", VTableIndex) << MethodName <<
'\n';
3662 const VirtualBaseInfo &MicrosoftVTableContext::computeVBTableRelatedInformation(
3669 std::unique_ptr<VirtualBaseInfo> &Entry = VBaseInfo[RD];
3672 Entry = llvm::make_unique<VirtualBaseInfo>();
3676 computeVTablePaths(
true, RD, VBI->
VBPtrPaths);
3684 computeVBTableRelatedInformation(VBPtrBase);
3692 for (
const auto &VB : RD->
vbases()) {
3693 const CXXRecordDecl *CurVBase = VB.getType()->getAsCXXRecordDecl();
3703 const VirtualBaseInfo &VBInfo = computeVBTableRelatedInformation(Derived);
3710 return computeVBTableRelatedInformation(RD).VBPtrPaths;
3715 computeVTableRelatedInformation(RD);
3717 assert(VFPtrLocations.count(RD) &&
"Couldn't find vfptr locations");
3718 return *VFPtrLocations[RD];
3724 computeVTableRelatedInformation(RD);
3726 VFTableIdTy
id(RD, VFPtrOffset);
3727 assert(VFTableLayouts.count(
id) &&
"Couldn't find a VFTable at this offset");
3728 return *VFTableLayouts[
id];
3733 assert(cast<CXXMethodDecl>(GD.
getDecl())->isVirtual() &&
3734 "Only use this method for virtual methods or dtors");
3735 if (isa<CXXDestructorDecl>(GD.
getDecl()))
3740 MethodVFTableLocationsTy::iterator I = MethodVFTableLocations.find(GD);
3741 if (I != MethodVFTableLocations.end())
3744 const CXXRecordDecl *RD = cast<CXXMethodDecl>(GD.getDecl())->getParent();
3746 computeVTableRelatedInformation(RD);
3748 I = MethodVFTableLocations.find(GD);
3749 assert(I != MethodVFTableLocations.end() &&
"Did not find index!");
Defines the clang::ASTContext interface.
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).
struct clang::ThisAdjustment::VirtualAdjustment::@133 Itanium
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...
struct clang::ReturnAdjustment::VirtualAdjustment::@131 Itanium
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...
~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)
struct clang::ReturnAdjustment::VirtualAdjustment::@132 Microsoft
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...
Qualifiers getTypeQuals() const
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.
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.
static std::string ComputeName(IdentKind IK, const Decl *CurrentDecl)
const VTableLayout & getVFTableLayout(const CXXRecordDecl *RD, CharUnits VFPtrOffset)
The same as PrettyFunction, except that the 'virtual' keyword is omitted for virtual member functions...
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 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.
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()
ASTImporterLookupTable & LT
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.
struct clang::ThisAdjustment::VirtualAdjustment::@134 Microsoft
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)