19 #include "llvm/ADT/SetOperations.h" 20 #include "llvm/ADT/SmallPtrSet.h" 21 #include "llvm/Support/Format.h" 22 #include "llvm/Support/raw_ostream.h" 26 using namespace clang;
28 #define DUMP_OVERRIDERS 0 49 BaseOffset() : DerivedClass(
nullptr), VirtualBase(
nullptr),
53 : DerivedClass(DerivedClass), VirtualBase(VirtualBase),
54 NonVirtualOffset(NonVirtualOffset) { }
56 bool isEmpty()
const {
return NonVirtualOffset.
isZero() && !VirtualBase; }
61 class FinalOverriders {
64 struct OverriderInfo {
75 OverriderInfo() : Method(
nullptr), VirtualBase(
nullptr),
101 typedef std::pair<const CXXMethodDecl *, CharUnits> MethodBaseOffsetPairTy;
103 typedef llvm::DenseMap<MethodBaseOffsetPairTy,
104 OverriderInfo> OverridersMapTy;
108 OverridersMapTy OverridersMap;
113 typedef llvm::DenseMap<std::pair<const CXXRecordDecl *, unsigned>,
116 typedef llvm::DenseMap<const CXXRecordDecl *, unsigned> SubobjectCountMapTy;
122 SubobjectOffsetMapTy &SubobjectOffsets,
123 SubobjectOffsetMapTy &SubobjectLayoutClassOffsets,
124 SubobjectCountMapTy &SubobjectCounts);
126 typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy;
131 VisitedVirtualBasesSetTy& VisitedVirtualBases);
142 assert(OverridersMap.count(std::make_pair(MD, BaseOffset)) &&
143 "Did not find overrider!");
145 return OverridersMap.lookup(std::make_pair(MD, BaseOffset));
150 VisitedVirtualBasesSetTy VisitedVirtualBases;
152 VisitedVirtualBases);
157 FinalOverriders::FinalOverriders(
const CXXRecordDecl *MostDerivedClass,
160 : MostDerivedClass(MostDerivedClass),
161 MostDerivedClassOffset(MostDerivedClassOffset), LayoutClass(LayoutClass),
166 SubobjectOffsetMapTy SubobjectOffsets;
167 SubobjectOffsetMapTy SubobjectLayoutClassOffsets;
168 SubobjectCountMapTy SubobjectCounts;
171 MostDerivedClassOffset,
172 SubobjectOffsets, SubobjectLayoutClassOffsets,
179 for (
const auto &Overrider : FinalOverriders) {
183 for (
const auto &M : Methods) {
184 unsigned SubobjectNumber = M.first;
185 assert(SubobjectOffsets.count(std::make_pair(MD->
getParent(),
187 "Did not find subobject offset!");
192 assert(M.second.size() == 1 &&
"Final overrider is not unique!");
196 assert(SubobjectLayoutClassOffsets.count(
197 std::make_pair(OverriderRD, Method.Subobject))
198 &&
"Did not find subobject offset!");
200 SubobjectLayoutClassOffsets[std::make_pair(OverriderRD,
203 OverriderInfo& Overrider = OverridersMap[std::make_pair(MD, BaseOffset)];
204 assert(!Overrider.Method &&
"Overrider should not exist yet!");
206 Overrider.Offset = OverriderOffset;
207 Overrider.Method = Method.Method;
208 Overrider.VirtualBase = Method.InVirtualSubobject;
218 static BaseOffset ComputeBaseOffset(
const ASTContext &Context,
223 unsigned NonVirtualStart = 0;
227 for (
int I = Path.size(), E = 0; I != E; --I) {
239 for (
unsigned I = NonVirtualStart, E = Path.size(); I != E; ++I) {
253 return BaseOffset(DerivedRD, VirtualBase, NonVirtualOffset);
257 static BaseOffset ComputeBaseOffset(
const ASTContext &Context,
264 llvm_unreachable(
"Class must be derived from the passed in base class!");
266 return ComputeBaseOffset(Context, DerivedRD, Paths.
front());
270 ComputeReturnAdjustmentBaseOffset(
ASTContext &Context,
282 assert(CanDerivedReturnType->getTypeClass() ==
283 CanBaseReturnType->getTypeClass() &&
284 "Types must have same type class!");
286 if (CanDerivedReturnType == CanBaseReturnType) {
291 if (isa<ReferenceType>(CanDerivedReturnType)) {
292 CanDerivedReturnType =
293 CanDerivedReturnType->getAs<
ReferenceType>()->getPointeeType();
296 }
else if (isa<PointerType>(CanDerivedReturnType)) {
297 CanDerivedReturnType =
298 CanDerivedReturnType->getAs<
PointerType>()->getPointeeType();
302 llvm_unreachable(
"Unexpected return type!");
308 if (CanDerivedReturnType.getUnqualifiedType() ==
315 cast<CXXRecordDecl>(cast<RecordType>(CanDerivedReturnType)->getDecl());
318 cast<CXXRecordDecl>(cast<RecordType>(CanBaseReturnType)->getDecl());
320 return ComputeBaseOffset(Context, BaseRD, DerivedRD);
326 SubobjectOffsetMapTy &SubobjectOffsets,
327 SubobjectOffsetMapTy &SubobjectLayoutClassOffsets,
328 SubobjectCountMapTy &SubobjectCounts) {
331 unsigned SubobjectNumber = 0;
333 SubobjectNumber = ++SubobjectCounts[RD];
336 assert(!SubobjectOffsets.count(std::make_pair(RD, SubobjectNumber))
337 &&
"Subobject offset already exists!");
338 assert(!SubobjectLayoutClassOffsets.count(std::make_pair(RD, SubobjectNumber))
339 &&
"Subobject offset already exists!");
341 SubobjectOffsets[std::make_pair(RD, SubobjectNumber)] = Base.
getBaseOffset();
342 SubobjectLayoutClassOffsets[std::make_pair(RD, SubobjectNumber)] =
346 for (
const auto &B : RD->
bases()) {
347 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
353 if (SubobjectOffsets.count(std::make_pair(BaseDecl, 0)))
359 BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
360 BaseOffsetInLayoutClass =
367 BaseOffsetInLayoutClass = OffsetInLayoutClass +
Offset;
371 B.isVirtual(), BaseOffsetInLayoutClass,
372 SubobjectOffsets, SubobjectLayoutClassOffsets,
378 VisitedVirtualBasesSetTy &VisitedVirtualBases) {
382 for (
const auto &B : RD->
bases()) {
383 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
391 if (!VisitedVirtualBases.insert(BaseDecl).second) {
396 BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
404 Out <<
"Final overriders for (";
410 for (
const auto *MD : RD->
methods()) {
411 if (!MD->isVirtual())
413 MD = MD->getCanonicalDecl();
415 OverriderInfo Overrider = getOverrider(MD, Base.
getBaseOffset());
418 MD->printQualifiedName(Out);
420 Overrider.Method->printQualifiedName(Out);
421 Out <<
", " << Overrider.Offset.getQuantity() <<
')';
424 if (!Overrider.Method->isPure())
425 Offset = ComputeReturnAdjustmentBaseOffset(Context, Overrider.Method, MD);
427 if (!Offset.isEmpty()) {
428 Out <<
" [ret-adj: ";
429 if (Offset.VirtualBase) {
430 Offset.VirtualBase->printQualifiedName(Out);
434 Out << Offset.NonVirtualOffset.getQuantity() <<
" nv]";
442 struct VCallOffsetMap {
444 typedef std::pair<const CXXMethodDecl *, CharUnits> MethodAndOffsetPairTy;
452 static bool MethodsCanShareVCallOffset(
const CXXMethodDecl *LHS,
466 bool empty()
const {
return Offsets.empty(); }
469 static bool HasSameVirtualSignature(
const CXXMethodDecl *LHS,
477 if (LT == RT)
return true;
487 bool VCallOffsetMap::MethodsCanShareVCallOffset(
const CXXMethodDecl *LHS,
489 assert(LHS->
isVirtual() &&
"LHS must be virtual!");
490 assert(RHS->
isVirtual() &&
"LHS must be virtual!");
493 if (isa<CXXDestructorDecl>(LHS))
494 return isa<CXXDestructorDecl>(RHS);
501 if (LHSName != RHSName)
505 return HasSameVirtualSignature(LHS, RHS);
511 for (
const auto &OffsetPair : Offsets) {
512 if (MethodsCanShareVCallOffset(OffsetPair.first, MD))
517 Offsets.push_back(MethodAndOffsetPairTy(MD, OffsetOffset));
523 for (
const auto &OffsetPair : Offsets) {
524 if (MethodsCanShareVCallOffset(OffsetPair.first, MD))
525 return OffsetPair.second;
528 llvm_unreachable(
"Should always find a vcall offset offset!");
532 class VCallAndVBaseOffsetBuilder {
534 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits>
535 VBaseOffsetOffsetsMapTy;
552 VTableComponentVectorTy Components;
555 llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBases;
558 VCallOffsetMap VCallOffsets;
563 VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
567 const FinalOverriders *Overriders;
571 void AddVCallAndVBaseOffsets(
BaseSubobject Base,
bool BaseIsVirtual,
583 CharUnits getCurrentOffsetOffset()
const;
586 VCallAndVBaseOffsetBuilder(
const CXXRecordDecl *MostDerivedClass,
588 const FinalOverriders *Overriders,
591 : MostDerivedClass(MostDerivedClass), LayoutClass(LayoutClass),
592 Context(MostDerivedClass->
getASTContext()), Overriders(Overriders) {
595 AddVCallAndVBaseOffsets(Base, BaseIsVirtual, OffsetInLayoutClass);
599 typedef VTableComponentVectorTy::const_reverse_iterator const_iterator;
600 const_iterator components_begin()
const {
return Components.rbegin(); }
601 const_iterator components_end()
const {
return Components.rend(); }
603 const VCallOffsetMap &getVCallOffsets()
const {
return VCallOffsets; }
604 const VBaseOffsetOffsetsMapTy &getVBaseOffsetOffsets()
const {
605 return VBaseOffsetOffsets;
610 VCallAndVBaseOffsetBuilder::AddVCallAndVBaseOffsets(
BaseSubobject Base,
630 if (PrimaryBaseIsVirtual) {
632 "Primary vbase should have a zero offset!");
638 MostDerivedClassLayout.getVBaseClassOffset(PrimaryBase);
641 "Primary base should have a zero offset!");
646 AddVCallAndVBaseOffsets(
648 PrimaryBaseIsVirtual, RealBaseOffset);
651 AddVBaseOffsets(Base.
getBase(), RealBaseOffset);
655 AddVCallOffsets(Base, RealBaseOffset);
658 CharUnits VCallAndVBaseOffsetBuilder::getCurrentOffsetOffset()
const {
663 int64_t OffsetIndex = -(int64_t)(3 + Components.size());
667 CharUnits OffsetOffset = PointerWidth * OffsetIndex;
671 void VCallAndVBaseOffsetBuilder::AddVCallOffsets(
BaseSubobject Base,
684 "Primary base should have a zero offset!");
691 for (
const auto *MD : RD->
methods()) {
696 CharUnits OffsetOffset = getCurrentOffsetOffset();
700 if (!VCallOffsets.AddVCallOffset(MD, OffsetOffset))
707 FinalOverriders::OverriderInfo Overrider =
712 Offset = Overrider.Offset - VBaseOffset;
715 Components.push_back(
720 for (
const auto &B : RD->
bases()) {
724 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
725 if (BaseDecl == PrimaryBase)
738 VCallAndVBaseOffsetBuilder::AddVBaseOffsets(
const CXXRecordDecl *RD,
744 for (
const auto &B : RD->
bases()) {
745 const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl();
748 if (B.isVirtual() && VisitedVirtualBases.insert(BaseDecl).second) {
753 assert(!VBaseOffsetOffsets.count(BaseDecl) &&
754 "vbase offset offset already exists!");
756 CharUnits VBaseOffsetOffset = getCurrentOffsetOffset();
757 VBaseOffsetOffsets.insert(
758 std::make_pair(BaseDecl, VBaseOffsetOffset));
760 Components.push_back(
765 AddVBaseOffsets(BaseDecl, OffsetInLayoutClass);
770 class ItaniumVTableBuilder {
775 PrimaryBasesSetVectorTy;
777 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits>
778 VBaseOffsetOffsetsMapTy;
782 typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVTableIndicesTy;
798 bool MostDerivedClassIsVirtual;
809 const FinalOverriders Overriders;
813 llvm::DenseMap<const CXXRecordDecl *, VCallOffsetMap> VCallOffsetsForVBases;
817 VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
823 AddressPointsMapTy AddressPoints;
837 const uint64_t VTableIndex;
840 uint64_t VTableIndex)
841 : BaseOffset(BaseOffset),
842 BaseOffsetInLayoutClass(BaseOffsetInLayoutClass),
843 VTableIndex(VTableIndex) { }
850 MethodInfo(MethodInfo
const&) =
default;
853 typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy;
857 MethodInfoMapTy MethodInfoMap;
861 MethodVTableIndicesTy MethodVTableIndices;
863 typedef llvm::DenseMap<uint64_t, ThunkInfo> VTableThunksMapTy;
867 VTableThunksMapTy VTableThunks;
870 typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
881 void ComputeThisAdjustments();
883 typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy;
887 VisitedVirtualBasesSetTy PrimaryVirtualBases;
895 BaseOffset ComputeThisAdjustmentBaseOffset(
BaseSubobject Base,
904 FinalOverriders::OverriderInfo Overrider);
932 CharUnits FirstBaseOffsetInLayoutClass)
const;
940 PrimaryBasesSetVectorTy &PrimaryBases);
955 bool BaseIsMorallyVirtual,
956 bool BaseIsVirtualInLayoutClass,
964 void LayoutSecondaryVTables(
BaseSubobject Base,
bool BaseIsMorallyVirtual,
971 VisitedVirtualBasesSetTy &VBases);
976 VisitedVirtualBasesSetTy &VBases);
980 bool isBuildingConstructorVTable()
const {
981 return MostDerivedClass != LayoutClass;
992 bool MostDerivedClassIsVirtual,
994 : VTables(VTables), MostDerivedClass(MostDerivedClass),
995 MostDerivedClassOffset(MostDerivedClassOffset),
996 MostDerivedClassIsVirtual(MostDerivedClassIsVirtual),
997 LayoutClass(LayoutClass), Context(MostDerivedClass->
getASTContext()),
998 Overriders(MostDerivedClass, MostDerivedClassOffset, LayoutClass) {
1004 dumpLayout(llvm::outs());
1007 uint64_t getNumThunks()
const {
1008 return Thunks.size();
1011 ThunksMapTy::const_iterator thunks_begin()
const {
1012 return Thunks.begin();
1015 ThunksMapTy::const_iterator thunks_end()
const {
1016 return Thunks.end();
1019 const VBaseOffsetOffsetsMapTy &getVBaseOffsetOffsets()
const {
1020 return VBaseOffsetOffsets;
1023 const AddressPointsMapTy &getAddressPoints()
const {
1024 return AddressPoints;
1027 MethodVTableIndicesTy::const_iterator vtable_indices_begin()
const {
1028 return MethodVTableIndices.begin();
1031 MethodVTableIndicesTy::const_iterator vtable_indices_end()
const {
1032 return MethodVTableIndices.end();
1037 AddressPointsMapTy::const_iterator address_points_begin()
const {
1038 return AddressPoints.begin();
1041 AddressPointsMapTy::const_iterator address_points_end()
const {
1042 return AddressPoints.end();
1045 VTableThunksMapTy::const_iterator vtable_thunks_begin()
const {
1046 return VTableThunks.begin();
1049 VTableThunksMapTy::const_iterator vtable_thunks_end()
const {
1050 return VTableThunks.end();
1054 void dumpLayout(raw_ostream&);
1057 void ItaniumVTableBuilder::AddThunk(
const CXXMethodDecl *MD,
1059 assert(!isBuildingConstructorVTable() &&
1060 "Can't add thunks for construction vtable");
1065 if (llvm::find(ThunksVector, Thunk) != ThunksVector.end())
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 std::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 (llvm::find(ThunksVector, Thunk) != ThunksVector.end())
2457 ThunksVector.push_back(Thunk);
2462 CharUnits ComputeThisOffset(FinalOverriders::OverriderInfo Overrider);
2464 void CalculateVtordispAdjustment(FinalOverriders::OverriderInfo Overrider,
2471 VTableThunks[Components.size()] = TI;
2476 "Destructor can't have return adjustment!");
2487 BasesSetVectorTy &VisitedBases);
2489 void LayoutVFTable() {
2491 if (HasRTTIComponent)
2494 BasesSetVectorTy VisitedBases;
2497 assert((HasRTTIComponent ? Components.size() - 1 : Components.size()) &&
2498 "vftable can't be empty");
2500 assert(MethodVFTableLocations.empty());
2501 for (
const auto &I : MethodInfoMap) {
2503 const MethodInfo &MI = I.second;
2508 if (MD->
getParent() != MostDerivedClass || MI.Shadowed)
2515 MethodVFTableLocations[MD] = Loc;
2525 MostDerivedClass(MostDerivedClass),
2528 Overriders(MostDerivedClass,
CharUnits(), MostDerivedClass) {
2535 HasRTTIComponent =
true;
2540 dumpLayout(llvm::outs());
2543 uint64_t getNumThunks()
const {
return Thunks.size(); }
2545 ThunksMapTy::const_iterator thunks_begin()
const {
return Thunks.begin(); }
2547 ThunksMapTy::const_iterator thunks_end()
const {
return Thunks.end(); }
2549 method_locations_range vtable_locations()
const {
2550 return method_locations_range(MethodVFTableLocations.begin(),
2551 MethodVFTableLocations.end());
2556 VTableThunksMapTy::const_iterator vtable_thunks_begin()
const {
2557 return VTableThunks.begin();
2560 VTableThunksMapTy::const_iterator vtable_thunks_end()
const {
2561 return VTableThunks.end();
2564 void dumpLayout(raw_ostream &);
2624 VFTableBuilder::ComputeThisOffset(FinalOverriders::OverriderInfo Overrider) {
2625 BasesSetVectorTy Bases;
2629 OverriddenMethodsSetTy VisitedOverriddenMethods;
2630 auto InitialOverriddenDefinitionCollector = [&](
2632 if (OverriddenMD->size_overridden_methods() == 0)
2633 Bases.insert(OverriddenMD->getParent());
2635 return VisitedOverriddenMethods.insert(OverriddenMD).second;
2637 visitAllOverriddenMethods(Overrider.Method,
2638 InitialOverriddenDefinitionCollector);
2643 if (Bases.size() == 0)
2644 return Overrider.Offset;
2647 Overrider.Method->getParent()->lookupInBases(
2663 CharUnits ThisOffset = Overrider.Offset;
2670 QualType CurTy = Element.Base->getType();
2675 if (Element.Base->isVirtual()) {
2686 LastVBaseOffset = ThisOffset =
2693 if (isa<CXXDestructorDecl>(Overrider.Method)) {
2694 if (LastVBaseOffset.
isZero()) {
2698 ThisOffset = Overrider.Offset;
2702 ThisOffset = LastVBaseOffset;
2706 if (Ret > ThisOffset || First) {
2712 assert(!First &&
"Method not found in the given subobject?");
2814 void VFTableBuilder::CalculateVtordispAdjustment(
2815 FinalOverriders::OverriderInfo Overrider,
CharUnits ThisOffset,
2818 MostDerivedClassLayout.getVBaseOffsetsMap();
2819 const ASTRecordLayout::VBaseOffsetsMapTy::const_iterator &VBaseMapEntry =
2820 VBaseMap.find(WhichVFPtr.getVBaseWithVPtr());
2821 assert(VBaseMapEntry != VBaseMap.end());
2825 if (!VBaseMapEntry->second.hasVtorDisp() ||
2826 Overrider.VirtualBase == WhichVFPtr.getVBaseWithVPtr())
2831 CharUnits OffsetOfVBaseWithVFPtr = VBaseMapEntry->second.VBaseOffset;
2833 (OffsetOfVBaseWithVFPtr - WhichVFPtr.FullOffsetInMDC).getQuantity() - 4;
2837 if (Overrider.Method->getParent() == MostDerivedClass ||
2838 !Overrider.VirtualBase)
2844 (OffsetOfVBaseWithVFPtr + WhichVFPtr.NonVirtualOffset -
2845 MostDerivedClassLayout.getVBPtrOffset()).getQuantity();
2848 VTables.getVBTableIndex(MostDerivedClass, Overrider.VirtualBase);
2850 TA.
NonVirtual = (ThisOffset - Overrider.Offset).getQuantity();
2864 typedef llvm::DenseMap<DeclarationName, unsigned> VisitedGroupIndicesTy;
2865 VisitedGroupIndicesTy VisitedGroupIndices;
2866 for (
const auto *D : RD->
decls()) {
2867 const auto *ND = dyn_cast<
NamedDecl>(D);
2870 VisitedGroupIndicesTy::iterator J;
2872 std::tie(J, Inserted) = VisitedGroupIndices.insert(
2873 std::make_pair(ND->getDeclName(), Groups.size()));
2875 Groups.push_back(MethodGroup());
2876 if (
const auto *MD = dyn_cast<CXXMethodDecl>(ND))
2877 if (MD->isVirtual())
2878 Groups[J->second].push_back(MD->getCanonicalDecl());
2881 for (
const MethodGroup &Group : Groups)
2882 VirtualMethods.append(Group.rbegin(), Group.rend());
2886 for (
const auto &B : RD->
bases()) {
2887 if (B.isVirtual() && B.getType()->getAsCXXRecordDecl() == Base)
2895 BasesSetVectorTy &VisitedBases) {
2905 const CXXRecordDecl *NextBase =
nullptr, *NextLastVBase = LastVBase;
2907 if (BaseDepth < WhichVFPtr.PathToIntroducingObject.size()) {
2908 NextBase = WhichVFPtr.PathToIntroducingObject[BaseDepth];
2910 NextLastVBase = NextBase;
2911 NextBaseOffset = MostDerivedClassLayout.getVBaseClassOffset(NextBase);
2918 "No primary virtual bases in this ABI");
2919 NextBase = PrimaryBase;
2924 AddMethods(
BaseSubobject(NextBase, NextBaseOffset), BaseDepth + 1,
2925 NextLastVBase, VisitedBases);
2926 if (!VisitedBases.insert(NextBase))
2927 llvm_unreachable(
"Found a duplicate primary base!");
2943 FinalOverriders::OverriderInfo FinalOverrider =
2945 const CXXMethodDecl *FinalOverriderMD = FinalOverrider.Method;
2947 FindNearestOverriddenMethod(MD, VisitedBases);
2950 bool ReturnAdjustingThunk =
false, ForceReturnAdjustmentMangling =
false;
2951 CharUnits ThisOffset = ComputeThisOffset(FinalOverrider);
2953 (ThisOffset - WhichVFPtr.FullOffsetInMDC).getQuantity();
2954 if ((OverriddenMD || FinalOverriderMD != MD) &&
2955 WhichVFPtr.getVBaseWithVPtr())
2956 CalculateVtordispAdjustment(FinalOverrider, ThisOffset,
2957 ThisAdjustmentOffset);
2960 LastVBase ? VTables.getVBTableIndex(MostDerivedClass, LastVBase) : 0;
2965 MethodInfoMapTy::iterator OverriddenMDIterator =
2966 MethodInfoMap.find(OverriddenMD);
2969 if (OverriddenMDIterator == MethodInfoMap.end())
2972 MethodInfo &OverriddenMethodInfo = OverriddenMDIterator->second;
2974 VBIndex = OverriddenMethodInfo.VBTableIndex;
2981 ReturnAdjustingThunk = !ComputeReturnAdjustmentBaseOffset(
2982 Context, MD, OverriddenMD).isEmpty() ||
2983 OverriddenMethodInfo.UsesExtraSlot;
2985 if (!ReturnAdjustingThunk) {
2988 MethodInfo MI(VBIndex, OverriddenMethodInfo.VFTableIndex);
2989 MethodInfoMap.erase(OverriddenMDIterator);
2991 assert(!MethodInfoMap.count(MD) &&
2992 "Should not have method info for this method yet!");
2993 MethodInfoMap.insert(std::make_pair(MD, MI));
2999 OverriddenMethodInfo.Shadowed =
true;
3003 ForceReturnAdjustmentMangling =
3004 !(MD == FinalOverriderMD && ThisAdjustmentOffset.
isEmpty());
3005 }
else if (Base.
getBaseOffset() != WhichVFPtr.FullOffsetInMDC ||
3006 MD->size_overridden_methods()) {
3015 MethodInfo MI(VBIndex,
3016 HasRTTIComponent ? Components.size() - 1 : Components.size(),
3017 ReturnAdjustingThunk);
3019 assert(!MethodInfoMap.count(MD) &&
3020 "Should not have method info for this method yet!");
3021 MethodInfoMap.insert(std::make_pair(MD, MI));
3025 BaseOffset ReturnAdjustmentOffset;
3027 if (!FinalOverriderMD->
isPure()) {
3028 ReturnAdjustmentOffset =
3029 ComputeReturnAdjustmentBaseOffset(Context, FinalOverriderMD, MD);
3031 if (!ReturnAdjustmentOffset.isEmpty()) {
3032 ForceReturnAdjustmentMangling =
true;
3034 ReturnAdjustmentOffset.NonVirtualOffset.getQuantity();
3035 if (ReturnAdjustmentOffset.VirtualBase) {
3041 VTables.getVBTableIndex(ReturnAdjustmentOffset.DerivedClass,
3042 ReturnAdjustmentOffset.VirtualBase);
3046 AddMethod(FinalOverriderMD,
3047 ThunkInfo(ThisAdjustmentOffset, ReturnAdjustment,
3048 ForceReturnAdjustmentMangling ? MD :
nullptr));
3054 llvm::make_range(Path.rbegin(), Path.rend())) {
3056 Elem->printQualifiedName(Out);
3062 bool ContinueFirstLine) {
3064 bool Multiline =
false;
3065 const char *LinePrefix =
"\n ";
3067 if (!ContinueFirstLine)
3069 Out <<
"[return adjustment (to type '" 3082 if (Multiline || !ContinueFirstLine)
3084 Out <<
"[this adjustment: ";
3092 Out << LinePrefix <<
" vboffset at " 3100 void VFTableBuilder::dumpLayout(raw_ostream &Out) {
3101 Out <<
"VFTable for ";
3104 MostDerivedClass->printQualifiedName(Out);
3105 Out <<
"' (" << Components.size()
3106 << (Components.size() == 1 ?
" entry" :
" entries") <<
").\n";
3108 for (
unsigned I = 0, E = Components.size(); I != E; ++I) {
3109 Out << llvm::format(
"%4d | ", I);
3114 switch (Component.
getKind()) {
3132 Out <<
" [deleted]";
3134 ThunkInfo Thunk = VTableThunks.lookup(I);
3145 Out <<
"() [scalar deleting]";
3150 ThunkInfo Thunk = VTableThunks.lookup(I);
3153 "No return adjustment needed for destructors!");
3164 "Unexpected vftable component type %0 for component number %1");
3165 Diags.
Report(MostDerivedClass->getLocation(), DiagID)
3176 std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls;
3178 for (
const auto &I :
Thunks) {
3183 MethodNamesAndDecls.insert(std::make_pair(MethodName, MD));
3186 for (
const auto &MethodNameAndDecl : MethodNamesAndDecls) {
3187 const std::string &MethodName = MethodNameAndDecl.first;
3191 llvm::stable_sort(ThunksVector, [](
const ThunkInfo &LHS,
3198 Out <<
"Thunks for '" << MethodName <<
"' (" << ThunksVector.size();
3199 Out << (ThunksVector.size() == 1 ?
" entry" :
" entries") <<
").\n";
3201 for (
unsigned I = 0, E = ThunksVector.size(); I != E; ++I) {
3202 const ThunkInfo &Thunk = ThunksVector[I];
3204 Out << llvm::format(
"%4d | ", I);
3248 void MicrosoftVTableContext::computeVTablePaths(
bool ForVBTables,
3251 assert(Paths.empty());
3255 if (ForVBTables ? Layout.hasOwnVBPtr() : Layout.hasOwnVFPtr())
3256 Paths.push_back(std::make_unique<VPtrInfo>(RD));
3260 llvm::SmallPtrSet<const CXXRecordDecl*, 4> VBasesSeen;
3261 for (
const auto &B : RD->
bases()) {
3262 const CXXRecordDecl *Base = B.getType()->getAsCXXRecordDecl();
3263 if (B.isVirtual() && VBasesSeen.count(Base))
3270 ForVBTables ? enumerateVBTables(Base) : getVFPtrOffsets(Base);
3272 for (
const std::unique_ptr<VPtrInfo> &BaseInfo : BasePaths) {
3279 auto P = std::make_unique<VPtrInfo>(*BaseInfo);
3283 if (
P->MangledPath.empty() ||
P->MangledPath.back() != Base)
3284 P->NextBaseToMangle = Base;
3289 if (
P->ObjectWithVPtr == Base &&
3290 Base == (ForVBTables ? Layout.getBaseSharingVBPtr()
3291 : Layout.getPrimaryBase()))
3292 P->ObjectWithVPtr = RD;
3297 P->ContainingVBases.push_back(Base);
3298 else if (
P->ContainingVBases.empty())
3299 P->NonVirtualOffset += Layout.getBaseClassOffset(Base);
3302 P->FullOffsetInMDC =
P->NonVirtualOffset;
3304 P->FullOffsetInMDC += Layout.getVBaseClassOffset(VB);
3306 Paths.push_back(std::move(
P));
3310 VBasesSeen.insert(Base);
3314 for (
const auto &VB : Base->
vbases())
3315 VBasesSeen.insert(VB.getType()->getAsCXXRecordDecl());
3320 bool Changed =
true;
3342 PathsSorted.reserve(Paths.size());
3343 for (
auto&
P : Paths)
3344 PathsSorted.push_back(*
P);
3348 bool Changed =
false;
3349 for (
size_t I = 0, E = PathsSorted.size(); I != E;) {
3351 size_t BucketStart = I;
3355 PathsSorted[BucketStart].
get().MangledPath ==
3356 PathsSorted[I].get().MangledPath);
3359 if (I - BucketStart > 1) {
3360 for (
size_t II = BucketStart; II != I; ++II)
3362 assert(Changed &&
"no paths were extended to fix ambiguity");
3371 typedef llvm::SetVector<BaseSubobject, std::vector<BaseSubobject>,
3381 FullPathTy &FullPath,
3382 std::list<FullPathTy> &Paths) {
3384 Paths.push_back(FullPath);
3391 const CXXRecordDecl *Base = BS.getType()->getAsCXXRecordDecl();
3397 IntroducingObject, FullPath, Paths);
3398 FullPath.pop_back();
3404 FullPaths.remove_if([&](
const FullPathTy &SpecificPath) {
3405 for (
const FullPathTy &OtherPath : FullPaths) {
3406 if (&SpecificPath == &OtherPath)
3408 if (llvm::all_of(SpecificPath, [&](
const BaseSubobject &BSO) {
3409 return OtherPath.count(BSO) != 0;
3420 const FullPathTy &FullPath) {
3441 : Offset + Layout.getBaseClassOffset(Base);
3453 std::list<FullPathTy> &FullPaths) {
3455 if (FullPaths.empty())
3457 if (FullPaths.size() == 1)
3458 return &FullPaths.front();
3460 const FullPathTy *BestPath =
nullptr;
3461 typedef std::set<const CXXMethodDecl *> OverriderSetTy;
3462 OverriderSetTy LastOverrides;
3463 for (
const FullPathTy &SpecificPath : FullPaths) {
3464 assert(!SpecificPath.empty());
3465 OverriderSetTy CurrentOverrides;
3466 const CXXRecordDecl *TopLevelRD = SpecificPath.begin()->getBase();
3471 FinalOverriders Overriders(TopLevelRD,
CharUnits::Zero(), TopLevelRD);
3473 if (!MD->isVirtual())
3475 FinalOverriders::OverriderInfo OI =
3476 Overriders.getOverrider(MD->getCanonicalDecl(), BaseOffset);
3480 if (ComputeReturnAdjustmentBaseOffset(Context, OverridingMethod, MD)
3486 if (llvm::none_of(SpecificPath, [&](
const BaseSubobject &BSO) {
3487 return BSO.
getBase() == OverridingParent;
3490 CurrentOverrides.insert(OverridingMethod);
3492 OverriderSetTy NewOverrides =
3493 llvm::set_difference(CurrentOverrides, LastOverrides);
3494 if (NewOverrides.empty())
3496 OverriderSetTy MissingOverrides =
3497 llvm::set_difference(LastOverrides, CurrentOverrides);
3498 if (MissingOverrides.empty()) {
3500 BestPath = &SpecificPath;
3501 std::swap(CurrentOverrides, LastOverrides);
3506 const CXXMethodDecl *ConflictMD = *MissingOverrides.begin();
3517 return BestPath ? BestPath : &FullPaths.front();
3524 FullPathTy FullPath;
3525 std::list<FullPathTy> FullPaths;
3526 for (
const std::unique_ptr<VPtrInfo>& Info : Paths) {
3529 BaseSubobject(Info->IntroducingObject, Info->FullOffsetInMDC), FullPath,
3533 Info->PathToIntroducingObject.clear();
3534 if (
const FullPathTy *BestPath =
3537 Info->PathToIntroducingObject.push_back(BSO.getBase());
3554 void MicrosoftVTableContext::computeVTableRelatedInformation(
3559 if (VFPtrLocations.count(RD))
3565 auto VFPtrs = std::make_unique<VPtrInfoVector>();
3566 computeVTablePaths(
false, RD, *VFPtrs);
3568 VFPtrLocations[RD] = std::move(VFPtrs);
3571 MethodVFTableLocationsTy NewMethodLocations;
3572 for (
const std::unique_ptr<VPtrInfo> &VFPtr : *VFPtrLocations[RD]) {
3573 VFTableBuilder Builder(*
this, RD, *VFPtr);
3575 VFTableIdTy id(RD, VFPtr->FullOffsetInMDC);
3576 assert(VFTableLayouts.count(
id) == 0);
3578 Builder.vtable_thunks_begin(), Builder.vtable_thunks_end());
3579 VFTableLayouts[id] = std::make_unique<VTableLayout>(
3581 EmptyAddressPointsMap);
3582 Thunks.insert(Builder.thunks_begin(), Builder.thunks_end());
3585 for (
const auto &Loc : Builder.vtable_locations()) {
3586 auto Insert = NewMethodLocations.insert(Loc);
3596 MethodVFTableLocations.insert(NewMethodLocations.begin(),
3597 NewMethodLocations.end());
3599 dumpMethodLocations(RD, NewMethodLocations, llvm::outs());
3602 void MicrosoftVTableContext::dumpMethodLocations(
3603 const CXXRecordDecl *RD,
const MethodVFTableLocationsTy &NewMethods,
3607 std::map<MethodVFTableLocation, std::string> IndicesMap;
3608 bool HasNonzeroOffset =
false;
3610 for (
const auto &I : NewMethods) {
3611 const CXXMethodDecl *MD = cast<const CXXMethodDecl>(I.first.getDecl());
3617 if (isa<CXXDestructorDecl>(MD)) {
3618 IndicesMap[I.second] = MethodName +
" [scalar deleting]";
3620 IndicesMap[I.second] = MethodName;
3623 if (!I.second.VFPtrOffset.isZero() || I.second.VBTableIndex != 0)
3624 HasNonzeroOffset =
true;
3628 if (!IndicesMap.empty()) {
3629 Out <<
"VFTable indices for ";
3632 Out <<
"' (" << IndicesMap.size()
3633 << (IndicesMap.size() == 1 ?
" entry" :
" entries") <<
").\n";
3636 uint64_t LastVBIndex = 0;
3637 for (
const auto &I : IndicesMap) {
3638 CharUnits VFPtrOffset = I.first.VFPtrOffset;
3639 uint64_t VBIndex = I.first.VBTableIndex;
3640 if (HasNonzeroOffset &&
3641 (VFPtrOffset != LastVFPtrOffset || VBIndex != LastVBIndex)) {
3642 assert(VBIndex > LastVBIndex || VFPtrOffset > LastVFPtrOffset);
3643 Out <<
" -- accessible via ";
3645 Out <<
"vbtable index " << VBIndex <<
", ";
3646 Out <<
"vfptr at offset " << VFPtrOffset.
getQuantity() <<
" --\n";
3647 LastVFPtrOffset = VFPtrOffset;
3648 LastVBIndex = VBIndex;
3651 uint64_t VTableIndex = I.first.Index;
3652 const std::string &MethodName = I.second;
3653 Out << llvm::format(
"%4" PRIu64
" | ", VTableIndex) << MethodName <<
'\n';
3661 const VirtualBaseInfo &MicrosoftVTableContext::computeVBTableRelatedInformation(
3668 std::unique_ptr<VirtualBaseInfo> &Entry = VBaseInfo[RD];
3671 Entry = std::make_unique<VirtualBaseInfo>();
3675 computeVTablePaths(
true, RD, VBI->
VBPtrPaths);
3683 computeVBTableRelatedInformation(VBPtrBase);
3691 for (
const auto &VB : RD->
vbases()) {
3692 const CXXRecordDecl *CurVBase = VB.getType()->getAsCXXRecordDecl();
3702 const VirtualBaseInfo &VBInfo = computeVBTableRelatedInformation(Derived);
3709 return computeVBTableRelatedInformation(RD).VBPtrPaths;
3714 computeVTableRelatedInformation(RD);
3716 assert(VFPtrLocations.count(RD) &&
"Couldn't find vfptr locations");
3717 return *VFPtrLocations[RD];
3723 computeVTableRelatedInformation(RD);
3725 VFTableIdTy id(RD, VFPtrOffset);
3726 assert(VFTableLayouts.count(
id) &&
"Couldn't find a VFTable at this offset");
3727 return *VFTableLayouts[id];
3732 assert(cast<CXXMethodDecl>(GD.
getDecl())->isVirtual() &&
3733 "Only use this method for virtual methods or dtors");
3734 if (isa<CXXDestructorDecl>(GD.
getDecl()))
3739 MethodVFTableLocationsTy::iterator I = MethodVFTableLocations.find(GD);
3740 if (I != MethodVFTableLocations.end())
3743 const CXXRecordDecl *RD = cast<CXXMethodDecl>(GD.getDecl())->getParent();
3745 computeVTableRelatedInformation(RD);
3747 I = MethodVFTableLocations.find(GD);
3748 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).
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...
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...
~ItaniumVTableContext() override
The set of methods that override a given virtual method in each subobject where it occurs...
CharUnits - This is an opaque type for sizes expressed in character units.
llvm::DenseMap< const CXXMethodDecl *, ThunkInfoVectorTy > ThunksMapTy
~MicrosoftVTableContext() override
static void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef< CounterExpression > Expressions, ArrayRef< CounterMappingRegion > Regions)
const CXXRecordDecl * IntroducingObject
This is the class that introduced the vptr by declaring new virtual methods or virtual bases...
Concrete class used by the front-end to report problems and issues.
const VPtrInfoVector & getVFPtrOffsets(const CXXRecordDecl *RD)
base_class_iterator bases_begin()
static void removeRedundantPaths(std::list< FullPathTy > &FullPaths)
uint64_t getMethodVTableIndex(GlobalDecl GD)
Locate a virtual function in the vtable.
CharUnits getVirtualBaseOffsetOffset(const CXXRecordDecl *RD, const CXXRecordDecl *VBase)
Return the offset in chars (relative to the vtable address point) where the offset of the virtual bas...
static bool setsIntersect(const llvm::SmallPtrSet< const CXXRecordDecl *, 4 > &A, ArrayRef< const CXXRecordDecl *> B)
static VTableComponent MakeDeletingDtor(const CXXDestructorDecl *DD)
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Represents a prototype with parameter type info, e.g.
bool isDynamicClass() const
union clang::ReturnAdjustment::VirtualAdjustment Virtual
struct clang::ReturnAdjustment::VirtualAdjustment::@136 Microsoft
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
static void GroupNewVirtualOverloads(const CXXRecordDecl *RD, SmallVector< const CXXMethodDecl *, 10 > &VirtualMethods)
SmallVector< ThunkInfo, 1 > ThunkInfoVectorTy
const T * castAs() const
Member-template castAs<specific type>.
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.
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)
struct clang::ThisAdjustment::VirtualAdjustment::@138 Microsoft
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 bool Ret(InterpState &S, CodePtr &PC, APValue &Result)
struct clang::ReturnAdjustment::VirtualAdjustment::@135 Itanium
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)
Qualifiers getMethodQuals() const
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
Return 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.
An entry that is never used.
struct clang::ThisAdjustment::VirtualAdjustment::@137 Itanium
SourceLocation getLocation() const
method_range methods() const
QualType getType() const
Retrieves the type of the base class.
static VTableComponent MakeOffsetToTop(CharUnits Offset)