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;
206 for (
const FieldDecl *FD : Class->fields()) {
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().RoundUpToAlignment(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() &&
1183 setSize(std::max(getSize(), Layout.
getSize()));
1184 UpdateAlignment(BaseAlign, UnpackedBaseAlign);
1190 if (!MaxFieldAlignment.isZero()) {
1191 BaseAlign = std::min(BaseAlign, MaxFieldAlignment);
1192 UnpackedBaseAlign = std::min(UnpackedBaseAlign, MaxFieldAlignment);
1195 if (!HasExternalLayout) {
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().RoundUpToAlignment(BaseAlign)){
1211 InferAlignment =
false;
1215 if (!Base->Class->isEmpty()) {
1219 setSize(std::max(getSize(), getDataSize()));
1221 setSize(std::max(getSize(), Offset + Layout.
getSize()));
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>())
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);
1295 llvm::RoundUpToAlignment(getSizeInBits(),
1297 NonVirtualAlignment = Alignment;
1300 LayoutVirtualBases(RD, RD);
1309 if (Base.isVirtual())
1312 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
1314 assert(Bases.count(BaseDecl) &&
"Did not find base offset!");
1319 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
1321 assert(VBases.count(BaseDecl) &&
"Did not find base offset!");
1335 setDataSize(getSize());
1338 InitializeLayout(D);
1342 LayoutField(IVD,
false);
1349 void ItaniumRecordLayoutBuilder::LayoutFields(
const RecordDecl *D) {
1358 InsertExtraPadding && (
Next !=
End || !HasFlexibleArrayMember));
1367 return llvm::RoundUpToAlignment(Size, CharAlignment);
1370 void ItaniumRecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize,
1375 "Can only have wide bit-fields in C++!");
1387 for (
const QualType &QT : IntegralPODTypes) {
1390 if (Size > FieldSize)
1395 assert(!Type.
isNull() &&
"Did not find a type!");
1400 UnfilledBitsInLastUnit = 0;
1401 LastBitfieldTypeSize = 0;
1403 uint64_t FieldOffset;
1404 uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;
1409 setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize));
1414 FieldOffset = llvm::RoundUpToAlignment(getDataSizeInBits(),
1417 uint64_t NewSizeInBits = FieldOffset + FieldSize;
1419 setDataSize(llvm::RoundUpToAlignment(NewSizeInBits,
1421 UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits;
1425 FieldOffsets.push_back(FieldOffset);
1427 CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, FieldOffset,
1431 setSize(std::max(getSizeInBits(), getDataSizeInBits()));
1434 UpdateAlignment(TypeAlign);
1437 void ItaniumRecordLayoutBuilder::LayoutBitField(
const FieldDecl *D) {
1438 bool FieldPacked = Packed || D->
hasAttr<PackedAttr>();
1441 uint64_t TypeSize = FieldInfo.
Width;
1442 unsigned FieldAlign = FieldInfo.
Align;
1504 FieldAlign = TypeSize;
1509 if (LastBitfieldTypeSize != TypeSize) {
1511 if (!LastBitfieldTypeSize && !FieldSize)
1514 UnfilledBitsInLastUnit = 0;
1515 LastBitfieldTypeSize = 0;
1521 if (FieldSize > TypeSize) {
1522 LayoutWideBitField(FieldSize, TypeSize, FieldPacked, D);
1527 uint64_t FieldOffset =
1528 IsUnion ? 0 : (getDataSizeInBits() - UnfilledBitsInLastUnit);
1533 if (FieldSize == 0 &&
1537 unsigned ZeroLengthBitfieldBoundary =
1539 FieldAlign = std::max(FieldAlign, ZeroLengthBitfieldBoundary);
1548 unsigned UnpackedFieldAlign = FieldAlign;
1551 if (!IsMsStruct && FieldPacked && FieldSize != 0)
1556 if (ExplicitFieldAlign) {
1557 FieldAlign = std::max(FieldAlign, ExplicitFieldAlign);
1558 UnpackedFieldAlign = std::max(UnpackedFieldAlign, ExplicitFieldAlign);
1563 if (!MaxFieldAlignment.isZero() && FieldSize) {
1564 unsigned MaxFieldAlignmentInBits =
Context.
toBits(MaxFieldAlignment);
1565 FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits);
1566 UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits);
1571 if (IsMsStruct && IsUnion) {
1572 FieldAlign = UnpackedFieldAlign = 1;
1578 uint64_t UnpaddedFieldOffset = FieldOffset;
1579 uint64_t UnpackedFieldOffset = FieldOffset;
1589 if (FieldSize == 0 || FieldSize > UnfilledBitsInLastUnit) {
1590 FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign);
1591 UnpackedFieldOffset = llvm::RoundUpToAlignment(UnpackedFieldOffset,
1592 UnpackedFieldAlign);
1593 UnfilledBitsInLastUnit = 0;
1598 bool AllowPadding = MaxFieldAlignment.isZero();
1601 if (FieldSize == 0 ||
1603 (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize)) {
1604 FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign);
1605 }
else if (ExplicitFieldAlign) {
1608 FieldOffset = llvm::RoundUpToAlignment(FieldOffset, ExplicitFieldAlign);
1612 if (FieldSize == 0 ||
1614 (UnpackedFieldOffset & (UnpackedFieldAlign-1)) + FieldSize > TypeSize))
1615 UnpackedFieldOffset = llvm::RoundUpToAlignment(UnpackedFieldOffset,
1616 UnpackedFieldAlign);
1617 else if (ExplicitFieldAlign)
1618 UnpackedFieldOffset = llvm::RoundUpToAlignment(UnpackedFieldOffset,
1619 ExplicitFieldAlign);
1624 if (UseExternalLayout)
1625 FieldOffset = updateExternalFieldOffset(D, FieldOffset);
1628 FieldOffsets.push_back(FieldOffset);
1637 FieldAlign = UnpackedFieldAlign = 1;
1640 if (!UseExternalLayout)
1641 CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, UnpackedFieldOffset,
1642 UnpackedFieldAlign, FieldPacked, D);
1650 uint64_t RoundedFieldSize;
1660 setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize));
1664 }
else if (IsMsStruct && FieldSize) {
1667 if (!UnfilledBitsInLastUnit) {
1668 setDataSize(FieldOffset + TypeSize);
1669 UnfilledBitsInLastUnit = TypeSize;
1671 UnfilledBitsInLastUnit -= FieldSize;
1672 LastBitfieldTypeSize = TypeSize;
1678 uint64_t NewSizeInBits = FieldOffset + FieldSize;
1680 setDataSize(llvm::RoundUpToAlignment(NewSizeInBits, CharAlignment));
1681 UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits;
1686 LastBitfieldTypeSize = 0;
1690 setSize(std::max(getSizeInBits(), getDataSizeInBits()));
1697 void ItaniumRecordLayoutBuilder::LayoutField(
const FieldDecl *D,
1698 bool InsertExtraPadding) {
1704 uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;
1707 UnfilledBitsInLastUnit = 0;
1708 LastBitfieldTypeSize = 0;
1710 bool FieldPacked = Packed || D->
hasAttr<PackedAttr>();
1731 std::pair<CharUnits, CharUnits> FieldInfo =
1733 FieldSize = FieldInfo.first;
1734 FieldAlign = FieldInfo.second;
1745 if (TypeSize > FieldAlign)
1746 FieldAlign = TypeSize;
1753 CharUnits UnpackedFieldAlign = FieldAlign;
1754 CharUnits UnpackedFieldOffset = FieldOffset;
1760 FieldAlign = std::max(FieldAlign, MaxAlignmentInChars);
1761 UnpackedFieldAlign = std::max(UnpackedFieldAlign, MaxAlignmentInChars);
1764 if (!MaxFieldAlignment.isZero()) {
1765 FieldAlign = std::min(FieldAlign, MaxFieldAlignment);
1766 UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignment);
1770 FieldOffset = FieldOffset.RoundUpToAlignment(FieldAlign);
1771 UnpackedFieldOffset =
1774 if (UseExternalLayout) {
1778 if (!IsUnion && EmptySubobjects) {
1780 bool Allowed = EmptySubobjects->CanPlaceFieldAtOffset(D, FieldOffset);
1782 assert(Allowed &&
"Externally-placed field cannot be placed here");
1785 if (!IsUnion && EmptySubobjects) {
1787 while (!EmptySubobjects->CanPlaceFieldAtOffset(D, FieldOffset)) {
1789 FieldOffset += FieldAlign;
1797 if (!UseExternalLayout)
1798 CheckFieldPadding(
Context.
toBits(FieldOffset), UnpaddedFieldOffset,
1802 if (InsertExtraPadding) {
1804 CharUnits ExtraSizeForAsan = ASanAlignment;
1805 if (FieldSize % ASanAlignment)
1808 FieldSize += ExtraSizeForAsan;
1814 setDataSize(std::max(getDataSizeInBits(), FieldSizeInBits));
1816 setDataSize(FieldOffset + FieldSize);
1819 setSize(std::max(getSizeInBits(), getDataSizeInBits()));
1822 UpdateAlignment(FieldAlign, UnpackedFieldAlign);
1825 void ItaniumRecordLayoutBuilder::FinishLayout(
const NamedDecl *D) {
1841 uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastUnit;
1842 uint64_t UnpackedSizeInBits =
1843 llvm::RoundUpToAlignment(getSizeInBits(),
1846 uint64_t RoundedSize
1847 = llvm::RoundUpToAlignment(getSizeInBits(),
Context.
toBits(Alignment));
1849 if (UseExternalLayout) {
1853 if (InferAlignment && External.Size < RoundedSize) {
1855 InferAlignment =
false;
1857 setSize(External.Size);
1862 setSize(RoundedSize);
1865 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
1867 if (getSizeInBits() > UnpaddedSize) {
1868 unsigned PadSize = getSizeInBits() - UnpaddedSize;
1870 if (PadSize % CharBitNum == 0) {
1871 PadSize = PadSize / CharBitNum;
1877 << (InBits ? 1 : 0);
1883 getSize() == UnpackedSize)
1889 void ItaniumRecordLayoutBuilder::UpdateAlignment(
1893 if (IsMac68kAlign || (UseExternalLayout && !InferAlignment))
1896 if (NewAlignment > Alignment) {
1897 assert(llvm::isPowerOf2_64(NewAlignment.
getQuantity()) &&
1898 "Alignment not a power of 2");
1899 Alignment = NewAlignment;
1902 if (UnpackedNewAlignment > UnpackedAlignment) {
1903 assert(llvm::isPowerOf2_64(UnpackedNewAlignment.
getQuantity()) &&
1904 "Alignment not a power of 2");
1905 UnpackedAlignment = UnpackedNewAlignment;
1910 ItaniumRecordLayoutBuilder::updateExternalFieldOffset(
const FieldDecl *Field,
1911 uint64_t ComputedOffset) {
1912 uint64_t ExternalFieldOffset = External.getExternalFieldOffset(Field);
1914 if (InferAlignment && ExternalFieldOffset < ComputedOffset) {
1918 InferAlignment =
false;
1922 return ExternalFieldOffset;
1935 default: llvm_unreachable(
"Invalid tag kind for field padding diagnostic!");
1939 void ItaniumRecordLayoutBuilder::CheckFieldPadding(
1940 uint64_t Offset, uint64_t UnpaddedOffset, uint64_t UnpackedOffset,
1941 unsigned UnpackedAlign,
bool isPacked,
const FieldDecl *D) {
1944 if (isa<ObjCIvarDecl>(D))
1955 if (!IsUnion && Offset > UnpaddedOffset) {
1956 unsigned PadSize = Offset - UnpaddedOffset;
1958 if (PadSize % CharBitNum == 0) {
1959 PadSize = PadSize / CharBitNum;
1974 << (InBits ? 1 : 0);
1979 if (isPacked && UnpackedAlign > CharBitNum && Offset == UnpackedOffset)
2004 bool allowInlineFunctions =
2008 if (!MD->isVirtual())
2016 if (MD->isImplicit())
2019 if (MD->isInlineSpecified())
2022 if (MD->hasInlineBody())
2026 if (!MD->isUserProvided())
2030 if (!allowInlineFunctions) {
2042 if (!MD->hasAttr<CUDADeviceAttr>())
2046 if (!MD->hasAttr<CUDAHostAttr>() && MD->hasAttr<CUDADeviceAttr>())
2054 if (MD->hasAttr<DLLImportAttr>() && !RD->
hasAttr<DLLImportAttr>())
2108 llvm_unreachable(
"bad tail-padding use kind");
2206 struct MicrosoftRecordLayoutBuilder {
2207 struct ElementInfo {
2211 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
2214 MicrosoftRecordLayoutBuilder(
const MicrosoftRecordLayoutBuilder &) =
delete;
2215 void operator=(
const MicrosoftRecordLayoutBuilder &) =
delete;
2235 void layoutBitField(
const FieldDecl *FD);
2238 void layoutZeroWidthBitField(
const FieldDecl *FD);
2247 ElementInfo getAdjustedElementInfo(
const FieldDecl *FD);
2249 void placeFieldAtOffset(
CharUnits FieldOffset) {
2253 void placeFieldAtBitOffset(uint64_t FieldOffset) {
2254 FieldOffsets.push_back(FieldOffset);
2257 void computeVtorDispSet(
2258 llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtorDispSet,
2283 ElementInfo PointerInfo;
2291 BaseOffsetsMapTy Bases;
2297 unsigned RemainingBitsInField;
2301 bool LastFieldIsNonZeroWidthBitfield : 1;
2303 bool HasOwnVFPtr : 1;
2309 bool EndsWithZeroSizedObject : 1;
2312 bool LeadsWithZeroSizedBase : 1;
2315 bool UseExternalLayout : 1;
2319 ExternalLayout External;
2323 MicrosoftRecordLayoutBuilder::ElementInfo
2324 MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
2329 if (!MaxFieldAlignment.isZero())
2330 Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment);
2336 Alignment = std::max(Alignment, Info.Alignment);
2343 MicrosoftRecordLayoutBuilder::ElementInfo
2344 MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
2349 std::tie(Info.Size, Info.Alignment) =
2356 FieldRequiredAlignment = std::max(
2362 Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment);
2368 FieldRequiredAlignment = std::max(FieldRequiredAlignment,
2372 RequiredAlignment = std::max(RequiredAlignment, FieldRequiredAlignment);
2375 if (!MaxFieldAlignment.isZero())
2376 Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment);
2377 if (FD->
hasAttr<PackedAttr>())
2379 Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment);
2383 void MicrosoftRecordLayoutBuilder::layout(
const RecordDecl *RD) {
2386 initializeLayout(RD);
2388 DataSize = Size = Size.RoundUpToAlignment(Alignment);
2389 RequiredAlignment = std::max(
2394 void MicrosoftRecordLayoutBuilder::cxxLayout(
const CXXRecordDecl *RD) {
2397 initializeLayout(RD);
2398 initializeCXXLayout(RD);
2399 layoutNonVirtualBases(RD);
2403 if (HasOwnVFPtr || (HasVBPtr && !SharedVBPtrBase))
2404 Alignment = std::max(Alignment, PointerInfo.Alignment);
2405 auto RoundingAlignment = Alignment;
2406 if (!MaxFieldAlignment.isZero())
2407 RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment);
2408 NonVirtualSize = Size = Size.RoundUpToAlignment(RoundingAlignment);
2409 RequiredAlignment = std::max(
2411 layoutVirtualBases(RD);
2415 void MicrosoftRecordLayoutBuilder::initializeLayout(
const RecordDecl *RD) {
2432 if (
const MaxFieldAlignmentAttr *MFAA = RD->
getAttr<MaxFieldAlignmentAttr>()){
2433 unsigned PackedAlignment = MFAA->getAlignment();
2438 if (RD->
hasAttr<PackedAttr>())
2442 UseExternalLayout =
false;
2444 UseExternalLayout = Source->layoutRecordType(
2445 RD, External.Size, External.Align, External.FieldOffsets,
2446 External.BaseOffsets, External.VirtualBaseOffsets);
2450 MicrosoftRecordLayoutBuilder::initializeCXXLayout(
const CXXRecordDecl *RD) {
2451 EndsWithZeroSizedObject =
false;
2452 LeadsWithZeroSizedBase =
false;
2453 HasOwnVFPtr =
false;
2455 PrimaryBase =
nullptr;
2456 SharedVBPtrBase =
nullptr;
2461 PointerInfo.Alignment =
2464 if (!MaxFieldAlignment.isZero())
2465 PointerInfo.Alignment = std::min(PointerInfo.Alignment, MaxFieldAlignment);
2469 MicrosoftRecordLayoutBuilder::layoutNonVirtualBases(
const CXXRecordDecl *RD) {
2479 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
2482 if (Base.isVirtual()) {
2487 if (!SharedVBPtrBase && BaseLayout.
hasVBPtr()) {
2488 SharedVBPtrBase = BaseDecl;
2496 PrimaryBase = BaseDecl;
2500 layoutNonVirtualBase(BaseDecl, BaseLayout, PreviousBaseLayout);
2506 !HasOwnVFPtr && i != e; ++i)
2507 HasOwnVFPtr = i->isVirtual() && i->size_overridden_methods() == 0;
2510 bool CheckLeadingLayout = !PrimaryBase;
2513 if (Base.isVirtual())
2515 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
2524 if (CheckLeadingLayout) {
2525 CheckLeadingLayout =
false;
2529 layoutNonVirtualBase(BaseDecl, BaseLayout, PreviousBaseLayout);
2535 else if (SharedVBPtrBase) {
2541 void MicrosoftRecordLayoutBuilder::layoutNonVirtualBase(
2551 ElementInfo Info = getAdjustedElementInfo(BaseLayout);
2555 bool FoundBase =
false;
2556 if (UseExternalLayout) {
2557 FoundBase = External.getExternalNVBaseOffset(BaseDecl, BaseOffset);
2559 assert(BaseOffset >= Size &&
"base offset already allocated");
2564 Bases.insert(std::make_pair(BaseDecl, BaseOffset));
2566 PreviousBaseLayout = &BaseLayout;
2569 void MicrosoftRecordLayoutBuilder::layoutFields(
const RecordDecl *RD) {
2570 LastFieldIsNonZeroWidthBitfield =
false;
2575 void MicrosoftRecordLayoutBuilder::layoutField(
const FieldDecl *FD) {
2580 LastFieldIsNonZeroWidthBitfield =
false;
2581 ElementInfo Info = getAdjustedElementInfo(FD);
2582 Alignment = std::max(Alignment, Info.Alignment);
2584 placeFieldAtOffset(CharUnits::Zero());
2585 Size = std::max(Size, Info.Size);
2588 if (UseExternalLayout) {
2591 assert(FieldOffset >= Size &&
"field offset already allocated");
2595 placeFieldAtOffset(FieldOffset);
2596 Size = FieldOffset + Info.Size;
2600 void MicrosoftRecordLayoutBuilder::layoutBitField(
const FieldDecl *FD) {
2603 layoutZeroWidthBitField(FD);
2606 ElementInfo Info = getAdjustedElementInfo(FD);
2614 if (!IsUnion && LastFieldIsNonZeroWidthBitfield &&
2615 CurrentBitfieldSize == Info.Size && Width <= RemainingBitsInField) {
2616 placeFieldAtBitOffset(
Context.
toBits(Size) - RemainingBitsInField);
2617 RemainingBitsInField -= Width;
2620 LastFieldIsNonZeroWidthBitfield =
true;
2621 CurrentBitfieldSize = Info.Size;
2623 placeFieldAtOffset(CharUnits::Zero());
2624 Size = std::max(Size, Info.Size);
2629 placeFieldAtOffset(FieldOffset);
2630 Size = FieldOffset + Info.Size;
2631 Alignment = std::max(Alignment, Info.Alignment);
2637 MicrosoftRecordLayoutBuilder::layoutZeroWidthBitField(
const FieldDecl *FD) {
2640 if (!LastFieldIsNonZeroWidthBitfield) {
2641 placeFieldAtOffset(IsUnion ? CharUnits::Zero() : Size);
2646 LastFieldIsNonZeroWidthBitfield =
false;
2647 ElementInfo Info = getAdjustedElementInfo(FD);
2649 placeFieldAtOffset(CharUnits::Zero());
2650 Size = std::max(Size, Info.Size);
2655 placeFieldAtOffset(FieldOffset);
2657 Alignment = std::max(Alignment, Info.Alignment);
2661 void MicrosoftRecordLayoutBuilder::injectVBPtr(
const CXXRecordDecl *RD) {
2662 if (!HasVBPtr || SharedVBPtrBase)
2670 if (UseExternalLayout)
2673 CharUnits FieldStart = VBPtrOffset + PointerInfo.Size;
2676 CharUnits Offset = (FieldStart - InjectionSite).RoundUpToAlignment(
2677 std::max(RequiredAlignment, Alignment));
2679 for (uint64_t &FieldOffset : FieldOffsets)
2681 for (BaseOffsetsMapTy::value_type &Base : Bases)
2682 if (Base.second >= InjectionSite)
2686 void MicrosoftRecordLayoutBuilder::injectVFPtr(
const CXXRecordDecl *RD) {
2692 std::max(RequiredAlignment, Alignment));
2698 if (UseExternalLayout)
2705 for (uint64_t &FieldOffset : FieldOffsets)
2707 for (BaseOffsetsMapTy::value_type &Base : Bases)
2711 void MicrosoftRecordLayoutBuilder::layoutVirtualBases(
const CXXRecordDecl *RD) {
2716 CharUnits VtorDispAlignment = VtorDispSize;
2718 if (!MaxFieldAlignment.isZero())
2719 VtorDispAlignment = std::min(VtorDispAlignment, MaxFieldAlignment);
2724 const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl();
2729 VtorDispAlignment = std::max(VtorDispAlignment, RequiredAlignment);
2731 llvm::SmallPtrSet<const CXXRecordDecl *, 2> HasVtorDispSet;
2732 computeVtorDispSet(HasVtorDispSet, RD);
2736 const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl();
2738 bool HasVtordisp = HasVtorDispSet.count(BaseDecl) > 0;
2746 Size = Size.RoundUpToAlignment(VtorDispAlignment) + VtorDispSize;
2747 Alignment = std::max(VtorDispAlignment, Alignment);
2750 ElementInfo Info = getAdjustedElementInfo(BaseLayout);
2754 bool FoundBase =
false;
2755 if (UseExternalLayout) {
2756 FoundBase = External.getExternalVBaseOffset(BaseDecl, BaseOffset);
2758 assert(BaseOffset >= Size &&
"base offset already allocated");
2763 VBases.insert(std::make_pair(BaseDecl,
2766 PreviousBaseLayout = &BaseLayout;
2770 void MicrosoftRecordLayoutBuilder::finalizeLayout(
const RecordDecl *RD) {
2774 if (!RequiredAlignment.isZero()) {
2775 Alignment = std::max(Alignment, RequiredAlignment);
2776 auto RoundingAlignment = Alignment;
2777 if (!MaxFieldAlignment.isZero())
2778 RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment);
2779 RoundingAlignment = std::max(RoundingAlignment, RequiredAlignment);
2780 Size = Size.RoundUpToAlignment(RoundingAlignment);
2782 if (Size.isZero()) {
2783 EndsWithZeroSizedObject =
true;
2784 LeadsWithZeroSizedBase =
true;
2787 if (RequiredAlignment >= MinEmptyStructSize)
2790 Size = MinEmptyStructSize;
2793 if (UseExternalLayout) {
2804 BasesWithOverriddenMethods,
2806 if (BasesWithOverriddenMethods.count(RD))
2811 if (!Base.isVirtual() &&
2813 Base.getType()->getAsCXXRecordDecl()))
2818 void MicrosoftRecordLayoutBuilder::computeVtorDispSet(
2819 llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtordispSet,
2825 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
2828 HasVtordispSet.insert(BaseDecl);
2836 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
2839 if (bi.second.hasVtorDisp())
2840 HasVtordispSet.insert(bi.first);
2856 llvm::SmallPtrSet<const CXXMethodDecl *, 8> Work;
2857 llvm::SmallPtrSet<const CXXRecordDecl *, 2> BasesWithOverriddenMethods;
2860 if (MD->isVirtual() && !isa<CXXDestructorDecl>(MD) && !MD->isPure())
2862 while (!Work.empty()) {
2868 BasesWithOverriddenMethods.insert(MD->
getParent());
2877 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
2878 if (!HasVtordispSet.count(BaseDecl) &&
2880 HasVtordispSet.insert(BaseDecl);
2898 assert(D &&
"Cannot get layout of forward declarations!");
2899 assert(!D->
isInvalidDecl() &&
"Cannot get layout of invalid decl!");
2906 if (Entry)
return *Entry;
2911 MicrosoftRecordLayoutBuilder
Builder(*
this);
2912 if (
const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
2913 Builder.cxxLayout(RD);
2915 *
this, Builder.Size, Builder.Alignment, Builder.RequiredAlignment,
2916 Builder.HasOwnVFPtr, Builder.HasOwnVFPtr || Builder.PrimaryBase,
2917 Builder.VBPtrOffset, Builder.NonVirtualSize,
2918 Builder.FieldOffsets.data(), Builder.FieldOffsets.size(),
2920 Builder.PrimaryBase,
false, Builder.SharedVBPtrBase,
2921 Builder.EndsWithZeroSizedObject, Builder.LeadsWithZeroSizedBase,
2922 Builder.Bases, Builder.VBases);
2926 *
this, Builder.Size, Builder.Alignment, Builder.RequiredAlignment,
2927 Builder.Size, Builder.FieldOffsets.data(),
2928 Builder.FieldOffsets.size());
2931 if (
const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
2932 EmptySubobjectMap EmptySubobjects(*
this, RD);
2933 ItaniumRecordLayoutBuilder
Builder(*
this, &EmptySubobjects);
2939 bool skipTailPadding =
2944 skipTailPadding ? Builder.getSize() : Builder.getDataSize();
2946 skipTailPadding ? DataSize : Builder.NonVirtualSize;
2948 *
this, Builder.getSize(), Builder.Alignment,
2952 Builder.FieldOffsets.size(), NonVirtualSize,
2953 Builder.NonVirtualAlignment,
2954 EmptySubobjects.SizeOfLargestEmptySubobject, Builder.PrimaryBase,
2955 Builder.PrimaryBaseIsVirtual,
nullptr,
false,
false, Builder.Bases,
2958 ItaniumRecordLayoutBuilder
Builder(*
this,
nullptr);
2962 *
this, Builder.getSize(), Builder.Alignment,
2964 Builder.Alignment, Builder.getSize(), Builder.FieldOffsets.data(),
2965 Builder.FieldOffsets.size());
2969 ASTRecordLayouts[D] = NewEntry;
2972 llvm::outs() <<
"\n*** Dumping AST Record Layout\n";
2983 assert(RD->
getDefinition() &&
"Cannot get key function for forward decl!");
2984 RD = cast<CXXRecordDecl>(RD->getDefinition());
2996 if (Entry.isOffset() || Entry.isValid() !=
bool(Result))
2997 KeyFunctions[RD] = const_cast<Decl*>(Result);
2999 return cast_or_null<CXXMethodDecl>(
Result);
3004 "not working with method declaration from class definition");
3009 const auto &
Map = KeyFunctions;
3013 if (I == Map.end())
return;
3021 KeyFunctions.erase(Method->
getParent());
3031 uint64_t OffsetInBits;
3032 if (
const FieldDecl *FD = dyn_cast<FieldDecl>(VD)) {
3042 return OffsetInBits;
3072 if (SynthCount == 0)
3073 return getObjCLayout(D,
nullptr);
3076 ItaniumRecordLayoutBuilder
Builder(*
this,
nullptr);
3088 ObjCLayouts[Key] = NewEntry;
3094 CharUnits Offset,
unsigned IndentLevel) {
3095 OS << llvm::format(
"%10" PRId64
" | ", (int64_t)Offset.
getQuantity());
3096 OS.indent(IndentLevel * 2);
3100 unsigned Begin,
unsigned Width,
3101 unsigned IndentLevel) {
3104 llvm::raw_svector_ostream BufferOS(Buffer);
3109 BufferOS << Begin <<
'-' << (Begin + Width - 1);
3113 OS << llvm::right_justify(Buffer, 10) <<
" | ";
3114 OS.indent(IndentLevel * 2);
3119 OS.indent(IndentLevel * 2);
3125 unsigned IndentLevel,
3126 const char* Description,
3128 bool IncludeVirtualBases) {
3135 OS <<
' ' << Description;
3136 if (CXXRD && CXXRD->isEmpty())
3149 if (CXXRD->isDynamicClass() && !PrimaryBase && !
isMsLayout(C)) {
3151 OS <<
'(' << *RD <<
" vtable pointer)\n";
3152 }
else if (HasOwnVFPtr) {
3155 OS <<
'(' << *RD <<
" vftable pointer)\n";
3161 assert(!Base.getType()->isDependentType() &&
3162 "Cannot layout class with dependent bases.");
3163 if (!Base.isVirtual())
3164 Bases.push_back(Base.getType()->getAsCXXRecordDecl());
3168 std::stable_sort(Bases.begin(), Bases.end(),
3177 Base == PrimaryBase ?
"(primary base)" :
"(base)",
3185 OS <<
'(' << *RD <<
" vbtable pointer)\n";
3190 uint64_t FieldNo = 0;
3194 uint64_t LocalFieldOffsetInBits = Layout.
getFieldOffset(FieldNo);
3208 uint64_t LocalFieldByteOffsetInBits = C.
toBits(FieldOffset - Offset);
3209 unsigned Begin = LocalFieldOffsetInBits - LocalFieldByteOffsetInBits;
3219 if (CXXRD && IncludeVirtualBases) {
3224 assert(Base.isVirtual() &&
"Found non-virtual class!");
3225 const CXXRecordDecl *VBase = Base.getType()->getAsCXXRecordDecl();
3229 if (VtorDisps.find(VBase)->second.hasVtorDisp()) {
3231 OS <<
"(vtordisp for vbase " << *VBase <<
")\n";
3236 "(primary virtual base)" :
"(virtual base)",
3242 if (!PrintSizeInfo)
return;
3261 bool Simple)
const {
3279 OS <<
"<ASTRecordLayout\n";
3284 OS <<
" FieldOffsets: [";
3285 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 hasZeroSizedSubObject() const
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.
Decl - This represents one declaration (or definition), e.g.
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.
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...
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.
unsigned getMaxAlignment() const
getMaxAlignment - return the maximum alignment specified by attributes on this decl, 0 if there are none.
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...
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...
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
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.
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.
return(x >> y)|(x<< (32-y))
bool isInvalidDecl() const
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...
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...
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.
SourceLocation getLocation() const
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...
CharUnits RoundUpToAlignment(const CharUnits &Align) const
RoundUpToAlignment - Returns the next integer (mod 2**64) that is greater than or equal to this quant...
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)