20 #include "llvm/ADT/SmallSet.h"
21 #include "llvm/Support/Format.h"
22 #include "llvm/Support/MathExtras.h"
24 using namespace clang;
39 struct BaseSubobjectInfo {
51 BaseSubobjectInfo *PrimaryVirtualBaseInfo;
54 const BaseSubobjectInfo *Derived;
60 struct ExternalLayout {
61 ExternalLayout() : Size(0), Align(0) {}
70 llvm::DenseMap<const FieldDecl *, uint64_t> FieldOffsets;
73 llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsets;
76 llvm::DenseMap<const CXXRecordDecl *, CharUnits> VirtualBaseOffsets;
80 uint64_t getExternalFieldOffset(
const FieldDecl *FD) {
81 assert(FieldOffsets.count(FD) &&
82 "Field does not have an external offset");
83 return FieldOffsets[FD];
87 auto Known = BaseOffsets.find(RD);
88 if (Known == BaseOffsets.end())
90 BaseOffset = Known->second;
95 auto Known = VirtualBaseOffsets.find(RD);
96 if (Known == VirtualBaseOffsets.end())
98 BaseOffset = Known->second;
105 class EmptySubobjectMap {
113 typedef llvm::TinyPtrVector<const CXXRecordDecl *> ClassVectorTy;
114 typedef llvm::DenseMap<CharUnits, ClassVectorTy> EmptyClassOffsetsMapTy;
115 EmptyClassOffsetsMapTy EmptyClassOffsets;
123 void ComputeEmptySubobjectSizes();
127 void UpdateEmptyBaseSubobjects(
const BaseSubobjectInfo *Info,
138 return Offset <= MaxEmptyClassOffset;
144 assert(FieldOffset % CharWidth == 0 &&
145 "Field offset not at char boundary!");
154 bool CanPlaceBaseSubobjectAtOffset(
const BaseSubobjectInfo *Info,
160 bool CanPlaceFieldSubobjectAtOffset(
const FieldDecl *FD,
170 : Context(Context), CharWidth(Context.
getCharWidth()), Class(Class) {
171 ComputeEmptySubobjectSizes();
178 bool CanPlaceBaseAtOffset(
const BaseSubobjectInfo *Info,
186 void EmptySubobjectMap::ComputeEmptySubobjectSizes() {
201 if (EmptySize > SizeOfLargestEmptySubobject)
202 SizeOfLargestEmptySubobject = EmptySize;
225 if (EmptySize > SizeOfLargestEmptySubobject)
226 SizeOfLargestEmptySubobject = EmptySize;
231 EmptySubobjectMap::CanPlaceSubobjectAtOffset(
const CXXRecordDecl *RD,
237 EmptyClassOffsetsMapTy::const_iterator
I = EmptyClassOffsets.find(Offset);
238 if (I == EmptyClassOffsets.end())
241 const ClassVectorTy &Classes = I->second;
242 if (std::find(Classes.begin(), Classes.end(), RD) == Classes.end())
249 void EmptySubobjectMap::AddSubobjectAtOffset(
const CXXRecordDecl *RD,
257 ClassVectorTy &Classes = EmptyClassOffsets[
Offset];
258 if (std::find(Classes.begin(), Classes.end(), RD) != Classes.end())
261 Classes.push_back(RD);
264 if (Offset > MaxEmptyClassOffset)
265 MaxEmptyClassOffset =
Offset;
269 EmptySubobjectMap::CanPlaceBaseSubobjectAtOffset(
const BaseSubobjectInfo *Info,
273 if (!AnyEmptySubobjectsBeyondOffset(Offset))
276 if (!CanPlaceSubobjectAtOffset(Info->Class, Offset))
281 for (
const BaseSubobjectInfo *
Base : Info->Bases) {
287 if (!CanPlaceBaseSubobjectAtOffset(Base, BaseOffset))
291 if (Info->PrimaryVirtualBaseInfo) {
292 BaseSubobjectInfo *PrimaryVirtualBaseInfo = Info->PrimaryVirtualBaseInfo;
294 if (Info == PrimaryVirtualBaseInfo->Derived) {
295 if (!CanPlaceBaseSubobjectAtOffset(PrimaryVirtualBaseInfo, Offset))
301 unsigned FieldNo = 0;
303 E = Info->Class->field_end(); I !=
E; ++
I, ++FieldNo) {
308 if (!CanPlaceFieldSubobjectAtOffset(*I, FieldOffset))
315 void EmptySubobjectMap::UpdateEmptyBaseSubobjects(
const BaseSubobjectInfo *Info,
317 bool PlacingEmptyBase) {
318 if (!PlacingEmptyBase && Offset >= SizeOfLargestEmptySubobject) {
327 AddSubobjectAtOffset(Info->Class, Offset);
331 for (
const BaseSubobjectInfo *Base : Info->Bases) {
336 UpdateEmptyBaseSubobjects(Base, BaseOffset, PlacingEmptyBase);
339 if (Info->PrimaryVirtualBaseInfo) {
340 BaseSubobjectInfo *PrimaryVirtualBaseInfo = Info->PrimaryVirtualBaseInfo;
342 if (Info == PrimaryVirtualBaseInfo->Derived)
343 UpdateEmptyBaseSubobjects(PrimaryVirtualBaseInfo, Offset,
348 unsigned FieldNo = 0;
350 E = Info->Class->field_end(); I !=
E; ++
I, ++FieldNo) {
355 UpdateEmptyFieldSubobjects(*I, FieldOffset);
359 bool EmptySubobjectMap::CanPlaceBaseAtOffset(
const BaseSubobjectInfo *Info,
363 if (SizeOfLargestEmptySubobject.isZero())
366 if (!CanPlaceBaseSubobjectAtOffset(Info, Offset))
371 UpdateEmptyBaseSubobjects(Info, Offset, Info->Class->isEmpty());
376 EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(
const CXXRecordDecl *RD,
381 if (!AnyEmptySubobjectsBeyondOffset(Offset))
384 if (!CanPlaceSubobjectAtOffset(RD, Offset))
391 if (Base.isVirtual())
394 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
397 if (!CanPlaceFieldSubobjectAtOffset(BaseDecl, Class, BaseOffset))
404 const CXXRecordDecl *VBaseDecl = Base.getType()->getAsCXXRecordDecl();
407 if (!CanPlaceFieldSubobjectAtOffset(VBaseDecl, Class, VBaseOffset))
413 unsigned FieldNo = 0;
415 I !=
E; ++
I, ++FieldNo) {
421 if (!CanPlaceFieldSubobjectAtOffset(*I, FieldOffset))
429 EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(
const FieldDecl *FD,
433 if (!AnyEmptySubobjectsBeyondOffset(Offset))
438 return CanPlaceFieldSubobjectAtOffset(RD, RD, Offset);
452 for (uint64_t I = 0; I != NumElements; ++
I) {
455 if (!AnyEmptySubobjectsBeyondOffset(ElementOffset))
458 if (!CanPlaceFieldSubobjectAtOffset(RD, RD, ElementOffset))
461 ElementOffset += Layout.
getSize();
469 EmptySubobjectMap::CanPlaceFieldAtOffset(
const FieldDecl *FD,
471 if (!CanPlaceFieldSubobjectAtOffset(FD, Offset))
476 UpdateEmptyFieldSubobjects(FD, Offset);
480 void EmptySubobjectMap::UpdateEmptyFieldSubobjects(
const CXXRecordDecl *RD,
488 if (Offset >= SizeOfLargestEmptySubobject)
491 AddSubobjectAtOffset(RD, Offset);
497 if (Base.isVirtual())
500 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
503 UpdateEmptyFieldSubobjects(BaseDecl, Class, BaseOffset);
509 const CXXRecordDecl *VBaseDecl = Base.getType()->getAsCXXRecordDecl();
512 UpdateEmptyFieldSubobjects(VBaseDecl, Class, VBaseOffset);
517 unsigned FieldNo = 0;
519 I !=
E; ++
I, ++FieldNo) {
525 UpdateEmptyFieldSubobjects(*I, FieldOffset);
529 void EmptySubobjectMap::UpdateEmptyFieldSubobjects(
const FieldDecl *FD,
533 UpdateEmptyFieldSubobjects(RD, RD, Offset);
550 for (uint64_t I = 0; I != NumElements; ++
I) {
556 if (ElementOffset >= SizeOfLargestEmptySubobject)
559 UpdateEmptyFieldSubobjects(RD, RD, ElementOffset);
560 ElementOffset += Layout.
getSize();
565 typedef llvm::SmallPtrSet<const CXXRecordDecl*, 4> ClassSetTy;
567 class ItaniumRecordLayoutBuilder {
574 EmptySubobjectMap *EmptySubobjects;
589 unsigned UseExternalLayout : 1;
593 unsigned InferAlignment : 1;
598 unsigned IsUnion : 1;
600 unsigned IsMac68kAlign : 1;
602 unsigned IsMsStruct : 1;
608 unsigned char UnfilledBitsInLastUnit;
611 unsigned char LastBitfieldTypeSize;
629 bool PrimaryBaseIsVirtual;
635 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
638 BaseOffsetsMapTy Bases;
653 llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBases;
656 ExternalLayout External;
659 EmptySubobjectMap *EmptySubobjects)
660 : Context(Context), EmptySubobjects(EmptySubobjects), Size(0),
664 UnfilledBitsInLastUnit(0), LastBitfieldTypeSize(0),
665 MaxFieldAlignment(
CharUnits::Zero()), DataSize(0),
667 NonVirtualAlignment(
CharUnits::One()), PrimaryBase(nullptr),
668 PrimaryBaseIsVirtual(
false), HasOwnVFPtr(
false),
669 FirstNearlyEmptyVBase(nullptr) {}
676 void LayoutField(
const FieldDecl *D,
bool InsertExtraPadding);
677 void LayoutWideBitField(uint64_t FieldSize, uint64_t TypeSize,
686 llvm::SpecificBumpPtrAllocator<BaseSubobjectInfo> BaseSubobjectInfoAllocator;
688 typedef llvm::DenseMap<const CXXRecordDecl *, BaseSubobjectInfo *>
689 BaseSubobjectInfoMapTy;
697 BaseSubobjectInfoMapTy NonVirtualBaseInfo;
705 BaseSubobjectInfo *ComputeBaseSubobjectInfo(
const CXXRecordDecl *RD,
707 BaseSubobjectInfo *Derived);
714 void EnsureVTablePointerAlignment(
CharUnits UnpackedBaseAlign);
721 void LayoutNonVirtualBase(
const BaseSubobjectInfo *Base);
723 void AddPrimaryVirtualBaseOffsets(
const BaseSubobjectInfo *Info,
731 void LayoutVirtualBase(
const BaseSubobjectInfo *Base);
735 CharUnits LayoutBase(
const BaseSubobjectInfo *Base);
738 void InitializeLayout(
const Decl *D);
745 void UpdateAlignment(
CharUnits NewAlignment) {
746 UpdateAlignment(NewAlignment, NewAlignment);
754 uint64_t updateExternalFieldOffset(
const FieldDecl *Field,
755 uint64_t ComputedOffset);
757 void CheckFieldPadding(uint64_t Offset, uint64_t UnpaddedOffset,
758 uint64_t UnpackedOffset,
unsigned UnpackedAlign,
767 uint64_t getSizeInBits()
const {
return Size; }
770 void setSize(uint64_t NewSize) { Size = NewSize; }
772 CharUnits getAligment()
const {
return Alignment; }
778 uint64_t getDataSizeInBits()
const {
return DataSize; }
781 void setDataSize(uint64_t NewSize) { DataSize = NewSize; }
783 ItaniumRecordLayoutBuilder(
const ItaniumRecordLayoutBuilder &) =
delete;
784 void operator=(
const ItaniumRecordLayoutBuilder &) =
delete;
788 void ItaniumRecordLayoutBuilder::SelectPrimaryVBase(
const CXXRecordDecl *RD) {
789 for (
const auto &I : RD->
bases()) {
790 assert(!I.getType()->isDependentType() &&
791 "Cannot layout class with dependent bases.");
793 const CXXRecordDecl *Base = I.getType()->getAsCXXRecordDecl();
799 if (!IndirectPrimaryBases.count(Base)) {
801 PrimaryBaseIsVirtual =
true;
806 if (!FirstNearlyEmptyVBase)
807 FirstNearlyEmptyVBase = Base;
810 SelectPrimaryVBase(Base);
817 void ItaniumRecordLayoutBuilder::DeterminePrimaryBase(
const CXXRecordDecl *RD) {
829 for (
const auto &I : RD->
bases()) {
834 const CXXRecordDecl *Base = I.getType()->getAsCXXRecordDecl();
839 PrimaryBaseIsVirtual =
false;
849 SelectPrimaryVBase(RD);
855 if (FirstNearlyEmptyVBase) {
856 PrimaryBase = FirstNearlyEmptyVBase;
857 PrimaryBaseIsVirtual =
true;
861 assert(!PrimaryBase &&
"Should not get here with a primary base!");
864 BaseSubobjectInfo *ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo(
865 const CXXRecordDecl *RD,
bool IsVirtual, BaseSubobjectInfo *Derived) {
866 BaseSubobjectInfo *Info;
872 assert(InfoSlot->Class == RD &&
"Wrong class for virtual base info!");
877 InfoSlot =
new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo;
880 Info =
new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo;
884 Info->IsVirtual = IsVirtual;
885 Info->Derived =
nullptr;
886 Info->PrimaryVirtualBaseInfo =
nullptr;
889 BaseSubobjectInfo *PrimaryVirtualBaseInfo =
nullptr;
897 assert(PrimaryVirtualBase &&
"Didn't have a primary virtual base!");
902 if (PrimaryVirtualBaseInfo) {
903 if (PrimaryVirtualBaseInfo->Derived) {
907 PrimaryVirtualBase =
nullptr;
910 Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;
911 PrimaryVirtualBaseInfo->Derived = Info;
918 for (
const auto &I : RD->
bases()) {
919 bool IsVirtual = I.isVirtual();
921 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
923 Info->Bases.push_back(ComputeBaseSubobjectInfo(BaseDecl, IsVirtual, Info));
926 if (PrimaryVirtualBase && !PrimaryVirtualBaseInfo) {
930 assert(PrimaryVirtualBaseInfo &&
931 "Did not create a primary virtual base!");
934 Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;
935 PrimaryVirtualBaseInfo->Derived = Info;
941 void ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo(
943 for (
const auto &I : RD->
bases()) {
944 bool IsVirtual = I.isVirtual();
946 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
949 BaseSubobjectInfo *Info = ComputeBaseSubobjectInfo(BaseDecl, IsVirtual,
955 "Did not add virtual base!");
958 assert(!NonVirtualBaseInfo.count(BaseDecl) &&
959 "Non-virtual base already exists!");
960 NonVirtualBaseInfo.insert(std::make_pair(BaseDecl, Info));
965 void ItaniumRecordLayoutBuilder::EnsureVTablePointerAlignment(
970 if (!MaxFieldAlignment.isZero()) {
971 BaseAlign =
std::min(BaseAlign, MaxFieldAlignment);
972 UnpackedBaseAlign =
std::min(UnpackedBaseAlign, MaxFieldAlignment);
976 setSize(getSize().alignTo(BaseAlign));
977 setDataSize(getSize());
980 UpdateAlignment(BaseAlign, UnpackedBaseAlign);
983 void ItaniumRecordLayoutBuilder::LayoutNonVirtualBases(
986 DeterminePrimaryBase(RD);
989 ComputeBaseSubobjectInfo(RD);
993 if (PrimaryBaseIsVirtual) {
996 BaseSubobjectInfo *PrimaryBaseInfo =
VirtualBaseInfo.lookup(PrimaryBase);
997 PrimaryBaseInfo->Derived =
nullptr;
1000 IndirectPrimaryBases.insert(PrimaryBase);
1002 assert(!VisitedVirtualBases.count(PrimaryBase) &&
1003 "vbase already visited!");
1004 VisitedVirtualBases.insert(PrimaryBase);
1006 LayoutVirtualBase(PrimaryBaseInfo);
1008 BaseSubobjectInfo *PrimaryBaseInfo =
1009 NonVirtualBaseInfo.lookup(PrimaryBase);
1010 assert(PrimaryBaseInfo &&
1011 "Did not find base info for non-virtual primary base!");
1013 LayoutNonVirtualBase(PrimaryBaseInfo);
1019 assert(DataSize == 0 &&
"Vtable pointer must be at offset zero!");
1024 EnsureVTablePointerAlignment(PtrAlign);
1026 setSize(getSize() + PtrWidth);
1027 setDataSize(getSize());
1031 for (
const auto &I : RD->
bases()) {
1037 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
1042 if (BaseDecl == PrimaryBase && !PrimaryBaseIsVirtual)
1046 BaseSubobjectInfo *BaseInfo = NonVirtualBaseInfo.
lookup(BaseDecl);
1047 assert(BaseInfo &&
"Did not find base info for non-virtual base!");
1049 LayoutNonVirtualBase(BaseInfo);
1053 void ItaniumRecordLayoutBuilder::LayoutNonVirtualBase(
1054 const BaseSubobjectInfo *Base) {
1059 assert(!Bases.count(Base->Class) &&
"base offset already exists!");
1060 Bases.insert(std::make_pair(Base->Class, Offset));
1062 AddPrimaryVirtualBaseOffsets(Base, Offset);
1065 void ItaniumRecordLayoutBuilder::AddPrimaryVirtualBaseOffsets(
1066 const BaseSubobjectInfo *Info,
CharUnits Offset) {
1068 if (!Info->Class->getNumVBases())
1072 if (Info->PrimaryVirtualBaseInfo) {
1073 assert(Info->PrimaryVirtualBaseInfo->IsVirtual &&
1074 "Primary virtual base is not virtual!");
1075 if (Info->PrimaryVirtualBaseInfo->Derived == Info) {
1077 assert(!VBases.count(Info->PrimaryVirtualBaseInfo->Class) &&
1078 "primary vbase offset already exists!");
1079 VBases.insert(std::make_pair(Info->PrimaryVirtualBaseInfo->Class,
1083 AddPrimaryVirtualBaseOffsets(Info->PrimaryVirtualBaseInfo, Offset);
1089 for (
const BaseSubobjectInfo *Base : Info->Bases) {
1090 if (Base->IsVirtual)
1094 AddPrimaryVirtualBaseOffsets(Base, BaseOffset);
1098 void ItaniumRecordLayoutBuilder::LayoutVirtualBases(
1101 bool PrimaryBaseIsVirtual;
1103 if (MostDerivedClass == RD) {
1104 PrimaryBase = this->PrimaryBase;
1105 PrimaryBaseIsVirtual = this->PrimaryBaseIsVirtual;
1113 assert(!Base.getType()->isDependentType() &&
1114 "Cannot layout class with dependent bases.");
1116 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
1118 if (Base.isVirtual()) {
1119 if (PrimaryBase != BaseDecl || !PrimaryBaseIsVirtual) {
1120 bool IndirectPrimaryBase = IndirectPrimaryBases.count(BaseDecl);
1123 if (!IndirectPrimaryBase) {
1125 if (!VisitedVirtualBases.insert(BaseDecl).second)
1129 assert(BaseInfo &&
"Did not find virtual base info!");
1130 LayoutVirtualBase(BaseInfo);
1135 if (!BaseDecl->getNumVBases()) {
1140 LayoutVirtualBases(BaseDecl, MostDerivedClass);
1144 void ItaniumRecordLayoutBuilder::LayoutVirtualBase(
1145 const BaseSubobjectInfo *Base) {
1146 assert(!Base->Derived &&
"Trying to lay out a primary virtual base!");
1152 assert(!VBases.count(Base->Class) &&
"vbase offset already exists!");
1153 VBases.insert(std::make_pair(Base->Class,
1156 AddPrimaryVirtualBaseOffsets(Base, Offset);
1160 ItaniumRecordLayoutBuilder::LayoutBase(
const BaseSubobjectInfo *Base) {
1167 bool HasExternalLayout =
false;
1168 if (UseExternalLayout) {
1170 if (Base->IsVirtual)
1171 HasExternalLayout = External.getExternalNVBaseOffset(Base->Class, Offset);
1173 HasExternalLayout = External.getExternalVBaseOffset(Base->Class, Offset);
1180 if (Base->Class->isEmpty() &&
1184 UpdateAlignment(BaseAlign, UnpackedBaseAlign);
1190 if (!MaxFieldAlignment.isZero()) {
1191 BaseAlign =
std::min(BaseAlign, MaxFieldAlignment);
1192 UnpackedBaseAlign =
std::min(UnpackedBaseAlign, MaxFieldAlignment);
1195 if (!HasExternalLayout) {
1197 Offset = getDataSize().
alignTo(BaseAlign);
1200 while (!EmptySubobjects->CanPlaceBaseAtOffset(Base, Offset))
1201 Offset += BaseAlign;
1203 bool Allowed = EmptySubobjects->CanPlaceBaseAtOffset(Base, Offset);
1205 assert(Allowed &&
"Base subobject externally placed at overlapping offset");
1207 if (InferAlignment && Offset < getDataSize().alignTo(BaseAlign)) {
1211 InferAlignment =
false;
1215 if (!Base->Class->isEmpty()) {
1219 setSize(
std::max(getSize(), getDataSize()));
1224 UpdateAlignment(BaseAlign, UnpackedBaseAlign);
1229 void ItaniumRecordLayoutBuilder::InitializeLayout(
const Decl *D) {
1230 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
1235 Packed = D->hasAttr<PackedAttr>();
1246 if (D->hasAttr<AlignMac68kAttr>()) {
1247 IsMac68kAlign =
true;
1251 if (
const MaxFieldAlignmentAttr *MFAA = D->getAttr<MaxFieldAlignmentAttr>())
1254 if (
unsigned MaxAlign = D->getMaxAlignment())
1259 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(D))
1261 UseExternalLayout = Source->layoutRecordType(
1262 RD, External.Size, External.Align, External.FieldOffsets,
1263 External.BaseOffsets, External.VirtualBaseOffsets);
1266 if (UseExternalLayout) {
1267 if (External.Align > 0) {
1271 InferAlignment =
true;
1277 void ItaniumRecordLayoutBuilder::Layout(
const RecordDecl *D) {
1278 InitializeLayout(D);
1286 void ItaniumRecordLayoutBuilder::Layout(
const CXXRecordDecl *RD) {
1287 InitializeLayout(RD);
1290 LayoutNonVirtualBases(RD);
1296 NonVirtualAlignment = Alignment;
1299 LayoutVirtualBases(RD, RD);
1308 if (Base.isVirtual())
1311 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
1313 assert(Bases.count(BaseDecl) &&
"Did not find base offset!");
1318 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
1320 assert(VBases.count(BaseDecl) &&
"Did not find base offset!");
1334 setDataSize(getSize());
1337 InitializeLayout(D);
1341 LayoutField(IVD,
false);
1348 void ItaniumRecordLayoutBuilder::LayoutFields(
const RecordDecl *D) {
1357 InsertExtraPadding && (
Next !=
End || !HasFlexibleArrayMember));
1366 return llvm::alignTo(Size, CharAlignment);
1369 void ItaniumRecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize,
1374 "Can only have wide bit-fields in C++!");
1386 for (
const QualType &QT : IntegralPODTypes) {
1389 if (Size > FieldSize)
1394 assert(!Type.
isNull() &&
"Did not find a type!");
1399 UnfilledBitsInLastUnit = 0;
1400 LastBitfieldTypeSize = 0;
1402 uint64_t FieldOffset;
1403 uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;
1408 setDataSize(
std::max(getDataSizeInBits(), RoundedFieldSize));
1413 FieldOffset = llvm::alignTo(getDataSizeInBits(),
Context.
toBits(TypeAlign));
1415 uint64_t NewSizeInBits = FieldOffset + FieldSize;
1419 UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits;
1423 FieldOffsets.push_back(FieldOffset);
1425 CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, FieldOffset,
1429 setSize(
std::max(getSizeInBits(), getDataSizeInBits()));
1432 UpdateAlignment(TypeAlign);
1435 void ItaniumRecordLayoutBuilder::LayoutBitField(
const FieldDecl *D) {
1436 bool FieldPacked = Packed || D->hasAttr<PackedAttr>();
1439 uint64_t TypeSize = FieldInfo.
Width;
1440 unsigned FieldAlign = FieldInfo.
Align;
1502 FieldAlign = TypeSize;
1507 if (LastBitfieldTypeSize != TypeSize) {
1509 if (!LastBitfieldTypeSize && !FieldSize)
1512 UnfilledBitsInLastUnit = 0;
1513 LastBitfieldTypeSize = 0;
1519 if (FieldSize > TypeSize) {
1520 LayoutWideBitField(FieldSize, TypeSize, FieldPacked, D);
1525 uint64_t FieldOffset =
1526 IsUnion ? 0 : (getDataSizeInBits() - UnfilledBitsInLastUnit);
1531 if (FieldSize == 0 &&
1535 unsigned ZeroLengthBitfieldBoundary =
1537 FieldAlign =
std::max(FieldAlign, ZeroLengthBitfieldBoundary);
1546 unsigned UnpackedFieldAlign = FieldAlign;
1549 if (!IsMsStruct && FieldPacked && FieldSize != 0)
1553 unsigned ExplicitFieldAlign = D->getMaxAlignment();
1554 if (ExplicitFieldAlign) {
1555 FieldAlign =
std::max(FieldAlign, ExplicitFieldAlign);
1556 UnpackedFieldAlign =
std::max(UnpackedFieldAlign, ExplicitFieldAlign);
1561 unsigned MaxFieldAlignmentInBits =
Context.
toBits(MaxFieldAlignment);
1562 if (!MaxFieldAlignment.isZero() && FieldSize) {
1563 UnpackedFieldAlign =
std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits);
1565 FieldAlign = UnpackedFieldAlign;
1567 FieldAlign =
std::min(FieldAlign, MaxFieldAlignmentInBits);
1572 if (IsMsStruct && IsUnion) {
1573 FieldAlign = UnpackedFieldAlign = 1;
1579 uint64_t UnpaddedFieldOffset = FieldOffset;
1580 uint64_t UnpackedFieldOffset = FieldOffset;
1590 if (FieldSize == 0 || FieldSize > UnfilledBitsInLastUnit) {
1591 FieldOffset = llvm::alignTo(FieldOffset, FieldAlign);
1592 UnpackedFieldOffset =
1593 llvm::alignTo(UnpackedFieldOffset, UnpackedFieldAlign);
1594 UnfilledBitsInLastUnit = 0;
1599 bool AllowPadding = MaxFieldAlignment.isZero();
1602 if (FieldSize == 0 ||
1604 (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize)) {
1605 FieldOffset = llvm::alignTo(FieldOffset, FieldAlign);
1606 }
else if (ExplicitFieldAlign &&
1607 (MaxFieldAlignmentInBits == 0 ||
1608 ExplicitFieldAlign <= MaxFieldAlignmentInBits) &&
1612 FieldOffset = llvm::alignTo(FieldOffset, ExplicitFieldAlign);
1616 if (FieldSize == 0 ||
1618 (UnpackedFieldOffset & (UnpackedFieldAlign-1)) + FieldSize > TypeSize))
1619 UnpackedFieldOffset =
1620 llvm::alignTo(UnpackedFieldOffset, UnpackedFieldAlign);
1621 else if (ExplicitFieldAlign &&
1622 (MaxFieldAlignmentInBits == 0 ||
1623 ExplicitFieldAlign <= MaxFieldAlignmentInBits) &&
1625 UnpackedFieldOffset =
1626 llvm::alignTo(UnpackedFieldOffset, ExplicitFieldAlign);
1631 if (UseExternalLayout)
1632 FieldOffset = updateExternalFieldOffset(D, FieldOffset);
1635 FieldOffsets.push_back(FieldOffset);
1644 FieldAlign = UnpackedFieldAlign = 1;
1647 if (!UseExternalLayout)
1648 CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, UnpackedFieldOffset,
1649 UnpackedFieldAlign, FieldPacked, D);
1657 uint64_t RoundedFieldSize;
1667 setDataSize(
std::max(getDataSizeInBits(), RoundedFieldSize));
1671 }
else if (IsMsStruct && FieldSize) {
1674 if (!UnfilledBitsInLastUnit) {
1675 setDataSize(FieldOffset + TypeSize);
1676 UnfilledBitsInLastUnit = TypeSize;
1678 UnfilledBitsInLastUnit -= FieldSize;
1679 LastBitfieldTypeSize = TypeSize;
1685 uint64_t NewSizeInBits = FieldOffset + FieldSize;
1687 setDataSize(llvm::alignTo(NewSizeInBits, CharAlignment));
1688 UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits;
1693 LastBitfieldTypeSize = 0;
1697 setSize(
std::max(getSizeInBits(), getDataSizeInBits()));
1704 void ItaniumRecordLayoutBuilder::LayoutField(
const FieldDecl *D,
1705 bool InsertExtraPadding) {
1711 uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;
1714 UnfilledBitsInLastUnit = 0;
1715 LastBitfieldTypeSize = 0;
1717 bool FieldPacked = Packed || D->hasAttr<PackedAttr>();
1738 std::pair<CharUnits, CharUnits> FieldInfo =
1740 FieldSize = FieldInfo.first;
1741 FieldAlign = FieldInfo.second;
1752 if (TypeSize > FieldAlign)
1753 FieldAlign = TypeSize;
1760 CharUnits UnpackedFieldAlign = FieldAlign;
1761 CharUnits UnpackedFieldOffset = FieldOffset;
1767 FieldAlign =
std::max(FieldAlign, MaxAlignmentInChars);
1768 UnpackedFieldAlign =
std::max(UnpackedFieldAlign, MaxAlignmentInChars);
1771 if (!MaxFieldAlignment.isZero()) {
1772 FieldAlign =
std::min(FieldAlign, MaxFieldAlignment);
1773 UnpackedFieldAlign =
std::min(UnpackedFieldAlign, MaxFieldAlignment);
1777 FieldOffset = FieldOffset.alignTo(FieldAlign);
1778 UnpackedFieldOffset = UnpackedFieldOffset.
alignTo(UnpackedFieldAlign);
1780 if (UseExternalLayout) {
1784 if (!IsUnion && EmptySubobjects) {
1786 bool Allowed = EmptySubobjects->CanPlaceFieldAtOffset(D, FieldOffset);
1788 assert(Allowed &&
"Externally-placed field cannot be placed here");
1791 if (!IsUnion && EmptySubobjects) {
1793 while (!EmptySubobjects->CanPlaceFieldAtOffset(D, FieldOffset)) {
1795 FieldOffset += FieldAlign;
1803 if (!UseExternalLayout)
1804 CheckFieldPadding(
Context.
toBits(FieldOffset), UnpaddedFieldOffset,
1808 if (InsertExtraPadding) {
1810 CharUnits ExtraSizeForAsan = ASanAlignment;
1811 if (FieldSize % ASanAlignment)
1814 FieldSize += ExtraSizeForAsan;
1820 setDataSize(
std::max(getDataSizeInBits(), FieldSizeInBits));
1822 setDataSize(FieldOffset + FieldSize);
1825 setSize(
std::max(getSizeInBits(), getDataSizeInBits()));
1828 UpdateAlignment(FieldAlign, UnpackedFieldAlign);
1831 void ItaniumRecordLayoutBuilder::FinishLayout(
const NamedDecl *D) {
1847 uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastUnit;
1848 uint64_t UnpackedSizeInBits =
1849 llvm::alignTo(getSizeInBits(),
Context.
toBits(UnpackedAlignment));
1851 uint64_t RoundedSize =
1854 if (UseExternalLayout) {
1858 if (InferAlignment && External.Size < RoundedSize) {
1860 InferAlignment =
false;
1862 setSize(External.Size);
1867 setSize(RoundedSize);
1870 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
1872 if (getSizeInBits() > UnpaddedSize) {
1873 unsigned PadSize = getSizeInBits() - UnpaddedSize;
1875 if (PadSize % CharBitNum == 0) {
1876 PadSize = PadSize / CharBitNum;
1879 Diag(RD->getLocation(), diag::warn_padded_struct_size)
1882 << (InBits ? 1 : 0);
1888 getSize() == UnpackedSize)
1889 Diag(D->getLocation(), diag::warn_unnecessary_packed)
1894 void ItaniumRecordLayoutBuilder::UpdateAlignment(
1898 if (IsMac68kAlign || (UseExternalLayout && !InferAlignment))
1901 if (NewAlignment > Alignment) {
1902 assert(llvm::isPowerOf2_64(NewAlignment.
getQuantity()) &&
1903 "Alignment not a power of 2");
1904 Alignment = NewAlignment;
1907 if (UnpackedNewAlignment > UnpackedAlignment) {
1908 assert(llvm::isPowerOf2_64(UnpackedNewAlignment.
getQuantity()) &&
1909 "Alignment not a power of 2");
1910 UnpackedAlignment = UnpackedNewAlignment;
1915 ItaniumRecordLayoutBuilder::updateExternalFieldOffset(
const FieldDecl *Field,
1916 uint64_t ComputedOffset) {
1917 uint64_t ExternalFieldOffset = External.getExternalFieldOffset(Field);
1919 if (InferAlignment && ExternalFieldOffset < ComputedOffset) {
1923 InferAlignment =
false;
1927 return ExternalFieldOffset;
1940 default: llvm_unreachable(
"Invalid tag kind for field padding diagnostic!");
1944 void ItaniumRecordLayoutBuilder::CheckFieldPadding(
1945 uint64_t Offset, uint64_t UnpaddedOffset, uint64_t UnpackedOffset,
1946 unsigned UnpackedAlign,
bool isPacked,
const FieldDecl *D) {
1949 if (isa<ObjCIvarDecl>(D))
1954 if (D->getLocation().isInvalid())
1960 if (!IsUnion && Offset > UnpaddedOffset) {
1961 unsigned PadSize = Offset - UnpaddedOffset;
1963 if (PadSize % CharBitNum == 0) {
1964 PadSize = PadSize / CharBitNum;
1968 Diag(D->getLocation(), diag::warn_padded_struct_field)
1975 Diag(D->getLocation(), diag::warn_padded_struct_anon_field)
1979 << (InBits ? 1 : 0);
1984 if (isPacked && UnpackedAlign > CharBitNum && Offset == UnpackedOffset)
1985 Diag(D->getLocation(), diag::warn_unnecessary_packed)
2009 bool allowInlineFunctions =
2013 if (!MD->isVirtual())
2021 if (MD->isImplicit())
2024 if (MD->isInlineSpecified())
2027 if (MD->hasInlineBody())
2031 if (!MD->isUserProvided())
2035 if (!allowInlineFunctions) {
2047 if (!MD->hasAttr<CUDADeviceAttr>())
2051 if (!MD->hasAttr<CUDAHostAttr>() && MD->hasAttr<CUDADeviceAttr>())
2059 if (MD->hasAttr<DLLImportAttr>() && !RD->hasAttr<DLLImportAttr>())
2113 llvm_unreachable(
"bad tail-padding use kind");
2211 struct MicrosoftRecordLayoutBuilder {
2212 struct ElementInfo {
2216 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
2219 MicrosoftRecordLayoutBuilder(
const MicrosoftRecordLayoutBuilder &) =
delete;
2220 void operator=(
const MicrosoftRecordLayoutBuilder &) =
delete;
2241 void layoutBitField(
const FieldDecl *FD);
2244 void layoutZeroWidthBitField(
const FieldDecl *FD);
2253 ElementInfo getAdjustedElementInfo(
const FieldDecl *FD);
2255 void placeFieldAtOffset(
CharUnits FieldOffset) {
2259 void placeFieldAtBitOffset(uint64_t FieldOffset) {
2260 FieldOffsets.push_back(FieldOffset);
2263 void computeVtorDispSet(
2264 llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtorDispSet,
2289 ElementInfo PointerInfo;
2297 BaseOffsetsMapTy Bases;
2303 unsigned RemainingBitsInField;
2307 bool LastFieldIsNonZeroWidthBitfield : 1;
2309 bool HasOwnVFPtr : 1;
2315 bool EndsWithZeroSizedObject : 1;
2318 bool LeadsWithZeroSizedBase : 1;
2321 bool UseExternalLayout : 1;
2325 ExternalLayout External;
2329 MicrosoftRecordLayoutBuilder::ElementInfo
2330 MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
2335 if (!MaxFieldAlignment.isZero())
2336 Info.Alignment =
std::min(Info.Alignment, MaxFieldAlignment);
2342 Alignment =
std::max(Alignment, Info.Alignment);
2349 MicrosoftRecordLayoutBuilder::ElementInfo
2350 MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
2355 std::tie(Info.Size, Info.Alignment) =
2368 Info.Alignment =
std::max(Info.Alignment, FieldRequiredAlignment);
2374 FieldRequiredAlignment =
std::max(FieldRequiredAlignment,
2378 RequiredAlignment =
std::max(RequiredAlignment, FieldRequiredAlignment);
2381 if (!MaxFieldAlignment.isZero())
2382 Info.Alignment =
std::min(Info.Alignment, MaxFieldAlignment);
2383 if (FD->hasAttr<PackedAttr>())
2385 Info.Alignment =
std::max(Info.Alignment, FieldRequiredAlignment);
2389 void MicrosoftRecordLayoutBuilder::layout(
const RecordDecl *RD) {
2392 initializeLayout(RD);
2394 DataSize = Size = Size.alignTo(Alignment);
2400 void MicrosoftRecordLayoutBuilder::cxxLayout(
const CXXRecordDecl *RD) {
2403 initializeLayout(RD);
2404 initializeCXXLayout(RD);
2405 layoutNonVirtualBases(RD);
2409 if (HasOwnVFPtr || (HasVBPtr && !SharedVBPtrBase))
2410 Alignment =
std::max(Alignment, PointerInfo.Alignment);
2411 auto RoundingAlignment = Alignment;
2412 if (!MaxFieldAlignment.isZero())
2413 RoundingAlignment =
std::min(RoundingAlignment, MaxFieldAlignment);
2414 NonVirtualSize = Size = Size.alignTo(RoundingAlignment);
2417 layoutVirtualBases(RD);
2421 void MicrosoftRecordLayoutBuilder::initializeLayout(
const RecordDecl *RD) {
2438 if (
const MaxFieldAlignmentAttr *MFAA = RD->getAttr<MaxFieldAlignmentAttr>()){
2439 unsigned PackedAlignment = MFAA->getAlignment();
2444 if (RD->hasAttr<PackedAttr>())
2448 UseExternalLayout =
false;
2450 UseExternalLayout = Source->layoutRecordType(
2451 RD, External.Size, External.Align, External.FieldOffsets,
2452 External.BaseOffsets, External.VirtualBaseOffsets);
2456 MicrosoftRecordLayoutBuilder::initializeCXXLayout(
const CXXRecordDecl *RD) {
2457 EndsWithZeroSizedObject =
false;
2458 LeadsWithZeroSizedBase =
false;
2459 HasOwnVFPtr =
false;
2461 PrimaryBase =
nullptr;
2462 SharedVBPtrBase =
nullptr;
2467 PointerInfo.Alignment =
2470 if (!MaxFieldAlignment.isZero())
2471 PointerInfo.Alignment =
std::min(PointerInfo.Alignment, MaxFieldAlignment);
2475 MicrosoftRecordLayoutBuilder::layoutNonVirtualBases(
const CXXRecordDecl *RD) {
2485 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
2488 if (Base.isVirtual()) {
2493 if (!SharedVBPtrBase && BaseLayout.
hasVBPtr()) {
2494 SharedVBPtrBase = BaseDecl;
2502 PrimaryBase = BaseDecl;
2506 layoutNonVirtualBase(RD, BaseDecl, BaseLayout, PreviousBaseLayout);
2512 !HasOwnVFPtr && i != e; ++i)
2513 HasOwnVFPtr = i->isVirtual() && i->size_overridden_methods() == 0;
2516 bool CheckLeadingLayout = !PrimaryBase;
2519 if (Base.isVirtual())
2521 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
2530 if (CheckLeadingLayout) {
2531 CheckLeadingLayout =
false;
2535 layoutNonVirtualBase(RD, BaseDecl, BaseLayout, PreviousBaseLayout);
2541 else if (SharedVBPtrBase) {
2548 if (!isa<CXXRecordDecl>(RD))
2550 if (RD->hasAttr<EmptyBasesAttr>())
2552 if (
auto *LVA = RD->getAttr<LayoutVersionAttr>())
2562 void MicrosoftRecordLayoutBuilder::layoutNonVirtualBase(
2574 ElementInfo Info = getAdjustedElementInfo(BaseLayout);
2578 bool FoundBase =
false;
2579 if (UseExternalLayout) {
2580 FoundBase = External.getExternalNVBaseOffset(BaseDecl, BaseOffset);
2582 assert(BaseOffset >= Size &&
"base offset already allocated");
2588 if (MDCUsesEBO && BaseDecl->
isEmpty() &&
2593 BaseOffset = Size = Size.
alignTo(Info.Alignment);
2596 Bases.insert(std::make_pair(BaseDecl, BaseOffset));
2598 PreviousBaseLayout = &BaseLayout;
2601 void MicrosoftRecordLayoutBuilder::layoutFields(
const RecordDecl *RD) {
2602 LastFieldIsNonZeroWidthBitfield =
false;
2607 void MicrosoftRecordLayoutBuilder::layoutField(
const FieldDecl *FD) {
2612 LastFieldIsNonZeroWidthBitfield =
false;
2613 ElementInfo Info = getAdjustedElementInfo(FD);
2614 Alignment =
std::max(Alignment, Info.Alignment);
2616 placeFieldAtOffset(CharUnits::Zero());
2620 if (UseExternalLayout) {
2623 assert(FieldOffset >= Size &&
"field offset already allocated");
2625 FieldOffset = Size.
alignTo(Info.Alignment);
2627 placeFieldAtOffset(FieldOffset);
2628 Size = FieldOffset + Info.Size;
2632 void MicrosoftRecordLayoutBuilder::layoutBitField(
const FieldDecl *FD) {
2635 layoutZeroWidthBitField(FD);
2638 ElementInfo Info = getAdjustedElementInfo(FD);
2646 if (!IsUnion && LastFieldIsNonZeroWidthBitfield &&
2647 CurrentBitfieldSize == Info.Size && Width <= RemainingBitsInField) {
2648 placeFieldAtBitOffset(
Context.
toBits(Size) - RemainingBitsInField);
2649 RemainingBitsInField -= Width;
2652 LastFieldIsNonZeroWidthBitfield =
true;
2653 CurrentBitfieldSize = Info.Size;
2655 placeFieldAtOffset(CharUnits::Zero());
2661 placeFieldAtOffset(FieldOffset);
2662 Size = FieldOffset + Info.Size;
2663 Alignment =
std::max(Alignment, Info.Alignment);
2669 MicrosoftRecordLayoutBuilder::layoutZeroWidthBitField(
const FieldDecl *FD) {
2672 if (!LastFieldIsNonZeroWidthBitfield) {
2673 placeFieldAtOffset(IsUnion ? CharUnits::Zero() : Size);
2678 LastFieldIsNonZeroWidthBitfield =
false;
2679 ElementInfo Info = getAdjustedElementInfo(FD);
2681 placeFieldAtOffset(CharUnits::Zero());
2687 placeFieldAtOffset(FieldOffset);
2689 Alignment =
std::max(Alignment, Info.Alignment);
2693 void MicrosoftRecordLayoutBuilder::injectVBPtr(
const CXXRecordDecl *RD) {
2694 if (!HasVBPtr || SharedVBPtrBase)
2699 VBPtrOffset = VBPtrOffset.
alignTo(PointerInfo.Alignment);
2702 if (UseExternalLayout)
2705 CharUnits FieldStart = VBPtrOffset + PointerInfo.Size;
2708 CharUnits Offset = (FieldStart - InjectionSite)
2709 .alignTo(
std::max(RequiredAlignment, Alignment));
2711 for (uint64_t &FieldOffset : FieldOffsets)
2713 for (BaseOffsetsMapTy::value_type &Base : Bases)
2714 if (Base.second >= InjectionSite)
2718 void MicrosoftRecordLayoutBuilder::injectVFPtr(
const CXXRecordDecl *RD) {
2730 if (UseExternalLayout)
2737 for (uint64_t &FieldOffset : FieldOffsets)
2739 for (BaseOffsetsMapTy::value_type &Base : Bases)
2743 void MicrosoftRecordLayoutBuilder::layoutVirtualBases(
const CXXRecordDecl *RD) {
2748 CharUnits VtorDispAlignment = VtorDispSize;
2750 if (!MaxFieldAlignment.isZero())
2751 VtorDispAlignment =
std::min(VtorDispAlignment, MaxFieldAlignment);
2756 const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl();
2761 VtorDispAlignment =
std::max(VtorDispAlignment, RequiredAlignment);
2763 llvm::SmallPtrSet<const CXXRecordDecl *, 2> HasVtorDispSet;
2764 computeVtorDispSet(HasVtorDispSet, RD);
2768 const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl();
2770 bool HasVtordisp = HasVtorDispSet.count(BaseDecl) > 0;
2779 Size = Size.alignTo(VtorDispAlignment) + VtorDispSize;
2780 Alignment =
std::max(VtorDispAlignment, Alignment);
2783 ElementInfo Info = getAdjustedElementInfo(BaseLayout);
2787 bool FoundBase =
false;
2788 if (UseExternalLayout) {
2789 FoundBase = External.getExternalVBaseOffset(BaseDecl, BaseOffset);
2791 assert(BaseOffset >= Size &&
"base offset already allocated");
2794 BaseOffset = Size.
alignTo(Info.Alignment);
2796 VBases.insert(std::make_pair(BaseDecl,
2799 PreviousBaseLayout = &BaseLayout;
2803 void MicrosoftRecordLayoutBuilder::finalizeLayout(
const RecordDecl *RD) {
2807 if (!RequiredAlignment.isZero()) {
2808 Alignment =
std::max(Alignment, RequiredAlignment);
2809 auto RoundingAlignment = Alignment;
2810 if (!MaxFieldAlignment.isZero())
2811 RoundingAlignment =
std::min(RoundingAlignment, MaxFieldAlignment);
2812 RoundingAlignment =
std::max(RoundingAlignment, RequiredAlignment);
2813 Size = Size.alignTo(RoundingAlignment);
2815 if (Size.isZero()) {
2816 if (!
recordUsesEBO(RD) || !cast<CXXRecordDecl>(RD)->isEmpty()) {
2817 EndsWithZeroSizedObject =
true;
2818 LeadsWithZeroSizedBase =
true;
2822 if (RequiredAlignment >= MinEmptyStructSize)
2825 Size = MinEmptyStructSize;
2828 if (UseExternalLayout) {
2839 BasesWithOverriddenMethods,
2841 if (BasesWithOverriddenMethods.count(RD))
2846 if (!Base.isVirtual() &&
2848 Base.getType()->getAsCXXRecordDecl()))
2853 void MicrosoftRecordLayoutBuilder::computeVtorDispSet(
2854 llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtordispSet,
2860 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
2863 HasVtordispSet.insert(BaseDecl);
2871 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
2874 if (bi.second.hasVtorDisp())
2875 HasVtordispSet.insert(bi.first);
2891 llvm::SmallPtrSet<const CXXMethodDecl *, 8> Work;
2892 llvm::SmallPtrSet<const CXXRecordDecl *, 2> BasesWithOverriddenMethods;
2895 if (MD->isVirtual() && !isa<CXXDestructorDecl>(MD) && !MD->isPure())
2897 while (!Work.empty()) {
2903 BasesWithOverriddenMethods.insert(MD->
getParent());
2912 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
2913 if (!HasVtordispSet.count(BaseDecl) &&
2915 HasVtordispSet.insert(BaseDecl);
2933 assert(D &&
"Cannot get layout of forward declarations!");
2934 assert(!D->isInvalidDecl() &&
"Cannot get layout of invalid decl!");
2941 if (Entry)
return *Entry;
2946 MicrosoftRecordLayoutBuilder
Builder(*
this);
2947 if (
const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
2948 Builder.cxxLayout(RD);
2950 *
this, Builder.Size, Builder.Alignment, Builder.RequiredAlignment,
2951 Builder.HasOwnVFPtr, Builder.HasOwnVFPtr || Builder.PrimaryBase,
2952 Builder.VBPtrOffset, Builder.DataSize, Builder.FieldOffsets,
2953 Builder.NonVirtualSize, Builder.Alignment, CharUnits::Zero(),
2954 Builder.PrimaryBase,
false, Builder.SharedVBPtrBase,
2955 Builder.EndsWithZeroSizedObject, Builder.LeadsWithZeroSizedBase,
2956 Builder.Bases, Builder.VBases);
2960 *
this, Builder.Size, Builder.Alignment, Builder.RequiredAlignment,
2961 Builder.Size, Builder.FieldOffsets);
2964 if (
const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
2965 EmptySubobjectMap EmptySubobjects(*
this, RD);
2966 ItaniumRecordLayoutBuilder
Builder(*
this, &EmptySubobjects);
2972 bool skipTailPadding =
2977 skipTailPadding ? Builder.getSize() : Builder.getDataSize();
2979 skipTailPadding ? DataSize : Builder.NonVirtualSize;
2981 *
this, Builder.getSize(), Builder.Alignment,
2985 NonVirtualSize, Builder.NonVirtualAlignment,
2986 EmptySubobjects.SizeOfLargestEmptySubobject, Builder.PrimaryBase,
2987 Builder.PrimaryBaseIsVirtual,
nullptr,
false,
false, Builder.Bases,
2990 ItaniumRecordLayoutBuilder
Builder(*
this,
nullptr);
2994 *
this, Builder.getSize(), Builder.Alignment,
2996 Builder.Alignment, Builder.getSize(), Builder.FieldOffsets);
3000 ASTRecordLayouts[D] = NewEntry;
3003 llvm::outs() <<
"\n*** Dumping AST Record Layout\n";
3014 assert(RD->
getDefinition() &&
"Cannot get key function for forward decl!");
3015 RD = cast<CXXRecordDecl>(RD->getDefinition());
3027 if (Entry.isOffset() || Entry.isValid() !=
bool(Result))
3028 KeyFunctions[RD] = const_cast<Decl*>(Result);
3030 return cast_or_null<CXXMethodDecl>(
Result);
3035 "not working with method declaration from class definition");
3040 const auto &
Map = KeyFunctions;
3044 if (I == Map.end())
return;
3052 KeyFunctions.erase(Method->
getParent());
3062 uint64_t OffsetInBits;
3063 if (
const FieldDecl *FD = dyn_cast<FieldDecl>(VD)) {
3073 return OffsetInBits;
3103 if (SynthCount == 0)
3104 return getObjCLayout(D,
nullptr);
3107 ItaniumRecordLayoutBuilder
Builder(*
this,
nullptr);
3118 ObjCLayouts[Key] = NewEntry;
3124 CharUnits Offset,
unsigned IndentLevel) {
3125 OS << llvm::format(
"%10" PRId64
" | ", (int64_t)Offset.
getQuantity());
3126 OS.indent(IndentLevel * 2);
3130 unsigned Begin,
unsigned Width,
3131 unsigned IndentLevel) {
3134 llvm::raw_svector_ostream BufferOS(Buffer);
3139 BufferOS << Begin <<
'-' << (Begin + Width - 1);
3143 OS << llvm::right_justify(Buffer, 10) <<
" | ";
3144 OS.indent(IndentLevel * 2);
3149 OS.indent(IndentLevel * 2);
3155 unsigned IndentLevel,
3156 const char* Description,
3158 bool IncludeVirtualBases) {
3165 OS <<
' ' << Description;
3166 if (CXXRD && CXXRD->isEmpty())
3179 if (CXXRD->isDynamicClass() && !PrimaryBase && !
isMsLayout(C)) {
3181 OS <<
'(' << *RD <<
" vtable pointer)\n";
3182 }
else if (HasOwnVFPtr) {
3185 OS <<
'(' << *RD <<
" vftable pointer)\n";
3191 assert(!Base.getType()->isDependentType() &&
3192 "Cannot layout class with dependent bases.");
3193 if (!Base.isVirtual())
3194 Bases.push_back(Base.getType()->getAsCXXRecordDecl());
3198 std::stable_sort(Bases.begin(), Bases.end(),
3207 Base == PrimaryBase ?
"(primary base)" :
"(base)",
3215 OS <<
'(' << *RD <<
" vbtable pointer)\n";
3220 uint64_t FieldNo = 0;
3224 uint64_t LocalFieldOffsetInBits = Layout.
getFieldOffset(FieldNo);
3238 uint64_t LocalFieldByteOffsetInBits = C.
toBits(FieldOffset - Offset);
3239 unsigned Begin = LocalFieldOffsetInBits - LocalFieldByteOffsetInBits;
3249 if (CXXRD && IncludeVirtualBases) {
3254 assert(Base.isVirtual() &&
"Found non-virtual class!");
3255 const CXXRecordDecl *VBase = Base.getType()->getAsCXXRecordDecl();
3259 if (VtorDisps.find(VBase)->second.hasVtorDisp()) {
3261 OS <<
"(vtordisp for vbase " << *VBase <<
")\n";
3266 "(primary virtual base)" :
"(virtual base)",
3272 if (!PrintSizeInfo)
return;
3291 bool Simple)
const {
3309 OS <<
"<ASTRecordLayout\n";
3314 OS <<
" FieldOffsets: [";
3315 for (
unsigned i = 0, e = Info.
getFieldCount(); i != e; ++i) {
static uint64_t getFieldOffset(const ASTContext &C, const FieldDecl *FD)
unsigned getAddressSpace() const
Return the address space of this type.
Defines the clang::ASTContext interface.
FunctionDecl - An instance of this class is created to represent a function declaration or definition...
Only allocate objects in the tail padding of a base class if the base class is not POD according to t...
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
getName - Get the name of identifier for this declaration as a StringRef.
unsigned getZeroLengthBitfieldBoundary() const
Get the fixed alignment value in bits for a member that follows a zero length bitfield.
A (possibly-)qualified type.
llvm::DenseMap< const CXXRecordDecl *, VBaseInfo > VBaseOffsetsMapTy
static bool mustSkipTailPadding(TargetCXXABI ABI, const CXXRecordDecl *RD)
Does the target C++ ABI require us to skip over the tail-padding of the given class (considering it a...
static void DumpRecordLayout(raw_ostream &OS, const RecordDecl *RD, const ASTContext &C, CharUnits Offset, unsigned IndentLevel, const char *Description, bool PrintSizeInfo, bool IncludeVirtualBases)
unsigned getFieldCount() const
getFieldCount - Get the number of fields in the layout.
bool isBitField() const
Determines whether this field is a bitfield.
The basic abstraction for the target C++ ABI.
IdentifierInfo * getIdentifier() const
getIdentifier - Get the identifier that names this declaration, if there is one.
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.
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.
std::string getAsString() const
The base class of the type hierarchy.
std::unique_ptr< llvm::MemoryBuffer > Buffer
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const
getVBaseClassOffset - Get the offset, in chars, for the given base class.
bool isPrimaryBaseVirtual() const
isPrimaryBaseVirtual - Get whether the primary base for this record is virtual or not...
CharUnits alignTo(const CharUnits &Align) const
alignTo - Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is ...
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
Return the specified type with any "sugar" removed from the type, removing any typedefs, typeofs, etc., as well as any qualifiers.
RecordDecl - Represents a struct/union/class.
return(__x >> __y)|(__x<< (32-__y))
MSVtorDispAttr::Mode getMSVtorDispMode() const
Controls when vtordisps will be emitted if this record is used as a virtual base. ...
bool endsWithZeroSizedObject() const
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...
FieldDecl - An instance of this class is created by Sema::ActOnField to represent a member of a struc...
bool isCompleteDefinition() const
isCompleteDefinition - Return true if this decl has its body fully specified.
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
ObjCContainerDecl - Represents a container for method declarations.
const LangOptions & getLangOpts() const
CharUnits - This is an opaque type for sizes expressed in character units.
const CXXRecordDecl * getParent() const
Returns the parent of this method declaration, which is the class in which this method is defined...
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
Type Query functions.
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
getFieldOffset - Get the offset of the given field index, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
Represents an ObjC class declaration.
detail::InMemoryDirectory::const_iterator I
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
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
bool hasOwnVBPtr() const
hasOwnVBPtr - Does this class provide its own virtual-base table pointer, rather than inheriting one ...
unsigned getCharAlign() const
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
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?
ValueDecl - Represent the declaration of a variable (in which case it is an lvalue) a function (in wh...
ArrayRef< NamedDecl * > chain() const
bool leadsWithZeroSizedBase() const
CharUnits getNonVirtualAlignment() const
getNonVirtualSize - Get the non-virtual alignment (in chars) of an object, which is the alignment of ...
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
char __ovld __cnfn min(char x, char y)
Returns y if y < x, otherwise it returns x.
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
bool isExternallyVisible() const
CharUnits getVBPtrOffset() const
getVBPtrOffset - Get the offset for virtual base table pointer.
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.
This template specialization was implicitly instantiated from a template.
RecordDecl * getDefinition() const
getDefinition - Returns the RecordDecl that actually defines this struct/union/class.
decl_type * getFirstDecl()
Return the first declaration of this declaration or itself if this is the only declaration.
static bool recordUsesEBO(const RecordDecl *RD)
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.
Only allocate objects in the tail padding of a base class if the base class is not POD according to t...
Encodes a location in the source.
ExternalASTSource * getExternalSource() const
Retrieve a pointer to the external AST source associated with this AST context, if any...
const TemplateArgument * iterator
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)
Represents a static or instance method of a struct/union/class.
bool hasExtendableVFPtr() const
hasVFPtr - Does this class have a virtual function table pointer that can be extended by a derived cl...
const ConstantArrayType * getAsConstantArrayType(QualType T) const
const VBaseOffsetsMapTy & getVBaseOffsetsMap() const
const Type * getBaseElementTypeUnsafe() const
Get the base element type of this type, potentially discarding type qualifiers.
T * get(ExternalASTSource *Source) const
Retrieve the pointer to the AST node that this lazy pointer.
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
This template specialization was instantiated from a template due to an explicit instantiation defini...
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.
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.
unsigned getCharWidth() const
IndirectFieldDecl - An instance of this class is created to represent a field injected from an anonym...
CanQualType UnsignedLongLongTy
ObjCInterfaceDecl * getDefinition()
Retrieve the definition of this class, or NULL if this class has been forward-declared (with @class) ...
This template specialization was instantiated from a template due to an explicit instantiation declar...
bool useExplicitBitFieldAlignment() const
Check whether explicit bitfield alignment attributes should be.
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
detail::InMemoryDirectory::const_iterator E
TemplateSpecializationKind
Describes the kind of template specialization that a particular template specialization declaration r...
bool isMsStruct(const ASTContext &C) const
isMsStrust - Get whether or not this is an ms_struct which can be turned on with an attribute...
specific_decl_iterator - Iterates over a subrange of declarations stored in a DeclContext, providing only those that are of type SpecificDecl (or a class derived from it).
unsigned Map[Count]
The type of a lookup table which maps from language-specific address spaces to target-specific ones...
All virtual base related information about a given record decl.
ObjCImplementationDecl - Represents a class definition - this is where method definitions are specifi...
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
const T * getAs() const
Member-template getAs<specific type>'.
CanQualType UnsignedLongTy
void setNonKeyFunction(const CXXMethodDecl *method)
Observe that the given method cannot be a key function.
virtual void CompleteType(TagDecl *Tag)
Gives the external AST source an opportunity to complete an incomplete type.
Base for LValueReferenceType and RValueReferenceType.
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
getNonVirtualSize - Get the non-virtual size (in chars) of an object, which is the size of the object...
unsigned getFieldIndex() const
getFieldIndex - Returns the index of this field within its record, as appropriate for passing to ASTR...
char __ovld __cnfn max(char x, char y)
Returns y if x < y, otherwise it returns x.
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.
ObjCIvarDecl - Represents an ObjC instance variable.
void DumpRecordLayout(const RecordDecl *RD, raw_ostream &OS, bool Simple=false) const
CharUnits getDataSize() const
getDataSize() - Get the record data size, which is the record size without tail padding, in characters.
static bool isMsLayout(const ASTContext &Context)
This class is used for builtin types like 'int'.
static const CXXMethodDecl * computeKeyFunction(ASTContext &Context, const CXXRecordDecl *RD)
The tail-padding of a base class is always theoretically available, even if it's POD.
Defines the clang::TargetInfo interface.
ObjCInterfaceDecl * getSuperClass() const
bool hasOwnVFPtr() const
hasOwnVFPtr - Does this class provide its own virtual-function table pointer, rather than inheriting ...
static void PrintBitFieldOffset(raw_ostream &OS, CharUnits Offset, unsigned Begin, unsigned Width, unsigned IndentLevel)
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.
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
NamedDecl - This represents a decl with a name.
ObjCIvarDecl * all_declared_ivar_begin()
all_declared_ivar_begin - return first ivar declared in this class, its extensions and its implementa...
const ASTRecordLayout & getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D) const
Get or compute information about the layout of the specified Objective-C interface.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
bool isPolymorphic() const
Whether this class is polymorphic (C++ [class.virtual]), which means that the class contains or inher...
Represents the canonical version of C arrays with a specified constant size.
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
getParent - Returns the parent of this field declaration, which is the struct in which this method is...
CanQualType UnsignedIntTy
bool isPOD() const
Whether this class is a POD-type (C++ [class]p4)