20#include "llvm/Support/Format.h"
21#include "llvm/Support/MathExtras.h"
38struct BaseSubobjectInfo {
40 const CXXRecordDecl *Class;
46 SmallVector<BaseSubobjectInfo*, 4> Bases;
50 BaseSubobjectInfo *PrimaryVirtualBaseInfo;
53 const BaseSubobjectInfo *Derived;
59struct ExternalLayout {
60 ExternalLayout() =
default;
69 llvm::DenseMap<const FieldDecl *, uint64_t> FieldOffsets;
72 llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsets;
75 llvm::DenseMap<const CXXRecordDecl *, CharUnits> VirtualBaseOffsets;
79 uint64_t getExternalFieldOffset(
const FieldDecl *FD) {
80 assert(FieldOffsets.count(FD) &&
81 "Field does not have an external offset");
82 return FieldOffsets[FD];
85 bool getExternalNVBaseOffset(
const CXXRecordDecl *RD, CharUnits &BaseOffset) {
86 auto Known = BaseOffsets.find(RD);
87 if (Known == BaseOffsets.end())
89 BaseOffset = Known->second;
93 bool getExternalVBaseOffset(
const CXXRecordDecl *RD, CharUnits &BaseOffset) {
94 auto Known = VirtualBaseOffsets.find(RD);
95 if (Known == VirtualBaseOffsets.end())
97 BaseOffset = Known->second;
104class EmptySubobjectMap {
105 const ASTContext &Context;
109 const CXXRecordDecl *Class;
112 typedef llvm::TinyPtrVector<const CXXRecordDecl *> ClassVectorTy;
113 typedef llvm::DenseMap<CharUnits, ClassVectorTy> EmptyClassOffsetsMapTy;
114 EmptyClassOffsetsMapTy EmptyClassOffsets;
118 CharUnits MaxEmptyClassOffset;
122 void ComputeEmptySubobjectSizes();
124 void AddSubobjectAtOffset(
const CXXRecordDecl *RD, CharUnits Offset);
126 void UpdateEmptyBaseSubobjects(
const BaseSubobjectInfo *Info,
127 CharUnits Offset,
bool PlacingEmptyBase);
129 void UpdateEmptyFieldSubobjects(
const CXXRecordDecl *RD,
130 const CXXRecordDecl *Class, CharUnits Offset,
131 bool PlacingOverlappingField);
132 void UpdateEmptyFieldSubobjects(
const FieldDecl *FD, CharUnits Offset,
133 bool PlacingOverlappingField);
137 bool AnyEmptySubobjectsBeyondOffset(CharUnits Offset)
const {
138 return Offset <= MaxEmptyClassOffset;
142 const FieldDecl *Field)
const {
144 assert(FieldOffset % CharWidth == 0 &&
145 "Field offset not at char boundary!");
147 return Context.toCharUnitsFromBits(FieldOffset);
151 bool CanPlaceSubobjectAtOffset(
const CXXRecordDecl *RD,
152 CharUnits Offset)
const;
154 bool CanPlaceBaseSubobjectAtOffset(
const BaseSubobjectInfo *Info,
157 bool CanPlaceFieldSubobjectAtOffset(
const CXXRecordDecl *RD,
158 const CXXRecordDecl *Class,
159 CharUnits Offset)
const;
160 bool CanPlaceFieldSubobjectAtOffset(
const FieldDecl *FD,
161 CharUnits Offset)
const;
167 CharUnits SizeOfLargestEmptySubobject;
169 EmptySubobjectMap(
const ASTContext &Context,
const CXXRecordDecl *Class)
170 : Context(Context), CharWidth(Context.
getCharWidth()), Class(Class) {
171 ComputeEmptySubobjectSizes();
178 bool CanPlaceBaseAtOffset(
const BaseSubobjectInfo *Info,
183 bool CanPlaceFieldAtOffset(
const FieldDecl *FD, CharUnits Offset);
186void EmptySubobjectMap::ComputeEmptySubobjectSizes() {
188 for (
const CXXBaseSpecifier &Base :
Class->bases()) {
189 const CXXRecordDecl *BaseDecl =
Base.getType()->getAsCXXRecordDecl();
190 assert(BaseDecl !=
Class &&
"Class cannot inherit from itself.");
202 if (EmptySize > SizeOfLargestEmptySubobject)
203 SizeOfLargestEmptySubobject = EmptySize;
207 for (
const FieldDecl *FD :
Class->fields()) {
209 const auto *MemberDecl =
216 if (MemberDecl->isEmpty()) {
224 if (EmptySize > SizeOfLargestEmptySubobject)
225 SizeOfLargestEmptySubobject = EmptySize;
230EmptySubobjectMap::CanPlaceSubobjectAtOffset(
const CXXRecordDecl *RD,
231 CharUnits Offset)
const {
236 EmptyClassOffsetsMapTy::const_iterator I = EmptyClassOffsets.find(Offset);
237 if (I == EmptyClassOffsets.end())
240 const ClassVectorTy &Classes = I->second;
241 if (!llvm::is_contained(Classes, RD))
248void EmptySubobjectMap::AddSubobjectAtOffset(
const CXXRecordDecl *RD,
256 ClassVectorTy &Classes = EmptyClassOffsets[Offset];
257 if (llvm::is_contained(Classes, RD))
260 Classes.push_back(RD);
263 if (Offset > MaxEmptyClassOffset)
264 MaxEmptyClassOffset = Offset;
268EmptySubobjectMap::CanPlaceBaseSubobjectAtOffset(
const BaseSubobjectInfo *Info,
272 if (!AnyEmptySubobjectsBeyondOffset(Offset))
275 if (!CanPlaceSubobjectAtOffset(Info->Class, Offset))
280 for (
const BaseSubobjectInfo *Base : Info->Bases) {
286 if (!CanPlaceBaseSubobjectAtOffset(Base, BaseOffset))
290 if (Info->PrimaryVirtualBaseInfo) {
291 BaseSubobjectInfo *PrimaryVirtualBaseInfo = Info->PrimaryVirtualBaseInfo;
293 if (Info == PrimaryVirtualBaseInfo->Derived) {
294 if (!CanPlaceBaseSubobjectAtOffset(PrimaryVirtualBaseInfo, Offset))
300 for (
const FieldDecl *Field : Info->Class->
fields()) {
301 if (
Field->isBitField())
305 if (!CanPlaceFieldSubobjectAtOffset(Field, FieldOffset))
312void EmptySubobjectMap::UpdateEmptyBaseSubobjects(
const BaseSubobjectInfo *Info,
314 bool PlacingEmptyBase) {
315 if (!PlacingEmptyBase && Offset >= SizeOfLargestEmptySubobject) {
324 AddSubobjectAtOffset(Info->Class, Offset);
328 for (
const BaseSubobjectInfo *Base : Info->Bases) {
333 UpdateEmptyBaseSubobjects(Base, BaseOffset, PlacingEmptyBase);
336 if (Info->PrimaryVirtualBaseInfo) {
337 BaseSubobjectInfo *PrimaryVirtualBaseInfo = Info->PrimaryVirtualBaseInfo;
339 if (Info == PrimaryVirtualBaseInfo->Derived)
340 UpdateEmptyBaseSubobjects(PrimaryVirtualBaseInfo, Offset,
345 for (
const FieldDecl *Field : Info->Class->
fields()) {
346 if (
Field->isBitField())
350 UpdateEmptyFieldSubobjects(Field, FieldOffset, PlacingEmptyBase);
354bool EmptySubobjectMap::CanPlaceBaseAtOffset(
const BaseSubobjectInfo *Info,
358 if (SizeOfLargestEmptySubobject.
isZero())
361 if (!CanPlaceBaseSubobjectAtOffset(Info, Offset))
366 UpdateEmptyBaseSubobjects(Info, Offset, Info->Class->
isEmpty());
371EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(
const CXXRecordDecl *RD,
372 const CXXRecordDecl *
Class,
373 CharUnits Offset)
const {
376 if (!AnyEmptySubobjectsBeyondOffset(Offset))
379 if (!CanPlaceSubobjectAtOffset(RD, Offset))
385 for (
const CXXBaseSpecifier &Base : RD->
bases()) {
386 if (
Base.isVirtual())
389 const CXXRecordDecl *BaseDecl =
Base.getType()->getAsCXXRecordDecl();
392 if (!CanPlaceFieldSubobjectAtOffset(BaseDecl,
Class, BaseOffset))
398 for (
const CXXBaseSpecifier &Base : RD->
vbases()) {
399 const CXXRecordDecl *VBaseDecl =
Base.getType()->getAsCXXRecordDecl();
402 if (!CanPlaceFieldSubobjectAtOffset(VBaseDecl,
Class, VBaseOffset))
408 for (
const FieldDecl *Field : RD->
fields()) {
409 if (
Field->isBitField())
413 if (!CanPlaceFieldSubobjectAtOffset(Field, FieldOffset))
421EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(
const FieldDecl *FD,
422 CharUnits Offset)
const {
425 if (!AnyEmptySubobjectsBeyondOffset(Offset))
430 return CanPlaceFieldSubobjectAtOffset(RD, RD, Offset);
442 CharUnits ElementOffset = Offset;
443 for (uint64_t I = 0; I != NumElements; ++I) {
446 if (!AnyEmptySubobjectsBeyondOffset(ElementOffset))
449 if (!CanPlaceFieldSubobjectAtOffset(RD, RD, ElementOffset))
452 ElementOffset += Layout.
getSize();
459bool EmptySubobjectMap::CanPlaceFieldAtOffset(
const FieldDecl *FD,
461 if (!CanPlaceFieldSubobjectAtOffset(FD, Offset))
466 UpdateEmptyFieldSubobjects(FD, Offset, FD->
hasAttr<NoUniqueAddressAttr>());
470void EmptySubobjectMap::UpdateEmptyFieldSubobjects(
471 const CXXRecordDecl *RD,
const CXXRecordDecl *
Class, CharUnits Offset,
472 bool PlacingOverlappingField) {
483 if (!PlacingOverlappingField && Offset >= SizeOfLargestEmptySubobject)
486 AddSubobjectAtOffset(RD, Offset);
491 for (
const CXXBaseSpecifier &Base : RD->
bases()) {
492 if (
Base.isVirtual())
495 const CXXRecordDecl *BaseDecl =
Base.getType()->getAsCXXRecordDecl();
498 UpdateEmptyFieldSubobjects(BaseDecl,
Class, BaseOffset,
499 PlacingOverlappingField);
504 for (
const CXXBaseSpecifier &Base : RD->
vbases()) {
505 const CXXRecordDecl *VBaseDecl =
Base.getType()->getAsCXXRecordDecl();
508 UpdateEmptyFieldSubobjects(VBaseDecl,
Class, VBaseOffset,
509 PlacingOverlappingField);
514 for (
const FieldDecl *Field : RD->
fields()) {
515 if (
Field->isBitField())
519 UpdateEmptyFieldSubobjects(Field, FieldOffset, PlacingOverlappingField);
523void EmptySubobjectMap::UpdateEmptyFieldSubobjects(
524 const FieldDecl *FD, CharUnits Offset,
bool PlacingOverlappingField) {
527 UpdateEmptyFieldSubobjects(RD, RD, Offset, PlacingOverlappingField);
541 CharUnits ElementOffset = Offset;
543 for (uint64_t I = 0; I != NumElements; ++I) {
549 if (!PlacingOverlappingField &&
550 ElementOffset >= SizeOfLargestEmptySubobject)
553 UpdateEmptyFieldSubobjects(RD, RD, ElementOffset,
554 PlacingOverlappingField);
555 ElementOffset += Layout.
getSize();
560typedef llvm::SmallPtrSet<const CXXRecordDecl*, 4> ClassSetTy;
562class ItaniumRecordLayoutBuilder {
565 friend class clang::ASTContext;
567 const ASTContext &Context;
569 EmptySubobjectMap *EmptySubobjects;
578 CharUnits PreferredAlignment;
581 CharUnits UnpackedAlignment;
584 CharUnits UnadjustedAlignment;
586 SmallVector<uint64_t, 16> FieldOffsets;
590 LLVM_PREFERRED_TYPE(
bool)
591 unsigned UseExternalLayout : 1;
595 LLVM_PREFERRED_TYPE(
bool)
596 unsigned InferAlignment : 1;
599 LLVM_PREFERRED_TYPE(
bool)
602 LLVM_PREFERRED_TYPE(
bool)
603 unsigned IsUnion : 1;
605 LLVM_PREFERRED_TYPE(
bool)
606 unsigned IsMac68kAlign : 1;
608 LLVM_PREFERRED_TYPE(
bool)
609 unsigned IsNaturalAlign : 1;
611 LLVM_PREFERRED_TYPE(
bool)
612 unsigned IsMsStruct : 1;
618 unsigned char UnfilledBitsInLastUnit;
622 unsigned char LastBitfieldStorageUnitSize;
626 CharUnits MaxFieldAlignment;
631 CharUnits NonVirtualSize;
632 CharUnits NonVirtualAlignment;
633 CharUnits PreferredNVAlignment;
637 CharUnits PaddedFieldSize;
641 const CXXRecordDecl *PrimaryBase;
645 bool PrimaryBaseIsVirtual;
658 bool HandledFirstNonOverlappingEmptyField;
660 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
663 BaseOffsetsMapTy Bases;
670 CXXIndirectPrimaryBaseSet IndirectPrimaryBases;
674 const CXXRecordDecl *FirstNearlyEmptyVBase;
678 llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBases;
683 ItaniumRecordLayoutBuilder(
const ASTContext &Context,
684 EmptySubobjectMap *EmptySubobjects)
685 : Context(Context), EmptySubobjects(EmptySubobjects),
Size(0),
686 Alignment(CharUnits::One()), PreferredAlignment(CharUnits::One()),
687 UnpackedAlignment(CharUnits::One()),
688 UnadjustedAlignment(CharUnits::One()), UseExternalLayout(
false),
690 IsMac68kAlign(
false),
691 IsNaturalAlign(!Context.getTargetInfo().getTriple().isOSAIX()),
692 IsMsStruct(
false), UnfilledBitsInLastUnit(0),
693 LastBitfieldStorageUnitSize(0), MaxFieldAlignment(CharUnits::
Zero()),
694 DataSize(0), NonVirtualSize(CharUnits::
Zero()),
695 NonVirtualAlignment(CharUnits::One()),
696 PreferredNVAlignment(CharUnits::One()),
697 PaddedFieldSize(CharUnits::
Zero()), PrimaryBase(
nullptr),
698 PrimaryBaseIsVirtual(
false), HasOwnVFPtr(
false), HasPackedField(
false),
699 HandledFirstNonOverlappingEmptyField(
false),
700 FirstNearlyEmptyVBase(
nullptr) {}
702 void Layout(
const RecordDecl *D);
703 void Layout(
const CXXRecordDecl *D);
704 void Layout(
const ObjCInterfaceDecl *D);
706 void LayoutFields(
const RecordDecl *D);
707 void LayoutField(
const FieldDecl *D,
bool InsertExtraPadding);
708 void LayoutWideBitField(uint64_t FieldSize, uint64_t StorageUnitSize,
709 bool FieldPacked,
const FieldDecl *D);
710 void LayoutBitField(
const FieldDecl *D);
712 TargetCXXABI getCXXABI()
const {
717 llvm::SpecificBumpPtrAllocator<BaseSubobjectInfo> BaseSubobjectInfoAllocator;
719 typedef llvm::DenseMap<const CXXRecordDecl *, BaseSubobjectInfo *>
720 BaseSubobjectInfoMapTy;
724 BaseSubobjectInfoMapTy VirtualBaseInfo;
728 BaseSubobjectInfoMapTy NonVirtualBaseInfo;
732 void ComputeBaseSubobjectInfo(
const CXXRecordDecl *RD);
736 BaseSubobjectInfo *ComputeBaseSubobjectInfo(
const CXXRecordDecl *RD,
738 BaseSubobjectInfo *Derived);
741 void DeterminePrimaryBase(
const CXXRecordDecl *RD);
743 void SelectPrimaryVBase(
const CXXRecordDecl *RD);
745 void EnsureVTablePointerAlignment(CharUnits UnpackedBaseAlign);
749 void LayoutNonVirtualBases(
const CXXRecordDecl *RD);
752 void LayoutNonVirtualBase(
const BaseSubobjectInfo *Base);
754 void AddPrimaryVirtualBaseOffsets(
const BaseSubobjectInfo *Info,
758 void LayoutVirtualBases(
const CXXRecordDecl *RD,
759 const CXXRecordDecl *MostDerivedClass);
762 void LayoutVirtualBase(
const BaseSubobjectInfo *Base);
766 CharUnits LayoutBase(
const BaseSubobjectInfo *Base);
769 void InitializeLayout(
const Decl *D);
773 void FinishLayout(
const NamedDecl *D);
775 void UpdateAlignment(CharUnits NewAlignment, CharUnits UnpackedNewAlignment,
776 CharUnits PreferredAlignment);
777 void UpdateAlignment(CharUnits NewAlignment, CharUnits UnpackedNewAlignment) {
778 UpdateAlignment(NewAlignment, UnpackedNewAlignment, NewAlignment);
780 void UpdateAlignment(CharUnits NewAlignment) {
781 UpdateAlignment(NewAlignment, NewAlignment, NewAlignment);
789 uint64_t updateExternalFieldOffset(
const FieldDecl *Field,
790 uint64_t ComputedOffset);
793 uint64_t UnpackedOffset,
unsigned UnpackedAlign,
794 bool isPacked,
const FieldDecl *D);
796 DiagnosticBuilder
Diag(SourceLocation Loc,
unsigned DiagID);
798 CharUnits getSize()
const {
804 void setSize(CharUnits NewSize) {
Size = Context.
toBits(NewSize); }
805 void setSize(uint64_t NewSize) {
Size = NewSize; }
807 CharUnits getAlignment()
const {
return Alignment; }
809 CharUnits getDataSize()
const {
813 uint64_t getDataSizeInBits()
const {
return DataSize; }
815 void setDataSize(CharUnits NewSize) { DataSize = Context.
toBits(NewSize); }
816 void setDataSize(uint64_t NewSize) { DataSize = NewSize; }
818 ItaniumRecordLayoutBuilder(
const ItaniumRecordLayoutBuilder &) =
delete;
819 void operator=(
const ItaniumRecordLayoutBuilder &) =
delete;
823void ItaniumRecordLayoutBuilder::SelectPrimaryVBase(
const CXXRecordDecl *RD) {
824 for (
const auto &I : RD->
bases()) {
825 assert(!I.getType()->isDependentType() &&
826 "Cannot layout class with dependent bases.");
828 const CXXRecordDecl *
Base = I.getType()->getAsCXXRecordDecl();
834 if (!IndirectPrimaryBases.count(Base)) {
836 PrimaryBaseIsVirtual =
true;
841 if (!FirstNearlyEmptyVBase)
842 FirstNearlyEmptyVBase =
Base;
845 SelectPrimaryVBase(Base);
852void ItaniumRecordLayoutBuilder::DeterminePrimaryBase(
const CXXRecordDecl *RD) {
864 for (
const auto &I : RD->
bases()) {
869 const CXXRecordDecl *
Base = I.getType()->getAsCXXRecordDecl();
871 if (
Base->isDynamicClass()) {
874 PrimaryBaseIsVirtual =
false;
884 SelectPrimaryVBase(RD);
890 if (FirstNearlyEmptyVBase) {
891 PrimaryBase = FirstNearlyEmptyVBase;
892 PrimaryBaseIsVirtual =
true;
896 assert(!PrimaryBase &&
"Should not get here with a primary base!");
899BaseSubobjectInfo *ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo(
900 const CXXRecordDecl *RD,
bool IsVirtual, BaseSubobjectInfo *Derived) {
901 BaseSubobjectInfo *Info;
905 BaseSubobjectInfo *&InfoSlot = VirtualBaseInfo[RD];
907 assert(InfoSlot->Class == RD &&
"Wrong class for virtual base info!");
912 InfoSlot =
new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo;
915 Info =
new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo;
919 Info->IsVirtual = IsVirtual;
920 Info->Derived =
nullptr;
921 Info->PrimaryVirtualBaseInfo =
nullptr;
923 const CXXRecordDecl *PrimaryVirtualBase =
nullptr;
924 BaseSubobjectInfo *PrimaryVirtualBaseInfo =
nullptr;
932 assert(PrimaryVirtualBase &&
"Didn't have a primary virtual base!");
935 PrimaryVirtualBaseInfo = VirtualBaseInfo.lookup(PrimaryVirtualBase);
937 if (PrimaryVirtualBaseInfo) {
938 if (PrimaryVirtualBaseInfo->Derived) {
942 PrimaryVirtualBase =
nullptr;
945 Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;
946 PrimaryVirtualBaseInfo->Derived = Info;
953 for (
const auto &I : RD->
bases()) {
954 bool IsVirtual = I.isVirtual();
956 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
958 Info->Bases.push_back(ComputeBaseSubobjectInfo(BaseDecl, IsVirtual, Info));
961 if (PrimaryVirtualBase && !PrimaryVirtualBaseInfo) {
964 PrimaryVirtualBaseInfo = VirtualBaseInfo.lookup(PrimaryVirtualBase);
965 assert(PrimaryVirtualBaseInfo &&
966 "Did not create a primary virtual base!");
969 Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;
970 PrimaryVirtualBaseInfo->Derived = Info;
976void ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo(
977 const CXXRecordDecl *RD) {
978 for (
const auto &I : RD->
bases()) {
979 bool IsVirtual = I.isVirtual();
981 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
984 BaseSubobjectInfo *Info = ComputeBaseSubobjectInfo(BaseDecl, IsVirtual,
989 assert(VirtualBaseInfo.count(BaseDecl) &&
990 "Did not add virtual base!");
993 assert(!NonVirtualBaseInfo.count(BaseDecl) &&
994 "Non-virtual base already exists!");
995 NonVirtualBaseInfo.insert(std::make_pair(BaseDecl, Info));
1000void ItaniumRecordLayoutBuilder::EnsureVTablePointerAlignment(
1001 CharUnits UnpackedBaseAlign) {
1005 if (!MaxFieldAlignment.
isZero()) {
1006 BaseAlign = std::min(BaseAlign, MaxFieldAlignment);
1007 UnpackedBaseAlign = std::min(UnpackedBaseAlign, MaxFieldAlignment);
1011 setSize(getSize().alignTo(BaseAlign));
1014 UpdateAlignment(BaseAlign, UnpackedBaseAlign, BaseAlign);
1017void ItaniumRecordLayoutBuilder::LayoutNonVirtualBases(
1018 const CXXRecordDecl *RD) {
1020 DeterminePrimaryBase(RD);
1023 ComputeBaseSubobjectInfo(RD);
1027 if (PrimaryBaseIsVirtual) {
1030 BaseSubobjectInfo *PrimaryBaseInfo = VirtualBaseInfo.lookup(PrimaryBase);
1031 PrimaryBaseInfo->Derived =
nullptr;
1034 IndirectPrimaryBases.insert(PrimaryBase);
1036 assert(!VisitedVirtualBases.count(PrimaryBase) &&
1037 "vbase already visited!");
1038 VisitedVirtualBases.insert(PrimaryBase);
1040 LayoutVirtualBase(PrimaryBaseInfo);
1042 BaseSubobjectInfo *PrimaryBaseInfo =
1043 NonVirtualBaseInfo.lookup(PrimaryBase);
1044 assert(PrimaryBaseInfo &&
1045 "Did not find base info for non-virtual primary base!");
1047 LayoutNonVirtualBase(PrimaryBaseInfo);
1053 assert(DataSize == 0 &&
"Vtable pointer must be at offset zero!");
1058 EnsureVTablePointerAlignment(PtrAlign);
1061 assert(!IsUnion &&
"Unions cannot be dynamic classes.");
1062 HandledFirstNonOverlappingEmptyField =
true;
1064 setSize(getSize() + PtrWidth);
1065 setDataSize(getSize());
1069 for (
const auto &I : RD->
bases()) {
1075 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
1080 if (BaseDecl == PrimaryBase && !PrimaryBaseIsVirtual)
1084 BaseSubobjectInfo *BaseInfo = NonVirtualBaseInfo.
lookup(BaseDecl);
1085 assert(BaseInfo &&
"Did not find base info for non-virtual base!");
1087 LayoutNonVirtualBase(BaseInfo);
1091void ItaniumRecordLayoutBuilder::LayoutNonVirtualBase(
1092 const BaseSubobjectInfo *Base) {
1094 CharUnits Offset = LayoutBase(Base);
1097 assert(!Bases.count(
Base->Class) &&
"base offset already exists!");
1098 Bases.insert(std::make_pair(
Base->Class, Offset));
1100 AddPrimaryVirtualBaseOffsets(Base, Offset);
1103void ItaniumRecordLayoutBuilder::AddPrimaryVirtualBaseOffsets(
1104 const BaseSubobjectInfo *Info, CharUnits Offset) {
1110 if (Info->PrimaryVirtualBaseInfo) {
1111 assert(Info->PrimaryVirtualBaseInfo->IsVirtual &&
1112 "Primary virtual base is not virtual!");
1113 if (Info->PrimaryVirtualBaseInfo->Derived == Info) {
1115 assert(!VBases.count(Info->PrimaryVirtualBaseInfo->Class) &&
1116 "primary vbase offset already exists!");
1117 VBases.insert(std::make_pair(Info->PrimaryVirtualBaseInfo->Class,
1118 ASTRecordLayout::VBaseInfo(Offset,
false)));
1121 AddPrimaryVirtualBaseOffsets(Info->PrimaryVirtualBaseInfo, Offset);
1127 for (
const BaseSubobjectInfo *Base : Info->Bases) {
1128 if (
Base->IsVirtual)
1132 AddPrimaryVirtualBaseOffsets(Base, BaseOffset);
1136void ItaniumRecordLayoutBuilder::LayoutVirtualBases(
1137 const CXXRecordDecl *RD,
const CXXRecordDecl *MostDerivedClass) {
1138 const CXXRecordDecl *PrimaryBase;
1139 bool PrimaryBaseIsVirtual;
1141 if (MostDerivedClass == RD) {
1142 PrimaryBase = this->PrimaryBase;
1143 PrimaryBaseIsVirtual = this->PrimaryBaseIsVirtual;
1150 for (
const CXXBaseSpecifier &Base : RD->
bases()) {
1151 assert(!
Base.getType()->isDependentType() &&
1152 "Cannot layout class with dependent bases.");
1154 const CXXRecordDecl *BaseDecl =
Base.getType()->getAsCXXRecordDecl();
1156 if (
Base.isVirtual()) {
1157 if (PrimaryBase != BaseDecl || !PrimaryBaseIsVirtual) {
1158 bool IndirectPrimaryBase = IndirectPrimaryBases.count(BaseDecl);
1161 if (!IndirectPrimaryBase) {
1163 if (!VisitedVirtualBases.insert(BaseDecl).second)
1166 const BaseSubobjectInfo *BaseInfo = VirtualBaseInfo.lookup(BaseDecl);
1167 assert(BaseInfo &&
"Did not find virtual base info!");
1168 LayoutVirtualBase(BaseInfo);
1178 LayoutVirtualBases(BaseDecl, MostDerivedClass);
1182void ItaniumRecordLayoutBuilder::LayoutVirtualBase(
1183 const BaseSubobjectInfo *Base) {
1184 assert(!
Base->Derived &&
"Trying to lay out a primary virtual base!");
1187 CharUnits Offset = LayoutBase(Base);
1190 assert(!VBases.count(
Base->Class) &&
"vbase offset already exists!");
1191 VBases.insert(std::make_pair(
Base->Class,
1192 ASTRecordLayout::VBaseInfo(Offset,
false)));
1194 AddPrimaryVirtualBaseOffsets(Base, Offset);
1198ItaniumRecordLayoutBuilder::LayoutBase(
const BaseSubobjectInfo *Base) {
1199 assert(!IsUnion &&
"Unions cannot have base classes.");
1205 bool HasExternalLayout =
false;
1206 if (UseExternalLayout) {
1207 if (
Base->IsVirtual)
1208 HasExternalLayout =
External.getExternalVBaseOffset(
Base->Class, Offset);
1210 HasExternalLayout =
External.getExternalNVBaseOffset(
Base->Class, Offset);
1213 auto getBaseOrPreferredBaseAlignFromUnpacked = [&](CharUnits UnpackedAlign) {
1217 LangOptions::ClangABI::Ver6) ||
1226 CharUnits BaseAlign =
1227 getBaseOrPreferredBaseAlignFromUnpacked(UnpackedBaseAlign);
1228 CharUnits PreferredBaseAlign =
1229 getBaseOrPreferredBaseAlignFromUnpacked(UnpackedPreferredBaseAlign);
1231 const bool DefaultsToAIXPowerAlignment =
1233 if (DefaultsToAIXPowerAlignment) {
1238 if (!
Base->Class->isEmpty() && !HandledFirstNonOverlappingEmptyField) {
1241 HandledFirstNonOverlappingEmptyField =
true;
1242 }
else if (!IsNaturalAlign) {
1243 UnpackedPreferredBaseAlign = UnpackedBaseAlign;
1244 PreferredBaseAlign = BaseAlign;
1248 CharUnits UnpackedAlignTo = !DefaultsToAIXPowerAlignment
1250 : UnpackedPreferredBaseAlign;
1252 if (
Base->Class->isEmpty() &&
1255 setSize(std::max(getSize(), Layout.
getSize()));
1258 UpdateAlignment(BaseAlign, UnpackedAlignTo, PreferredBaseAlign);
1265 if (!MaxFieldAlignment.
isZero()) {
1266 BaseAlign = std::min(BaseAlign, MaxFieldAlignment);
1267 PreferredBaseAlign = std::min(PreferredBaseAlign, MaxFieldAlignment);
1268 UnpackedAlignTo = std::min(UnpackedAlignTo, MaxFieldAlignment);
1272 !DefaultsToAIXPowerAlignment ? BaseAlign : PreferredBaseAlign;
1273 if (!HasExternalLayout) {
1275 Offset = getDataSize().
alignTo(AlignTo);
1278 while (!EmptySubobjects->CanPlaceBaseAtOffset(Base, Offset))
1281 bool Allowed = EmptySubobjects->CanPlaceBaseAtOffset(Base, Offset);
1283 assert(Allowed &&
"Base subobject externally placed at overlapping offset");
1285 if (InferAlignment && Offset < getDataSize().alignTo(AlignTo)) {
1289 InferAlignment =
false;
1293 if (!
Base->Class->isEmpty()) {
1297 setSize(std::max(getSize(), getDataSize()));
1299 setSize(std::max(getSize(), Offset + Layout.
getSize()));
1302 UnadjustedAlignment = std::max(UnadjustedAlignment, BaseAlign);
1303 UpdateAlignment(BaseAlign, UnpackedAlignTo, PreferredBaseAlign);
1308void ItaniumRecordLayoutBuilder::InitializeLayout(
const Decl *D) {
1309 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
1317 if (
unsigned DefaultMaxFieldAlignment = Context.
getLangOpts().PackStruct) {
1325 if (D->
hasAttr<AlignMac68kAttr>()) {
1327 !D->
hasAttr<AlignNaturalAttr>() &&
1328 "Having both mac68k and natural alignment on a decl is not allowed.");
1329 IsMac68kAlign =
true;
1334 if (D->
hasAttr<AlignNaturalAttr>())
1335 IsNaturalAlign =
true;
1337 if (
const MaxFieldAlignmentAttr *MFAA = D->
getAttr<MaxFieldAlignmentAttr>())
1344 HandledFirstNonOverlappingEmptyField =
1348 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(D))
1350 UseExternalLayout = Source->layoutRecordType(
1355 if (UseExternalLayout) {
1361 InferAlignment =
true;
1367void ItaniumRecordLayoutBuilder::Layout(
const RecordDecl *D) {
1368 InitializeLayout(D);
1376void ItaniumRecordLayoutBuilder::Layout(
const CXXRecordDecl *RD) {
1377 InitializeLayout(RD);
1380 LayoutNonVirtualBases(RD);
1386 NonVirtualAlignment = Alignment;
1387 PreferredNVAlignment = PreferredAlignment;
1390 LayoutVirtualBases(RD, RD);
1398 for (
const CXXBaseSpecifier &Base : RD->
bases()) {
1399 if (
Base.isVirtual())
1402 const CXXRecordDecl *BaseDecl =
Base.getType()->getAsCXXRecordDecl();
1404 assert(Bases.count(BaseDecl) &&
"Did not find base offset!");
1408 for (
const CXXBaseSpecifier &Base : RD->
vbases()) {
1409 const CXXRecordDecl *BaseDecl =
Base.getType()->getAsCXXRecordDecl();
1411 assert(VBases.count(BaseDecl) &&
"Did not find base offset!");
1416void ItaniumRecordLayoutBuilder::Layout(
const ObjCInterfaceDecl *D) {
1425 setSize(getDataSize());
1428 InitializeLayout(D);
1432 LayoutField(IVD,
false);
1439void ItaniumRecordLayoutBuilder::LayoutFields(
const RecordDecl *D) {
1445 LayoutField(*I, InsertExtraPadding &&
1446 (std::next(I) != End || !HasFlexibleArrayMember));
1454 uint64_t CharAlignment = Context.getTargetInfo().getCharAlign();
1455 return llvm::alignTo(Size, CharAlignment);
1458void ItaniumRecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize,
1459 uint64_t StorageUnitSize,
1461 const FieldDecl *D) {
1463 "Can only have wide bit-fields in C++!");
1469 QualType IntegralPODTypes[] = {
1478 for (
const QualType &QT : IntegralPODTypes) {
1481 if (Size > FieldSize || Size > MaxSize)
1486 assert(!
Type.isNull() &&
"Did not find a type!");
1491 UnfilledBitsInLastUnit = 0;
1492 LastBitfieldStorageUnitSize = 0;
1495 uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;
1500 setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize));
1505 FieldOffset = llvm::alignTo(getDataSizeInBits(), Context.
toBits(TypeAlign));
1507 uint64_t NewSizeInBits = FieldOffset + FieldSize;
1511 UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits;
1515 FieldOffsets.push_back(FieldOffset);
1518 Context.
toBits(TypeAlign), FieldPacked, D);
1521 setSize(std::max(getSizeInBits(), getDataSizeInBits()));
1524 UnadjustedAlignment = std::max(UnadjustedAlignment, TypeAlign);
1525 UpdateAlignment(TypeAlign);
1529 return Context.getTargetInfo().getTriple().getOS() == llvm::Triple::AIX;
1532void ItaniumRecordLayoutBuilder::LayoutBitField(
const FieldDecl *D) {
1537 unsigned FieldAlign = FieldInfo.
Align;
1539 unsigned char PaddingInLastUnit = 0;
1601 FieldAlign = StorageUnitSize;
1606 if (LastBitfieldStorageUnitSize != StorageUnitSize ||
1607 UnfilledBitsInLastUnit < FieldSize) {
1609 if (!LastBitfieldStorageUnitSize && !FieldSize)
1612 PaddingInLastUnit = UnfilledBitsInLastUnit;
1613 UnfilledBitsInLastUnit = 0;
1614 LastBitfieldStorageUnitSize = 0;
1628 StorageUnitSize = 32;
1630 if (!AlignIsRequired)
1634 if (FieldAlign < StorageUnitSize) {
1637 FieldAlign = StorageUnitSize;
1644 if (FieldSize > StorageUnitSize && !
isAIXLayout(Context)) {
1645 LayoutWideBitField(FieldSize, StorageUnitSize, FieldPacked, D);
1651 IsUnion ? 0 : (getDataSizeInBits() - UnfilledBitsInLastUnit);
1656 if (FieldSize == 0 &&
1659 if (!IsUnion && FieldOffset == 0 &&
1665 unsigned ZeroLengthBitfieldBoundary =
1667 FieldAlign = std::max(FieldAlign, ZeroLengthBitfieldBoundary);
1676 unsigned UnpackedFieldAlign = FieldAlign;
1679 if (!IsMsStruct && FieldPacked && FieldSize != 0)
1684 if (ExplicitFieldAlign) {
1685 FieldAlign = std::max(FieldAlign, ExplicitFieldAlign);
1686 UnpackedFieldAlign = std::max(UnpackedFieldAlign, ExplicitFieldAlign);
1691 unsigned MaxFieldAlignmentInBits = Context.
toBits(MaxFieldAlignment);
1692 if (!MaxFieldAlignment.
isZero() && FieldSize) {
1693 UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits);
1695 FieldAlign = UnpackedFieldAlign;
1697 FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits);
1702 if (IsMsStruct && IsUnion) {
1703 FieldAlign = UnpackedFieldAlign = 1;
1709 uint64_t UnpaddedFieldOffset = FieldOffset - PaddingInLastUnit;
1710 uint64_t UnpackedFieldOffset = FieldOffset;
1720 if (FieldSize == 0 || FieldSize > UnfilledBitsInLastUnit) {
1721 FieldOffset = llvm::alignTo(FieldOffset, FieldAlign);
1722 UnpackedFieldOffset =
1723 llvm::alignTo(UnpackedFieldOffset, UnpackedFieldAlign);
1724 UnfilledBitsInLastUnit = 0;
1729 bool AllowPadding = MaxFieldAlignment.
isZero();
1732 if (FieldSize == 0 ||
1734 (FieldOffset & (FieldAlign - 1)) + FieldSize > StorageUnitSize)) {
1735 FieldOffset = llvm::alignTo(FieldOffset, FieldAlign);
1736 }
else if (ExplicitFieldAlign &&
1737 (MaxFieldAlignmentInBits == 0 ||
1738 ExplicitFieldAlign <= MaxFieldAlignmentInBits) &&
1742 FieldOffset = llvm::alignTo(FieldOffset, ExplicitFieldAlign);
1746 if (FieldSize == 0 ||
1748 (UnpackedFieldOffset & (UnpackedFieldAlign - 1)) + FieldSize >
1750 UnpackedFieldOffset =
1751 llvm::alignTo(UnpackedFieldOffset, UnpackedFieldAlign);
1752 else if (ExplicitFieldAlign &&
1753 (MaxFieldAlignmentInBits == 0 ||
1754 ExplicitFieldAlign <= MaxFieldAlignmentInBits) &&
1756 UnpackedFieldOffset =
1757 llvm::alignTo(UnpackedFieldOffset, ExplicitFieldAlign);
1762 if (UseExternalLayout)
1763 FieldOffset = updateExternalFieldOffset(D, FieldOffset);
1766 FieldOffsets.push_back(FieldOffset);
1775 FieldAlign = UnpackedFieldAlign = 1;
1783 if (!MaxFieldAlignment.
isZero()) {
1784 UnpackedFieldAlign =
1785 std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits);
1786 FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits);
1791 if (!UseExternalLayout)
1793 UnpackedFieldAlign, FieldPacked, D);
1803 RoundedFieldSize = (FieldSize ? StorageUnitSize
1811 setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize));
1815 }
else if (IsMsStruct && FieldSize) {
1818 if (!UnfilledBitsInLastUnit) {
1819 setDataSize(FieldOffset + StorageUnitSize);
1820 UnfilledBitsInLastUnit = StorageUnitSize;
1822 UnfilledBitsInLastUnit -= FieldSize;
1823 LastBitfieldStorageUnitSize = StorageUnitSize;
1829 uint64_t NewSizeInBits = FieldOffset + FieldSize;
1831 setDataSize(llvm::alignTo(NewSizeInBits, CharAlignment));
1832 UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits;
1837 LastBitfieldStorageUnitSize = 0;
1841 setSize(std::max(getSizeInBits(), getDataSizeInBits()));
1844 UnadjustedAlignment =
1850void ItaniumRecordLayoutBuilder::LayoutField(
const FieldDecl *D,
1851 bool InsertExtraPadding) {
1853 bool IsOverlappingEmptyField =
1856 CharUnits FieldOffset =
1857 (IsUnion || IsOverlappingEmptyField) ?
CharUnits::Zero() : getDataSize();
1859 const bool DefaultsToAIXPowerAlignment =
1861 bool FoundFirstNonOverlappingEmptyFieldForAIX =
false;
1862 if (DefaultsToAIXPowerAlignment && !HandledFirstNonOverlappingEmptyField) {
1864 "The first non-overlapping empty field should have been handled.");
1866 if (!IsOverlappingEmptyField) {
1867 FoundFirstNonOverlappingEmptyFieldForAIX =
true;
1874 HandledFirstNonOverlappingEmptyField = !IsUnion;
1883 uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;
1885 UnfilledBitsInLastUnit = 0;
1886 LastBitfieldStorageUnitSize = 0;
1891 CharUnits FieldSize;
1892 CharUnits FieldAlign;
1896 CharUnits EffectiveFieldSize;
1898 auto setDeclInfo = [&](
bool IsIncompleteArrayType) {
1900 FieldAlign = TI.Align;
1903 EffectiveFieldSize = FieldSize =
1905 AlignRequirement = TI.AlignRequirement;
1911 setDeclInfo(
false );
1917 EffectiveFieldSize =
1928 if (
const BuiltinType *BTy =
T->
getAs<BuiltinType>()) {
1931 if (!llvm::isPowerOf2_64(TypeSize.
getQuantity())) {
1934 "Non PowerOf2 size in MSVC mode");
1956 if (TypeSize > FieldAlign &&
1958 FieldAlign = TypeSize;
1963 bool FieldPacked = (
Packed && (!FieldClass || FieldClass->isPOD() ||
1964 FieldClass->hasAttr<PackedAttr>() ||
1966 LangOptions::ClangABI::Ver15 ||
1975 auto alignedAttrCanDecreaseAIXAlignment = [AlignRequirement, FieldPacked] {
1979 return AlignRequirement == AlignRequirementKind::RequiredByTypedef ||
1980 (AlignRequirement == AlignRequirementKind::RequiredByRecord &&
1993 CharUnits PreferredAlign = FieldAlign;
1994 if (DefaultsToAIXPowerAlignment && !alignedAttrCanDecreaseAIXAlignment() &&
1995 (FoundFirstNonOverlappingEmptyFieldForAIX || IsNaturalAlign)) {
1996 auto performBuiltinTypeAlignmentUpgrade = [&](
const BuiltinType *BTy) {
1997 if (BTy->getKind() == BuiltinType::Double ||
1998 BTy->getKind() == BuiltinType::LongDouble) {
2000 "No need to upgrade the alignment value.");
2006 if (
const ComplexType *CTy = BaseTy->
getAs<ComplexType>()) {
2007 performBuiltinTypeAlignmentUpgrade(
2008 CTy->getElementType()->castAs<BuiltinType>());
2009 }
else if (
const BuiltinType *BTy = BaseTy->
getAs<BuiltinType>()) {
2010 performBuiltinTypeAlignmentUpgrade(BTy);
2011 }
else if (
const RecordType *RT = BaseTy->
getAsCanonical<RecordType>()) {
2012 const RecordDecl *RD = RT->getOriginalDecl();
2020 CharUnits UnpackedFieldAlign = FieldAlign;
2022 CharUnits UnpackedFieldOffset = FieldOffset;
2023 CharUnits OriginalFieldAlign = UnpackedFieldAlign;
2025 CharUnits MaxAlignmentInChars =
2027 PackedFieldAlign = std::max(PackedFieldAlign, MaxAlignmentInChars);
2028 PreferredAlign = std::max(PreferredAlign, MaxAlignmentInChars);
2029 UnpackedFieldAlign = std::max(UnpackedFieldAlign, MaxAlignmentInChars);
2032 if (!MaxFieldAlignment.
isZero()) {
2033 PackedFieldAlign = std::min(PackedFieldAlign, MaxFieldAlignment);
2034 PreferredAlign = std::min(PreferredAlign, MaxFieldAlignment);
2035 UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignment);
2040 FieldAlign = UnpackedFieldAlign;
2041 if (DefaultsToAIXPowerAlignment)
2042 UnpackedFieldAlign = PreferredAlign;
2044 PreferredAlign = PackedFieldAlign;
2045 FieldAlign = PackedFieldAlign;
2049 !DefaultsToAIXPowerAlignment ? FieldAlign : PreferredAlign;
2051 FieldOffset = FieldOffset.
alignTo(AlignTo);
2052 UnpackedFieldOffset = UnpackedFieldOffset.
alignTo(UnpackedFieldAlign);
2054 if (UseExternalLayout) {
2056 updateExternalFieldOffset(D, Context.
toBits(FieldOffset)));
2058 if (!IsUnion && EmptySubobjects) {
2060 bool Allowed = EmptySubobjects->CanPlaceFieldAtOffset(D, FieldOffset);
2062 assert(Allowed &&
"Externally-placed field cannot be placed here");
2065 if (!IsUnion && EmptySubobjects) {
2067 while (!EmptySubobjects->CanPlaceFieldAtOffset(D, FieldOffset)) {
2072 FieldOffset = getDataSize().
alignTo(AlignTo);
2074 FieldOffset += AlignTo;
2080 FieldOffsets.push_back(Context.
toBits(FieldOffset));
2082 if (!UseExternalLayout)
2084 Context.
toBits(UnpackedFieldOffset),
2085 Context.
toBits(UnpackedFieldAlign), FieldPacked, D);
2087 if (InsertExtraPadding) {
2089 CharUnits ExtraSizeForAsan = ASanAlignment;
2090 if (FieldSize % ASanAlignment)
2093 EffectiveFieldSize = FieldSize = FieldSize + ExtraSizeForAsan;
2097 if (!IsOverlappingEmptyField) {
2098 uint64_t EffectiveFieldSizeInBits = Context.
toBits(EffectiveFieldSize);
2100 setDataSize(std::max(getDataSizeInBits(), EffectiveFieldSizeInBits));
2102 setDataSize(FieldOffset + EffectiveFieldSize);
2104 PaddedFieldSize = std::max(PaddedFieldSize, FieldOffset + FieldSize);
2105 setSize(std::max(getSizeInBits(), getDataSizeInBits()));
2107 setSize(std::max(getSizeInBits(),
2108 (uint64_t)Context.
toBits(FieldOffset + FieldSize)));
2112 UnadjustedAlignment = std::max(UnadjustedAlignment, FieldAlign);
2113 UpdateAlignment(FieldAlign, UnpackedFieldAlign, PreferredAlign);
2117 if (
const RecordDecl *RD = D->
getParent()) {
2119 if (RD->
hasAttr<PackedAttr>() || !MaxFieldAlignment.
isZero())
2120 if (FieldAlign < OriginalFieldAlign)
2125 if (FieldOffset % OriginalFieldAlign != 0)
2132 if (
Packed && !FieldPacked && PackedFieldAlign < FieldAlign)
2136void ItaniumRecordLayoutBuilder::FinishLayout(
const NamedDecl *D) {
2138 if (Context.
getLangOpts().CPlusPlus && getSizeInBits() == 0) {
2139 if (
const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
2152 setSize(std::max(getSizeInBits(), (uint64_t)Context.
toBits(PaddedFieldSize)));
2156 uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastUnit;
2158 llvm::alignTo(getSizeInBits(), Context.
toBits(UnpackedAlignment));
2160 uint64_t RoundedSize = llvm::alignTo(
2164 : PreferredAlignment));
2166 if (UseExternalLayout) {
2170 if (InferAlignment &&
External.Size < RoundedSize) {
2173 InferAlignment =
false;
2180 setSize(RoundedSize);
2183 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
2185 if (getSizeInBits() > UnpaddedSize) {
2186 unsigned PadSize = getSizeInBits() - UnpaddedSize;
2188 if (PadSize % CharBitNum == 0) {
2189 PadSize = PadSize / CharBitNum;
2194 << (InBits ? 1 : 0);
2197 const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD);
2205 if (
Packed && UnpackedAlignment <= Alignment &&
2206 UnpackedSizeInBits == getSizeInBits() && !HasPackedField &&
2207 (!CXXRD || CXXRD->isPOD() ||
2209 LangOptions::ClangABI::Ver15))
2215void ItaniumRecordLayoutBuilder::UpdateAlignment(
2216 CharUnits NewAlignment, CharUnits UnpackedNewAlignment,
2217 CharUnits PreferredNewAlignment) {
2220 if (IsMac68kAlign || (UseExternalLayout && !InferAlignment))
2223 if (NewAlignment > Alignment) {
2224 assert(llvm::isPowerOf2_64(NewAlignment.
getQuantity()) &&
2225 "Alignment not a power of 2");
2226 Alignment = NewAlignment;
2229 if (UnpackedNewAlignment > UnpackedAlignment) {
2230 assert(llvm::isPowerOf2_64(UnpackedNewAlignment.
getQuantity()) &&
2231 "Alignment not a power of 2");
2232 UnpackedAlignment = UnpackedNewAlignment;
2235 if (PreferredNewAlignment > PreferredAlignment) {
2236 assert(llvm::isPowerOf2_64(PreferredNewAlignment.
getQuantity()) &&
2237 "Alignment not a power of 2");
2238 PreferredAlignment = PreferredNewAlignment;
2243ItaniumRecordLayoutBuilder::updateExternalFieldOffset(
const FieldDecl *Field,
2244 uint64_t ComputedOffset) {
2247 if (InferAlignment && ExternalFieldOffset < ComputedOffset) {
2252 InferAlignment =
false;
2256 return ExternalFieldOffset;
2272 default: llvm_unreachable(
"Invalid tag kind for field padding diagnostic!");
2277 uint64_t Offset, uint64_t UnpaddedOffset,
2289 unsigned CharBitNum = Context.getTargetInfo().getCharWidth();
2292 if (!IsUnion && Offset > UnpaddedOffset) {
2293 unsigned PadSize = Offset - UnpaddedOffset;
2295 if (PadSize % CharBitNum == 0) {
2296 PadSize = PadSize / CharBitNum;
2301 : diag::warn_padded_struct_field;
2305 << Context.getCanonicalTagType(D->
getParent()) << PadSize
2310 : diag::warn_padded_struct_anon_field;
2314 << Context.getCanonicalTagType(D->
getParent()) << PadSize
2315 << (InBits ? 1 : 0);
2320void ItaniumRecordLayoutBuilder::CheckFieldPadding(
2321 uint64_t Offset, uint64_t UnpaddedOffset, uint64_t UnpackedOffset,
2322 unsigned UnpackedAlign,
bool isPacked,
const FieldDecl *D) {
2324 if (isPacked && Offset != UnpackedOffset) {
2325 HasPackedField =
true;
2349 bool allowInlineFunctions =
2350 Context.getTargetInfo().getCXXABI().canKeyFunctionBeInline();
2353 if (!MD->isVirtual())
2356 if (MD->isPureVirtual())
2361 if (MD->isImplicit())
2364 if (MD->isInlineSpecified() || MD->isConstexpr())
2367 if (MD->hasInlineBody())
2371 if (!MD->isUserProvided())
2375 if (!allowInlineFunctions) {
2381 if (Context.getLangOpts().CUDA) {
2385 if (Context.getLangOpts().CUDAIsDevice) {
2387 if (!MD->hasAttr<CUDADeviceAttr>())
2391 if (!MD->hasAttr<CUDAHostAttr>() && MD->hasAttr<CUDADeviceAttr>())
2399 if (MD->hasAttr<DLLImportAttr>() && !RD->
hasAttr<DLLImportAttr>() &&
2400 !Context.getTargetInfo().hasPS4DLLImportExport())
2410DiagnosticBuilder ItaniumRecordLayoutBuilder::Diag(SourceLocation Loc,
2454 llvm_unreachable(
"bad tail-padding use kind");
2548struct MicrosoftRecordLayoutBuilder {
2549 struct ElementInfo {
2551 CharUnits Alignment;
2553 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
2554 MicrosoftRecordLayoutBuilder(
const ASTContext &Context,
2555 EmptySubobjectMap *EmptySubobjects)
2556 : Context(Context), EmptySubobjects(EmptySubobjects),
2557 RemainingBitsInField(0) {}
2560 MicrosoftRecordLayoutBuilder(
const MicrosoftRecordLayoutBuilder &) =
delete;
2561 void operator=(
const MicrosoftRecordLayoutBuilder &) =
delete;
2563 void layout(
const RecordDecl *RD);
2564 void cxxLayout(
const CXXRecordDecl *RD);
2566 void initializeLayout(
const RecordDecl *RD);
2570 void initializeCXXLayout(
const CXXRecordDecl *RD);
2571 void layoutNonVirtualBases(
const CXXRecordDecl *RD);
2572 void layoutNonVirtualBase(
const CXXRecordDecl *RD,
2573 const CXXRecordDecl *BaseDecl,
2574 const ASTRecordLayout &BaseLayout,
2575 const ASTRecordLayout *&PreviousBaseLayout);
2576 void injectVFPtr(
const CXXRecordDecl *RD);
2577 void injectVBPtr(
const CXXRecordDecl *RD);
2580 void layoutFields(
const RecordDecl *RD);
2581 void layoutField(
const FieldDecl *FD);
2582 void layoutBitField(
const FieldDecl *FD);
2585 void layoutZeroWidthBitField(
const FieldDecl *FD);
2586 void layoutVirtualBases(
const CXXRecordDecl *RD);
2587 void finalizeLayout(
const RecordDecl *RD);
2590 ElementInfo getAdjustedElementInfo(
const ASTRecordLayout &Layout);
2594 ElementInfo getAdjustedElementInfo(
const FieldDecl *FD);
2596 void placeFieldAtOffset(CharUnits FieldOffset) {
2597 FieldOffsets.push_back(Context.
toBits(FieldOffset));
2600 void placeFieldAtBitOffset(uint64_t FieldOffset) {
2601 FieldOffsets.push_back(FieldOffset);
2604 void computeVtorDispSet(
2605 llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtorDispSet,
2606 const CXXRecordDecl *RD)
const;
2607 const ASTContext &Context;
2608 EmptySubobjectMap *EmptySubobjects;
2613 CharUnits NonVirtualSize;
2617 CharUnits Alignment;
2619 CharUnits MaxFieldAlignment;
2622 CharUnits RequiredAlignment;
2626 CharUnits CurrentBitfieldSize;
2628 CharUnits VBPtrOffset;
2630 CharUnits MinEmptyStructSize;
2632 ElementInfo PointerInfo;
2634 const CXXRecordDecl *PrimaryBase;
2636 const CXXRecordDecl *SharedVBPtrBase;
2638 SmallVector<uint64_t, 16> FieldOffsets;
2640 BaseOffsetsMapTy Bases;
2644 unsigned RemainingBitsInField;
2648 bool LastFieldIsNonZeroWidthBitfield : 1;
2650 bool HasOwnVFPtr : 1;
2656 bool EndsWithZeroSizedObject : 1;
2659 bool LeadsWithZeroSizedBase : 1;
2662 bool UseExternalLayout : 1;
2670MicrosoftRecordLayoutBuilder::ElementInfo
2671MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
2672 const ASTRecordLayout &Layout) {
2676 if (!MaxFieldAlignment.
isZero())
2677 Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment);
2683 Alignment = std::max(Alignment, Info.Alignment);
2690MicrosoftRecordLayoutBuilder::ElementInfo
2691MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
2692 const FieldDecl *FD) {
2697 ElementInfo Info{TInfo.Width, TInfo.Align};
2699 CharUnits FieldRequiredAlignment =
2703 FieldRequiredAlignment = std::max(
2709 Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment);
2711 if (
const auto *RT = FD->
getType()
2716 FieldRequiredAlignment = std::max(FieldRequiredAlignment,
2720 RequiredAlignment = std::max(RequiredAlignment, FieldRequiredAlignment);
2723 if (!MaxFieldAlignment.
isZero())
2724 Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment);
2725 if (FD->
hasAttr<PackedAttr>())
2727 Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment);
2731void MicrosoftRecordLayoutBuilder::layout(
const RecordDecl *RD) {
2734 initializeLayout(RD);
2736 DataSize =
Size =
Size.alignTo(Alignment);
2737 RequiredAlignment = std::max(
2742void MicrosoftRecordLayoutBuilder::cxxLayout(
const CXXRecordDecl *RD) {
2745 initializeLayout(RD);
2746 initializeCXXLayout(RD);
2747 layoutNonVirtualBases(RD);
2751 if (HasOwnVFPtr || (HasVBPtr && !SharedVBPtrBase))
2752 Alignment = std::max(Alignment, PointerInfo.Alignment);
2753 auto RoundingAlignment = Alignment;
2754 if (!MaxFieldAlignment.
isZero())
2755 RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment);
2756 if (!UseExternalLayout)
2757 Size =
Size.alignTo(RoundingAlignment);
2758 NonVirtualSize =
Size;
2759 RequiredAlignment = std::max(
2761 layoutVirtualBases(RD);
2765void MicrosoftRecordLayoutBuilder::initializeLayout(
const RecordDecl *RD) {
2774 : CharUnits::
Zero();
2778 if (
unsigned DefaultMaxFieldAlignment = Context.
getLangOpts().PackStruct)
2782 if (
const MaxFieldAlignmentAttr *MFAA = RD->
getAttr<MaxFieldAlignmentAttr>()){
2783 unsigned PackedAlignment = MFAA->getAlignment();
2784 if (PackedAlignment <=
2789 if (RD->
hasAttr<PackedAttr>())
2793 UseExternalLayout =
false;
2795 UseExternalLayout = Source->layoutRecordType(
2801MicrosoftRecordLayoutBuilder::initializeCXXLayout(
const CXXRecordDecl *RD) {
2802 EndsWithZeroSizedObject =
false;
2803 LeadsWithZeroSizedBase =
false;
2804 HasOwnVFPtr =
false;
2806 PrimaryBase =
nullptr;
2807 SharedVBPtrBase =
nullptr;
2815 if (!MaxFieldAlignment.
isZero())
2816 PointerInfo.Alignment = std::min(PointerInfo.Alignment, MaxFieldAlignment);
2820MicrosoftRecordLayoutBuilder::layoutNonVirtualBases(
const CXXRecordDecl *RD) {
2827 const ASTRecordLayout *PreviousBaseLayout =
nullptr;
2828 bool HasPolymorphicBaseClass =
false;
2830 for (
const CXXBaseSpecifier &Base : RD->
bases()) {
2831 const CXXRecordDecl *BaseDecl =
Base.getType()->getAsCXXRecordDecl();
2835 if (
Base.isVirtual()) {
2840 if (!SharedVBPtrBase && BaseLayout.
hasVBPtr()) {
2841 SharedVBPtrBase = BaseDecl;
2849 PrimaryBase = BaseDecl;
2853 layoutNonVirtualBase(RD, BaseDecl, BaseLayout, PreviousBaseLayout);
2857 if (!HasPolymorphicBaseClass)
2861 else if (!PrimaryBase) {
2864 for (CXXMethodDecl *M : RD->
methods()) {
2865 if (MicrosoftVTableContext::hasVtableSlot(M) &&
2866 M->size_overridden_methods() == 0) {
2875 bool CheckLeadingLayout = !PrimaryBase;
2877 for (
const CXXBaseSpecifier &Base : RD->
bases()) {
2878 if (
Base.isVirtual())
2880 const CXXRecordDecl *BaseDecl =
Base.getType()->getAsCXXRecordDecl();
2889 if (CheckLeadingLayout) {
2890 CheckLeadingLayout =
false;
2894 layoutNonVirtualBase(RD, BaseDecl, BaseLayout, PreviousBaseLayout);
2900 else if (SharedVBPtrBase) {
2909 if (RD->
hasAttr<EmptyBasesAttr>())
2911 if (
auto *LVA = RD->
getAttr<LayoutVersionAttr>())
2921void MicrosoftRecordLayoutBuilder::layoutNonVirtualBase(
2922 const CXXRecordDecl *RD,
const CXXRecordDecl *BaseDecl,
2923 const ASTRecordLayout &BaseLayout,
2924 const ASTRecordLayout *&PreviousBaseLayout) {
2932 ElementInfo Info = getAdjustedElementInfo(BaseLayout);
2933 CharUnits BaseOffset;
2936 bool FoundBase =
false;
2937 if (UseExternalLayout) {
2938 FoundBase =
External.getExternalNVBaseOffset(BaseDecl, BaseOffset);
2939 if (BaseOffset > Size) {
2945 if (MDCUsesEBO && BaseDecl->
isEmpty() &&
2950 BaseOffset =
Size =
Size.alignTo(Info.Alignment);
2953 Bases.insert(std::make_pair(BaseDecl, BaseOffset));
2956 PreviousBaseLayout = &BaseLayout;
2959void MicrosoftRecordLayoutBuilder::layoutFields(
const RecordDecl *RD) {
2960 LastFieldIsNonZeroWidthBitfield =
false;
2961 for (
const FieldDecl *Field : RD->
fields())
2965void MicrosoftRecordLayoutBuilder::layoutField(
const FieldDecl *FD) {
2970 LastFieldIsNonZeroWidthBitfield =
false;
2971 ElementInfo Info = getAdjustedElementInfo(FD);
2972 Alignment = std::max(Alignment, Info.Alignment);
2977 FieldClass->
fields().empty();
2980 if (UseExternalLayout) {
2983 }
else if (IsUnion) {
2985 }
else if (EmptySubobjects) {
2986 if (!IsOverlappingEmptyField)
2987 FieldOffset = DataSize.alignTo(Info.Alignment);
2989 while (!EmptySubobjects->CanPlaceFieldAtOffset(FD, FieldOffset)) {
2991 bool HasBases = ParentClass && (!ParentClass->
bases().empty() ||
2992 !ParentClass->
vbases().empty());
2997 FieldOffset = DataSize.alignTo(Info.Alignment);
2999 FieldOffset += Info.Alignment;
3003 FieldOffset =
Size.alignTo(Info.Alignment);
3006 uint64_t UnpaddedFielddOffsetInBits =
3007 Context.
toBits(DataSize) - RemainingBitsInField;
3010 UnpaddedFielddOffsetInBits, FD);
3012 RemainingBitsInField = 0;
3014 placeFieldAtOffset(FieldOffset);
3016 if (!IsOverlappingEmptyField)
3017 DataSize = std::max(DataSize, FieldOffset + Info.Size);
3019 Size = std::max(Size, FieldOffset + Info.Size);
3022void MicrosoftRecordLayoutBuilder::layoutBitField(
const FieldDecl *FD) {
3025 layoutZeroWidthBitField(FD);
3028 ElementInfo Info = getAdjustedElementInfo(FD);
3031 if (Width > Context.
toBits(Info.Size))
3032 Width = Context.
toBits(Info.Size);
3036 if (!UseExternalLayout && !IsUnion && LastFieldIsNonZeroWidthBitfield &&
3037 CurrentBitfieldSize == Info.Size && Width <= RemainingBitsInField) {
3038 placeFieldAtBitOffset(Context.
toBits(Size) - RemainingBitsInField);
3039 RemainingBitsInField -= Width;
3042 LastFieldIsNonZeroWidthBitfield =
true;
3043 CurrentBitfieldSize = Info.Size;
3044 if (UseExternalLayout) {
3045 auto FieldBitOffset =
External.getExternalFieldOffset(FD);
3046 placeFieldAtBitOffset(FieldBitOffset);
3048 llvm::alignDown(FieldBitOffset, Context.
toBits(Info.Alignment)) +
3049 Context.
toBits(Info.Size));
3050 Size = std::max(Size, NewSize);
3051 Alignment = std::max(Alignment, Info.Alignment);
3052 }
else if (IsUnion) {
3054 Size = std::max(Size, Info.Size);
3058 CharUnits FieldOffset =
Size.alignTo(Info.Alignment);
3059 uint64_t UnpaddedFieldOffsetInBits =
3060 Context.
toBits(DataSize) - RemainingBitsInField;
3061 placeFieldAtOffset(FieldOffset);
3062 Size = FieldOffset + Info.Size;
3063 Alignment = std::max(Alignment, Info.Alignment);
3064 RemainingBitsInField = Context.
toBits(Info.Size) - Width;
3066 UnpaddedFieldOffsetInBits, FD);
3072MicrosoftRecordLayoutBuilder::layoutZeroWidthBitField(
const FieldDecl *FD) {
3075 if (!LastFieldIsNonZeroWidthBitfield) {
3081 LastFieldIsNonZeroWidthBitfield =
false;
3082 ElementInfo Info = getAdjustedElementInfo(FD);
3085 Size = std::max(Size, Info.Size);
3089 CharUnits FieldOffset =
Size.alignTo(Info.Alignment);
3090 uint64_t UnpaddedFieldOffsetInBits =
3091 Context.
toBits(DataSize) - RemainingBitsInField;
3092 placeFieldAtOffset(FieldOffset);
3093 RemainingBitsInField = 0;
3095 Alignment = std::max(Alignment, Info.Alignment);
3097 UnpaddedFieldOffsetInBits, FD);
3102void MicrosoftRecordLayoutBuilder::injectVBPtr(
const CXXRecordDecl *RD) {
3103 if (!HasVBPtr || SharedVBPtrBase)
3106 CharUnits InjectionSite = VBPtrOffset;
3108 VBPtrOffset = VBPtrOffset.
alignTo(PointerInfo.Alignment);
3110 CharUnits FieldStart = VBPtrOffset + PointerInfo.Size;
3113 if (UseExternalLayout) {
3116 if (Size < FieldStart)
3122 CharUnits Offset = (FieldStart - InjectionSite)
3123 .alignTo(std::max(RequiredAlignment, Alignment));
3125 for (uint64_t &FieldOffset : FieldOffsets)
3126 FieldOffset += Context.
toBits(Offset);
3127 for (BaseOffsetsMapTy::value_type &Base : Bases)
3128 if (
Base.second >= InjectionSite)
3129 Base.second += Offset;
3132void MicrosoftRecordLayoutBuilder::injectVFPtr(
const CXXRecordDecl *RD) {
3138 PointerInfo.Size.
alignTo(std::max(RequiredAlignment, Alignment));
3142 VBPtrOffset += Offset;
3144 if (UseExternalLayout) {
3156 for (uint64_t &FieldOffset : FieldOffsets)
3157 FieldOffset += Context.
toBits(Offset);
3158 for (BaseOffsetsMapTy::value_type &Base : Bases)
3159 Base.second += Offset;
3162void MicrosoftRecordLayoutBuilder::layoutVirtualBases(
const CXXRecordDecl *RD) {
3167 CharUnits VtorDispAlignment = VtorDispSize;
3169 if (!MaxFieldAlignment.
isZero())
3170 VtorDispAlignment = std::min(VtorDispAlignment, MaxFieldAlignment);
3174 for (
const CXXBaseSpecifier &VBase : RD->
vbases()) {
3175 const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl();
3180 VtorDispAlignment = std::max(VtorDispAlignment, RequiredAlignment);
3182 llvm::SmallPtrSet<const CXXRecordDecl *, 2> HasVtorDispSet;
3183 computeVtorDispSet(HasVtorDispSet, RD);
3185 const ASTRecordLayout *PreviousBaseLayout =
nullptr;
3186 for (
const CXXBaseSpecifier &VBase : RD->
vbases()) {
3187 const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl();
3189 bool HasVtordisp = HasVtorDispSet.contains(BaseDecl);
3198 Size =
Size.alignTo(VtorDispAlignment) + VtorDispSize;
3199 Alignment = std::max(VtorDispAlignment, Alignment);
3202 ElementInfo Info = getAdjustedElementInfo(BaseLayout);
3203 CharUnits BaseOffset;
3206 if (UseExternalLayout) {
3207 if (!
External.getExternalVBaseOffset(BaseDecl, BaseOffset))
3210 BaseOffset =
Size.alignTo(Info.Alignment);
3212 assert(BaseOffset >= Size &&
"base offset already allocated");
3214 VBases.insert(std::make_pair(BaseDecl,
3215 ASTRecordLayout::VBaseInfo(BaseOffset, HasVtordisp)));
3217 PreviousBaseLayout = &BaseLayout;
3221void MicrosoftRecordLayoutBuilder::finalizeLayout(
const RecordDecl *RD) {
3223 UnpaddedSizeInBits -= RemainingBitsInField;
3228 UnpaddedSizeInBits += 8;
3233 if (!RequiredAlignment.
isZero()) {
3234 Alignment = std::max(Alignment, RequiredAlignment);
3235 auto RoundingAlignment = Alignment;
3236 if (!MaxFieldAlignment.
isZero())
3237 RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment);
3238 RoundingAlignment = std::max(RoundingAlignment, RequiredAlignment);
3239 Size =
Size.alignTo(RoundingAlignment);
3241 if (
Size.isZero()) {
3243 EndsWithZeroSizedObject =
true;
3244 LeadsWithZeroSizedBase =
true;
3248 if (RequiredAlignment >= MinEmptyStructSize)
3251 Size = MinEmptyStructSize;
3254 if (UseExternalLayout) {
3263 if (SizeInBits > UnpaddedSizeInBits) {
3264 unsigned int PadSize = SizeInBits - UnpaddedSizeInBits;
3266 if (PadSize % CharBitNum == 0) {
3267 PadSize = PadSize / CharBitNum;
3272 diag::warn_padded_struct_size)
3274 << (InBits ? 1 : 0);
3282 BasesWithOverriddenMethods,
3284 if (BasesWithOverriddenMethods.count(RD))
3289 if (!
Base.isVirtual() &&
3291 Base.getType()->getAsCXXRecordDecl()))
3296void MicrosoftRecordLayoutBuilder::computeVtorDispSet(
3297 llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtordispSet,
3298 const CXXRecordDecl *RD)
const {
3302 for (
const CXXBaseSpecifier &Base : RD->
vbases()) {
3303 const CXXRecordDecl *BaseDecl =
Base.getType()->getAsCXXRecordDecl();
3306 HasVtordispSet.insert(BaseDecl);
3313 for (
const CXXBaseSpecifier &Base : RD->
bases()) {
3314 const CXXRecordDecl *BaseDecl =
Base.getType()->getAsCXXRecordDecl();
3317 if (bi.second.hasVtorDisp())
3318 HasVtordispSet.insert(bi.first);
3334 llvm::SmallPtrSet<const CXXMethodDecl *, 8> Work;
3335 llvm::SmallPtrSet<const CXXRecordDecl *, 2> BasesWithOverriddenMethods;
3337 for (
const CXXMethodDecl *MD : RD->
methods())
3338 if (MicrosoftVTableContext::hasVtableSlot(MD) &&
3341 while (!Work.empty()) {
3342 const CXXMethodDecl *MD = *Work.begin();
3345 if (MethodRange.begin() == MethodRange.end())
3346 BasesWithOverriddenMethods.insert(MD->
getParent());
3348 Work.insert_range(MethodRange);
3354 for (
const CXXBaseSpecifier &Base : RD->
vbases()) {
3355 const CXXRecordDecl *BaseDecl =
Base.getType()->getAsCXXRecordDecl();
3356 if (!HasVtordispSet.count(BaseDecl) &&
3358 HasVtordispSet.insert(BaseDecl);
3365const ASTRecordLayout &
3378 assert(D &&
"Cannot get layout of forward declarations!");
3379 assert(!D->
isInvalidDecl() &&
"Cannot get layout of invalid decl!");
3386 if (Entry)
return *Entry;
3391 if (
const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
3392 EmptySubobjectMap EmptySubobjects(*
this, RD);
3393 MicrosoftRecordLayoutBuilder Builder(*
this, &EmptySubobjects);
3394 Builder.cxxLayout(RD);
3396 *
this, Builder.Size, Builder.Alignment, Builder.Alignment,
3397 Builder.Alignment, Builder.RequiredAlignment, Builder.HasOwnVFPtr,
3398 Builder.HasOwnVFPtr || Builder.PrimaryBase, Builder.VBPtrOffset,
3399 Builder.DataSize, Builder.FieldOffsets, Builder.NonVirtualSize,
3401 Builder.PrimaryBase,
false, Builder.SharedVBPtrBase,
3402 Builder.EndsWithZeroSizedObject, Builder.LeadsWithZeroSizedBase,
3403 Builder.Bases, Builder.VBases);
3405 MicrosoftRecordLayoutBuilder Builder(*
this,
nullptr);
3408 *
this, Builder.Size, Builder.Alignment, Builder.Alignment,
3409 Builder.Alignment, Builder.RequiredAlignment, Builder.Size,
3410 Builder.FieldOffsets);
3413 if (
const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
3414 EmptySubobjectMap EmptySubobjects(*
this, RD);
3415 ItaniumRecordLayoutBuilder Builder(*
this, &EmptySubobjects);
3421 bool skipTailPadding =
3426 skipTailPadding ? Builder.getSize() : Builder.getDataSize();
3428 skipTailPadding ? DataSize : Builder.NonVirtualSize;
3430 *
this, Builder.getSize(), Builder.Alignment,
3431 Builder.PreferredAlignment, Builder.UnadjustedAlignment,
3435 NonVirtualSize, Builder.NonVirtualAlignment,
3436 Builder.PreferredNVAlignment,
3437 EmptySubobjects.SizeOfLargestEmptySubobject, Builder.PrimaryBase,
3438 Builder.PrimaryBaseIsVirtual,
nullptr,
false,
false, Builder.Bases,
3441 ItaniumRecordLayoutBuilder Builder(*
this,
nullptr);
3445 *
this, Builder.getSize(), Builder.Alignment,
3446 Builder.PreferredAlignment, Builder.UnadjustedAlignment,
3448 Builder.Alignment, Builder.getSize(), Builder.FieldOffsets);
3452 ASTRecordLayouts[D] = NewEntry;
3454 constexpr uint64_t MaxStructSizeInBytes = 1ULL << 60;
3456 if (
static_cast<uint64_t
>(StructSize.
getQuantity()) >= MaxStructSizeInBytes) {
3458 << D->
getName() << MaxStructSizeInBytes;
3462 llvm::outs() <<
"\n*** Dumping AST Record Layout\n";
3473 assert(RD->
getDefinition() &&
"Cannot get key function for forward decl!");
3487 KeyFunctions[RD] =
const_cast<Decl*
>(
Result);
3489 return cast_or_null<CXXMethodDecl>(
Result);
3494 "not working with method declaration from class definition");
3499 const auto &Map = KeyFunctions;
3500 auto I = Map.find(
Method->getParent());
3503 if (I == Map.end())
return;
3511 KeyFunctions.erase(
Method->getParent());
3521 uint64_t OffsetInBits;
3522 if (
const FieldDecl *FD = dyn_cast<FieldDecl>(VD)) {
3532 return OffsetInBits;
3554 assert(Index < RL->getFieldCount() &&
"Ivar is not inside record layout!");
3571 "Invalid interface decl!");
3577 ItaniumRecordLayoutBuilder Builder(*
this,
nullptr);
3581 *
this, Builder.getSize(), Builder.Alignment, Builder.PreferredAlignment,
3582 Builder.UnadjustedAlignment,
3584 Builder.Alignment, Builder.getDataSize(), Builder.FieldOffsets);
3586 ObjCLayouts[D] = NewEntry;
3593 OS << llvm::format(
"%10" PRId64
" | ", (int64_t)Offset.getQuantity());
3598 unsigned Begin,
unsigned Width,
3602 llvm::raw_svector_ostream BufferOS(Buffer);
3603 BufferOS << Offset.getQuantity() <<
':';
3607 BufferOS << Begin <<
'-' << (Begin + Width - 1);
3611 OS << llvm::right_justify(Buffer, 10) <<
" | ";
3624 const char* Description,
3626 bool IncludeVirtualBases) {
3628 auto CXXRD = dyn_cast<CXXRecordDecl>(RD);
3631 OS <<
C.getCanonicalTagType(
const_cast<RecordDecl *
>(RD));
3633 OS <<
' ' << Description;
3634 if (CXXRD && CXXRD->isEmpty())
3647 if (CXXRD->isDynamicClass() && !PrimaryBase &&
3648 !
C.getTargetInfo().hasMicrosoftRecordLayout()) {
3650 OS <<
'(' << *RD <<
" vtable pointer)\n";
3651 }
else if (HasOwnVFPtr) {
3654 OS <<
'(' << *RD <<
" vftable pointer)\n";
3660 assert(!
Base.getType()->isDependentType() &&
3661 "Cannot layout class with dependent bases.");
3662 if (!
Base.isVirtual())
3663 Bases.push_back(
Base.getType()->getAsCXXRecordDecl());
3676 Base == PrimaryBase ?
"(primary base)" :
"(base)",
3684 OS <<
'(' << *RD <<
" vbtable pointer)\n";
3690 uint64_t LocalFieldOffsetInBits =
3693 Offset +
C.toCharUnitsFromBits(LocalFieldOffsetInBits);
3696 if (
const auto *RD = Field->getType()->getAsRecordDecl()) {
3698 Field->getName().data(),
3704 if (Field->isBitField()) {
3705 uint64_t LocalFieldByteOffsetInBits =
C.toBits(FieldOffset - Offset);
3706 unsigned Begin = LocalFieldOffsetInBits - LocalFieldByteOffsetInBits;
3707 unsigned Width = Field->getBitWidthValue();
3712 const QualType &FieldType =
C.getLangOpts().DumpRecordLayoutsCanonical
3713 ? Field->getType().getCanonicalType()
3715 OS << FieldType <<
' ' << *Field <<
'\n';
3719 if (CXXRD && IncludeVirtualBases) {
3724 assert(
Base.isVirtual() &&
"Found non-virtual class!");
3729 if (VtorDisps.find(VBase)->second.hasVtorDisp()) {
3731 OS <<
"(vtordisp for vbase " << *VBase <<
")\n";
3736 "(primary virtual base)" :
"(virtual base)",
3742 if (!PrintSizeInfo)
return;
3746 if (CXXRD && !
C.getTargetInfo().hasMicrosoftRecordLayout())
3749 if (
C.getTargetInfo().defaultsToAIXPowerAlignment())
3757 if (
C.getTargetInfo().defaultsToAIXPowerAlignment())
3758 OS <<
", preferrednvalign="
3765 bool Simple)
const {
3783 OS <<
"<ASTRecordLayout\n";
3788 if (Target->defaultsToAIXPowerAlignment())
3791 if (
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
3792 OS <<
" BaseOffsets: [";
3794 for (
auto I : CXXRD->bases()) {
3799 Base = I.getType()->getAsCXXRecordDecl();
3800 OS << Info.CXXInfo->BaseOffsets[
Base].getQuantity();
3803 OS <<
" VBaseOffsets: [";
3805 for (
auto I : CXXRD->vbases()) {
3808 VBase = I.getType()->getAsCXXRecordDecl();
3809 OS << Info.CXXInfo->VBaseOffsets[VBase].VBaseOffset.getQuantity();
3813 OS <<
" FieldOffsets: [";
3814 for (
unsigned i = 0, e = Info.
getFieldCount(); i != e; ++i) {
Defines the clang::ASTContext interface.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
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.
static unsigned getCharWidth(tok::TokenKind kind, const TargetInfo &Target)
llvm::MachO::Target Target
static const CXXMethodDecl * computeKeyFunction(ASTContext &Context, const CXXRecordDecl *RD)
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 bool isAIXLayout(const ASTContext &Context)
static void PrintIndentNoOffset(raw_ostream &OS, unsigned IndentLevel)
static uint64_t roundUpSizeToCharAlignment(uint64_t Size, const ASTContext &Context)
static void PrintOffset(raw_ostream &OS, CharUnits Offset, unsigned IndentLevel)
static unsigned getPaddingDiagFromTagKind(TagTypeKind Tag)
Get diagnostic select index for tag kind for field padding diagnostic message.
static void DumpRecordLayout(raw_ostream &OS, const RecordDecl *RD, const ASTContext &C, CharUnits Offset, unsigned IndentLevel, const char *Description, bool PrintSizeInfo, bool IncludeVirtualBases)
static void CheckFieldPadding(const ASTContext &Context, bool IsUnion, uint64_t Offset, uint64_t UnpaddedOffset, const FieldDecl *D)
static uint64_t getFieldOffset(const ASTContext &C, const FieldDecl *FD)
static bool RequiresVtordisp(const llvm::SmallPtrSetImpl< const CXXRecordDecl * > &BasesWithOverriddenMethods, const CXXRecordDecl *RD)
static void PrintBitFieldOffset(raw_ostream &OS, CharUnits Offset, unsigned Begin, unsigned Width, unsigned IndentLevel)
static bool recordUsesEBO(const RecordDecl *RD)
uint64_t getFieldOffset(const ValueDecl *FD) const
Get the offset of a FieldDecl or IndirectFieldDecl, in bits.
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
void DumpRecordLayout(const RecordDecl *RD, raw_ostream &OS, bool Simple=false) const
const CXXMethodDecl * getCurrentKeyFunction(const CXXRecordDecl *RD)
Get our current best idea for the key function of the given record decl, or nullptr if there isn't on...
uint64_t lookupFieldBitOffset(const ObjCInterfaceDecl *OID, const ObjCIvarDecl *Ivar) const
Get the offset of an ObjCIvarDecl in bits.
void setNonKeyFunction(const CXXMethodDecl *method)
Observe that the given method cannot be a key function.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const ConstantArrayType * getAsConstantArrayType(QualType T) const
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
const LangOptions & getLangOpts() const
const ASTRecordLayout & getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D) const
Get or compute information about the layout of the specified Objective-C interface.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
bool isNearlyEmpty(const CXXRecordDecl *RD) const
friend class CXXRecordDecl
CanQualType UnsignedLongTy
TypeInfo getTypeInfo(const Type *T) const
Get the size and alignment of the specified complete type in bits.
bool isAlignmentRequired(const Type *T) const
Determine if the alignment the type has was required using an alignment attribute.
TypeInfoChars getTypeInfoInChars(const Type *T) const
int64_t toBits(CharUnits CharSize) const
Convert a size in characters to a size in bits.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CanQualType UnsignedInt128Ty
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CanQualType UnsignedCharTy
CanQualType UnsignedIntTy
CanQualType UnsignedLongLongTy
CanQualType UnsignedShortTy
DiagnosticsEngine & getDiagnostics() const
const TargetInfo & getTargetInfo() const
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
ExternalASTSource * getExternalSource() const
Retrieve a pointer to the external AST source associated with this AST context, if any.
uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const
Return number of constant array elements.
CanQualType getCanonicalTagType(const TagDecl *TD) const
uint64_t getCharWidth() const
Return the size of the character type, in bits.
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
bool endsWithZeroSizedObject() const
bool hasOwnVFPtr() const
hasOwnVFPtr - Does this class provide its own virtual-function table pointer, rather than inheriting ...
CharUnits getAlignment() const
getAlignment - Get the record alignment in characters.
CharUnits getPreferredAlignment() const
getPreferredFieldAlignment - Get the record preferred alignment in characters.
bool hasOwnVBPtr() const
hasOwnVBPtr - Does this class provide its own virtual-base table pointer, rather than inheriting one ...
llvm::DenseMap< const CXXRecordDecl *, VBaseInfo > VBaseOffsetsMapTy
CharUnits getSize() const
getSize - Get the record size in characters.
unsigned getFieldCount() const
getFieldCount - Get the number of fields in the layout.
bool hasVBPtr() const
hasVBPtr - Does this class have a virtual function table pointer.
bool leadsWithZeroSizedBase() const
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
CharUnits getNonVirtualAlignment() const
getNonVirtualAlignment - Get the non-virtual alignment (in chars) of an object, which is the alignmen...
CharUnits getVBPtrOffset() const
getVBPtrOffset - Get the offset for virtual base table pointer.
CharUnits getDataSize() const
getDataSize() - Get the record data size, which is the record size without tail padding,...
CharUnits getRequiredAlignment() const
CharUnits getSizeOfLargestEmptySubobject() const
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
CharUnits getPreferredNVAlignment() const
getPreferredNVAlignment - Get the preferred non-virtual alignment (in chars) of an object,...
CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const
getVBaseClassOffset - Get the offset, in chars, for the given base class.
const VBaseOffsetsMapTy & getVBaseOffsetsMap() const
const CXXRecordDecl * getPrimaryBase() const
getPrimaryBase - Get the primary base for this record.
bool hasExtendableVFPtr() const
hasVFPtr - Does this class have a virtual function table pointer that can be extended by a derived cl...
bool isPrimaryBaseVirtual() const
isPrimaryBaseVirtual - Get whether the primary base for this record is virtual or not.
CharUnits getNonVirtualSize() const
getNonVirtualSize - Get the non-virtual size (in chars) of an object, which is the size of the object...
Represents a base class of a C++ class.
Represents a static or instance method of a struct/union/class.
overridden_method_range overridden_methods() const
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Represents a C++ struct/union/class.
void getIndirectPrimaryBases(CXXIndirectPrimaryBaseSet &Bases) const
Get the indirect primary bases for this class.
bool hasUserDeclaredDestructor() const
Determine whether this class has a user-declared destructor.
method_range methods() const
CXXRecordDecl * getDefinition() const
bool isPolymorphic() const
Whether this class is polymorphic (C++ [class.virtual]), which means that the class contains or inher...
TemplateSpecializationKind getTemplateSpecializationKind() const
Determine whether this particular class is a specialization or instantiation of a class template or m...
base_class_range vbases()
bool isDynamicClass() const
bool isCXX11StandardLayout() const
Determine whether this class was standard-layout per C++11 [class]p7, specifically using the C++11 ru...
bool hasUserDeclaredConstructor() const
Determine whether this class has any user-declared constructors.
bool isPOD() const
Whether this class is a POD-type (C++ [class]p4)
MSVtorDispMode 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]).
bool isTrivial() const
Determine whether this class is considered trivial.
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
CharUnits - This is an opaque type for sizes expressed in character units.
bool isZero() const
isZero - Test whether the quantity equals zero.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
static CharUnits One()
One - Construct a CharUnits quantity of one.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
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 ...
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
bool hasExternalLexicalStorage() const
Whether this DeclContext has external storage containing additional declarations that are lexically i...
Decl - This represents one declaration (or definition), e.g.
unsigned getMaxAlignment() const
getMaxAlignment - return the maximum alignment specified by attributes on this decl,...
bool isInvalidDecl() const
SourceLocation getLocation() const
A little helper class (which is basically a smart pointer that forwards info from DiagnosticsEngine a...
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Represents a member of a struct/union/class.
bool isBitField() const
Determines whether this field is a bitfield.
unsigned getBitWidthValue() const
Computes the bit width of this field, if this is a bit field.
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
bool isPotentiallyOverlapping() const
Determine if this field is of potentially-overlapping class type, that is, subobject with the [[no_un...
Represents a function declaration or definition.
bool isInlineSpecified() const
Determine whether the "inline" keyword was specified for this function.
Represents a field injected from an anonymous union/struct into the parent scope.
ArrayRef< NamedDecl * > chain() const
This represents a decl that may have a name.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
bool isExternallyVisible() const
Represents an ObjC class declaration.
ObjCIvarDecl * all_declared_ivar_begin()
all_declared_ivar_begin - return first ivar declared in this class, its extensions and its implementa...
bool isThisDeclarationADefinition() const
Determine whether this particular declaration of this class is actually also a definition.
ObjCInterfaceDecl * getSuperClass() const
ObjCInterfaceDecl * getDefinition()
Retrieve the definition of this class, or NULL if this class has been forward-declared (with @class) ...
ObjCIvarDecl - Represents an ObjC instance variable.
ObjCInterfaceDecl * getContainingInterface()
Return the class interface that this ivar is logically contained in; this is either the interface whe...
ObjCIvarDecl * getNextIvar()
ObjCIvarDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this field.
A (possibly-)qualified type.
Represents a struct/union/class.
bool isMsStruct(const ASTContext &C) const
Get whether or not this is an ms_struct which can be turned on with an attribute, pragma,...
bool hasFlexibleArrayMember() const
field_iterator field_end() const
field_range fields() const
bool mayInsertExtraPadding(bool EmitRemark=false) const
Whether we are allowed to insert extra padding between fields.
RecordDecl * getMostRecentDecl()
RecordDecl * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
field_iterator field_begin() const
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
TagKind getTagKind() const
The basic abstraction for the target C++ ABI.
TailPaddingUseRules getTailPaddingUseRules() const
@ AlwaysUseTailPadding
The tail-padding of a base class is always theoretically available, even if it's POD.
@ UseTailPaddingUnlessPOD11
Only allocate objects in the tail padding of a base class if the base class is not POD according to t...
@ UseTailPaddingUnlessPOD03
Only allocate objects in the tail padding of a base class if the base class is not POD according to t...
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
bool useLeadingZeroLengthBitfield() const
Check whether zero length bitfield alignment is respected if they are leading members.
uint64_t getPointerWidth(LangAS AddrSpace) const
Return the width of pointers on this target, for the specified address space.
unsigned getLargestOverSizedBitfieldContainer() const
virtual bool defaultsToAIXPowerAlignment() const
Whether target defaults to the power alignment rules of AIX.
unsigned getCharAlign() const
unsigned getZeroLengthBitfieldBoundary() const
Get the fixed alignment value in bits for a member that follows a zero length bitfield.
bool useExplicitBitFieldAlignment() const
Check whether explicit bitfield alignment attributes should be.
uint64_t getPointerAlign(LangAS AddrSpace) const
TargetCXXABI getCXXABI() const
Get the C++ ABI currently in use.
unsigned getCharWidth() const
bool useZeroLengthBitfieldAlignment() const
Check whether zero length bitfields should force alignment of the next member.
bool useBitFieldTypeAlignment() const
Check whether the alignment of bit-field types is respected when laying out structures.
bool isIncompleteArrayType() const
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
const Type * getBaseElementTypeUnsafe() const
Get the base element type of this type, potentially discarding type qualifiers.
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
const T * getAs() const
Member-template getAs<specific type>'.
const Type * getUnqualifiedDesugaredType() const
Return the specified type with any "sugar" removed from the type, removing any typedefs,...
bool isRecordType() const
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Defines the clang::TargetInfo interface.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
LazyOffsetPtr< Decl, GlobalDeclID, &ExternalASTSource::GetExternalDecl > LazyDeclPtr
A lazy pointer to a declaration.
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
@ External
External linkage, which indicates that the entity can be referred to from other translation units.
@ Result
The result type of a method or function.
const FunctionProtoType * T
TagTypeKind
The kind of a tag type.
@ Interface
The "__interface" keyword.
@ Struct
The "struct" keyword.
@ Class
The "class" keyword.
@ Type
The name was classified as a type.
TemplateSpecializationKind
Describes the kind of template specialization that a particular template specialization declaration r...
@ TSK_ExplicitInstantiationDefinition
This template specialization was instantiated from a template due to an explicit instantiation defini...
@ TSK_ExplicitInstantiationDeclaration
This template specialization was instantiated from a template due to an explicit instantiation declar...
@ TSK_ImplicitInstantiation
This template specialization was implicitly instantiated from a template.
U cast(CodeGen::Address addr)
@ Class
The "class" keyword introduces the elaborated-type-specifier.
bool isValid() const
Whether this pointer is non-NULL.
bool isOffset() const
Whether this pointer is currently stored as an offset.
T * get(ExternalASTSource *Source) const
Retrieve the pointer to the AST node that this lazy pointer points to.