20#include "llvm/Support/Format.h"
21#include "llvm/Support/MathExtras.h"
38struct BaseSubobjectInfo {
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;
80 assert(FieldOffsets.count(FD) &&
81 "Field does not have an external offset");
82 return FieldOffsets[FD];
86 auto Known = BaseOffsets.find(RD);
87 if (Known == BaseOffsets.end())
89 BaseOffset = Known->second;
94 auto Known = VirtualBaseOffsets.find(RD);
95 if (Known == VirtualBaseOffsets.end())
97 BaseOffset = Known->second;
104class EmptySubobjectMap {
112 typedef llvm::TinyPtrVector<const CXXRecordDecl *> ClassVectorTy;
113 typedef llvm::DenseMap<CharUnits, ClassVectorTy> EmptyClassOffsetsMapTy;
114 EmptyClassOffsetsMapTy EmptyClassOffsets;
122 void ComputeEmptySubobjectSizes();
126 void UpdateEmptyBaseSubobjects(
const BaseSubobjectInfo *Info,
127 CharUnits Offset,
bool PlacingEmptyBase);
131 bool PlacingOverlappingField);
133 bool PlacingOverlappingField);
137 bool AnyEmptySubobjectsBeyondOffset(
CharUnits Offset)
const {
138 return Offset <= MaxEmptyClassOffset;
144 assert(FieldOffset % CharWidth == 0 &&
145 "Field offset not at char boundary!");
154 bool CanPlaceBaseSubobjectAtOffset(
const BaseSubobjectInfo *Info,
160 bool CanPlaceFieldSubobjectAtOffset(
const FieldDecl *FD,
171 ComputeEmptySubobjectSizes();
178 bool CanPlaceBaseAtOffset(
const BaseSubobjectInfo *Info,
186void EmptySubobjectMap::ComputeEmptySubobjectSizes() {
201 if (EmptySize > SizeOfLargestEmptySubobject)
202 SizeOfLargestEmptySubobject = EmptySize;
225 if (EmptySize > SizeOfLargestEmptySubobject)
226 SizeOfLargestEmptySubobject = EmptySize;
231EmptySubobjectMap::CanPlaceSubobjectAtOffset(
const CXXRecordDecl *RD,
237 EmptyClassOffsetsMapTy::const_iterator I = EmptyClassOffsets.find(Offset);
238 if (I == EmptyClassOffsets.end())
241 const ClassVectorTy &Classes = I->second;
242 if (!llvm::is_contained(Classes, RD))
249void EmptySubobjectMap::AddSubobjectAtOffset(
const CXXRecordDecl *RD,
257 ClassVectorTy &Classes = EmptyClassOffsets[Offset];
258 if (llvm::is_contained(Classes, RD))
261 Classes.push_back(RD);
264 if (Offset > MaxEmptyClassOffset)
265 MaxEmptyClassOffset = Offset;
269EmptySubobjectMap::CanPlaceBaseSubobjectAtOffset(
const BaseSubobjectInfo *Info,
273 if (!AnyEmptySubobjectsBeyondOffset(Offset))
276 if (!CanPlaceSubobjectAtOffset(Info->Class, Offset))
281 for (
const BaseSubobjectInfo *
Base : Info->Bases) {
287 if (!CanPlaceBaseSubobjectAtOffset(
Base, BaseOffset))
291 if (Info->PrimaryVirtualBaseInfo) {
292 BaseSubobjectInfo *PrimaryVirtualBaseInfo = Info->PrimaryVirtualBaseInfo;
294 if (Info == PrimaryVirtualBaseInfo->Derived) {
295 if (!CanPlaceBaseSubobjectAtOffset(PrimaryVirtualBaseInfo, Offset))
301 for (
const FieldDecl *Field : Info->Class->fields()) {
302 if (
Field->isBitField())
306 if (!CanPlaceFieldSubobjectAtOffset(Field, FieldOffset))
313void EmptySubobjectMap::UpdateEmptyBaseSubobjects(
const BaseSubobjectInfo *Info,
315 bool PlacingEmptyBase) {
316 if (!PlacingEmptyBase && Offset >= SizeOfLargestEmptySubobject) {
325 AddSubobjectAtOffset(Info->Class, Offset);
329 for (
const BaseSubobjectInfo *
Base : Info->Bases) {
334 UpdateEmptyBaseSubobjects(
Base, BaseOffset, PlacingEmptyBase);
337 if (Info->PrimaryVirtualBaseInfo) {
338 BaseSubobjectInfo *PrimaryVirtualBaseInfo = Info->PrimaryVirtualBaseInfo;
340 if (Info == PrimaryVirtualBaseInfo->Derived)
341 UpdateEmptyBaseSubobjects(PrimaryVirtualBaseInfo, Offset,
346 for (
const FieldDecl *Field : Info->Class->fields()) {
347 if (
Field->isBitField())
351 UpdateEmptyFieldSubobjects(Field, FieldOffset, PlacingEmptyBase);
355bool EmptySubobjectMap::CanPlaceBaseAtOffset(
const BaseSubobjectInfo *Info,
359 if (SizeOfLargestEmptySubobject.isZero())
362 if (!CanPlaceBaseSubobjectAtOffset(Info, Offset))
367 UpdateEmptyBaseSubobjects(Info, Offset, Info->Class->isEmpty());
372EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(
const CXXRecordDecl *RD,
377 if (!AnyEmptySubobjectsBeyondOffset(Offset))
380 if (!CanPlaceSubobjectAtOffset(RD, Offset))
387 if (
Base.isVirtual())
393 if (!CanPlaceFieldSubobjectAtOffset(BaseDecl, Class, BaseOffset))
403 if (!CanPlaceFieldSubobjectAtOffset(VBaseDecl, Class, VBaseOffset))
410 if (
Field->isBitField())
414 if (!CanPlaceFieldSubobjectAtOffset(Field, FieldOffset))
422EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(
const FieldDecl *FD,
426 if (!AnyEmptySubobjectsBeyondOffset(Offset))
431 return CanPlaceFieldSubobjectAtOffset(RD, RD, Offset);
445 for (uint64_t I = 0; I != NumElements; ++I) {
448 if (!AnyEmptySubobjectsBeyondOffset(ElementOffset))
451 if (!CanPlaceFieldSubobjectAtOffset(RD, RD, ElementOffset))
454 ElementOffset += Layout.
getSize();
461bool EmptySubobjectMap::CanPlaceFieldAtOffset(
const FieldDecl *FD,
463 if (!CanPlaceFieldSubobjectAtOffset(FD, Offset))
468 UpdateEmptyFieldSubobjects(FD, Offset, FD->
hasAttr<NoUniqueAddressAttr>());
472void EmptySubobjectMap::UpdateEmptyFieldSubobjects(
474 bool PlacingOverlappingField) {
485 if (!PlacingOverlappingField && Offset >= SizeOfLargestEmptySubobject)
488 AddSubobjectAtOffset(RD, Offset);
494 if (
Base.isVirtual())
500 UpdateEmptyFieldSubobjects(BaseDecl, Class, BaseOffset,
501 PlacingOverlappingField);
510 UpdateEmptyFieldSubobjects(VBaseDecl, Class, VBaseOffset,
511 PlacingOverlappingField);
517 if (
Field->isBitField())
521 UpdateEmptyFieldSubobjects(Field, FieldOffset, PlacingOverlappingField);
525void EmptySubobjectMap::UpdateEmptyFieldSubobjects(
529 UpdateEmptyFieldSubobjects(RD, RD, Offset, PlacingOverlappingField);
546 for (uint64_t I = 0; I != NumElements; ++I) {
552 if (!PlacingOverlappingField &&
553 ElementOffset >= SizeOfLargestEmptySubobject)
556 UpdateEmptyFieldSubobjects(RD, RD, ElementOffset,
557 PlacingOverlappingField);
558 ElementOffset += Layout.
getSize();
565class ItaniumRecordLayoutBuilder {
572 EmptySubobjectMap *EmptySubobjects;
593 LLVM_PREFERRED_TYPE(
bool)
594 unsigned UseExternalLayout : 1;
598 LLVM_PREFERRED_TYPE(
bool)
599 unsigned InferAlignment : 1;
602 LLVM_PREFERRED_TYPE(
bool)
605 LLVM_PREFERRED_TYPE(
bool)
606 unsigned IsUnion : 1;
608 LLVM_PREFERRED_TYPE(
bool)
609 unsigned IsMac68kAlign : 1;
611 LLVM_PREFERRED_TYPE(
bool)
612 unsigned IsNaturalAlign : 1;
614 LLVM_PREFERRED_TYPE(
bool)
615 unsigned IsMsStruct : 1;
621 unsigned char UnfilledBitsInLastUnit;
625 unsigned char LastBitfieldStorageUnitSize;
648 bool PrimaryBaseIsVirtual;
661 bool HandledFirstNonOverlappingEmptyField;
663 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
666 BaseOffsetsMapTy Bases;
686 ItaniumRecordLayoutBuilder(
const ASTContext &Context,
687 EmptySubobjectMap *EmptySubobjects)
688 : Context(Context), EmptySubobjects(EmptySubobjects),
Size(0),
693 IsMac68kAlign(
false),
694 IsNaturalAlign(!Context.getTargetInfo().getTriple().isOSAIX()),
695 IsMsStruct(
false), UnfilledBitsInLastUnit(0),
696 LastBitfieldStorageUnitSize(0), MaxFieldAlignment(
CharUnits::
Zero()),
701 PrimaryBaseIsVirtual(
false), HasOwnVFPtr(
false), HasPackedField(
false),
702 HandledFirstNonOverlappingEmptyField(
false),
703 FirstNearlyEmptyVBase(nullptr) {}
710 void LayoutField(
const FieldDecl *
D,
bool InsertExtraPadding);
711 void LayoutWideBitField(uint64_t FieldSize, uint64_t StorageUnitSize,
720 llvm::SpecificBumpPtrAllocator<BaseSubobjectInfo> BaseSubobjectInfoAllocator;
722 typedef llvm::DenseMap<const CXXRecordDecl *, BaseSubobjectInfo *>
723 BaseSubobjectInfoMapTy;
731 BaseSubobjectInfoMapTy NonVirtualBaseInfo;
739 BaseSubobjectInfo *ComputeBaseSubobjectInfo(
const CXXRecordDecl *RD,
741 BaseSubobjectInfo *Derived);
748 void EnsureVTablePointerAlignment(
CharUnits UnpackedBaseAlign);
755 void LayoutNonVirtualBase(
const BaseSubobjectInfo *
Base);
757 void AddPrimaryVirtualBaseOffsets(
const BaseSubobjectInfo *Info,
765 void LayoutVirtualBase(
const BaseSubobjectInfo *
Base);
772 void InitializeLayout(
const Decl *
D);
781 UpdateAlignment(NewAlignment, UnpackedNewAlignment, NewAlignment);
783 void UpdateAlignment(
CharUnits NewAlignment) {
784 UpdateAlignment(NewAlignment, NewAlignment, NewAlignment);
793 uint64_t ComputedOffset);
795 void CheckFieldPadding(uint64_t Offset, uint64_t UnpaddedOffset,
796 uint64_t UnpackedOffset,
unsigned UnpackedAlign,
808 void setSize(uint64_t NewSize) {
Size = NewSize; }
810 CharUnits getAlignment()
const {
return Alignment; }
816 uint64_t getDataSizeInBits()
const {
return DataSize; }
818 void setDataSize(
CharUnits NewSize) { DataSize = Context.
toBits(NewSize); }
819 void setDataSize(uint64_t NewSize) { DataSize = NewSize; }
821 ItaniumRecordLayoutBuilder(
const ItaniumRecordLayoutBuilder &) =
delete;
822 void operator=(
const ItaniumRecordLayoutBuilder &) =
delete;
826void ItaniumRecordLayoutBuilder::SelectPrimaryVBase(
const CXXRecordDecl *RD) {
827 for (
const auto &I : RD->
bases()) {
828 assert(!I.getType()->isDependentType() &&
829 "Cannot layout class with dependent bases.");
837 if (!IndirectPrimaryBases.count(
Base)) {
839 PrimaryBaseIsVirtual =
true;
844 if (!FirstNearlyEmptyVBase)
845 FirstNearlyEmptyVBase =
Base;
848 SelectPrimaryVBase(
Base);
855void ItaniumRecordLayoutBuilder::DeterminePrimaryBase(
const CXXRecordDecl *RD) {
867 for (
const auto &I : RD->
bases()) {
874 if (
Base->isDynamicClass()) {
877 PrimaryBaseIsVirtual =
false;
887 SelectPrimaryVBase(RD);
893 if (FirstNearlyEmptyVBase) {
894 PrimaryBase = FirstNearlyEmptyVBase;
895 PrimaryBaseIsVirtual =
true;
899 assert(!PrimaryBase &&
"Should not get here with a primary base!");
902BaseSubobjectInfo *ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo(
903 const CXXRecordDecl *RD,
bool IsVirtual, BaseSubobjectInfo *Derived) {
904 BaseSubobjectInfo *Info;
910 assert(InfoSlot->Class == RD &&
"Wrong class for virtual base info!");
915 InfoSlot =
new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo;
918 Info =
new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo;
922 Info->IsVirtual = IsVirtual;
923 Info->Derived =
nullptr;
924 Info->PrimaryVirtualBaseInfo =
nullptr;
927 BaseSubobjectInfo *PrimaryVirtualBaseInfo =
nullptr;
935 assert(PrimaryVirtualBase &&
"Didn't have a primary virtual base!");
940 if (PrimaryVirtualBaseInfo) {
941 if (PrimaryVirtualBaseInfo->Derived) {
945 PrimaryVirtualBase =
nullptr;
948 Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;
949 PrimaryVirtualBaseInfo->Derived = Info;
956 for (
const auto &I : RD->
bases()) {
957 bool IsVirtual = I.isVirtual();
959 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
961 Info->Bases.push_back(ComputeBaseSubobjectInfo(BaseDecl, IsVirtual, Info));
964 if (PrimaryVirtualBase && !PrimaryVirtualBaseInfo) {
968 assert(PrimaryVirtualBaseInfo &&
969 "Did not create a primary virtual base!");
972 Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;
973 PrimaryVirtualBaseInfo->Derived = Info;
979void ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo(
981 for (
const auto &I : RD->
bases()) {
982 bool IsVirtual = I.isVirtual();
984 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
987 BaseSubobjectInfo *Info = ComputeBaseSubobjectInfo(BaseDecl, IsVirtual,
993 "Did not add virtual base!");
996 assert(!NonVirtualBaseInfo.count(BaseDecl) &&
997 "Non-virtual base already exists!");
998 NonVirtualBaseInfo.insert(std::make_pair(BaseDecl, Info));
1003void ItaniumRecordLayoutBuilder::EnsureVTablePointerAlignment(
1008 if (!MaxFieldAlignment.
isZero()) {
1009 BaseAlign = std::min(BaseAlign, MaxFieldAlignment);
1010 UnpackedBaseAlign = std::min(UnpackedBaseAlign, MaxFieldAlignment);
1014 setSize(getSize().alignTo(BaseAlign));
1017 UpdateAlignment(BaseAlign, UnpackedBaseAlign, BaseAlign);
1020void ItaniumRecordLayoutBuilder::LayoutNonVirtualBases(
1023 DeterminePrimaryBase(RD);
1026 ComputeBaseSubobjectInfo(RD);
1030 if (PrimaryBaseIsVirtual) {
1033 BaseSubobjectInfo *PrimaryBaseInfo =
VirtualBaseInfo.lookup(PrimaryBase);
1034 PrimaryBaseInfo->Derived =
nullptr;
1037 IndirectPrimaryBases.insert(PrimaryBase);
1039 assert(!VisitedVirtualBases.count(PrimaryBase) &&
1040 "vbase already visited!");
1041 VisitedVirtualBases.insert(PrimaryBase);
1043 LayoutVirtualBase(PrimaryBaseInfo);
1045 BaseSubobjectInfo *PrimaryBaseInfo =
1046 NonVirtualBaseInfo.lookup(PrimaryBase);
1047 assert(PrimaryBaseInfo &&
1048 "Did not find base info for non-virtual primary base!");
1050 LayoutNonVirtualBase(PrimaryBaseInfo);
1056 assert(DataSize == 0 &&
"Vtable pointer must be at offset zero!");
1061 EnsureVTablePointerAlignment(PtrAlign);
1064 assert(!IsUnion &&
"Unions cannot be dynamic classes.");
1065 HandledFirstNonOverlappingEmptyField =
true;
1067 setSize(getSize() + PtrWidth);
1068 setDataSize(getSize());
1072 for (
const auto &I : RD->
bases()) {
1078 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
1083 if (BaseDecl == PrimaryBase && !PrimaryBaseIsVirtual)
1087 BaseSubobjectInfo *BaseInfo = NonVirtualBaseInfo.
lookup(BaseDecl);
1088 assert(BaseInfo &&
"Did not find base info for non-virtual base!");
1090 LayoutNonVirtualBase(BaseInfo);
1094void ItaniumRecordLayoutBuilder::LayoutNonVirtualBase(
1095 const BaseSubobjectInfo *
Base) {
1100 assert(!Bases.count(
Base->Class) &&
"base offset already exists!");
1101 Bases.insert(std::make_pair(
Base->Class, Offset));
1103 AddPrimaryVirtualBaseOffsets(
Base, Offset);
1106void ItaniumRecordLayoutBuilder::AddPrimaryVirtualBaseOffsets(
1107 const BaseSubobjectInfo *Info,
CharUnits Offset) {
1109 if (!Info->Class->getNumVBases())
1113 if (Info->PrimaryVirtualBaseInfo) {
1114 assert(Info->PrimaryVirtualBaseInfo->IsVirtual &&
1115 "Primary virtual base is not virtual!");
1116 if (Info->PrimaryVirtualBaseInfo->Derived == Info) {
1118 assert(!VBases.count(Info->PrimaryVirtualBaseInfo->Class) &&
1119 "primary vbase offset already exists!");
1120 VBases.insert(std::make_pair(Info->PrimaryVirtualBaseInfo->Class,
1124 AddPrimaryVirtualBaseOffsets(Info->PrimaryVirtualBaseInfo, Offset);
1130 for (
const BaseSubobjectInfo *
Base : Info->Bases) {
1131 if (
Base->IsVirtual)
1135 AddPrimaryVirtualBaseOffsets(
Base, BaseOffset);
1139void ItaniumRecordLayoutBuilder::LayoutVirtualBases(
1142 bool PrimaryBaseIsVirtual;
1144 if (MostDerivedClass == RD) {
1145 PrimaryBase = this->PrimaryBase;
1146 PrimaryBaseIsVirtual = this->PrimaryBaseIsVirtual;
1154 assert(!
Base.getType()->isDependentType() &&
1155 "Cannot layout class with dependent bases.");
1159 if (
Base.isVirtual()) {
1160 if (PrimaryBase != BaseDecl || !PrimaryBaseIsVirtual) {
1161 bool IndirectPrimaryBase = IndirectPrimaryBases.count(BaseDecl);
1164 if (!IndirectPrimaryBase) {
1166 if (!VisitedVirtualBases.insert(BaseDecl).second)
1170 assert(BaseInfo &&
"Did not find virtual base info!");
1171 LayoutVirtualBase(BaseInfo);
1181 LayoutVirtualBases(BaseDecl, MostDerivedClass);
1185void ItaniumRecordLayoutBuilder::LayoutVirtualBase(
1186 const BaseSubobjectInfo *
Base) {
1187 assert(!
Base->Derived &&
"Trying to lay out a primary virtual base!");
1193 assert(!VBases.count(
Base->Class) &&
"vbase offset already exists!");
1194 VBases.insert(std::make_pair(
Base->Class,
1197 AddPrimaryVirtualBaseOffsets(
Base, Offset);
1201ItaniumRecordLayoutBuilder::LayoutBase(
const BaseSubobjectInfo *
Base) {
1202 assert(!IsUnion &&
"Unions cannot have base classes.");
1208 bool HasExternalLayout =
false;
1209 if (UseExternalLayout) {
1210 if (
Base->IsVirtual)
1211 HasExternalLayout =
External.getExternalVBaseOffset(
Base->Class, Offset);
1213 HasExternalLayout =
External.getExternalNVBaseOffset(
Base->Class, Offset);
1216 auto getBaseOrPreferredBaseAlignFromUnpacked = [&](
CharUnits UnpackedAlign) {
1219 return (Packed && ((Context.
getLangOpts().getClangABICompat() <=
1230 getBaseOrPreferredBaseAlignFromUnpacked(UnpackedBaseAlign);
1232 getBaseOrPreferredBaseAlignFromUnpacked(UnpackedPreferredBaseAlign);
1234 const bool DefaultsToAIXPowerAlignment =
1236 if (DefaultsToAIXPowerAlignment) {
1241 if (!
Base->Class->isEmpty() && !HandledFirstNonOverlappingEmptyField) {
1244 HandledFirstNonOverlappingEmptyField =
true;
1245 }
else if (!IsNaturalAlign) {
1246 UnpackedPreferredBaseAlign = UnpackedBaseAlign;
1247 PreferredBaseAlign = BaseAlign;
1251 CharUnits UnpackedAlignTo = !DefaultsToAIXPowerAlignment
1253 : UnpackedPreferredBaseAlign;
1255 if (
Base->Class->isEmpty() &&
1258 setSize(std::max(getSize(), Layout.
getSize()));
1261 UpdateAlignment(BaseAlign, UnpackedAlignTo, PreferredBaseAlign);
1268 if (!MaxFieldAlignment.
isZero()) {
1269 BaseAlign = std::min(BaseAlign, MaxFieldAlignment);
1270 PreferredBaseAlign = std::min(PreferredBaseAlign, MaxFieldAlignment);
1271 UnpackedAlignTo = std::min(UnpackedAlignTo, MaxFieldAlignment);
1275 !DefaultsToAIXPowerAlignment ? BaseAlign : PreferredBaseAlign;
1276 if (!HasExternalLayout) {
1278 Offset = getDataSize().alignTo(AlignTo);
1281 while (!EmptySubobjects->CanPlaceBaseAtOffset(
Base, Offset))
1284 bool Allowed = EmptySubobjects->CanPlaceBaseAtOffset(
Base, Offset);
1286 assert(Allowed &&
"Base subobject externally placed at overlapping offset");
1288 if (InferAlignment && Offset < getDataSize().alignTo(AlignTo)) {
1292 InferAlignment =
false;
1296 if (!
Base->Class->isEmpty()) {
1300 setSize(std::max(getSize(), getDataSize()));
1302 setSize(std::max(getSize(), Offset + Layout.
getSize()));
1305 UpdateAlignment(BaseAlign, UnpackedAlignTo, PreferredBaseAlign);
1310void ItaniumRecordLayoutBuilder::InitializeLayout(
const Decl *
D) {
1311 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(
D)) {
1319 if (
unsigned DefaultMaxFieldAlignment = Context.
getLangOpts().PackStruct) {
1327 if (
D->
hasAttr<AlignMac68kAttr>()) {
1330 "Having both mac68k and natural alignment on a decl is not allowed.");
1331 IsMac68kAlign =
true;
1336 if (
D->
hasAttr<AlignNaturalAttr>())
1337 IsNaturalAlign =
true;
1339 if (
const MaxFieldAlignmentAttr *MFAA =
D->
getAttr<MaxFieldAlignmentAttr>())
1346 HandledFirstNonOverlappingEmptyField =
1350 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(
D))
1352 UseExternalLayout = Source->layoutRecordType(
1357 if (UseExternalLayout) {
1363 InferAlignment =
true;
1369void ItaniumRecordLayoutBuilder::Layout(
const RecordDecl *
D) {
1370 InitializeLayout(
D);
1378void ItaniumRecordLayoutBuilder::Layout(
const CXXRecordDecl *RD) {
1379 InitializeLayout(RD);
1382 LayoutNonVirtualBases(RD);
1388 NonVirtualAlignment = Alignment;
1389 PreferredNVAlignment = PreferredAlignment;
1392 LayoutVirtualBases(RD, RD);
1401 if (
Base.isVirtual())
1406 assert(Bases.count(BaseDecl) &&
"Did not find base offset!");
1413 assert(VBases.count(BaseDecl) &&
"Did not find base offset!");
1427 setSize(getDataSize());
1430 InitializeLayout(
D);
1432 for (
const ObjCIvarDecl *IVD =
D->all_declared_ivar_begin(); IVD;
1433 IVD = IVD->getNextIvar())
1434 LayoutField(IVD,
false);
1441void ItaniumRecordLayoutBuilder::LayoutFields(
const RecordDecl *
D) {
1444 bool InsertExtraPadding =
D->mayInsertExtraPadding(
true);
1445 bool HasFlexibleArrayMember =
D->hasFlexibleArrayMember();
1446 for (
auto I =
D->field_begin(), End =
D->field_end(); I != End; ++I) {
1447 LayoutField(*I, InsertExtraPadding &&
1448 (std::next(I) != End || !HasFlexibleArrayMember));
1457 return llvm::alignTo(Size, CharAlignment);
1460void ItaniumRecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize,
1461 uint64_t StorageUnitSize,
1465 "Can only have wide bit-fields in C++!");
1477 for (
const QualType &QT : IntegralPODTypes) {
1480 if (Size > FieldSize)
1485 assert(!
Type.isNull() &&
"Did not find a type!");
1490 UnfilledBitsInLastUnit = 0;
1491 LastBitfieldStorageUnitSize = 0;
1494 uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;
1499 setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize));
1504 FieldOffset = llvm::alignTo(getDataSizeInBits(), Context.
toBits(TypeAlign));
1506 uint64_t NewSizeInBits = FieldOffset + FieldSize;
1510 UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits;
1514 FieldOffsets.push_back(FieldOffset);
1516 CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, FieldOffset,
1517 Context.
toBits(TypeAlign), FieldPacked,
D);
1520 setSize(std::max(getSizeInBits(), getDataSizeInBits()));
1523 UpdateAlignment(TypeAlign);
1530void ItaniumRecordLayoutBuilder::LayoutBitField(
const FieldDecl *
D) {
1531 bool FieldPacked = Packed ||
D->
hasAttr<PackedAttr>();
1532 uint64_t FieldSize =
D->getBitWidthValue();
1535 unsigned FieldAlign = FieldInfo.
Align;
1598 FieldAlign = StorageUnitSize;
1603 if (LastBitfieldStorageUnitSize != StorageUnitSize ||
1604 UnfilledBitsInLastUnit < FieldSize) {
1606 if (!LastBitfieldStorageUnitSize && !FieldSize)
1609 UnfilledBitsInLastUnit = 0;
1610 LastBitfieldStorageUnitSize = 0;
1624 StorageUnitSize = 32;
1626 if (!AlignIsRequired)
1630 if (FieldAlign < StorageUnitSize) {
1633 FieldAlign = StorageUnitSize;
1640 if (FieldSize > StorageUnitSize && !
isAIXLayout(Context)) {
1641 LayoutWideBitField(FieldSize, StorageUnitSize, FieldPacked,
D);
1647 IsUnion ? 0 : (getDataSizeInBits() - UnfilledBitsInLastUnit);
1652 if (FieldSize == 0 &&
1655 if (!IsUnion && FieldOffset == 0 &&
1661 unsigned ZeroLengthBitfieldBoundary =
1663 FieldAlign = std::max(FieldAlign, ZeroLengthBitfieldBoundary);
1672 unsigned UnpackedFieldAlign = FieldAlign;
1675 if (!IsMsStruct && FieldPacked && FieldSize != 0)
1680 if (ExplicitFieldAlign) {
1681 FieldAlign = std::max(FieldAlign, ExplicitFieldAlign);
1682 UnpackedFieldAlign = std::max(UnpackedFieldAlign, ExplicitFieldAlign);
1687 unsigned MaxFieldAlignmentInBits = Context.
toBits(MaxFieldAlignment);
1688 if (!MaxFieldAlignment.
isZero() && FieldSize) {
1689 UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits);
1691 FieldAlign = UnpackedFieldAlign;
1693 FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits);
1698 if (IsMsStruct && IsUnion) {
1699 FieldAlign = UnpackedFieldAlign = 1;
1705 uint64_t UnpaddedFieldOffset = FieldOffset;
1706 uint64_t UnpackedFieldOffset = FieldOffset;
1716 if (FieldSize == 0 || FieldSize > UnfilledBitsInLastUnit) {
1717 FieldOffset = llvm::alignTo(FieldOffset, FieldAlign);
1718 UnpackedFieldOffset =
1719 llvm::alignTo(UnpackedFieldOffset, UnpackedFieldAlign);
1720 UnfilledBitsInLastUnit = 0;
1725 bool AllowPadding = MaxFieldAlignment.
isZero();
1728 if (FieldSize == 0 ||
1730 (FieldOffset & (FieldAlign - 1)) + FieldSize > StorageUnitSize)) {
1731 FieldOffset = llvm::alignTo(FieldOffset, FieldAlign);
1732 }
else if (ExplicitFieldAlign &&
1733 (MaxFieldAlignmentInBits == 0 ||
1734 ExplicitFieldAlign <= MaxFieldAlignmentInBits) &&
1738 FieldOffset = llvm::alignTo(FieldOffset, ExplicitFieldAlign);
1742 if (FieldSize == 0 ||
1744 (UnpackedFieldOffset & (UnpackedFieldAlign - 1)) + FieldSize >
1746 UnpackedFieldOffset =
1747 llvm::alignTo(UnpackedFieldOffset, UnpackedFieldAlign);
1748 else if (ExplicitFieldAlign &&
1749 (MaxFieldAlignmentInBits == 0 ||
1750 ExplicitFieldAlign <= MaxFieldAlignmentInBits) &&
1752 UnpackedFieldOffset =
1753 llvm::alignTo(UnpackedFieldOffset, ExplicitFieldAlign);
1758 if (UseExternalLayout)
1759 FieldOffset = updateExternalFieldOffset(
D, FieldOffset);
1762 FieldOffsets.push_back(FieldOffset);
1770 !
D->getIdentifier())
1771 FieldAlign = UnpackedFieldAlign = 1;
1779 if (!MaxFieldAlignment.
isZero()) {
1780 UnpackedFieldAlign =
1781 std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits);
1782 FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits);
1787 if (!UseExternalLayout)
1788 CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, UnpackedFieldOffset,
1789 UnpackedFieldAlign, FieldPacked,
D);
1799 RoundedFieldSize = (FieldSize ? StorageUnitSize
1807 setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize));
1811 }
else if (IsMsStruct && FieldSize) {
1814 if (!UnfilledBitsInLastUnit) {
1815 setDataSize(FieldOffset + StorageUnitSize);
1816 UnfilledBitsInLastUnit = StorageUnitSize;
1818 UnfilledBitsInLastUnit -= FieldSize;
1819 LastBitfieldStorageUnitSize = StorageUnitSize;
1825 uint64_t NewSizeInBits = FieldOffset + FieldSize;
1827 setDataSize(llvm::alignTo(NewSizeInBits, CharAlignment));
1828 UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits;
1833 LastBitfieldStorageUnitSize = 0;
1837 setSize(std::max(getSizeInBits(), getDataSizeInBits()));
1840 UnadjustedAlignment =
1846void ItaniumRecordLayoutBuilder::LayoutField(
const FieldDecl *
D,
1847 bool InsertExtraPadding) {
1848 auto *FieldClass =
D->getType()->getAsCXXRecordDecl();
1849 bool IsOverlappingEmptyField =
1850 D->isPotentiallyOverlapping() && FieldClass->isEmpty();
1853 (IsUnion || IsOverlappingEmptyField) ?
CharUnits::Zero() : getDataSize();
1855 const bool DefaultsToAIXPowerAlignment =
1857 bool FoundFirstNonOverlappingEmptyFieldForAIX =
false;
1858 if (DefaultsToAIXPowerAlignment && !HandledFirstNonOverlappingEmptyField) {
1860 "The first non-overlapping empty field should have been handled.");
1862 if (!IsOverlappingEmptyField) {
1863 FoundFirstNonOverlappingEmptyFieldForAIX =
true;
1870 HandledFirstNonOverlappingEmptyField = !IsUnion;
1874 if (
D->isBitField()) {
1879 uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;
1881 UnfilledBitsInLastUnit = 0;
1882 LastBitfieldStorageUnitSize = 0;
1894 auto setDeclInfo = [&](
bool IsIncompleteArrayType) {
1896 FieldAlign = TI.Align;
1899 EffectiveFieldSize = FieldSize =
1901 AlignRequirement = TI.AlignRequirement;
1904 if (
D->getType()->isIncompleteArrayType()) {
1907 setDeclInfo(
false );
1911 if (
D->isPotentiallyOverlapping()) {
1913 EffectiveFieldSize =
1927 if (!llvm::isPowerOf2_64(TypeSize.
getQuantity())) {
1930 "Non PowerOf2 size in MSVC mode");
1952 if (TypeSize > FieldAlign &&
1954 FieldAlign = TypeSize;
1959 bool FieldPacked = (Packed && (!FieldClass || FieldClass->isPOD() ||
1960 FieldClass->hasAttr<PackedAttr>() ||
1971 auto alignedAttrCanDecreaseAIXAlignment = [AlignRequirement, FieldPacked] {
1990 if (DefaultsToAIXPowerAlignment && !alignedAttrCanDecreaseAIXAlignment() &&
1991 (FoundFirstNonOverlappingEmptyFieldForAIX || IsNaturalAlign)) {
1992 auto performBuiltinTypeAlignmentUpgrade = [&](
const BuiltinType *BTy) {
1993 if (BTy->getKind() == BuiltinType::Double ||
1994 BTy->getKind() == BuiltinType::LongDouble) {
1996 "No need to upgrade the alignment value.");
2001 const Type *BaseTy =
D->getType()->getBaseElementTypeUnsafe();
2003 performBuiltinTypeAlignmentUpgrade(
2006 performBuiltinTypeAlignmentUpgrade(BTy);
2009 assert(RD &&
"Expected non-null RecordDecl.");
2017 CharUnits UnpackedFieldAlign = FieldAlign;
2019 CharUnits UnpackedFieldOffset = FieldOffset;
2020 CharUnits OriginalFieldAlign = UnpackedFieldAlign;
2024 PackedFieldAlign = std::max(PackedFieldAlign, MaxAlignmentInChars);
2025 PreferredAlign = std::max(PreferredAlign, MaxAlignmentInChars);
2026 UnpackedFieldAlign = std::max(UnpackedFieldAlign, MaxAlignmentInChars);
2029 if (!MaxFieldAlignment.
isZero()) {
2030 PackedFieldAlign = std::min(PackedFieldAlign, MaxFieldAlignment);
2031 PreferredAlign = std::min(PreferredAlign, MaxFieldAlignment);
2032 UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignment);
2037 FieldAlign = UnpackedFieldAlign;
2038 if (DefaultsToAIXPowerAlignment)
2039 UnpackedFieldAlign = PreferredAlign;
2041 PreferredAlign = PackedFieldAlign;
2042 FieldAlign = PackedFieldAlign;
2046 !DefaultsToAIXPowerAlignment ? FieldAlign : PreferredAlign;
2048 FieldOffset = FieldOffset.
alignTo(AlignTo);
2049 UnpackedFieldOffset = UnpackedFieldOffset.
alignTo(UnpackedFieldAlign);
2051 if (UseExternalLayout) {
2053 updateExternalFieldOffset(
D, Context.
toBits(FieldOffset)));
2055 if (!IsUnion && EmptySubobjects) {
2057 bool Allowed = EmptySubobjects->CanPlaceFieldAtOffset(
D, FieldOffset);
2059 assert(Allowed &&
"Externally-placed field cannot be placed here");
2062 if (!IsUnion && EmptySubobjects) {
2064 while (!EmptySubobjects->CanPlaceFieldAtOffset(
D, FieldOffset)) {
2069 FieldOffset = getDataSize().
alignTo(AlignTo);
2071 FieldOffset += AlignTo;
2077 FieldOffsets.push_back(Context.
toBits(FieldOffset));
2079 if (!UseExternalLayout)
2080 CheckFieldPadding(Context.
toBits(FieldOffset), UnpaddedFieldOffset,
2081 Context.
toBits(UnpackedFieldOffset),
2082 Context.
toBits(UnpackedFieldAlign), FieldPacked,
D);
2084 if (InsertExtraPadding) {
2086 CharUnits ExtraSizeForAsan = ASanAlignment;
2087 if (FieldSize % ASanAlignment)
2090 EffectiveFieldSize = FieldSize = FieldSize + ExtraSizeForAsan;
2094 if (!IsOverlappingEmptyField) {
2095 uint64_t EffectiveFieldSizeInBits = Context.
toBits(EffectiveFieldSize);
2097 setDataSize(std::max(getDataSizeInBits(), EffectiveFieldSizeInBits));
2099 setDataSize(FieldOffset + EffectiveFieldSize);
2101 PaddedFieldSize = std::max(PaddedFieldSize, FieldOffset + FieldSize);
2102 setSize(std::max(getSizeInBits(), getDataSizeInBits()));
2104 setSize(std::max(getSizeInBits(),
2105 (uint64_t)Context.
toBits(FieldOffset + FieldSize)));
2109 UnadjustedAlignment = std::max(UnadjustedAlignment, FieldAlign);
2110 UpdateAlignment(FieldAlign, UnpackedFieldAlign, PreferredAlign);
2116 if (RD->
hasAttr<PackedAttr>() || !MaxFieldAlignment.
isZero())
2117 if (FieldAlign < OriginalFieldAlign)
2118 if (
D->getType()->isRecordType()) {
2122 if (FieldOffset % OriginalFieldAlign != 0)
2128 if (Packed && !FieldPacked && PackedFieldAlign < FieldAlign)
2132void ItaniumRecordLayoutBuilder::FinishLayout(
const NamedDecl *
D) {
2134 if (Context.
getLangOpts().CPlusPlus && getSizeInBits() == 0) {
2148 setSize(std::max(getSizeInBits(), (uint64_t)Context.
toBits(PaddedFieldSize)));
2152 uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastUnit;
2154 llvm::alignTo(getSizeInBits(), Context.
toBits(UnpackedAlignment));
2156 uint64_t RoundedSize = llvm::alignTo(
2160 : PreferredAlignment));
2162 if (UseExternalLayout) {
2166 if (InferAlignment &&
External.Size < RoundedSize) {
2169 InferAlignment =
false;
2176 setSize(RoundedSize);
2179 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(
D)) {
2181 if (getSizeInBits() > UnpaddedSize) {
2182 unsigned PadSize = getSizeInBits() - UnpaddedSize;
2184 if (PadSize % CharBitNum == 0) {
2185 PadSize = PadSize / CharBitNum;
2191 << (InBits ? 1 : 0);
2194 const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD);
2202 if (Packed && UnpackedAlignment <= Alignment &&
2203 UnpackedSizeInBits == getSizeInBits() && !HasPackedField &&
2204 (!CXXRD || CXXRD->isPOD() ||
2212void ItaniumRecordLayoutBuilder::UpdateAlignment(
2217 if (IsMac68kAlign || (UseExternalLayout && !InferAlignment))
2220 if (NewAlignment > Alignment) {
2221 assert(llvm::isPowerOf2_64(NewAlignment.
getQuantity()) &&
2222 "Alignment not a power of 2");
2223 Alignment = NewAlignment;
2226 if (UnpackedNewAlignment > UnpackedAlignment) {
2227 assert(llvm::isPowerOf2_64(UnpackedNewAlignment.
getQuantity()) &&
2228 "Alignment not a power of 2");
2229 UnpackedAlignment = UnpackedNewAlignment;
2232 if (PreferredNewAlignment > PreferredAlignment) {
2233 assert(llvm::isPowerOf2_64(PreferredNewAlignment.
getQuantity()) &&
2234 "Alignment not a power of 2");
2235 PreferredAlignment = PreferredNewAlignment;
2240ItaniumRecordLayoutBuilder::updateExternalFieldOffset(
const FieldDecl *Field,
2241 uint64_t ComputedOffset) {
2244 if (InferAlignment && ExternalFieldOffset < ComputedOffset) {
2249 InferAlignment =
false;
2253 return ExternalFieldOffset;
2269 default: llvm_unreachable(
"Invalid tag kind for field padding diagnostic!");
2273void ItaniumRecordLayoutBuilder::CheckFieldPadding(
2274 uint64_t Offset, uint64_t UnpaddedOffset, uint64_t UnpackedOffset,
2275 unsigned UnpackedAlign,
bool isPacked,
const FieldDecl *
D) {
2278 if (isa<ObjCIvarDecl>(
D))
2289 if (!IsUnion && Offset > UnpaddedOffset) {
2290 unsigned PadSize = Offset - UnpaddedOffset;
2292 if (PadSize % CharBitNum == 0) {
2293 PadSize = PadSize / CharBitNum;
2296 if (
D->getIdentifier()) {
2297 auto Diagnostic =
D->isBitField() ? diag::warn_padded_struct_bitfield
2298 : diag::warn_padded_struct_field;
2303 <<
D->getIdentifier();
2305 auto Diagnostic =
D->isBitField() ? diag::warn_padded_struct_anon_bitfield
2306 : diag::warn_padded_struct_anon_field;
2310 << (InBits ? 1 : 0);
2313 if (isPacked && Offset != UnpackedOffset) {
2314 HasPackedField =
true;
2338 bool allowInlineFunctions =
2342 if (!MD->isVirtual())
2345 if (MD->isPureVirtual())
2350 if (MD->isImplicit())
2353 if (MD->isInlineSpecified() || MD->isConstexpr())
2356 if (MD->hasInlineBody())
2360 if (!MD->isUserProvided())
2364 if (!allowInlineFunctions) {
2376 if (!MD->hasAttr<CUDADeviceAttr>())
2380 if (!MD->hasAttr<CUDAHostAttr>() && MD->hasAttr<CUDADeviceAttr>())
2388 if (MD->hasAttr<DLLImportAttr>() && !RD->
hasAttr<DLLImportAttr>() &&
2443 llvm_unreachable(
"bad tail-padding use kind");
2546struct MicrosoftRecordLayoutBuilder {
2547 struct ElementInfo {
2551 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
2552 MicrosoftRecordLayoutBuilder(
const ASTContext &Context,
2553 EmptySubobjectMap *EmptySubobjects)
2554 : Context(Context), EmptySubobjects(EmptySubobjects) {}
2557 MicrosoftRecordLayoutBuilder(
const MicrosoftRecordLayoutBuilder &) =
delete;
2558 void operator=(
const MicrosoftRecordLayoutBuilder &) =
delete;
2579 void layoutBitField(
const FieldDecl *FD);
2582 void layoutZeroWidthBitField(
const FieldDecl *FD);
2591 ElementInfo getAdjustedElementInfo(
const FieldDecl *FD);
2593 void placeFieldAtOffset(
CharUnits FieldOffset) {
2594 FieldOffsets.push_back(Context.
toBits(FieldOffset));
2597 void placeFieldAtBitOffset(uint64_t FieldOffset) {
2598 FieldOffsets.push_back(FieldOffset);
2601 void computeVtorDispSet(
2602 llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtorDispSet,
2605 EmptySubobjectMap *EmptySubobjects;
2629 ElementInfo PointerInfo;
2637 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(
2675 if (!MaxFieldAlignment.
isZero())
2676 Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment);
2682 Alignment = std::max(Alignment, Info.Alignment);
2689MicrosoftRecordLayoutBuilder::ElementInfo
2690MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
2696 ElementInfo Info{TInfo.
Width, TInfo.Align};
2702 FieldRequiredAlignment = std::max(
2708 Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment);
2714 FieldRequiredAlignment = std::max(FieldRequiredAlignment,
2718 RequiredAlignment = std::max(RequiredAlignment, FieldRequiredAlignment);
2721 if (!MaxFieldAlignment.
isZero())
2722 Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment);
2723 if (FD->
hasAttr<PackedAttr>())
2725 Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment);
2729void MicrosoftRecordLayoutBuilder::layout(
const RecordDecl *RD) {
2732 initializeLayout(RD);
2734 DataSize =
Size =
Size.alignTo(Alignment);
2735 RequiredAlignment = std::max(
2740void MicrosoftRecordLayoutBuilder::cxxLayout(
const CXXRecordDecl *RD) {
2743 initializeLayout(RD);
2744 initializeCXXLayout(RD);
2745 layoutNonVirtualBases(RD);
2749 if (HasOwnVFPtr || (HasVBPtr && !SharedVBPtrBase))
2750 Alignment = std::max(Alignment, PointerInfo.Alignment);
2751 auto RoundingAlignment = Alignment;
2752 if (!MaxFieldAlignment.
isZero())
2753 RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment);
2754 if (!UseExternalLayout)
2755 Size =
Size.alignTo(RoundingAlignment);
2756 NonVirtualSize =
Size;
2757 RequiredAlignment = std::max(
2759 layoutVirtualBases(RD);
2763void MicrosoftRecordLayoutBuilder::initializeLayout(
const RecordDecl *RD) {
2776 if (
unsigned DefaultMaxFieldAlignment = Context.
getLangOpts().PackStruct)
2780 if (
const MaxFieldAlignmentAttr *MFAA = RD->
getAttr<MaxFieldAlignmentAttr>()){
2781 unsigned PackedAlignment = MFAA->getAlignment();
2782 if (PackedAlignment <=
2787 if (RD->
hasAttr<PackedAttr>())
2791 UseExternalLayout =
false;
2793 UseExternalLayout = Source->layoutRecordType(
2799MicrosoftRecordLayoutBuilder::initializeCXXLayout(
const CXXRecordDecl *RD) {
2800 EndsWithZeroSizedObject =
false;
2801 LeadsWithZeroSizedBase =
false;
2802 HasOwnVFPtr =
false;
2804 PrimaryBase =
nullptr;
2805 SharedVBPtrBase =
nullptr;
2813 if (!MaxFieldAlignment.
isZero())
2814 PointerInfo.Alignment = std::min(PointerInfo.Alignment, MaxFieldAlignment);
2818MicrosoftRecordLayoutBuilder::layoutNonVirtualBases(
const CXXRecordDecl *RD) {
2826 bool HasPolymorphicBaseClass =
false;
2833 if (
Base.isVirtual()) {
2838 if (!SharedVBPtrBase && BaseLayout.
hasVBPtr()) {
2839 SharedVBPtrBase = BaseDecl;
2847 PrimaryBase = BaseDecl;
2851 layoutNonVirtualBase(RD, BaseDecl, BaseLayout, PreviousBaseLayout);
2855 if (!HasPolymorphicBaseClass)
2859 else if (!PrimaryBase) {
2863 if (MicrosoftVTableContext::hasVtableSlot(M) &&
2864 M->size_overridden_methods() == 0) {
2873 bool CheckLeadingLayout = !PrimaryBase;
2876 if (
Base.isVirtual())
2887 if (CheckLeadingLayout) {
2888 CheckLeadingLayout =
false;
2892 layoutNonVirtualBase(RD, BaseDecl, BaseLayout, PreviousBaseLayout);
2898 else if (SharedVBPtrBase) {
2905 if (!isa<CXXRecordDecl>(RD))
2907 if (RD->
hasAttr<EmptyBasesAttr>())
2909 if (
auto *LVA = RD->
getAttr<LayoutVersionAttr>())
2911 if (LVA->getVersion() <= LangOptions::MSVC2015)
2919void MicrosoftRecordLayoutBuilder::layoutNonVirtualBase(
2930 ElementInfo Info = getAdjustedElementInfo(BaseLayout);
2934 bool FoundBase =
false;
2935 if (UseExternalLayout) {
2936 FoundBase =
External.getExternalNVBaseOffset(BaseDecl, BaseOffset);
2937 if (BaseOffset > Size) {
2943 if (MDCUsesEBO && BaseDecl->
isEmpty() &&
2948 BaseOffset =
Size =
Size.alignTo(Info.Alignment);
2951 Bases.insert(std::make_pair(BaseDecl, BaseOffset));
2954 PreviousBaseLayout = &BaseLayout;
2957void MicrosoftRecordLayoutBuilder::layoutFields(
const RecordDecl *RD) {
2958 LastFieldIsNonZeroWidthBitfield =
false;
2963void MicrosoftRecordLayoutBuilder::layoutField(
const FieldDecl *FD) {
2968 LastFieldIsNonZeroWidthBitfield =
false;
2969 ElementInfo Info = getAdjustedElementInfo(FD);
2970 Alignment = std::max(Alignment, Info.Alignment);
2975 FieldClass->
fields().empty();
2978 if (UseExternalLayout) {
2981 }
else if (IsUnion) {
2983 }
else if (EmptySubobjects) {
2984 if (!IsOverlappingEmptyField)
2985 FieldOffset = DataSize.
alignTo(Info.Alignment);
2987 while (!EmptySubobjects->CanPlaceFieldAtOffset(FD, FieldOffset)) {
2989 bool HasBases = ParentClass && (!ParentClass->
bases().empty() ||
2990 !ParentClass->
vbases().empty());
2995 FieldOffset = DataSize.
alignTo(Info.Alignment);
2997 FieldOffset += Info.Alignment;
3001 FieldOffset =
Size.alignTo(Info.Alignment);
3003 placeFieldAtOffset(FieldOffset);
3005 if (!IsOverlappingEmptyField)
3006 DataSize = std::max(DataSize, FieldOffset + Info.Size);
3008 Size = std::max(Size, FieldOffset + Info.Size);
3011void MicrosoftRecordLayoutBuilder::layoutBitField(
const FieldDecl *FD) {
3014 layoutZeroWidthBitField(FD);
3017 ElementInfo Info = getAdjustedElementInfo(FD);
3020 if (Width > Context.
toBits(Info.Size))
3021 Width = Context.
toBits(Info.Size);
3025 if (!UseExternalLayout && !IsUnion && LastFieldIsNonZeroWidthBitfield &&
3026 CurrentBitfieldSize == Info.Size && Width <= RemainingBitsInField) {
3027 placeFieldAtBitOffset(Context.
toBits(Size) - RemainingBitsInField);
3028 RemainingBitsInField -= Width;
3031 LastFieldIsNonZeroWidthBitfield =
true;
3032 CurrentBitfieldSize = Info.Size;
3033 if (UseExternalLayout) {
3034 auto FieldBitOffset =
External.getExternalFieldOffset(FD);
3035 placeFieldAtBitOffset(FieldBitOffset);
3037 llvm::alignDown(FieldBitOffset, Context.
toBits(Info.Alignment)) +
3038 Context.
toBits(Info.Size));
3039 Size = std::max(Size, NewSize);
3040 Alignment = std::max(Alignment, Info.Alignment);
3041 }
else if (IsUnion) {
3043 Size = std::max(Size, Info.Size);
3048 placeFieldAtOffset(FieldOffset);
3049 Size = FieldOffset + Info.Size;
3050 Alignment = std::max(Alignment, Info.Alignment);
3051 RemainingBitsInField = Context.
toBits(Info.Size) - Width;
3057MicrosoftRecordLayoutBuilder::layoutZeroWidthBitField(
const FieldDecl *FD) {
3060 if (!LastFieldIsNonZeroWidthBitfield) {
3066 LastFieldIsNonZeroWidthBitfield =
false;
3067 ElementInfo Info = getAdjustedElementInfo(FD);
3070 Size = std::max(Size, Info.Size);
3075 placeFieldAtOffset(FieldOffset);
3077 Alignment = std::max(Alignment, Info.Alignment);
3082void MicrosoftRecordLayoutBuilder::injectVBPtr(
const CXXRecordDecl *RD) {
3083 if (!HasVBPtr || SharedVBPtrBase)
3088 VBPtrOffset = VBPtrOffset.
alignTo(PointerInfo.Alignment);
3090 CharUnits FieldStart = VBPtrOffset + PointerInfo.Size;
3093 if (UseExternalLayout) {
3096 if (Size < FieldStart)
3102 CharUnits Offset = (FieldStart - InjectionSite)
3103 .alignTo(std::max(RequiredAlignment, Alignment));
3105 for (uint64_t &FieldOffset : FieldOffsets)
3106 FieldOffset += Context.
toBits(Offset);
3107 for (BaseOffsetsMapTy::value_type &
Base : Bases)
3108 if (
Base.second >= InjectionSite)
3109 Base.second += Offset;
3112void MicrosoftRecordLayoutBuilder::injectVFPtr(
const CXXRecordDecl *RD) {
3118 PointerInfo.Size.alignTo(std::max(RequiredAlignment, Alignment));
3122 VBPtrOffset += Offset;
3124 if (UseExternalLayout) {
3136 for (uint64_t &FieldOffset : FieldOffsets)
3137 FieldOffset += Context.
toBits(Offset);
3138 for (BaseOffsetsMapTy::value_type &
Base : Bases)
3139 Base.second += Offset;
3142void MicrosoftRecordLayoutBuilder::layoutVirtualBases(
const CXXRecordDecl *RD) {
3147 CharUnits VtorDispAlignment = VtorDispSize;
3149 if (!MaxFieldAlignment.
isZero())
3150 VtorDispAlignment = std::min(VtorDispAlignment, MaxFieldAlignment);
3155 const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl();
3160 VtorDispAlignment = std::max(VtorDispAlignment, RequiredAlignment);
3163 computeVtorDispSet(HasVtorDispSet, RD);
3167 const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl();
3169 bool HasVtordisp = HasVtorDispSet.contains(BaseDecl);
3178 Size =
Size.alignTo(VtorDispAlignment) + VtorDispSize;
3179 Alignment = std::max(VtorDispAlignment, Alignment);
3182 ElementInfo Info = getAdjustedElementInfo(BaseLayout);
3186 if (UseExternalLayout) {
3187 if (!
External.getExternalVBaseOffset(BaseDecl, BaseOffset))
3190 BaseOffset =
Size.alignTo(Info.Alignment);
3192 assert(BaseOffset >= Size &&
"base offset already allocated");
3194 VBases.insert(std::make_pair(BaseDecl,
3197 PreviousBaseLayout = &BaseLayout;
3201void MicrosoftRecordLayoutBuilder::finalizeLayout(
const RecordDecl *RD) {
3205 if (!RequiredAlignment.isZero()) {
3206 Alignment = std::max(Alignment, RequiredAlignment);
3207 auto RoundingAlignment = Alignment;
3208 if (!MaxFieldAlignment.
isZero())
3209 RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment);
3210 RoundingAlignment = std::max(RoundingAlignment, RequiredAlignment);
3211 Size =
Size.alignTo(RoundingAlignment);
3213 if (
Size.isZero()) {
3214 if (!
recordUsesEBO(RD) || !cast<CXXRecordDecl>(RD)->isEmpty()) {
3215 EndsWithZeroSizedObject =
true;
3216 LeadsWithZeroSizedBase =
true;
3220 if (RequiredAlignment >= MinEmptyStructSize)
3223 Size = MinEmptyStructSize;
3226 if (UseExternalLayout) {
3237 BasesWithOverriddenMethods,
3239 if (BasesWithOverriddenMethods.count(RD))
3244 if (!
Base.isVirtual() &&
3246 Base.getType()->getAsCXXRecordDecl()))
3251void MicrosoftRecordLayoutBuilder::computeVtorDispSet(
3252 llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtordispSet,
3261 HasVtordispSet.insert(BaseDecl);
3272 if (bi.second.hasVtorDisp())
3273 HasVtordispSet.insert(bi.first);
3293 if (MicrosoftVTableContext::hasVtableSlot(MD) &&
3294 !isa<CXXDestructorDecl>(MD) && !MD->isPureVirtual())
3296 while (!Work.empty()) {
3300 if (MethodRange.begin() == MethodRange.end())
3301 BasesWithOverriddenMethods.insert(MD->
getParent());
3303 Work.insert(MethodRange.begin(), MethodRange.end());
3311 if (!HasVtordispSet.count(BaseDecl) &&
3313 HasVtordispSet.insert(BaseDecl);
3327 if (
D->hasExternalLexicalStorage() && !
D->getDefinition())
3332 D =
D->getDefinition();
3333 assert(
D &&
"Cannot get layout of forward declarations!");
3334 assert(!
D->
isInvalidDecl() &&
"Cannot get layout of invalid decl!");
3335 assert(
D->isCompleteDefinition() &&
"Cannot layout type before complete!");
3341 if (Entry)
return *Entry;
3346 if (
const auto *RD = dyn_cast<CXXRecordDecl>(
D)) {
3347 EmptySubobjectMap EmptySubobjects(*
this, RD);
3348 MicrosoftRecordLayoutBuilder Builder(*
this, &EmptySubobjects);
3349 Builder.cxxLayout(RD);
3351 *
this, Builder.Size, Builder.Alignment, Builder.Alignment,
3352 Builder.Alignment, Builder.RequiredAlignment, Builder.HasOwnVFPtr,
3353 Builder.HasOwnVFPtr || Builder.PrimaryBase, Builder.VBPtrOffset,
3354 Builder.DataSize, Builder.FieldOffsets, Builder.NonVirtualSize,
3356 Builder.PrimaryBase,
false, Builder.SharedVBPtrBase,
3357 Builder.EndsWithZeroSizedObject, Builder.LeadsWithZeroSizedBase,
3358 Builder.Bases, Builder.VBases);
3360 MicrosoftRecordLayoutBuilder Builder(*
this,
nullptr);
3363 *
this, Builder.Size, Builder.Alignment, Builder.Alignment,
3364 Builder.Alignment, Builder.RequiredAlignment, Builder.Size,
3365 Builder.FieldOffsets);
3368 if (
const auto *RD = dyn_cast<CXXRecordDecl>(
D)) {
3369 EmptySubobjectMap EmptySubobjects(*
this, RD);
3370 ItaniumRecordLayoutBuilder Builder(*
this, &EmptySubobjects);
3376 bool skipTailPadding =
3381 skipTailPadding ? Builder.getSize() : Builder.getDataSize();
3383 skipTailPadding ? DataSize : Builder.NonVirtualSize;
3385 *
this, Builder.getSize(), Builder.Alignment,
3386 Builder.PreferredAlignment, Builder.UnadjustedAlignment,
3390 NonVirtualSize, Builder.NonVirtualAlignment,
3391 Builder.PreferredNVAlignment,
3392 EmptySubobjects.SizeOfLargestEmptySubobject, Builder.PrimaryBase,
3393 Builder.PrimaryBaseIsVirtual,
nullptr,
false,
false, Builder.Bases,
3396 ItaniumRecordLayoutBuilder Builder(*
this,
nullptr);
3400 *
this, Builder.getSize(), Builder.Alignment,
3401 Builder.PreferredAlignment, Builder.UnadjustedAlignment,
3403 Builder.Alignment, Builder.getSize(), Builder.FieldOffsets);
3407 ASTRecordLayouts[
D] = NewEntry;
3410 llvm::outs() <<
"\n*** Dumping AST Record Layout\n";
3421 assert(RD->
getDefinition() &&
"Cannot get key function for forward decl!");
3435 KeyFunctions[RD] =
const_cast<Decl*
>(
Result);
3437 return cast_or_null<CXXMethodDecl>(
Result);
3442 "not working with method declaration from class definition");
3447 const auto &Map = KeyFunctions;
3451 if (I == Map.end())
return;
3459 KeyFunctions.erase(Method->
getParent());
3469 uint64_t OffsetInBits;
3470 if (
const FieldDecl *FD = dyn_cast<FieldDecl>(VD)) {
3480 return OffsetInBits;
3508 for (
const ObjCIvarDecl *IVD = Container->all_declared_ivar_begin();
3509 IVD; IVD = IVD->getNextIvar()) {
3514 assert(Index < RL->getFieldCount() &&
"Ivar is not inside record layout!");
3528 if (
D->hasExternalLexicalStorage() && !
D->getDefinition())
3530 D =
D->getDefinition();
3532 "Invalid interface decl!");
3547 if (SynthCount == 0)
3548 return getObjCLayout(
D,
nullptr);
3551 ItaniumRecordLayoutBuilder Builder(*
this,
nullptr);
3555 *
this, Builder.getSize(), Builder.Alignment, Builder.PreferredAlignment,
3556 Builder.UnadjustedAlignment,
3558 Builder.Alignment, Builder.getDataSize(), Builder.FieldOffsets);
3560 ObjCLayouts[Key] = NewEntry;
3566 CharUnits Offset,
unsigned IndentLevel) {
3567 OS << llvm::format(
"%10" PRId64
" | ", (int64_t)Offset.getQuantity());
3568 OS.indent(IndentLevel * 2);
3572 unsigned Begin,
unsigned Width,
3573 unsigned IndentLevel) {
3576 llvm::raw_svector_ostream BufferOS(Buffer);
3577 BufferOS << Offset.getQuantity() <<
':';
3581 BufferOS <<
Begin <<
'-' << (
Begin + Width - 1);
3585 OS << llvm::right_justify(Buffer, 10) <<
" | ";
3586 OS.indent(IndentLevel * 2);
3591 OS.indent(IndentLevel * 2);
3597 unsigned IndentLevel,
3598 const char* Description,
3600 bool IncludeVirtualBases) {
3602 auto CXXRD = dyn_cast<CXXRecordDecl>(RD);
3605 OS <<
C.getTypeDeclType(
const_cast<RecordDecl *
>(RD));
3607 OS <<
' ' << Description;
3608 if (CXXRD && CXXRD->isEmpty())
3621 if (CXXRD->isDynamicClass() && !PrimaryBase && !
isMsLayout(
C)) {
3623 OS <<
'(' << *RD <<
" vtable pointer)\n";
3624 }
else if (HasOwnVFPtr) {
3627 OS <<
'(' << *RD <<
" vftable pointer)\n";
3633 assert(!
Base.getType()->isDependentType() &&
3634 "Cannot layout class with dependent bases.");
3635 if (!
Base.isVirtual())
3636 Bases.push_back(
Base.getType()->getAsCXXRecordDecl());
3649 Base == PrimaryBase ?
"(primary base)" :
"(base)",
3657 OS <<
'(' << *RD <<
" vbtable pointer)\n";
3663 uint64_t LocalFieldOffsetInBits =
3666 Offset +
C.toCharUnitsFromBits(LocalFieldOffsetInBits);
3669 if (
auto RT = Field->getType()->getAs<
RecordType>()) {
3671 Field->getName().data(),
3677 if (Field->isBitField()) {
3678 uint64_t LocalFieldByteOffsetInBits =
C.toBits(FieldOffset - Offset);
3679 unsigned Begin = LocalFieldOffsetInBits - LocalFieldByteOffsetInBits;
3680 unsigned Width = Field->getBitWidthValue();
3685 const QualType &FieldType =
C.getLangOpts().DumpRecordLayoutsCanonical
3686 ? Field->getType().getCanonicalType()
3688 OS << FieldType <<
' ' << *Field <<
'\n';
3692 if (CXXRD && IncludeVirtualBases) {
3697 assert(
Base.isVirtual() &&
"Found non-virtual class!");
3702 if (VtorDisps.find(VBase)->second.hasVtorDisp()) {
3704 OS <<
"(vtordisp for vbase " << *VBase <<
")\n";
3709 "(primary virtual base)" :
"(virtual base)",
3715 if (!PrintSizeInfo)
return;
3722 if (
C.getTargetInfo().defaultsToAIXPowerAlignment())
3730 if (
C.getTargetInfo().defaultsToAIXPowerAlignment())
3731 OS <<
", preferrednvalign="
3738 bool Simple)
const {
3756 OS <<
"<ASTRecordLayout\n";
3761 if (
Target->defaultsToAIXPowerAlignment())
3764 if (
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
3765 OS <<
" BaseOffsets: [";
3767 for (
auto I : CXXRD->bases()) {
3772 Base = I.getType()->getAsCXXRecordDecl();
3773 OS << Info.CXXInfo->BaseOffsets[
Base].getQuantity();
3776 OS <<
" VBaseOffsets: [";
3778 for (
auto I : CXXRD->vbases()) {
3781 VBase = I.getType()->getAsCXXRecordDecl();
3782 OS << Info.CXXInfo->VBaseOffsets[VBase].VBaseOffset.getQuantity();
3786 OS <<
" FieldOffsets: [";
3787 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 bool isMsLayout(const ASTContext &Context)
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)
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.
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...
const ASTRecordLayout & getASTObjCImplementationLayout(const ObjCImplementationDecl *D) const
Get or compute information about the layout of the specified Objective-C implementation.
QualType getTypeDeclType(const TypeDecl *Decl, const TypeDecl *PrevDecl=nullptr) const
Return the unique reference to the type for the specified type declaration.
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.
unsigned CountNonClassIvars(const ObjCInterfaceDecl *OI) const
bool isNearlyEmpty(const CXXRecordDecl *RD) const
const TargetInfo * getAuxTargetInfo() const
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.
void setNonKeyFunction(const CXXMethodDecl *method)
Observe that the given method cannot be a key function.
TypeInfoChars getTypeInfoInChars(const Type *T) const
int64_t toBits(CharUnits CharSize) const
Convert a size in characters to a size in bits.
uint64_t lookupFieldBitOffset(const ObjCInterfaceDecl *OID, const ObjCImplementationDecl *ID, const ObjCIvarDecl *Ivar) const
Get the offset of an ObjCIvarDecl in bits.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
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.
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...
This class is used for builtin types like 'int'.
Represents a base class of a C++ class.
A set of all the primary bases for a 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.
Complex values, per C99 6.2.5p11.
Represents the canonical version of C arrays with a specified constant size.
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
Decl - This represents one declaration (or definition), e.g.
Decl * getMostRecentDecl()
Retrieve the most recent declaration that declares the same entity as this declaration (which may be ...
unsigned getMaxAlignment() const
getMaxAlignment - return the maximum alignment specified by attributes on this decl,...
bool isInvalidDecl() const
SourceLocation getLocation() const
A little helper class used to produce diagnostics.
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.
Abstract interface for external sources of AST nodes.
virtual void CompleteType(TagDecl *Tag)
Gives the external AST source an opportunity to complete an incomplete type.
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
@ Ver6
Attempt to be ABI-compatible with code generated by Clang 6.0.x (SVN r321711).
@ Ver15
Attempt to be ABI-compatible with code generated by Clang 15.0.x.
This represents a decl that may have a name.
bool isExternallyVisible() const
ObjCContainerDecl - Represents a container for method declarations.
ObjCImplementationDecl - Represents a class definition - this is where method definitions are specifi...
Represents an ObjC class declaration.
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 * 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,...
field_range fields() const
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
RecordDecl * getDecl() const
decl_type * getFirstDecl()
Return the first declaration of this declaration or itself if this is the only declaration.
Encodes a location in the source.
The basic abstraction for the target C++ ABI.
TailPaddingUseRules getTailPaddingUseRules() const
bool isMicrosoft() const
Is this ABI an MSVC-compatible ABI?
bool canKeyFunctionBeInline() const
Can an out-of-line inline function serve as a key function?
@ 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.
virtual bool hasPS4DLLImportExport() 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.
The base class of the type hierarchy.
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 * 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,...
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Defines the clang::TargetInfo interface.
bool Zero(InterpState &S, CodePtr OpPC)
The JSON file list parser is used to communicate input to InstallAPI.
@ 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.
TagTypeKind
The kind of a tag type.
@ Interface
The "__interface" keyword.
@ Struct
The "struct" keyword.
@ Class
The "class" keyword.
const FunctionProtoType * T
bool declaresSameEntity(const Decl *D1, const Decl *D2)
Determine whether two declarations declare the same entity.
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.
@ None
The alignment was not explicit in code.
@ RequiredByTypedef
The alignment comes from an alignment attribute on a typedef.
@ RequiredByRecord
The alignment comes from an alignment attribute on a record type.
@ 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.
All virtual base related information about a given record decl.