20 #include "llvm/ADT/SmallSet.h"
21 #include "llvm/Support/CrashRecoveryContext.h"
22 #include "llvm/Support/Format.h"
23 #include "llvm/Support/MathExtras.h"
25 using namespace clang;
40 struct BaseSubobjectInfo {
52 BaseSubobjectInfo *PrimaryVirtualBaseInfo;
55 const BaseSubobjectInfo *Derived;
61 struct ExternalLayout {
62 ExternalLayout() : Size(0), Align(0) {}
71 llvm::DenseMap<const FieldDecl *, uint64_t> FieldOffsets;
74 llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsets;
77 llvm::DenseMap<const CXXRecordDecl *, CharUnits> VirtualBaseOffsets;
81 uint64_t getExternalFieldOffset(
const FieldDecl *FD) {
82 assert(FieldOffsets.count(FD) &&
83 "Field does not have an external offset");
84 return FieldOffsets[FD];
88 auto Known = BaseOffsets.find(RD);
89 if (Known == BaseOffsets.end())
91 BaseOffset = Known->second;
96 auto Known = VirtualBaseOffsets.find(RD);
97 if (Known == VirtualBaseOffsets.end())
99 BaseOffset = Known->second;
106 class EmptySubobjectMap {
114 typedef llvm::TinyPtrVector<const CXXRecordDecl *> ClassVectorTy;
115 typedef llvm::DenseMap<CharUnits, ClassVectorTy> EmptyClassOffsetsMapTy;
116 EmptyClassOffsetsMapTy EmptyClassOffsets;
124 void ComputeEmptySubobjectSizes();
128 void UpdateEmptyBaseSubobjects(
const BaseSubobjectInfo *Info,
139 return Offset <= MaxEmptyClassOffset;
145 assert(FieldOffset % CharWidth == 0 &&
146 "Field offset not at char boundary!");
155 bool CanPlaceBaseSubobjectAtOffset(
const BaseSubobjectInfo *Info,
161 bool CanPlaceFieldSubobjectAtOffset(
const FieldDecl *FD,
171 : Context(Context), CharWidth(Context.
getCharWidth()), Class(Class) {
172 ComputeEmptySubobjectSizes();
179 bool CanPlaceBaseAtOffset(
const BaseSubobjectInfo *Info,
187 void EmptySubobjectMap::ComputeEmptySubobjectSizes() {
202 if (EmptySize > SizeOfLargestEmptySubobject)
203 SizeOfLargestEmptySubobject = EmptySize;
207 for (
const FieldDecl *FD : Class->fields()) {
226 if (EmptySize > SizeOfLargestEmptySubobject)
227 SizeOfLargestEmptySubobject = EmptySize;
232 EmptySubobjectMap::CanPlaceSubobjectAtOffset(
const CXXRecordDecl *RD,
238 EmptyClassOffsetsMapTy::const_iterator I = EmptyClassOffsets.find(Offset);
239 if (I == EmptyClassOffsets.end())
242 const ClassVectorTy &Classes = I->second;
243 if (std::find(Classes.begin(), Classes.end(), RD) == Classes.end())
250 void EmptySubobjectMap::AddSubobjectAtOffset(
const CXXRecordDecl *RD,
258 ClassVectorTy &Classes = EmptyClassOffsets[
Offset];
259 if (std::find(Classes.begin(), Classes.end(), RD) != Classes.end())
262 Classes.push_back(RD);
265 if (Offset > MaxEmptyClassOffset)
266 MaxEmptyClassOffset =
Offset;
270 EmptySubobjectMap::CanPlaceBaseSubobjectAtOffset(
const BaseSubobjectInfo *Info,
274 if (!AnyEmptySubobjectsBeyondOffset(Offset))
277 if (!CanPlaceSubobjectAtOffset(Info->Class, Offset))
282 for (
const BaseSubobjectInfo *
Base : Info->Bases) {
288 if (!CanPlaceBaseSubobjectAtOffset(Base, BaseOffset))
292 if (Info->PrimaryVirtualBaseInfo) {
293 BaseSubobjectInfo *PrimaryVirtualBaseInfo = Info->PrimaryVirtualBaseInfo;
295 if (Info == PrimaryVirtualBaseInfo->Derived) {
296 if (!CanPlaceBaseSubobjectAtOffset(PrimaryVirtualBaseInfo, Offset))
302 unsigned FieldNo = 0;
304 E = Info->Class->field_end(); I != E; ++I, ++FieldNo) {
309 if (!CanPlaceFieldSubobjectAtOffset(*I, FieldOffset))
316 void EmptySubobjectMap::UpdateEmptyBaseSubobjects(
const BaseSubobjectInfo *Info,
318 bool PlacingEmptyBase) {
319 if (!PlacingEmptyBase && Offset >= SizeOfLargestEmptySubobject) {
328 AddSubobjectAtOffset(Info->Class, Offset);
332 for (
const BaseSubobjectInfo *Base : Info->Bases) {
337 UpdateEmptyBaseSubobjects(Base, BaseOffset, PlacingEmptyBase);
340 if (Info->PrimaryVirtualBaseInfo) {
341 BaseSubobjectInfo *PrimaryVirtualBaseInfo = Info->PrimaryVirtualBaseInfo;
343 if (Info == PrimaryVirtualBaseInfo->Derived)
344 UpdateEmptyBaseSubobjects(PrimaryVirtualBaseInfo, Offset,
349 unsigned FieldNo = 0;
351 E = Info->Class->field_end(); I != E; ++I, ++FieldNo) {
356 UpdateEmptyFieldSubobjects(*I, FieldOffset);
360 bool EmptySubobjectMap::CanPlaceBaseAtOffset(
const BaseSubobjectInfo *Info,
364 if (SizeOfLargestEmptySubobject.isZero())
367 if (!CanPlaceBaseSubobjectAtOffset(Info, Offset))
372 UpdateEmptyBaseSubobjects(Info, Offset, Info->Class->isEmpty());
377 EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(
const CXXRecordDecl *RD,
382 if (!AnyEmptySubobjectsBeyondOffset(Offset))
385 if (!CanPlaceSubobjectAtOffset(RD, Offset))
392 if (Base.isVirtual())
395 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
398 if (!CanPlaceFieldSubobjectAtOffset(BaseDecl, Class, BaseOffset))
405 const CXXRecordDecl *VBaseDecl = Base.getType()->getAsCXXRecordDecl();
408 if (!CanPlaceFieldSubobjectAtOffset(VBaseDecl, Class, VBaseOffset))
414 unsigned FieldNo = 0;
416 I != E; ++I, ++FieldNo) {
422 if (!CanPlaceFieldSubobjectAtOffset(*I, FieldOffset))
430 EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(
const FieldDecl *FD,
434 if (!AnyEmptySubobjectsBeyondOffset(Offset))
439 return CanPlaceFieldSubobjectAtOffset(RD, RD, Offset);
453 for (uint64_t I = 0; I != NumElements; ++I) {
456 if (!AnyEmptySubobjectsBeyondOffset(ElementOffset))
459 if (!CanPlaceFieldSubobjectAtOffset(RD, RD, ElementOffset))
462 ElementOffset += Layout.
getSize();
470 EmptySubobjectMap::CanPlaceFieldAtOffset(
const FieldDecl *FD,
472 if (!CanPlaceFieldSubobjectAtOffset(FD, Offset))
477 UpdateEmptyFieldSubobjects(FD, Offset);
481 void EmptySubobjectMap::UpdateEmptyFieldSubobjects(
const CXXRecordDecl *RD,
489 if (Offset >= SizeOfLargestEmptySubobject)
492 AddSubobjectAtOffset(RD, Offset);
498 if (Base.isVirtual())
501 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
504 UpdateEmptyFieldSubobjects(BaseDecl, Class, BaseOffset);
510 const CXXRecordDecl *VBaseDecl = Base.getType()->getAsCXXRecordDecl();
513 UpdateEmptyFieldSubobjects(VBaseDecl, Class, VBaseOffset);
518 unsigned FieldNo = 0;
520 I != E; ++I, ++FieldNo) {
526 UpdateEmptyFieldSubobjects(*I, FieldOffset);
530 void EmptySubobjectMap::UpdateEmptyFieldSubobjects(
const FieldDecl *FD,
534 UpdateEmptyFieldSubobjects(RD, RD, Offset);
551 for (uint64_t I = 0; I != NumElements; ++I) {
557 if (ElementOffset >= SizeOfLargestEmptySubobject)
560 UpdateEmptyFieldSubobjects(RD, RD, ElementOffset);
561 ElementOffset += Layout.
getSize();
566 typedef llvm::SmallPtrSet<const CXXRecordDecl*, 4> ClassSetTy;
568 class RecordLayoutBuilder {
575 EmptySubobjectMap *EmptySubobjects;
590 unsigned UseExternalLayout : 1;
594 unsigned InferAlignment : 1;
599 unsigned IsUnion : 1;
601 unsigned IsMac68kAlign : 1;
603 unsigned IsMsStruct : 1;
609 unsigned char UnfilledBitsInLastUnit;
612 unsigned char LastBitfieldTypeSize;
630 bool PrimaryBaseIsVirtual;
636 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
639 BaseOffsetsMapTy Bases;
654 llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBases;
657 ExternalLayout External;
660 EmptySubobjectMap *EmptySubobjects)
661 : Context(Context), EmptySubobjects(EmptySubobjects), Size(0),
663 UseExternalLayout(
false), InferAlignment(
false),
665 UnfilledBitsInLastUnit(0), LastBitfieldTypeSize(0),
667 DataSize(0), NonVirtualSize(
CharUnits::Zero()),
669 PrimaryBase(nullptr), PrimaryBaseIsVirtual(
false),
671 FirstNearlyEmptyVBase(nullptr) {}
678 void LayoutField(
const FieldDecl *D,
bool InsertExtraPadding);
679 void LayoutWideBitField(uint64_t FieldSize, uint64_t TypeSize,
688 llvm::SpecificBumpPtrAllocator<BaseSubobjectInfo> BaseSubobjectInfoAllocator;
690 typedef llvm::DenseMap<const CXXRecordDecl *, BaseSubobjectInfo *>
691 BaseSubobjectInfoMapTy;
699 BaseSubobjectInfoMapTy NonVirtualBaseInfo;
707 BaseSubobjectInfo *ComputeBaseSubobjectInfo(
const CXXRecordDecl *RD,
709 BaseSubobjectInfo *Derived);
716 void EnsureVTablePointerAlignment(
CharUnits UnpackedBaseAlign);
723 void LayoutNonVirtualBase(
const BaseSubobjectInfo *Base);
725 void AddPrimaryVirtualBaseOffsets(
const BaseSubobjectInfo *Info,
733 void LayoutVirtualBase(
const BaseSubobjectInfo *Base);
737 CharUnits LayoutBase(
const BaseSubobjectInfo *Base);
740 void InitializeLayout(
const Decl *D);
747 void UpdateAlignment(
CharUnits NewAlignment) {
748 UpdateAlignment(NewAlignment, NewAlignment);
756 uint64_t updateExternalFieldOffset(
const FieldDecl *Field,
757 uint64_t ComputedOffset);
759 void CheckFieldPadding(uint64_t Offset, uint64_t UnpaddedOffset,
760 uint64_t UnpackedOffset,
unsigned UnpackedAlign,
769 uint64_t getSizeInBits()
const {
return Size; }
772 void setSize(uint64_t NewSize) { Size = NewSize; }
774 CharUnits getAligment()
const {
return Alignment; }
780 uint64_t getDataSizeInBits()
const {
return DataSize; }
783 void setDataSize(uint64_t NewSize) { DataSize = NewSize; }
785 RecordLayoutBuilder(
const RecordLayoutBuilder &) =
delete;
786 void operator=(
const RecordLayoutBuilder &) =
delete;
791 RecordLayoutBuilder::SelectPrimaryVBase(
const CXXRecordDecl *RD) {
792 for (
const auto &I : RD->
bases()) {
793 assert(!I.getType()->isDependentType() &&
794 "Cannot layout class with dependent bases.");
796 const CXXRecordDecl *Base = I.getType()->getAsCXXRecordDecl();
802 if (!IndirectPrimaryBases.count(Base)) {
804 PrimaryBaseIsVirtual =
true;
809 if (!FirstNearlyEmptyVBase)
810 FirstNearlyEmptyVBase = Base;
813 SelectPrimaryVBase(Base);
820 void RecordLayoutBuilder::DeterminePrimaryBase(
const CXXRecordDecl *RD) {
832 for (
const auto &I : RD->
bases()) {
837 const CXXRecordDecl *Base = I.getType()->getAsCXXRecordDecl();
842 PrimaryBaseIsVirtual =
false;
852 SelectPrimaryVBase(RD);
858 if (FirstNearlyEmptyVBase) {
859 PrimaryBase = FirstNearlyEmptyVBase;
860 PrimaryBaseIsVirtual =
true;
864 assert(!PrimaryBase &&
"Should not get here with a primary base!");
868 RecordLayoutBuilder::ComputeBaseSubobjectInfo(
const CXXRecordDecl *RD,
870 BaseSubobjectInfo *Derived) {
871 BaseSubobjectInfo *Info;
877 assert(InfoSlot->Class == RD &&
"Wrong class for virtual base info!");
882 InfoSlot =
new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo;
885 Info =
new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo;
889 Info->IsVirtual = IsVirtual;
890 Info->Derived =
nullptr;
891 Info->PrimaryVirtualBaseInfo =
nullptr;
894 BaseSubobjectInfo *PrimaryVirtualBaseInfo =
nullptr;
902 assert(PrimaryVirtualBase &&
"Didn't have a primary virtual base!");
907 if (PrimaryVirtualBaseInfo) {
908 if (PrimaryVirtualBaseInfo->Derived) {
912 PrimaryVirtualBase =
nullptr;
915 Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;
916 PrimaryVirtualBaseInfo->Derived = Info;
923 for (
const auto &I : RD->
bases()) {
924 bool IsVirtual = I.isVirtual();
926 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
928 Info->Bases.push_back(ComputeBaseSubobjectInfo(BaseDecl, IsVirtual, Info));
931 if (PrimaryVirtualBase && !PrimaryVirtualBaseInfo) {
935 assert(PrimaryVirtualBaseInfo &&
936 "Did not create a primary virtual base!");
939 Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;
940 PrimaryVirtualBaseInfo->Derived = Info;
946 void RecordLayoutBuilder::ComputeBaseSubobjectInfo(
const CXXRecordDecl *RD) {
947 for (
const auto &I : RD->
bases()) {
948 bool IsVirtual = I.isVirtual();
950 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
953 BaseSubobjectInfo *Info = ComputeBaseSubobjectInfo(BaseDecl, IsVirtual,
959 "Did not add virtual base!");
962 assert(!NonVirtualBaseInfo.count(BaseDecl) &&
963 "Non-virtual base already exists!");
964 NonVirtualBaseInfo.insert(std::make_pair(BaseDecl, Info));
970 RecordLayoutBuilder::EnsureVTablePointerAlignment(
CharUnits UnpackedBaseAlign) {
974 if (!MaxFieldAlignment.isZero()) {
975 BaseAlign = std::min(BaseAlign, MaxFieldAlignment);
976 UnpackedBaseAlign = std::min(UnpackedBaseAlign, MaxFieldAlignment);
980 setSize(getSize().RoundUpToAlignment(BaseAlign));
981 setDataSize(getSize());
984 UpdateAlignment(BaseAlign, UnpackedBaseAlign);
988 RecordLayoutBuilder::LayoutNonVirtualBases(
const CXXRecordDecl *RD) {
990 DeterminePrimaryBase(RD);
993 ComputeBaseSubobjectInfo(RD);
997 if (PrimaryBaseIsVirtual) {
1000 BaseSubobjectInfo *PrimaryBaseInfo =
VirtualBaseInfo.lookup(PrimaryBase);
1001 PrimaryBaseInfo->Derived =
nullptr;
1004 IndirectPrimaryBases.insert(PrimaryBase);
1006 assert(!VisitedVirtualBases.count(PrimaryBase) &&
1007 "vbase already visited!");
1008 VisitedVirtualBases.insert(PrimaryBase);
1010 LayoutVirtualBase(PrimaryBaseInfo);
1012 BaseSubobjectInfo *PrimaryBaseInfo =
1013 NonVirtualBaseInfo.lookup(PrimaryBase);
1014 assert(PrimaryBaseInfo &&
1015 "Did not find base info for non-virtual primary base!");
1017 LayoutNonVirtualBase(PrimaryBaseInfo);
1023 assert(DataSize == 0 &&
"Vtable pointer must be at offset zero!");
1028 EnsureVTablePointerAlignment(PtrAlign);
1030 setSize(getSize() + PtrWidth);
1031 setDataSize(getSize());
1035 for (
const auto &I : RD->
bases()) {
1041 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
1046 if (BaseDecl == PrimaryBase && !PrimaryBaseIsVirtual)
1050 BaseSubobjectInfo *BaseInfo = NonVirtualBaseInfo.
lookup(BaseDecl);
1051 assert(BaseInfo &&
"Did not find base info for non-virtual base!");
1053 LayoutNonVirtualBase(BaseInfo);
1057 void RecordLayoutBuilder::LayoutNonVirtualBase(
const BaseSubobjectInfo *Base) {
1062 assert(!Bases.count(Base->Class) &&
"base offset already exists!");
1063 Bases.insert(std::make_pair(Base->Class, Offset));
1065 AddPrimaryVirtualBaseOffsets(Base, Offset);
1069 RecordLayoutBuilder::AddPrimaryVirtualBaseOffsets(
const BaseSubobjectInfo *Info,
1072 if (!Info->Class->getNumVBases())
1076 if (Info->PrimaryVirtualBaseInfo) {
1077 assert(Info->PrimaryVirtualBaseInfo->IsVirtual &&
1078 "Primary virtual base is not virtual!");
1079 if (Info->PrimaryVirtualBaseInfo->Derived == Info) {
1081 assert(!VBases.count(Info->PrimaryVirtualBaseInfo->Class) &&
1082 "primary vbase offset already exists!");
1083 VBases.insert(std::make_pair(Info->PrimaryVirtualBaseInfo->Class,
1087 AddPrimaryVirtualBaseOffsets(Info->PrimaryVirtualBaseInfo, Offset);
1093 for (
const BaseSubobjectInfo *Base : Info->Bases) {
1094 if (Base->IsVirtual)
1098 AddPrimaryVirtualBaseOffsets(Base, BaseOffset);
1103 RecordLayoutBuilder::LayoutVirtualBases(
const CXXRecordDecl *RD,
1106 bool PrimaryBaseIsVirtual;
1108 if (MostDerivedClass == RD) {
1109 PrimaryBase = this->PrimaryBase;
1110 PrimaryBaseIsVirtual = this->PrimaryBaseIsVirtual;
1118 assert(!Base.getType()->isDependentType() &&
1119 "Cannot layout class with dependent bases.");
1121 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
1123 if (Base.isVirtual()) {
1124 if (PrimaryBase != BaseDecl || !PrimaryBaseIsVirtual) {
1125 bool IndirectPrimaryBase = IndirectPrimaryBases.count(BaseDecl);
1128 if (!IndirectPrimaryBase) {
1130 if (!VisitedVirtualBases.insert(BaseDecl).second)
1134 assert(BaseInfo &&
"Did not find virtual base info!");
1135 LayoutVirtualBase(BaseInfo);
1140 if (!BaseDecl->getNumVBases()) {
1145 LayoutVirtualBases(BaseDecl, MostDerivedClass);
1149 void RecordLayoutBuilder::LayoutVirtualBase(
const BaseSubobjectInfo *Base) {
1150 assert(!Base->Derived &&
"Trying to lay out a primary virtual base!");
1156 assert(!VBases.count(Base->Class) &&
"vbase offset already exists!");
1157 VBases.insert(std::make_pair(Base->Class,
1160 AddPrimaryVirtualBaseOffsets(Base, Offset);
1163 CharUnits RecordLayoutBuilder::LayoutBase(
const BaseSubobjectInfo *Base) {
1170 bool HasExternalLayout =
false;
1171 if (UseExternalLayout) {
1172 llvm::DenseMap<const CXXRecordDecl *, CharUnits>::iterator Known;
1173 if (Base->IsVirtual)
1174 HasExternalLayout = External.getExternalNVBaseOffset(Base->Class, Offset);
1176 HasExternalLayout = External.getExternalVBaseOffset(Base->Class, Offset);
1183 if (Base->Class->isEmpty() &&
1186 setSize(std::max(getSize(), Layout.
getSize()));
1187 UpdateAlignment(BaseAlign, UnpackedBaseAlign);
1193 if (!MaxFieldAlignment.isZero()) {
1194 BaseAlign = std::min(BaseAlign, MaxFieldAlignment);
1195 UnpackedBaseAlign = std::min(UnpackedBaseAlign, MaxFieldAlignment);
1198 if (!HasExternalLayout) {
1203 while (!EmptySubobjects->CanPlaceBaseAtOffset(Base, Offset))
1204 Offset += BaseAlign;
1206 bool Allowed = EmptySubobjects->CanPlaceBaseAtOffset(Base, Offset);
1208 assert(Allowed &&
"Base subobject externally placed at overlapping offset");
1210 if (InferAlignment && Offset < getDataSize().RoundUpToAlignment(BaseAlign)){
1214 InferAlignment =
false;
1218 if (!Base->Class->isEmpty()) {
1222 setSize(std::max(getSize(), getDataSize()));
1224 setSize(std::max(getSize(), Offset + Layout.
getSize()));
1227 UpdateAlignment(BaseAlign, UnpackedBaseAlign);
1232 void RecordLayoutBuilder::InitializeLayout(
const Decl *D) {
1233 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
1238 Packed = D->
hasAttr<PackedAttr>();
1249 if (D->
hasAttr<AlignMac68kAttr>()) {
1250 IsMac68kAlign =
true;
1254 if (
const MaxFieldAlignmentAttr *MFAA = D->
getAttr<MaxFieldAlignmentAttr>())
1262 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(D))
1264 UseExternalLayout = Source->layoutRecordType(
1265 RD, External.Size, External.Align, External.FieldOffsets,
1266 External.BaseOffsets, External.VirtualBaseOffsets);
1269 if (UseExternalLayout) {
1270 if (External.Align > 0) {
1274 InferAlignment =
true;
1280 void RecordLayoutBuilder::Layout(
const RecordDecl *D) {
1281 InitializeLayout(D);
1290 InitializeLayout(RD);
1293 LayoutNonVirtualBases(RD);
1298 llvm::RoundUpToAlignment(getSizeInBits(),
1300 NonVirtualAlignment = Alignment;
1303 LayoutVirtualBases(RD, RD);
1312 if (Base.isVirtual())
1315 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
1317 assert(Bases.count(BaseDecl) &&
"Did not find base offset!");
1322 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
1324 assert(VBases.count(BaseDecl) &&
"Did not find base offset!");
1338 setDataSize(getSize());
1341 InitializeLayout(D);
1345 LayoutField(IVD,
false);
1352 void RecordLayoutBuilder::LayoutFields(
const RecordDecl *D) {
1361 InsertExtraPadding && (
Next !=
End || !HasFlexibleArrayMember));
1370 return llvm::RoundUpToAlignment(Size, CharAlignment);
1373 void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize,
1378 "Can only have wide bit-fields in C++!");
1390 for (
const QualType &QT : IntegralPODTypes) {
1393 if (Size > FieldSize)
1398 assert(!Type.
isNull() &&
"Did not find a type!");
1403 UnfilledBitsInLastUnit = 0;
1404 LastBitfieldTypeSize = 0;
1406 uint64_t FieldOffset;
1407 uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;
1412 setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize));
1417 FieldOffset = llvm::RoundUpToAlignment(getDataSizeInBits(),
1420 uint64_t NewSizeInBits = FieldOffset + FieldSize;
1422 setDataSize(llvm::RoundUpToAlignment(NewSizeInBits,
1424 UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits;
1428 FieldOffsets.push_back(FieldOffset);
1430 CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, FieldOffset,
1434 setSize(std::max(getSizeInBits(), getDataSizeInBits()));
1437 UpdateAlignment(TypeAlign);
1440 void RecordLayoutBuilder::LayoutBitField(
const FieldDecl *D) {
1441 bool FieldPacked = Packed || D->
hasAttr<PackedAttr>();
1444 uint64_t TypeSize = FieldInfo.
Width;
1445 unsigned FieldAlign = FieldInfo.
Align;
1507 FieldAlign = TypeSize;
1512 if (LastBitfieldTypeSize != TypeSize) {
1514 if (!LastBitfieldTypeSize && !FieldSize)
1517 UnfilledBitsInLastUnit = 0;
1518 LastBitfieldTypeSize = 0;
1524 if (FieldSize > TypeSize) {
1525 LayoutWideBitField(FieldSize, TypeSize, FieldPacked, D);
1530 uint64_t FieldOffset =
1531 IsUnion ? 0 : (getDataSizeInBits() - UnfilledBitsInLastUnit);
1536 if (FieldSize == 0 &&
1540 unsigned ZeroLengthBitfieldBoundary =
1542 FieldAlign = std::max(FieldAlign, ZeroLengthBitfieldBoundary);
1551 unsigned UnpackedFieldAlign = FieldAlign;
1554 if (!IsMsStruct && FieldPacked && FieldSize != 0)
1559 FieldAlign = std::max(FieldAlign, ExplicitFieldAlign);
1560 UnpackedFieldAlign = std::max(UnpackedFieldAlign, ExplicitFieldAlign);
1565 if (!MaxFieldAlignment.isZero() && FieldSize) {
1566 unsigned MaxFieldAlignmentInBits =
Context.
toBits(MaxFieldAlignment);
1567 FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits);
1568 UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits);
1574 uint64_t UnpaddedFieldOffset = FieldOffset;
1575 uint64_t UnpackedFieldOffset = FieldOffset;
1585 if (FieldSize == 0 || FieldSize > UnfilledBitsInLastUnit) {
1586 FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign);
1587 UnpackedFieldOffset = llvm::RoundUpToAlignment(UnpackedFieldOffset,
1588 UnpackedFieldAlign);
1589 UnfilledBitsInLastUnit = 0;
1594 bool AllowPadding = MaxFieldAlignment.isZero();
1597 if (FieldSize == 0 ||
1599 (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize)) {
1600 FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign);
1604 if (FieldSize == 0 ||
1606 (UnpackedFieldOffset & (UnpackedFieldAlign-1)) + FieldSize > TypeSize))
1607 UnpackedFieldOffset = llvm::RoundUpToAlignment(UnpackedFieldOffset,
1608 UnpackedFieldAlign);
1613 if (UseExternalLayout)
1614 FieldOffset = updateExternalFieldOffset(D, FieldOffset);
1617 FieldOffsets.push_back(FieldOffset);
1626 FieldAlign = UnpackedFieldAlign = 1;
1629 if (!UseExternalLayout)
1630 CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, UnpackedFieldOffset,
1631 UnpackedFieldAlign, FieldPacked, D);
1639 setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize));
1642 }
else if (IsMsStruct && FieldSize) {
1645 if (!UnfilledBitsInLastUnit) {
1646 setDataSize(FieldOffset + TypeSize);
1647 UnfilledBitsInLastUnit = TypeSize;
1649 UnfilledBitsInLastUnit -= FieldSize;
1650 LastBitfieldTypeSize = TypeSize;
1656 uint64_t NewSizeInBits = FieldOffset + FieldSize;
1658 setDataSize(llvm::RoundUpToAlignment(NewSizeInBits, CharAlignment));
1659 UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits;
1664 LastBitfieldTypeSize = 0;
1668 setSize(std::max(getSizeInBits(), getDataSizeInBits()));
1675 void RecordLayoutBuilder::LayoutField(
const FieldDecl *D,
1676 bool InsertExtraPadding) {
1682 uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;
1685 UnfilledBitsInLastUnit = 0;
1686 LastBitfieldTypeSize = 0;
1688 bool FieldPacked = Packed || D->
hasAttr<PackedAttr>();
1709 std::pair<CharUnits, CharUnits> FieldInfo =
1711 FieldSize = FieldInfo.first;
1712 FieldAlign = FieldInfo.second;
1723 if (TypeSize > FieldAlign)
1724 FieldAlign = TypeSize;
1731 CharUnits UnpackedFieldAlign = FieldAlign;
1732 CharUnits UnpackedFieldOffset = FieldOffset;
1738 FieldAlign = std::max(FieldAlign, MaxAlignmentInChars);
1739 UnpackedFieldAlign = std::max(UnpackedFieldAlign, MaxAlignmentInChars);
1742 if (!MaxFieldAlignment.isZero()) {
1743 FieldAlign = std::min(FieldAlign, MaxFieldAlignment);
1744 UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignment);
1748 FieldOffset = FieldOffset.RoundUpToAlignment(FieldAlign);
1749 UnpackedFieldOffset =
1752 if (UseExternalLayout) {
1756 if (!IsUnion && EmptySubobjects) {
1758 bool Allowed = EmptySubobjects->CanPlaceFieldAtOffset(D, FieldOffset);
1760 assert(Allowed &&
"Externally-placed field cannot be placed here");
1763 if (!IsUnion && EmptySubobjects) {
1765 while (!EmptySubobjects->CanPlaceFieldAtOffset(D, FieldOffset)) {
1767 FieldOffset += FieldAlign;
1775 if (!UseExternalLayout)
1776 CheckFieldPadding(
Context.
toBits(FieldOffset), UnpaddedFieldOffset,
1780 if (InsertExtraPadding) {
1782 CharUnits ExtraSizeForAsan = ASanAlignment;
1783 if (FieldSize % ASanAlignment)
1786 FieldSize += ExtraSizeForAsan;
1792 setDataSize(std::max(getDataSizeInBits(), FieldSizeInBits));
1794 setDataSize(FieldOffset + FieldSize);
1797 setSize(std::max(getSizeInBits(), getDataSizeInBits()));
1800 UpdateAlignment(FieldAlign, UnpackedFieldAlign);
1803 void RecordLayoutBuilder::FinishLayout(
const NamedDecl *D) {
1819 uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastUnit;
1820 uint64_t UnpackedSizeInBits =
1821 llvm::RoundUpToAlignment(getSizeInBits(),
1824 uint64_t RoundedSize
1825 = llvm::RoundUpToAlignment(getSizeInBits(),
Context.
toBits(Alignment));
1827 if (UseExternalLayout) {
1831 if (InferAlignment && External.Size < RoundedSize) {
1833 InferAlignment =
false;
1835 setSize(External.Size);
1840 setSize(RoundedSize);
1843 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
1845 if (getSizeInBits() > UnpaddedSize) {
1846 unsigned PadSize = getSizeInBits() - UnpaddedSize;
1848 if (PadSize % CharBitNum == 0) {
1849 PadSize = PadSize / CharBitNum;
1855 << (InBits ? 1 : 0) << (PadSize > 1);
1861 getSize() == UnpackedSize)
1867 void RecordLayoutBuilder::UpdateAlignment(
CharUnits NewAlignment,
1871 if (IsMac68kAlign || (UseExternalLayout && !InferAlignment))
1874 if (NewAlignment > Alignment) {
1875 assert(llvm::isPowerOf2_64(NewAlignment.
getQuantity()) &&
1876 "Alignment not a power of 2");
1877 Alignment = NewAlignment;
1880 if (UnpackedNewAlignment > UnpackedAlignment) {
1881 assert(llvm::isPowerOf2_64(UnpackedNewAlignment.
getQuantity()) &&
1882 "Alignment not a power of 2");
1883 UnpackedAlignment = UnpackedNewAlignment;
1888 RecordLayoutBuilder::updateExternalFieldOffset(
const FieldDecl *Field,
1889 uint64_t ComputedOffset) {
1890 uint64_t ExternalFieldOffset = External.getExternalFieldOffset(Field);
1892 if (InferAlignment && ExternalFieldOffset < ComputedOffset) {
1896 InferAlignment =
false;
1900 return ExternalFieldOffset;
1913 default: llvm_unreachable(
"Invalid tag kind for field padding diagnostic!");
1917 void RecordLayoutBuilder::CheckFieldPadding(uint64_t Offset,
1918 uint64_t UnpaddedOffset,
1919 uint64_t UnpackedOffset,
1920 unsigned UnpackedAlign,
1925 if (isa<ObjCIvarDecl>(D))
1936 if (!IsUnion && Offset > UnpaddedOffset) {
1937 unsigned PadSize = Offset - UnpaddedOffset;
1939 if (PadSize % CharBitNum == 0) {
1940 PadSize = PadSize / CharBitNum;
1948 << (InBits ? 1 : 0) << (PadSize > 1)
1955 << (InBits ? 1 : 0) << (PadSize > 1);
1960 if (isPacked && UnpackedAlign > CharBitNum && Offset == UnpackedOffset)
1985 bool allowInlineFunctions =
1989 if (!MD->isVirtual())
1997 if (MD->isImplicit())
2000 if (MD->isInlineSpecified())
2003 if (MD->hasInlineBody())
2007 if (!MD->isUserProvided())
2011 if (!allowInlineFunctions) {
2020 if (MD->hasAttr<DLLImportAttr>() && !RD->
hasAttr<DLLImportAttr>())
2074 llvm_unreachable(
"bad tail-padding use kind");
2172 struct MicrosoftRecordLayoutBuilder {
2173 struct ElementInfo {
2177 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
2180 MicrosoftRecordLayoutBuilder(
const MicrosoftRecordLayoutBuilder &) =
delete;
2181 void operator=(
const MicrosoftRecordLayoutBuilder &) =
delete;
2201 void layoutBitField(
const FieldDecl *FD);
2204 void layoutZeroWidthBitField(
const FieldDecl *FD);
2213 ElementInfo getAdjustedElementInfo(
const FieldDecl *FD);
2215 void placeFieldAtOffset(
CharUnits FieldOffset) {
2219 void placeFieldAtBitOffset(uint64_t FieldOffset) {
2220 FieldOffsets.push_back(FieldOffset);
2223 void computeVtorDispSet(
2224 llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtorDispSet,
2249 ElementInfo PointerInfo;
2257 BaseOffsetsMapTy Bases;
2263 unsigned RemainingBitsInField;
2267 bool LastFieldIsNonZeroWidthBitfield : 1;
2269 bool HasOwnVFPtr : 1;
2275 bool EndsWithZeroSizedObject : 1;
2278 bool LeadsWithZeroSizedBase : 1;
2281 bool UseExternalLayout : 1;
2285 ExternalLayout External;
2289 MicrosoftRecordLayoutBuilder::ElementInfo
2290 MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
2295 if (!MaxFieldAlignment.isZero())
2296 Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment);
2302 Alignment = std::max(Alignment, Info.Alignment);
2309 MicrosoftRecordLayoutBuilder::ElementInfo
2310 MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
2315 std::tie(Info.Size, Info.Alignment) =
2322 FieldRequiredAlignment = std::max(
2328 Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment);
2334 FieldRequiredAlignment = std::max(FieldRequiredAlignment,
2338 RequiredAlignment = std::max(RequiredAlignment, FieldRequiredAlignment);
2341 if (!MaxFieldAlignment.isZero())
2342 Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment);
2343 if (FD->
hasAttr<PackedAttr>())
2345 Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment);
2349 void MicrosoftRecordLayoutBuilder::layout(
const RecordDecl *RD) {
2352 initializeLayout(RD);
2354 DataSize = Size = Size.RoundUpToAlignment(Alignment);
2355 RequiredAlignment = std::max(
2360 void MicrosoftRecordLayoutBuilder::cxxLayout(
const CXXRecordDecl *RD) {
2363 initializeLayout(RD);
2364 initializeCXXLayout(RD);
2365 layoutNonVirtualBases(RD);
2369 if (HasOwnVFPtr || (HasVBPtr && !SharedVBPtrBase))
2370 Alignment = std::max(Alignment, PointerInfo.Alignment);
2371 auto RoundingAlignment = Alignment;
2372 if (!MaxFieldAlignment.isZero())
2373 RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment);
2374 NonVirtualSize = Size = Size.RoundUpToAlignment(RoundingAlignment);
2375 RequiredAlignment = std::max(
2377 layoutVirtualBases(RD);
2381 void MicrosoftRecordLayoutBuilder::initializeLayout(
const RecordDecl *RD) {
2398 if (
const MaxFieldAlignmentAttr *MFAA = RD->
getAttr<MaxFieldAlignmentAttr>()){
2399 unsigned PackedAlignment = MFAA->getAlignment();
2404 if (RD->
hasAttr<PackedAttr>())
2408 UseExternalLayout =
false;
2410 UseExternalLayout = Source->layoutRecordType(
2411 RD, External.Size, External.Align, External.FieldOffsets,
2412 External.BaseOffsets, External.VirtualBaseOffsets);
2416 MicrosoftRecordLayoutBuilder::initializeCXXLayout(
const CXXRecordDecl *RD) {
2417 EndsWithZeroSizedObject =
false;
2418 LeadsWithZeroSizedBase =
false;
2419 HasOwnVFPtr =
false;
2421 PrimaryBase =
nullptr;
2422 SharedVBPtrBase =
nullptr;
2427 PointerInfo.Alignment =
2430 if (!MaxFieldAlignment.isZero())
2431 PointerInfo.Alignment = std::min(PointerInfo.Alignment, MaxFieldAlignment);
2435 MicrosoftRecordLayoutBuilder::layoutNonVirtualBases(
const CXXRecordDecl *RD) {
2445 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
2448 if (Base.isVirtual()) {
2453 if (!SharedVBPtrBase && BaseLayout.
hasVBPtr()) {
2454 SharedVBPtrBase = BaseDecl;
2462 PrimaryBase = BaseDecl;
2466 layoutNonVirtualBase(BaseDecl, BaseLayout, PreviousBaseLayout);
2472 !HasOwnVFPtr && i != e; ++i)
2473 HasOwnVFPtr = i->isVirtual() && i->size_overridden_methods() == 0;
2476 bool CheckLeadingLayout = !PrimaryBase;
2479 if (Base.isVirtual())
2481 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
2490 if (CheckLeadingLayout) {
2491 CheckLeadingLayout =
false;
2495 layoutNonVirtualBase(BaseDecl, BaseLayout, PreviousBaseLayout);
2501 else if (SharedVBPtrBase) {
2507 void MicrosoftRecordLayoutBuilder::layoutNonVirtualBase(
2517 ElementInfo Info = getAdjustedElementInfo(BaseLayout);
2521 bool FoundBase =
false;
2522 if (UseExternalLayout) {
2523 FoundBase = External.getExternalNVBaseOffset(BaseDecl, BaseOffset);
2525 assert(BaseOffset >= Size &&
"base offset already allocated");
2530 Bases.insert(std::make_pair(BaseDecl, BaseOffset));
2532 PreviousBaseLayout = &BaseLayout;
2535 void MicrosoftRecordLayoutBuilder::layoutFields(
const RecordDecl *RD) {
2536 LastFieldIsNonZeroWidthBitfield =
false;
2541 void MicrosoftRecordLayoutBuilder::layoutField(
const FieldDecl *FD) {
2546 LastFieldIsNonZeroWidthBitfield =
false;
2547 ElementInfo Info = getAdjustedElementInfo(FD);
2548 Alignment = std::max(Alignment, Info.Alignment);
2550 placeFieldAtOffset(CharUnits::Zero());
2551 Size = std::max(Size, Info.Size);
2554 if (UseExternalLayout) {
2557 assert(FieldOffset >= Size &&
"field offset already allocated");
2561 placeFieldAtOffset(FieldOffset);
2562 Size = FieldOffset + Info.Size;
2566 void MicrosoftRecordLayoutBuilder::layoutBitField(
const FieldDecl *FD) {
2569 layoutZeroWidthBitField(FD);
2572 ElementInfo Info = getAdjustedElementInfo(FD);
2580 if (!IsUnion && LastFieldIsNonZeroWidthBitfield &&
2581 CurrentBitfieldSize == Info.Size && Width <= RemainingBitsInField) {
2582 placeFieldAtBitOffset(
Context.
toBits(Size) - RemainingBitsInField);
2583 RemainingBitsInField -= Width;
2586 LastFieldIsNonZeroWidthBitfield =
true;
2587 CurrentBitfieldSize = Info.Size;
2589 placeFieldAtOffset(CharUnits::Zero());
2590 Size = std::max(Size, Info.Size);
2595 placeFieldAtOffset(FieldOffset);
2596 Size = FieldOffset + Info.Size;
2597 Alignment = std::max(Alignment, Info.Alignment);
2603 MicrosoftRecordLayoutBuilder::layoutZeroWidthBitField(
const FieldDecl *FD) {
2606 if (!LastFieldIsNonZeroWidthBitfield) {
2607 placeFieldAtOffset(IsUnion ? CharUnits::Zero() : Size);
2612 LastFieldIsNonZeroWidthBitfield =
false;
2613 ElementInfo Info = getAdjustedElementInfo(FD);
2615 placeFieldAtOffset(CharUnits::Zero());
2616 Size = std::max(Size, Info.Size);
2621 placeFieldAtOffset(FieldOffset);
2623 Alignment = std::max(Alignment, Info.Alignment);
2627 void MicrosoftRecordLayoutBuilder::injectVBPtr(
const CXXRecordDecl *RD) {
2628 if (!HasVBPtr || SharedVBPtrBase)
2636 if (UseExternalLayout)
2639 CharUnits FieldStart = VBPtrOffset + PointerInfo.Size;
2642 CharUnits Offset = (FieldStart - InjectionSite).RoundUpToAlignment(
2643 std::max(RequiredAlignment, Alignment));
2645 for (uint64_t &FieldOffset : FieldOffsets)
2647 for (BaseOffsetsMapTy::value_type &Base : Bases)
2648 if (Base.second >= InjectionSite)
2652 void MicrosoftRecordLayoutBuilder::injectVFPtr(
const CXXRecordDecl *RD) {
2658 std::max(RequiredAlignment, Alignment));
2662 for (uint64_t &FieldOffset : FieldOffsets)
2666 for (BaseOffsetsMapTy::value_type &Base : Bases)
2670 void MicrosoftRecordLayoutBuilder::layoutVirtualBases(
const CXXRecordDecl *RD) {
2675 CharUnits VtorDispAlignment = VtorDispSize;
2677 if (!MaxFieldAlignment.isZero())
2678 VtorDispAlignment = std::min(VtorDispAlignment, MaxFieldAlignment);
2683 const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl();
2688 VtorDispAlignment = std::max(VtorDispAlignment, RequiredAlignment);
2690 llvm::SmallPtrSet<const CXXRecordDecl *, 2> HasVtorDispSet;
2691 computeVtorDispSet(HasVtorDispSet, RD);
2695 const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl();
2697 bool HasVtordisp = HasVtorDispSet.count(BaseDecl) > 0;
2705 Size = Size.RoundUpToAlignment(VtorDispAlignment) + VtorDispSize;
2706 Alignment = std::max(VtorDispAlignment, Alignment);
2709 ElementInfo Info = getAdjustedElementInfo(BaseLayout);
2713 bool FoundBase =
false;
2714 if (UseExternalLayout) {
2715 FoundBase = External.getExternalVBaseOffset(BaseDecl, BaseOffset);
2717 assert(BaseOffset >= Size &&
"base offset already allocated");
2722 VBases.insert(std::make_pair(BaseDecl,
2725 PreviousBaseLayout = &BaseLayout;
2729 void MicrosoftRecordLayoutBuilder::finalizeLayout(
const RecordDecl *RD) {
2733 if (!RequiredAlignment.isZero()) {
2734 Alignment = std::max(Alignment, RequiredAlignment);
2735 auto RoundingAlignment = Alignment;
2736 if (!MaxFieldAlignment.isZero())
2737 RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment);
2738 RoundingAlignment = std::max(RoundingAlignment, RequiredAlignment);
2739 Size = Size.RoundUpToAlignment(RoundingAlignment);
2741 if (Size.isZero()) {
2742 EndsWithZeroSizedObject =
true;
2743 LeadsWithZeroSizedBase =
true;
2746 if (RequiredAlignment >= MinEmptyStructSize)
2749 Size = MinEmptyStructSize;
2752 if (UseExternalLayout) {
2763 BasesWithOverriddenMethods,
2765 if (BasesWithOverriddenMethods.count(RD))
2770 if (!Base.isVirtual() &&
2772 Base.getType()->getAsCXXRecordDecl()))
2777 void MicrosoftRecordLayoutBuilder::computeVtorDispSet(
2778 llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtordispSet,
2784 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
2787 HasVtordispSet.insert(BaseDecl);
2795 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
2798 if (bi.second.hasVtorDisp())
2799 HasVtordispSet.insert(bi.first);
2815 llvm::SmallPtrSet<const CXXMethodDecl *, 8> Work;
2816 llvm::SmallPtrSet<const CXXRecordDecl *, 2> BasesWithOverriddenMethods;
2819 if (MD->isVirtual() && !isa<CXXDestructorDecl>(MD) && !MD->isPure())
2821 while (!Work.empty()) {
2827 BasesWithOverriddenMethods.insert(MD->
getParent());
2836 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
2837 if (!HasVtordispSet.count(BaseDecl) &&
2839 HasVtordispSet.insert(BaseDecl);
2848 MicrosoftRecordLayoutBuilder
Builder(*
this);
2850 Builder.cxxLayout(RD);
2852 *
this, Builder.Size, Builder.Alignment, Builder.RequiredAlignment,
2853 Builder.HasOwnVFPtr,
2854 Builder.HasOwnVFPtr || Builder.PrimaryBase,
2855 Builder.VBPtrOffset, Builder.NonVirtualSize, Builder.FieldOffsets.data(),
2856 Builder.FieldOffsets.size(), Builder.NonVirtualSize,
2858 false, Builder.SharedVBPtrBase,
2859 Builder.EndsWithZeroSizedObject, Builder.LeadsWithZeroSizedBase,
2860 Builder.Bases, Builder.VBases);
2864 *
this, Builder.Size, Builder.Alignment, Builder.RequiredAlignment,
2865 Builder.Size, Builder.FieldOffsets.data(), Builder.FieldOffsets.size());
2883 assert(D &&
"Cannot get layout of forward declarations!");
2884 assert(!D->
isInvalidDecl() &&
"Cannot get layout of invalid decl!");
2891 if (Entry)
return *Entry;
2897 }
else if (
const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
2898 EmptySubobjectMap EmptySubobjects(*
this, RD);
2899 RecordLayoutBuilder
Builder(*
this, &EmptySubobjects);
2905 bool skipTailPadding =
2910 skipTailPadding ? Builder.getSize() : Builder.getDataSize();
2912 skipTailPadding ? DataSize : Builder.NonVirtualSize;
2918 Builder.HasOwnVFPtr,
2922 Builder.FieldOffsets.data(),
2923 Builder.FieldOffsets.size(),
2925 Builder.NonVirtualAlignment,
2926 EmptySubobjects.SizeOfLargestEmptySubobject,
2927 Builder.PrimaryBase,
2928 Builder.PrimaryBaseIsVirtual,
2929 nullptr,
false,
false,
2930 Builder.Bases, Builder.VBases);
2932 RecordLayoutBuilder
Builder(*
this,
nullptr);
2941 Builder.FieldOffsets.data(),
2942 Builder.FieldOffsets.size());
2945 ASTRecordLayouts[D] = NewEntry;
2948 llvm::outs() <<
"\n*** Dumping AST Record Layout\n";
2959 assert(RD->
getDefinition() &&
"Cannot get key function for forward decl!");
2960 RD = cast<CXXRecordDecl>(RD->getDefinition());
2972 if (Entry.isOffset() || Entry.isValid() !=
bool(Result))
2973 KeyFunctions[RD] = const_cast<Decl*>(Result);
2975 return cast_or_null<CXXMethodDecl>(
Result);
2980 "not working with method declaration from class definition");
2985 const auto &
Map = KeyFunctions;
2989 if (I == Map.end())
return;
2997 KeyFunctions.erase(Method->
getParent());
3007 uint64_t OffsetInBits;
3008 if (
const FieldDecl *FD = dyn_cast<FieldDecl>(VD)) {
3018 return OffsetInBits;
3048 if (SynthCount == 0)
3049 return getObjCLayout(D,
nullptr);
3052 RecordLayoutBuilder
Builder(*
this,
nullptr);
3064 ObjCLayouts[Key] = NewEntry;
3070 CharUnits Offset,
unsigned IndentLevel) {
3071 OS << llvm::format(
"%4" PRId64
" | ", (int64_t)Offset.
getQuantity());
3072 OS.indent(IndentLevel * 2);
3077 OS.indent(IndentLevel * 2);
3083 unsigned IndentLevel,
3084 const char* Description,
3085 bool IncludeVirtualBases) {
3091 OS <<
' ' << Description;
3105 OS <<
'(' << *RD <<
" vtable pointer)\n";
3106 }
else if (HasOwnVFPtr) {
3109 OS <<
'(' << *RD <<
" vftable pointer)\n";
3115 assert(!Base.getType()->isDependentType() &&
3116 "Cannot layout class with dependent bases.");
3117 if (!Base.isVirtual())
3118 Bases.push_back(Base.getType()->getAsCXXRecordDecl());
3122 std::stable_sort(Bases.begin(), Bases.end(),
3131 Base == PrimaryBase ?
"(primary base)" :
"(base)",
3138 OS <<
'(' << *RD <<
" vbtable pointer)\n";
3142 uint64_t FieldNo = 0;
3144 E = RD->
field_end(); I != E; ++I, ++FieldNo) {
3160 if (!IncludeVirtualBases)
3167 assert(Base.isVirtual() &&
"Found non-virtual class!");
3168 const CXXRecordDecl *VBase = Base.getType()->getAsCXXRecordDecl();
3172 if (vtordisps.find(VBase)->second.hasVtorDisp()) {
3174 OS <<
"(vtordisp for vbase " << *VBase <<
")\n";
3178 VBase == PrimaryBase ?
3179 "(primary virtual base)" :
"(virtual base)",
3196 bool Simple)
const {
3199 if (
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))
3210 OS <<
"<ASTRecordLayout\n";
3215 OS <<
" FieldOffsets: [";
3216 for (
unsigned i = 0, e = Info.
getFieldCount(); i != e; ++i) {
static uint64_t getFieldOffset(const ASTContext &C, const FieldDecl *FD)
unsigned getAddressSpace() const
getAddressSpace - Return the address space of this type.
Defines the clang::ASTContext interface.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
StringRef getName() const
unsigned getZeroLengthBitfieldBoundary() const
Get the fixed alignment value in bits for a member that follows a zero length bitfield.
llvm::DenseMap< const CXXRecordDecl *, VBaseInfo > VBaseOffsetsMapTy
static bool mustSkipTailPadding(TargetCXXABI ABI, const CXXRecordDecl *RD)
unsigned getFieldCount() const
getFieldCount - Get the number of fields in the layout.
bool hasZeroSizedSubObject() const
bool isBitField() const
Determines whether this field is a bitfield.
The basic abstraction for the target C++ ABI.
IdentifierInfo * getIdentifier() const
method_range methods() const
CharUnits getAlignment() const
getAlignment - Get the record alignment in characters.
bool isThisDeclarationADefinition() const
Determine whether this particular declaration of this class is actually also a definition.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
chain_range chain() const
bool hasFlexibleArrayMember() const
bool isAlignmentRequired(const Type *T) const
Determine if the alignment the type has was required using an alignment attribute.
method_iterator method_begin() const
Method begin iterator. Iterates in the order the methods were declared.
std::string getAsString() const
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const
getVBaseClassOffset - Get the offset, in chars, for the given base class.
bool isPrimaryBaseVirtual() const
field_iterator field_begin() const
The "__interface" keyword.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
const Type * getUnqualifiedDesugaredType() const
unsigned getMaxAlignment() const
MSVtorDispAttr::Mode getMSVtorDispMode() const
Controls when vtordisps will be emitted if this record is used as a virtual base. ...
bool isEmpty() const
Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).
method_iterator end_overridden_methods() const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
bool hasExternalLexicalStorage() const
Whether this DeclContext has external storage containing additional declarations that are lexically i...
const ASTRecordLayout * BuildMicrosoftASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class), which indicates its size and field position information.
bool isCompleteDefinition() const
static bool RequiresVtordisp(const llvm::SmallPtrSetImpl< const CXXRecordDecl * > &BasesWithOverriddenMethods, const CXXRecordDecl *RD)
CXXRecordDecl * getDefinition() const
TagKind getTagKind() const
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
QualType getTypeDeclType(const TypeDecl *Decl, const TypeDecl *PrevDecl=nullptr) const
Return the unique reference to the type for the specified type declaration.
void getIndirectPrimaryBases(CXXIndirectPrimaryBaseSet &Bases) const
Get the indirect primary bases for this class.
bool isNearlyEmpty(const CXXRecordDecl *RD) const
unsigned CountNonClassIvars(const ObjCInterfaceDecl *OI) const
const TargetInfo & getTargetInfo() const
const LangOptions & getLangOpts() const
const CXXRecordDecl * getParent() const
field_range fields() const
CharUnits getRequiredAlignment() const
bool hasVBPtr() const
hasVBPtr - Does this class have a virtual function table pointer.
const ArrayType * getAsArrayType(QualType T) const
RecordDecl * getDecl() const
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D...
uint64_t getFieldOffset(unsigned FieldNo) const
static void DumpCXXRecordLayout(raw_ostream &OS, const CXXRecordDecl *RD, const ASTContext &C, CharUnits Offset, unsigned IndentLevel, const char *Description, bool IncludeVirtualBases)
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
Represents an ObjC class declaration.
std::pair< CharUnits, CharUnits > getTypeInfoInChars(const Type *T) const
CanQualType UnsignedCharTy
DiagnosticsEngine & getDiagnostics() const
field_iterator field_end() const
static CharUnits One()
One - Construct a CharUnits quantity of one.
A little helper class used to produce diagnostics.
static void PrintOffset(raw_ostream &OS, CharUnits Offset, unsigned IndentLevel)
const CXXMethodDecl *const * method_iterator
QualType getPointeeType() const
unsigned getCharAlign() const
bool canKeyFunctionBeInline() const
Can an out-of-line inline function serve as a key function?
bool isMicrosoft() const
Is this ABI an MSVC-compatible ABI?
bool leadsWithZeroSizedBase() const
CharUnits getNonVirtualAlignment() const
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
bool useZeroLengthBitfieldAlignment() const
Check whether zero length bitfields should force alignment of the next member.
TailPaddingUseRules getTailPaddingUseRules() const
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
bool isExternallyVisible() const
CharUnits getVBPtrOffset() const
bool useBitFieldTypeAlignment() const
Check whether the alignment of bit-field types is respected when laying out structures.
specific_decl_iterator< FieldDecl > field_iterator
CharUnits getSizeOfLargestEmptySubobject() const
The result type of a method or function.
RecordDecl * getDefinition() const
decl_type * getFirstDecl()
Return the first declaration of this declaration or itself if this is the only declaration.
uint64_t getFieldOffset(const ValueDecl *FD) const
Get the offset of a FieldDecl or IndirectFieldDecl, in bits.
Abstract interface for external sources of AST nodes.
static uint64_t roundUpSizeToCharAlignment(uint64_t Size, const ASTContext &Context)
TypeInfo getTypeInfo(const Type *T) const
Get the size and alignment of the specified complete type in bits.
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
uint64_t getPointerAlign(unsigned AddrSpace) const
bool mayInsertExtraPadding(bool EmitRemark=false) const
Whether we are allowed to insert extra padding between fields. These padding are added to help Addres...
Encodes a location in the source. The SourceManager can decode this to get at the full include stack...
ExternalASTSource * getExternalSource() const
Retrieve a pointer to the external AST source associated with this AST context, if any...
CharUnits getSize() const
getSize - Get the record size in characters.
method_iterator begin_overridden_methods() const
unsigned getBitWidthValue(const ASTContext &Ctx) const
const CXXRecordDecl * getPrimaryBase() const
getPrimaryBase - Get the primary base for this record.
A set of all the primary bases for a class.
static void PrintIndentNoOffset(raw_ostream &OS, unsigned IndentLevel)
ASTContext & getASTContext() const LLVM_READONLY
Represents a static or instance method of a struct/union/class.
bool hasExtendableVFPtr() const
const ConstantArrayType * getAsConstantArrayType(QualType T) const
const VBaseOffsetsMapTy & getVBaseOffsetsMap() const
const Type * getBaseElementTypeUnsafe() const
T * get(ExternalASTSource *Source) const
Retrieve the pointer to the AST node that this lazy pointer.
lookup_result lookup(DeclarationName Name) const
method_iterator method_end() const
Method past-the-end iterator.
bool isInlineSpecified() const
Determine whether the "inline" keyword was specified for this function.
static unsigned getPaddingDiagFromTagKind(TagTypeKind Tag)
Get diagnostic select index for tag kind for field padding diagnostic message. WARNING: Indexes apply...
bool isDynamicClass() const
CanQualType UnsignedShortTy
ObjCIvarDecl * getNextIvar()
if(T->getSizeExpr()) TRY_TO(TraverseStmt(T-> getSizeExpr()))
TemplateSpecializationKind getTemplateSpecializationKind() const
Determine whether this particular class is a specialization or instantiation of a class template or m...
TagTypeKind
The kind of a tag type.
return(x >> y)|(x<< (32-y))
bool isInvalidDecl() const
unsigned getCharWidth() const
CanQualType UnsignedLongLongTy
ObjCInterfaceDecl * getDefinition()
Retrieve the definition of this class, or NULL if this class has been forward-declared (with @class) ...
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
TemplateSpecializationKind
Describes the kind of template specialization that a particular template specialization declaration r...
bool isMsStruct(const ASTContext &C) const
CanQualType UnsignedLongTy
void setNonKeyFunction(const CXXMethodDecl *method)
Observe that the given method cannot be a key function. Checks the key-function cache for the method'...
virtual void CompleteType(TagDecl *Tag)
Gives the external AST source an opportunity to complete an incomplete type.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isTrivial() const
Determine whether this class is considered trivial.
uint64_t getCharWidth() const
Return the size of the character type, in bits.
Represents a base class of a C++ class.
CharUnits getNonVirtualSize() const
unsigned getFieldIndex() const
uint64_t getPointerWidth(unsigned AddrSpace) const
Return the width of pointers on this target, for the specified address space.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate.h) and friends (in DeclFriend.h).
const CXXMethodDecl * getCurrentKeyFunction(const CXXRecordDecl *RD)
Get our current best idea for the key function of the given record decl, or NULL if there isn't one...
Represents a C++ struct/union/class.
BoundNodesTreeBuilder *const Builder
TargetCXXABI getCXXABI() const
Get the C++ ABI currently in use.
bool hasUserDeclaredDestructor() const
Determine whether this class has a user-declared destructor.
void DumpRecordLayout(const RecordDecl *RD, raw_ostream &OS, bool Simple=false) const
CharUnits getDataSize() const
static const CXXMethodDecl * computeKeyFunction(ASTContext &Context, const CXXRecordDecl *RD)
static bool isMsLayout(const RecordDecl *D)
Defines the clang::TargetInfo interface.
ObjCInterfaceDecl * getSuperClass() const
bool isIncompleteArrayType() const
bool isStandardLayout() const
Determine whether this class has standard layout per (C++ [class]p7)
QualType getElementType() const
uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const
Return number of constant array elements.
int64_t toBits(CharUnits CharSize) const
Convert a size in characters to a size in bits.
SourceLocation getLocation() const
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
ObjCIvarDecl * all_declared_ivar_begin()
const ASTRecordLayout & getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D) const
Get or compute information about the layout of the specified Objective-C interface.
bool isNull() const
isNull - Return true if this QualType doesn't point to a type yet.
bool isPolymorphic() const
CharUnits RoundUpToAlignment(const CharUnits &Align) const
base_class_range vbases()
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
bool hasUserDeclaredConstructor() const
Determine whether this class has any user-declared constructors.
const RecordDecl * getParent() const
CanQualType UnsignedIntTy
bool isPOD() const
Whether this class is a POD-type (C++ [class]p4)