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;
2091 ExtraSizeForAsan += ASanAlignment - (FieldSize % ASanAlignment);
2092 EffectiveFieldSize = FieldSize = FieldSize + ExtraSizeForAsan;
2096 if (!IsOverlappingEmptyField) {
2097 uint64_t EffectiveFieldSizeInBits = Context.
toBits(EffectiveFieldSize);
2099 setDataSize(std::max(getDataSizeInBits(), EffectiveFieldSizeInBits));
2101 setDataSize(FieldOffset + EffectiveFieldSize);
2103 PaddedFieldSize = std::max(PaddedFieldSize, FieldOffset + FieldSize);
2104 setSize(std::max(getSizeInBits(), getDataSizeInBits()));
2106 setSize(std::max(getSizeInBits(),
2107 (uint64_t)Context.
toBits(FieldOffset + FieldSize)));
2111 UnadjustedAlignment = std::max(UnadjustedAlignment, FieldAlign);
2112 UpdateAlignment(FieldAlign, UnpackedFieldAlign, PreferredAlign);
2116 if (
const RecordDecl *RD = D->
getParent()) {
2118 if (RD->
hasAttr<PackedAttr>() || !MaxFieldAlignment.
isZero())
2119 if (FieldAlign < OriginalFieldAlign)
2131 if (
Packed && !FieldPacked && PackedFieldAlign < FieldAlign)
2135void ItaniumRecordLayoutBuilder::FinishLayout(
const NamedDecl *D) {
2137 if (Context.
getLangOpts().CPlusPlus && getSizeInBits() == 0) {
2138 if (
const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
2151 setSize(std::max(getSizeInBits(), (uint64_t)Context.
toBits(PaddedFieldSize)));
2155 uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastUnit;
2157 llvm::alignTo(getSizeInBits(), Context.
toBits(UnpackedAlignment));
2159 uint64_t RoundedSize = llvm::alignTo(
2163 : PreferredAlignment));
2165 if (UseExternalLayout) {
2169 if (InferAlignment &&
External.Size < RoundedSize) {
2172 InferAlignment =
false;
2179 setSize(RoundedSize);
2182 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
2184 if (getSizeInBits() > UnpaddedSize) {
2185 unsigned PadSize = getSizeInBits() - UnpaddedSize;
2187 if (PadSize % CharBitNum == 0) {
2188 PadSize = PadSize / CharBitNum;
2193 << (InBits ? 1 : 0);
2196 const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD);
2204 if (
Packed && UnpackedAlignment <= Alignment &&
2205 UnpackedSizeInBits == getSizeInBits() && !HasPackedField &&
2206 (!CXXRD || CXXRD->isPOD() ||
2208 LangOptions::ClangABI::Ver15))
2214void ItaniumRecordLayoutBuilder::UpdateAlignment(
2215 CharUnits NewAlignment, CharUnits UnpackedNewAlignment,
2216 CharUnits PreferredNewAlignment) {
2219 if (IsMac68kAlign || (UseExternalLayout && !InferAlignment))
2222 if (NewAlignment > Alignment) {
2223 assert(llvm::isPowerOf2_64(NewAlignment.
getQuantity()) &&
2224 "Alignment not a power of 2");
2225 Alignment = NewAlignment;
2228 if (UnpackedNewAlignment > UnpackedAlignment) {
2229 assert(llvm::isPowerOf2_64(UnpackedNewAlignment.
getQuantity()) &&
2230 "Alignment not a power of 2");
2231 UnpackedAlignment = UnpackedNewAlignment;
2234 if (PreferredNewAlignment > PreferredAlignment) {
2235 assert(llvm::isPowerOf2_64(PreferredNewAlignment.
getQuantity()) &&
2236 "Alignment not a power of 2");
2237 PreferredAlignment = PreferredNewAlignment;
2242ItaniumRecordLayoutBuilder::updateExternalFieldOffset(
const FieldDecl *Field,
2243 uint64_t ComputedOffset) {
2246 if (InferAlignment && ExternalFieldOffset < ComputedOffset) {
2251 InferAlignment =
false;
2255 return ExternalFieldOffset;
2271 default: llvm_unreachable(
"Invalid tag kind for field padding diagnostic!");
2276 uint64_t Offset, uint64_t UnpaddedOffset,
2288 unsigned CharBitNum = Context.getTargetInfo().getCharWidth();
2291 if (!IsUnion && Offset > UnpaddedOffset) {
2292 unsigned PadSize = Offset - UnpaddedOffset;
2294 if (PadSize % CharBitNum == 0) {
2295 PadSize = PadSize / CharBitNum;
2300 : diag::warn_padded_struct_field;
2304 << Context.getCanonicalTagType(D->
getParent()) << PadSize
2309 : diag::warn_padded_struct_anon_field;
2313 << Context.getCanonicalTagType(D->
getParent()) << PadSize
2314 << (InBits ? 1 : 0);
2319void ItaniumRecordLayoutBuilder::CheckFieldPadding(
2320 uint64_t Offset, uint64_t UnpaddedOffset, uint64_t UnpackedOffset,
2321 unsigned UnpackedAlign,
bool isPacked,
const FieldDecl *D) {
2323 if (isPacked && Offset != UnpackedOffset) {
2324 HasPackedField =
true;
2348 bool allowInlineFunctions =
2349 Context.getTargetInfo().getCXXABI().canKeyFunctionBeInline();
2352 if (!MD->isVirtual())
2355 if (MD->isPureVirtual())
2360 if (MD->isImplicit())
2363 if (MD->isInlineSpecified() || MD->isConstexpr())
2366 if (MD->hasInlineBody())
2370 if (!MD->isUserProvided())
2374 if (!allowInlineFunctions) {
2380 if (Context.getLangOpts().CUDA) {
2384 if (Context.getLangOpts().CUDAIsDevice) {
2386 if (!MD->hasAttr<CUDADeviceAttr>())
2390 if (!MD->hasAttr<CUDAHostAttr>() && MD->hasAttr<CUDADeviceAttr>())
2398 if (MD->hasAttr<DLLImportAttr>() && !RD->
hasAttr<DLLImportAttr>() &&
2399 !Context.getTargetInfo().hasPS4DLLImportExport())
2409DiagnosticBuilder ItaniumRecordLayoutBuilder::Diag(SourceLocation Loc,
2453 llvm_unreachable(
"bad tail-padding use kind");
2547struct MicrosoftRecordLayoutBuilder {
2548 struct ElementInfo {
2550 CharUnits Alignment;
2552 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
2553 MicrosoftRecordLayoutBuilder(
const ASTContext &Context,
2554 EmptySubobjectMap *EmptySubobjects)
2555 : Context(Context), EmptySubobjects(EmptySubobjects),
2556 RemainingBitsInField(0) {}
2559 MicrosoftRecordLayoutBuilder(
const MicrosoftRecordLayoutBuilder &) =
delete;
2560 void operator=(
const MicrosoftRecordLayoutBuilder &) =
delete;
2562 void layout(
const RecordDecl *RD);
2563 void cxxLayout(
const CXXRecordDecl *RD);
2565 void initializeLayout(
const RecordDecl *RD);
2569 void initializeCXXLayout(
const CXXRecordDecl *RD);
2570 void layoutNonVirtualBases(
const CXXRecordDecl *RD);
2571 void layoutNonVirtualBase(
const CXXRecordDecl *RD,
2572 const CXXRecordDecl *BaseDecl,
2573 const ASTRecordLayout &BaseLayout,
2574 const ASTRecordLayout *&PreviousBaseLayout);
2575 void injectVFPtr(
const CXXRecordDecl *RD);
2576 void injectVBPtr(
const CXXRecordDecl *RD);
2579 void layoutFields(
const RecordDecl *RD);
2580 void layoutField(
const FieldDecl *FD);
2581 void layoutBitField(
const FieldDecl *FD);
2584 void layoutZeroWidthBitField(
const FieldDecl *FD);
2585 void layoutVirtualBases(
const CXXRecordDecl *RD);
2586 void finalizeLayout(
const RecordDecl *RD);
2589 ElementInfo getAdjustedElementInfo(
const ASTRecordLayout &Layout);
2593 ElementInfo getAdjustedElementInfo(
const FieldDecl *FD);
2595 void placeFieldAtOffset(CharUnits FieldOffset) {
2596 FieldOffsets.push_back(Context.
toBits(FieldOffset));
2599 void placeFieldAtBitOffset(uint64_t FieldOffset) {
2600 FieldOffsets.push_back(FieldOffset);
2603 void computeVtorDispSet(
2604 llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtorDispSet,
2605 const CXXRecordDecl *RD)
const;
2606 const ASTContext &Context;
2607 EmptySubobjectMap *EmptySubobjects;
2612 CharUnits NonVirtualSize;
2616 CharUnits Alignment;
2618 CharUnits MaxFieldAlignment;
2621 CharUnits RequiredAlignment;
2625 CharUnits CurrentBitfieldSize;
2627 CharUnits VBPtrOffset;
2629 CharUnits MinEmptyStructSize;
2631 ElementInfo PointerInfo;
2633 const CXXRecordDecl *PrimaryBase;
2635 const CXXRecordDecl *SharedVBPtrBase;
2637 SmallVector<uint64_t, 16> FieldOffsets;
2639 BaseOffsetsMapTy Bases;
2643 unsigned RemainingBitsInField;
2647 bool LastFieldIsNonZeroWidthBitfield : 1;
2649 bool HasOwnVFPtr : 1;
2655 bool EndsWithZeroSizedObject : 1;
2658 bool LeadsWithZeroSizedBase : 1;
2661 bool UseExternalLayout : 1;
2669MicrosoftRecordLayoutBuilder::ElementInfo
2670MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
2671 const ASTRecordLayout &Layout) {
2675 if (!MaxFieldAlignment.
isZero())
2676 Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment);
2682 Alignment = std::max(Alignment, Info.Alignment);
2689MicrosoftRecordLayoutBuilder::ElementInfo
2690MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
2691 const FieldDecl *FD) {
2696 ElementInfo Info{TInfo.Width, TInfo.Align};
2698 CharUnits FieldRequiredAlignment =
2702 FieldRequiredAlignment = std::max(
2708 Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment);
2710 if (
const auto *RT = FD->
getType()
2715 FieldRequiredAlignment = std::max(FieldRequiredAlignment,
2719 RequiredAlignment = std::max(RequiredAlignment, FieldRequiredAlignment);
2722 if (!MaxFieldAlignment.
isZero())
2723 Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment);
2724 if (FD->
hasAttr<PackedAttr>())
2726 Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment);
2730void MicrosoftRecordLayoutBuilder::layout(
const RecordDecl *RD) {
2733 initializeLayout(RD);
2735 DataSize =
Size =
Size.alignTo(Alignment);
2736 RequiredAlignment = std::max(
2741void MicrosoftRecordLayoutBuilder::cxxLayout(
const CXXRecordDecl *RD) {
2744 initializeLayout(RD);
2745 initializeCXXLayout(RD);
2746 layoutNonVirtualBases(RD);
2750 if (HasOwnVFPtr || (HasVBPtr && !SharedVBPtrBase))
2751 Alignment = std::max(Alignment, PointerInfo.Alignment);
2752 auto RoundingAlignment = Alignment;
2753 if (!MaxFieldAlignment.
isZero())
2754 RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment);
2755 if (!UseExternalLayout)
2756 Size =
Size.alignTo(RoundingAlignment);
2757 NonVirtualSize =
Size;
2758 RequiredAlignment = std::max(
2760 layoutVirtualBases(RD);
2764void MicrosoftRecordLayoutBuilder::initializeLayout(
const RecordDecl *RD) {
2773 : CharUnits::
Zero();
2777 if (
unsigned DefaultMaxFieldAlignment = Context.
getLangOpts().PackStruct)
2781 if (
const MaxFieldAlignmentAttr *MFAA = RD->
getAttr<MaxFieldAlignmentAttr>()){
2782 unsigned PackedAlignment = MFAA->getAlignment();
2783 if (PackedAlignment <=
2788 if (RD->
hasAttr<PackedAttr>())
2792 UseExternalLayout =
false;
2794 UseExternalLayout = Source->layoutRecordType(
2800MicrosoftRecordLayoutBuilder::initializeCXXLayout(
const CXXRecordDecl *RD) {
2801 EndsWithZeroSizedObject =
false;
2802 LeadsWithZeroSizedBase =
false;
2803 HasOwnVFPtr =
false;
2805 PrimaryBase =
nullptr;
2806 SharedVBPtrBase =
nullptr;
2814 if (!MaxFieldAlignment.
isZero())
2815 PointerInfo.Alignment = std::min(PointerInfo.Alignment, MaxFieldAlignment);
2819MicrosoftRecordLayoutBuilder::layoutNonVirtualBases(
const CXXRecordDecl *RD) {
2826 const ASTRecordLayout *PreviousBaseLayout =
nullptr;
2827 bool HasPolymorphicBaseClass =
false;
2829 for (
const CXXBaseSpecifier &Base : RD->
bases()) {
2830 const CXXRecordDecl *BaseDecl =
Base.getType()->getAsCXXRecordDecl();
2834 if (
Base.isVirtual()) {
2839 if (!SharedVBPtrBase && BaseLayout.
hasVBPtr()) {
2840 SharedVBPtrBase = BaseDecl;
2848 PrimaryBase = BaseDecl;
2852 layoutNonVirtualBase(RD, BaseDecl, BaseLayout, PreviousBaseLayout);
2856 if (!HasPolymorphicBaseClass)
2860 else if (!PrimaryBase) {
2863 for (CXXMethodDecl *M : RD->
methods()) {
2864 if (MicrosoftVTableContext::hasVtableSlot(M) &&
2865 M->size_overridden_methods() == 0) {
2874 bool CheckLeadingLayout = !PrimaryBase;
2876 for (
const CXXBaseSpecifier &Base : RD->
bases()) {
2877 if (
Base.isVirtual())
2879 const CXXRecordDecl *BaseDecl =
Base.getType()->getAsCXXRecordDecl();
2888 if (CheckLeadingLayout) {
2889 CheckLeadingLayout =
false;
2893 layoutNonVirtualBase(RD, BaseDecl, BaseLayout, PreviousBaseLayout);
2899 else if (SharedVBPtrBase) {
2908 if (RD->
hasAttr<EmptyBasesAttr>())
2910 if (
auto *LVA = RD->
getAttr<LayoutVersionAttr>())
2920void MicrosoftRecordLayoutBuilder::layoutNonVirtualBase(
2921 const CXXRecordDecl *RD,
const CXXRecordDecl *BaseDecl,
2922 const ASTRecordLayout &BaseLayout,
2923 const ASTRecordLayout *&PreviousBaseLayout) {
2931 ElementInfo Info = getAdjustedElementInfo(BaseLayout);
2932 CharUnits BaseOffset;
2935 bool FoundBase =
false;
2936 if (UseExternalLayout) {
2937 FoundBase =
External.getExternalNVBaseOffset(BaseDecl, BaseOffset);
2938 if (BaseOffset > Size) {
2944 if (MDCUsesEBO && BaseDecl->
isEmpty() &&
2949 BaseOffset =
Size =
Size.alignTo(Info.Alignment);
2952 Bases.insert(std::make_pair(BaseDecl, BaseOffset));
2955 PreviousBaseLayout = &BaseLayout;
2958void MicrosoftRecordLayoutBuilder::layoutFields(
const RecordDecl *RD) {
2959 LastFieldIsNonZeroWidthBitfield =
false;
2960 for (
const FieldDecl *Field : RD->
fields())
2964void MicrosoftRecordLayoutBuilder::layoutField(
const FieldDecl *FD) {
2969 LastFieldIsNonZeroWidthBitfield =
false;
2970 ElementInfo Info = getAdjustedElementInfo(FD);
2971 Alignment = std::max(Alignment, Info.Alignment);
2976 FieldClass->
fields().empty();
2979 if (UseExternalLayout) {
2982 }
else if (IsUnion) {
2984 }
else if (EmptySubobjects) {
2985 if (!IsOverlappingEmptyField)
2986 FieldOffset = DataSize.alignTo(Info.Alignment);
2988 while (!EmptySubobjects->CanPlaceFieldAtOffset(FD, FieldOffset)) {
2990 bool HasBases = ParentClass && (!ParentClass->
bases().empty() ||
2991 !ParentClass->
vbases().empty());
2996 FieldOffset = DataSize.alignTo(Info.Alignment);
2998 FieldOffset += Info.Alignment;
3002 FieldOffset =
Size.alignTo(Info.Alignment);
3005 uint64_t UnpaddedFielddOffsetInBits =
3006 Context.
toBits(DataSize) - RemainingBitsInField;
3009 UnpaddedFielddOffsetInBits, FD);
3011 RemainingBitsInField = 0;
3013 placeFieldAtOffset(FieldOffset);
3015 if (!IsOverlappingEmptyField)
3016 DataSize = std::max(DataSize, FieldOffset + Info.Size);
3018 Size = std::max(Size, FieldOffset + Info.Size);
3021void MicrosoftRecordLayoutBuilder::layoutBitField(
const FieldDecl *FD) {
3024 layoutZeroWidthBitField(FD);
3027 ElementInfo Info = getAdjustedElementInfo(FD);
3030 if (Width > Context.
toBits(Info.Size))
3031 Width = Context.
toBits(Info.Size);
3035 if (!UseExternalLayout && !IsUnion && LastFieldIsNonZeroWidthBitfield &&
3036 CurrentBitfieldSize == Info.Size && Width <= RemainingBitsInField) {
3037 placeFieldAtBitOffset(Context.
toBits(Size) - RemainingBitsInField);
3038 RemainingBitsInField -= Width;
3041 LastFieldIsNonZeroWidthBitfield =
true;
3042 CurrentBitfieldSize = Info.Size;
3043 if (UseExternalLayout) {
3044 auto FieldBitOffset =
External.getExternalFieldOffset(FD);
3045 placeFieldAtBitOffset(FieldBitOffset);
3047 llvm::alignDown(FieldBitOffset, Context.
toBits(Info.Alignment)) +
3048 Context.
toBits(Info.Size));
3049 Size = std::max(Size, NewSize);
3050 Alignment = std::max(Alignment, Info.Alignment);
3051 }
else if (IsUnion) {
3053 Size = std::max(Size, Info.Size);
3057 CharUnits FieldOffset =
Size.alignTo(Info.Alignment);
3058 uint64_t UnpaddedFieldOffsetInBits =
3059 Context.
toBits(DataSize) - RemainingBitsInField;
3060 placeFieldAtOffset(FieldOffset);
3061 Size = FieldOffset + Info.Size;
3062 Alignment = std::max(Alignment, Info.Alignment);
3063 RemainingBitsInField = Context.
toBits(Info.Size) - Width;
3065 UnpaddedFieldOffsetInBits, FD);
3071MicrosoftRecordLayoutBuilder::layoutZeroWidthBitField(
const FieldDecl *FD) {
3074 if (!LastFieldIsNonZeroWidthBitfield) {
3080 LastFieldIsNonZeroWidthBitfield =
false;
3081 ElementInfo Info = getAdjustedElementInfo(FD);
3084 Size = std::max(Size, Info.Size);
3088 CharUnits FieldOffset =
Size.alignTo(Info.Alignment);
3089 uint64_t UnpaddedFieldOffsetInBits =
3090 Context.
toBits(DataSize) - RemainingBitsInField;
3091 placeFieldAtOffset(FieldOffset);
3092 RemainingBitsInField = 0;
3094 Alignment = std::max(Alignment, Info.Alignment);
3096 UnpaddedFieldOffsetInBits, FD);
3101void MicrosoftRecordLayoutBuilder::injectVBPtr(
const CXXRecordDecl *RD) {
3102 if (!HasVBPtr || SharedVBPtrBase)
3105 CharUnits InjectionSite = VBPtrOffset;
3107 VBPtrOffset = VBPtrOffset.
alignTo(PointerInfo.Alignment);
3109 CharUnits FieldStart = VBPtrOffset + PointerInfo.Size;
3112 if (UseExternalLayout) {
3115 if (Size < FieldStart)
3121 CharUnits Offset = (FieldStart - InjectionSite)
3122 .alignTo(std::max(RequiredAlignment, Alignment));
3124 for (uint64_t &FieldOffset : FieldOffsets)
3125 FieldOffset += Context.
toBits(Offset);
3126 for (BaseOffsetsMapTy::value_type &Base : Bases)
3127 if (
Base.second >= InjectionSite)
3128 Base.second += Offset;
3131void MicrosoftRecordLayoutBuilder::injectVFPtr(
const CXXRecordDecl *RD) {
3137 PointerInfo.Size.
alignTo(std::max(RequiredAlignment, Alignment));
3141 VBPtrOffset += Offset;
3143 if (UseExternalLayout) {
3155 for (uint64_t &FieldOffset : FieldOffsets)
3156 FieldOffset += Context.
toBits(Offset);
3157 for (BaseOffsetsMapTy::value_type &Base : Bases)
3158 Base.second += Offset;
3161void MicrosoftRecordLayoutBuilder::layoutVirtualBases(
const CXXRecordDecl *RD) {
3166 CharUnits VtorDispAlignment = VtorDispSize;
3168 if (!MaxFieldAlignment.
isZero())
3169 VtorDispAlignment = std::min(VtorDispAlignment, MaxFieldAlignment);
3173 for (
const CXXBaseSpecifier &VBase : RD->
vbases()) {
3174 const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl();
3179 VtorDispAlignment = std::max(VtorDispAlignment, RequiredAlignment);
3181 llvm::SmallPtrSet<const CXXRecordDecl *, 2> HasVtorDispSet;
3182 computeVtorDispSet(HasVtorDispSet, RD);
3184 const ASTRecordLayout *PreviousBaseLayout =
nullptr;
3185 for (
const CXXBaseSpecifier &VBase : RD->
vbases()) {
3186 const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl();
3188 bool HasVtordisp = HasVtorDispSet.contains(BaseDecl);
3197 Size =
Size.alignTo(VtorDispAlignment) + VtorDispSize;
3198 Alignment = std::max(VtorDispAlignment, Alignment);
3201 ElementInfo Info = getAdjustedElementInfo(BaseLayout);
3202 CharUnits BaseOffset;
3205 if (UseExternalLayout) {
3206 if (!
External.getExternalVBaseOffset(BaseDecl, BaseOffset))
3209 BaseOffset =
Size.alignTo(Info.Alignment);
3211 assert(BaseOffset >= Size &&
"base offset already allocated");
3213 VBases.insert(std::make_pair(BaseDecl,
3214 ASTRecordLayout::VBaseInfo(BaseOffset, HasVtordisp)));
3216 PreviousBaseLayout = &BaseLayout;
3220void MicrosoftRecordLayoutBuilder::finalizeLayout(
const RecordDecl *RD) {
3222 UnpaddedSizeInBits -= RemainingBitsInField;
3227 UnpaddedSizeInBits += 8;
3232 if (!RequiredAlignment.
isZero()) {
3233 Alignment = std::max(Alignment, RequiredAlignment);
3234 auto RoundingAlignment = Alignment;
3235 if (!MaxFieldAlignment.
isZero())
3236 RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment);
3237 RoundingAlignment = std::max(RoundingAlignment, RequiredAlignment);
3238 Size =
Size.alignTo(RoundingAlignment);
3240 if (
Size.isZero()) {
3242 EndsWithZeroSizedObject =
true;
3243 LeadsWithZeroSizedBase =
true;
3247 if (RequiredAlignment >= MinEmptyStructSize)
3250 Size = MinEmptyStructSize;
3253 if (UseExternalLayout) {
3262 if (SizeInBits > UnpaddedSizeInBits) {
3263 unsigned int PadSize = SizeInBits - UnpaddedSizeInBits;
3265 if (PadSize % CharBitNum == 0) {
3266 PadSize = PadSize / CharBitNum;
3271 diag::warn_padded_struct_size)
3273 << (InBits ? 1 : 0);
3281 BasesWithOverriddenMethods,
3283 if (BasesWithOverriddenMethods.count(RD))
3288 if (!
Base.isVirtual() &&
3290 Base.getType()->getAsCXXRecordDecl()))
3295void MicrosoftRecordLayoutBuilder::computeVtorDispSet(
3296 llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtordispSet,
3297 const CXXRecordDecl *RD)
const {
3301 for (
const CXXBaseSpecifier &Base : RD->
vbases()) {
3302 const CXXRecordDecl *BaseDecl =
Base.getType()->getAsCXXRecordDecl();
3305 HasVtordispSet.insert(BaseDecl);
3312 for (
const CXXBaseSpecifier &Base : RD->
bases()) {
3313 const CXXRecordDecl *BaseDecl =
Base.getType()->getAsCXXRecordDecl();
3316 if (bi.second.hasVtorDisp())
3317 HasVtordispSet.insert(bi.first);
3333 llvm::SmallPtrSet<const CXXMethodDecl *, 8> Work;
3334 llvm::SmallPtrSet<const CXXRecordDecl *, 2> BasesWithOverriddenMethods;
3336 for (
const CXXMethodDecl *MD : RD->
methods())
3337 if (MicrosoftVTableContext::hasVtableSlot(MD) &&
3340 while (!Work.empty()) {
3341 const CXXMethodDecl *MD = *Work.begin();
3344 if (MethodRange.begin() == MethodRange.end())
3345 BasesWithOverriddenMethods.insert(MD->
getParent());
3347 Work.insert_range(MethodRange);
3353 for (
const CXXBaseSpecifier &Base : RD->
vbases()) {
3354 const CXXRecordDecl *BaseDecl =
Base.getType()->getAsCXXRecordDecl();
3355 if (!HasVtordispSet.count(BaseDecl) &&
3357 HasVtordispSet.insert(BaseDecl);
3364const ASTRecordLayout &
3377 assert(D &&
"Cannot get layout of forward declarations!");
3378 assert(!D->
isInvalidDecl() &&
"Cannot get layout of invalid decl!");
3385 if (Entry)
return *Entry;
3390 if (
const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
3391 EmptySubobjectMap EmptySubobjects(*
this, RD);
3392 MicrosoftRecordLayoutBuilder Builder(*
this, &EmptySubobjects);
3393 Builder.cxxLayout(RD);
3395 *
this, Builder.Size, Builder.Alignment, Builder.Alignment,
3396 Builder.Alignment, Builder.RequiredAlignment, Builder.HasOwnVFPtr,
3397 Builder.HasOwnVFPtr || Builder.PrimaryBase, Builder.VBPtrOffset,
3398 Builder.DataSize, Builder.FieldOffsets, Builder.NonVirtualSize,
3400 Builder.PrimaryBase,
false, Builder.SharedVBPtrBase,
3401 Builder.EndsWithZeroSizedObject, Builder.LeadsWithZeroSizedBase,
3402 Builder.Bases, Builder.VBases);
3404 MicrosoftRecordLayoutBuilder Builder(*
this,
nullptr);
3407 *
this, Builder.Size, Builder.Alignment, Builder.Alignment,
3408 Builder.Alignment, Builder.RequiredAlignment, Builder.Size,
3409 Builder.FieldOffsets);
3412 if (
const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
3413 EmptySubobjectMap EmptySubobjects(*
this, RD);
3414 ItaniumRecordLayoutBuilder Builder(*
this, &EmptySubobjects);
3420 bool skipTailPadding =
3425 skipTailPadding ? Builder.getSize() : Builder.getDataSize();
3427 skipTailPadding ? DataSize : Builder.NonVirtualSize;
3429 *
this, Builder.getSize(), Builder.Alignment,
3430 Builder.PreferredAlignment, Builder.UnadjustedAlignment,
3434 NonVirtualSize, Builder.NonVirtualAlignment,
3435 Builder.PreferredNVAlignment,
3436 EmptySubobjects.SizeOfLargestEmptySubobject, Builder.PrimaryBase,
3437 Builder.PrimaryBaseIsVirtual,
nullptr,
false,
false, Builder.Bases,
3440 ItaniumRecordLayoutBuilder Builder(*
this,
nullptr);
3444 *
this, Builder.getSize(), Builder.Alignment,
3445 Builder.PreferredAlignment, Builder.UnadjustedAlignment,
3447 Builder.Alignment, Builder.getSize(), Builder.FieldOffsets);
3451 ASTRecordLayouts[D] = NewEntry;
3453 constexpr uint64_t MaxStructSizeInBytes = 1ULL << 60;
3455 if (
static_cast<uint64_t
>(StructSize.
getQuantity()) >= MaxStructSizeInBytes) {
3457 << D->
getName() << MaxStructSizeInBytes;
3461 llvm::outs() <<
"\n*** Dumping AST Record Layout\n";
3472 assert(RD->
getDefinition() &&
"Cannot get key function for forward decl!");
3486 KeyFunctions[RD] =
const_cast<Decl*
>(
Result);
3488 return cast_or_null<CXXMethodDecl>(
Result);
3493 "not working with method declaration from class definition");
3498 const auto &Map = KeyFunctions;
3499 auto I = Map.find(
Method->getParent());
3502 if (I == Map.end())
return;
3510 KeyFunctions.erase(
Method->getParent());
3520 uint64_t OffsetInBits;
3521 if (
const FieldDecl *FD = dyn_cast<FieldDecl>(VD)) {
3531 return OffsetInBits;
3553 assert(Index < RL->getFieldCount() &&
"Ivar is not inside record layout!");
3570 "Invalid interface decl!");
3576 ItaniumRecordLayoutBuilder Builder(*
this,
nullptr);
3580 *
this, Builder.getSize(), Builder.Alignment, Builder.PreferredAlignment,
3581 Builder.UnadjustedAlignment,
3583 Builder.Alignment, Builder.getDataSize(), Builder.FieldOffsets);
3585 ObjCLayouts[D] = NewEntry;
3592 OS << llvm::format(
"%10" PRId64
" | ", (int64_t)Offset.getQuantity());
3597 unsigned Begin,
unsigned Width,
3601 llvm::raw_svector_ostream BufferOS(Buffer);
3602 BufferOS << Offset.getQuantity() <<
':';
3606 BufferOS << Begin <<
'-' << (Begin + Width - 1);
3610 OS << llvm::right_justify(Buffer, 10) <<
" | ";
3623 const char* Description,
3625 bool IncludeVirtualBases) {
3627 auto CXXRD = dyn_cast<CXXRecordDecl>(RD);
3630 OS <<
C.getCanonicalTagType(
const_cast<RecordDecl *
>(RD));
3632 OS <<
' ' << Description;
3633 if (CXXRD && CXXRD->isEmpty())
3646 if (CXXRD->isDynamicClass() && !PrimaryBase &&
3647 !
C.getTargetInfo().hasMicrosoftRecordLayout()) {
3649 OS <<
'(' << *RD <<
" vtable pointer)\n";
3650 }
else if (HasOwnVFPtr) {
3653 OS <<
'(' << *RD <<
" vftable pointer)\n";
3659 assert(!
Base.getType()->isDependentType() &&
3660 "Cannot layout class with dependent bases.");
3661 if (!
Base.isVirtual())
3662 Bases.push_back(
Base.getType()->getAsCXXRecordDecl());
3675 Base == PrimaryBase ?
"(primary base)" :
"(base)",
3683 OS <<
'(' << *RD <<
" vbtable pointer)\n";
3689 uint64_t LocalFieldOffsetInBits =
3692 Offset +
C.toCharUnitsFromBits(LocalFieldOffsetInBits);
3695 if (
const auto *RD = Field->getType()->getAsRecordDecl()) {
3697 Field->getName().data(),
3703 if (Field->isBitField()) {
3704 uint64_t LocalFieldByteOffsetInBits =
C.toBits(FieldOffset - Offset);
3705 unsigned Begin = LocalFieldOffsetInBits - LocalFieldByteOffsetInBits;
3706 unsigned Width = Field->getBitWidthValue();
3711 const QualType &FieldType =
C.getLangOpts().DumpRecordLayoutsCanonical
3712 ? Field->getType().getCanonicalType()
3714 OS << FieldType <<
' ' << *Field <<
'\n';
3718 if (CXXRD && IncludeVirtualBases) {
3723 assert(
Base.isVirtual() &&
"Found non-virtual class!");
3728 if (VtorDisps.find(VBase)->second.hasVtorDisp()) {
3730 OS <<
"(vtordisp for vbase " << *VBase <<
")\n";
3735 "(primary virtual base)" :
"(virtual base)",
3741 if (!PrintSizeInfo)
return;
3745 if (CXXRD && !
C.getTargetInfo().hasMicrosoftRecordLayout())
3748 if (
C.getTargetInfo().defaultsToAIXPowerAlignment())
3756 if (
C.getTargetInfo().defaultsToAIXPowerAlignment())
3757 OS <<
", preferrednvalign="
3764 bool Simple)
const {
3782 OS <<
"<ASTRecordLayout\n";
3787 if (Target->defaultsToAIXPowerAlignment())
3790 if (
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
3791 OS <<
" BaseOffsets: [";
3793 for (
auto I : CXXRD->bases()) {
3798 Base = I.getType()->getAsCXXRecordDecl();
3799 OS << Info.CXXInfo->BaseOffsets[
Base].getQuantity();
3802 OS <<
" VBaseOffsets: [";
3804 for (
auto I : CXXRD->vbases()) {
3807 VBase = I.getType()->getAsCXXRecordDecl();
3808 OS << Info.CXXInfo->VBaseOffsets[VBase].VBaseOffset.getQuantity();
3812 OS <<
" FieldOffsets: [";
3813 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.
bool isMultipleOf(CharUnits N) const
Test whether this is a multiple of the other value.
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.