20#include "llvm/ADT/SmallSet.h"
21#include "llvm/Support/Format.h"
22#include "llvm/Support/MathExtras.h"
39struct BaseSubobjectInfo {
51 BaseSubobjectInfo *PrimaryVirtualBaseInfo;
54 const BaseSubobjectInfo *Derived;
60struct ExternalLayout {
61 ExternalLayout() =
default;
70 llvm::DenseMap<const FieldDecl *, uint64_t> FieldOffsets;
73 llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsets;
76 llvm::DenseMap<const CXXRecordDecl *, CharUnits> VirtualBaseOffsets;
81 assert(FieldOffsets.count(FD) &&
82 "Field does not have an external offset");
83 return FieldOffsets[FD];
87 auto Known = BaseOffsets.find(RD);
88 if (Known == BaseOffsets.end())
90 BaseOffset = Known->second;
95 auto Known = VirtualBaseOffsets.find(RD);
96 if (Known == VirtualBaseOffsets.end())
98 BaseOffset = Known->second;
105class EmptySubobjectMap {
113 typedef llvm::TinyPtrVector<const CXXRecordDecl *> ClassVectorTy;
114 typedef llvm::DenseMap<CharUnits, ClassVectorTy> EmptyClassOffsetsMapTy;
115 EmptyClassOffsetsMapTy EmptyClassOffsets;
123 void ComputeEmptySubobjectSizes();
127 void UpdateEmptyBaseSubobjects(
const BaseSubobjectInfo *Info,
128 CharUnits Offset,
bool PlacingEmptyBase);
132 bool PlacingOverlappingField);
134 bool PlacingOverlappingField);
138 bool AnyEmptySubobjectsBeyondOffset(
CharUnits Offset)
const {
139 return Offset <= MaxEmptyClassOffset;
145 assert(FieldOffset % CharWidth == 0 &&
146 "Field offset not at char boundary!");
155 bool CanPlaceBaseSubobjectAtOffset(
const BaseSubobjectInfo *Info,
161 bool CanPlaceFieldSubobjectAtOffset(
const FieldDecl *FD,
172 ComputeEmptySubobjectSizes();
179 bool CanPlaceBaseAtOffset(
const BaseSubobjectInfo *Info,
187void EmptySubobjectMap::ComputeEmptySubobjectSizes() {
202 if (EmptySize > SizeOfLargestEmptySubobject)
203 SizeOfLargestEmptySubobject = EmptySize;
226 if (EmptySize > SizeOfLargestEmptySubobject)
227 SizeOfLargestEmptySubobject = EmptySize;
232EmptySubobjectMap::CanPlaceSubobjectAtOffset(
const CXXRecordDecl *RD,
238 EmptyClassOffsetsMapTy::const_iterator I = EmptyClassOffsets.find(Offset);
239 if (I == EmptyClassOffsets.end())
242 const ClassVectorTy &Classes = I->second;
243 if (!llvm::is_contained(Classes, RD))
250void EmptySubobjectMap::AddSubobjectAtOffset(
const CXXRecordDecl *RD,
258 ClassVectorTy &Classes = EmptyClassOffsets[Offset];
259 if (llvm::is_contained(Classes, RD))
262 Classes.push_back(RD);
265 if (Offset > MaxEmptyClassOffset)
266 MaxEmptyClassOffset = Offset;
270EmptySubobjectMap::CanPlaceBaseSubobjectAtOffset(
const BaseSubobjectInfo *Info,
274 if (!AnyEmptySubobjectsBeyondOffset(Offset))
277 if (!CanPlaceSubobjectAtOffset(Info->Class, Offset))
282 for (
const BaseSubobjectInfo *
Base : Info->Bases) {
288 if (!CanPlaceBaseSubobjectAtOffset(
Base, BaseOffset))
292 if (Info->PrimaryVirtualBaseInfo) {
293 BaseSubobjectInfo *PrimaryVirtualBaseInfo = Info->PrimaryVirtualBaseInfo;
295 if (Info == PrimaryVirtualBaseInfo->Derived) {
296 if (!CanPlaceBaseSubobjectAtOffset(PrimaryVirtualBaseInfo, Offset))
302 unsigned FieldNo = 0;
304 E = Info->Class->field_end(); I !=
E; ++I, ++FieldNo) {
309 if (!CanPlaceFieldSubobjectAtOffset(*I, FieldOffset))
316void EmptySubobjectMap::UpdateEmptyBaseSubobjects(
const BaseSubobjectInfo *Info,
318 bool PlacingEmptyBase) {
319 if (!PlacingEmptyBase && Offset >= SizeOfLargestEmptySubobject) {
328 AddSubobjectAtOffset(Info->Class, Offset);
332 for (
const BaseSubobjectInfo *
Base : Info->Bases) {
337 UpdateEmptyBaseSubobjects(
Base, BaseOffset, PlacingEmptyBase);
340 if (Info->PrimaryVirtualBaseInfo) {
341 BaseSubobjectInfo *PrimaryVirtualBaseInfo = Info->PrimaryVirtualBaseInfo;
343 if (Info == PrimaryVirtualBaseInfo->Derived)
344 UpdateEmptyBaseSubobjects(PrimaryVirtualBaseInfo, Offset,
349 unsigned FieldNo = 0;
351 E = Info->Class->field_end(); I !=
E; ++I, ++FieldNo) {
356 UpdateEmptyFieldSubobjects(*I, FieldOffset, PlacingEmptyBase);
360bool EmptySubobjectMap::CanPlaceBaseAtOffset(
const BaseSubobjectInfo *Info,
364 if (SizeOfLargestEmptySubobject.isZero())
367 if (!CanPlaceBaseSubobjectAtOffset(Info, Offset))
372 UpdateEmptyBaseSubobjects(Info, Offset, Info->Class->isEmpty());
377EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(
const CXXRecordDecl *RD,
382 if (!AnyEmptySubobjectsBeyondOffset(Offset))
385 if (!CanPlaceSubobjectAtOffset(RD, Offset))
392 if (
Base.isVirtual())
398 if (!CanPlaceFieldSubobjectAtOffset(BaseDecl, Class, BaseOffset))
408 if (!CanPlaceFieldSubobjectAtOffset(VBaseDecl, Class, VBaseOffset))
414 unsigned FieldNo = 0;
416 I !=
E; ++I, ++FieldNo) {
422 if (!CanPlaceFieldSubobjectAtOffset(*I, FieldOffset))
430EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(
const FieldDecl *FD,
434 if (!AnyEmptySubobjectsBeyondOffset(Offset))
439 return CanPlaceFieldSubobjectAtOffset(RD, RD, Offset);
453 for (uint64_t I = 0; I != NumElements; ++I) {
456 if (!AnyEmptySubobjectsBeyondOffset(ElementOffset))
459 if (!CanPlaceFieldSubobjectAtOffset(RD, RD, ElementOffset))
462 ElementOffset += Layout.
getSize();
470EmptySubobjectMap::CanPlaceFieldAtOffset(
const FieldDecl *FD,
472 if (!CanPlaceFieldSubobjectAtOffset(FD, Offset))
477 UpdateEmptyFieldSubobjects(FD, Offset, FD->
hasAttr<NoUniqueAddressAttr>());
481void EmptySubobjectMap::UpdateEmptyFieldSubobjects(
483 bool PlacingOverlappingField) {
494 if (!PlacingOverlappingField && Offset >= SizeOfLargestEmptySubobject)
497 AddSubobjectAtOffset(RD, Offset);
503 if (
Base.isVirtual())
509 UpdateEmptyFieldSubobjects(BaseDecl, Class, BaseOffset,
510 PlacingOverlappingField);
519 UpdateEmptyFieldSubobjects(VBaseDecl, Class, VBaseOffset,
520 PlacingOverlappingField);
525 unsigned FieldNo = 0;
527 I !=
E; ++I, ++FieldNo) {
533 UpdateEmptyFieldSubobjects(*I, FieldOffset, PlacingOverlappingField);
537void EmptySubobjectMap::UpdateEmptyFieldSubobjects(
541 UpdateEmptyFieldSubobjects(RD, RD, Offset, PlacingOverlappingField);
558 for (uint64_t I = 0; I != NumElements; ++I) {
564 if (!PlacingOverlappingField &&
565 ElementOffset >= SizeOfLargestEmptySubobject)
568 UpdateEmptyFieldSubobjects(RD, RD, ElementOffset,
569 PlacingOverlappingField);
570 ElementOffset += Layout.
getSize();
577class ItaniumRecordLayoutBuilder {
584 EmptySubobjectMap *EmptySubobjects;
605 LLVM_PREFERRED_TYPE(
bool)
606 unsigned UseExternalLayout : 1;
610 LLVM_PREFERRED_TYPE(
bool)
611 unsigned InferAlignment : 1;
614 LLVM_PREFERRED_TYPE(
bool)
617 LLVM_PREFERRED_TYPE(
bool)
618 unsigned IsUnion : 1;
620 LLVM_PREFERRED_TYPE(
bool)
621 unsigned IsMac68kAlign : 1;
623 LLVM_PREFERRED_TYPE(
bool)
624 unsigned IsNaturalAlign : 1;
626 LLVM_PREFERRED_TYPE(
bool)
627 unsigned IsMsStruct : 1;
633 unsigned char UnfilledBitsInLastUnit;
637 unsigned char LastBitfieldStorageUnitSize;
660 bool PrimaryBaseIsVirtual;
673 bool HandledFirstNonOverlappingEmptyField;
675 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
678 BaseOffsetsMapTy Bases;
698 ItaniumRecordLayoutBuilder(
const ASTContext &Context,
699 EmptySubobjectMap *EmptySubobjects)
700 : Context(Context), EmptySubobjects(EmptySubobjects),
Size(0),
705 IsMac68kAlign(
false),
706 IsNaturalAlign(!Context.getTargetInfo().getTriple().isOSAIX()),
707 IsMsStruct(
false), UnfilledBitsInLastUnit(0),
708 LastBitfieldStorageUnitSize(0), MaxFieldAlignment(
CharUnits::
Zero()),
713 PrimaryBaseIsVirtual(
false), HasOwnVFPtr(
false), HasPackedField(
false),
714 HandledFirstNonOverlappingEmptyField(
false),
715 FirstNearlyEmptyVBase(nullptr) {}
722 void LayoutField(
const FieldDecl *
D,
bool InsertExtraPadding);
723 void LayoutWideBitField(uint64_t FieldSize, uint64_t StorageUnitSize,
732 llvm::SpecificBumpPtrAllocator<BaseSubobjectInfo> BaseSubobjectInfoAllocator;
734 typedef llvm::DenseMap<const CXXRecordDecl *, BaseSubobjectInfo *>
735 BaseSubobjectInfoMapTy;
743 BaseSubobjectInfoMapTy NonVirtualBaseInfo;
751 BaseSubobjectInfo *ComputeBaseSubobjectInfo(
const CXXRecordDecl *RD,
753 BaseSubobjectInfo *Derived);
760 void EnsureVTablePointerAlignment(
CharUnits UnpackedBaseAlign);
767 void LayoutNonVirtualBase(
const BaseSubobjectInfo *
Base);
769 void AddPrimaryVirtualBaseOffsets(
const BaseSubobjectInfo *Info,
777 void LayoutVirtualBase(
const BaseSubobjectInfo *
Base);
784 void InitializeLayout(
const Decl *
D);
793 UpdateAlignment(NewAlignment, UnpackedNewAlignment, NewAlignment);
795 void UpdateAlignment(
CharUnits NewAlignment) {
796 UpdateAlignment(NewAlignment, NewAlignment, NewAlignment);
805 uint64_t ComputedOffset);
807 void CheckFieldPadding(uint64_t Offset, uint64_t UnpaddedOffset,
808 uint64_t UnpackedOffset,
unsigned UnpackedAlign,
820 void setSize(uint64_t NewSize) {
Size = NewSize; }
822 CharUnits getAligment()
const {
return Alignment; }
828 uint64_t getDataSizeInBits()
const {
return DataSize; }
830 void setDataSize(
CharUnits NewSize) { DataSize = Context.
toBits(NewSize); }
831 void setDataSize(uint64_t NewSize) { DataSize = NewSize; }
833 ItaniumRecordLayoutBuilder(
const ItaniumRecordLayoutBuilder &) =
delete;
834 void operator=(
const ItaniumRecordLayoutBuilder &) =
delete;
838void ItaniumRecordLayoutBuilder::SelectPrimaryVBase(
const CXXRecordDecl *RD) {
839 for (
const auto &I : RD->
bases()) {
840 assert(!I.getType()->isDependentType() &&
841 "Cannot layout class with dependent bases.");
849 if (!IndirectPrimaryBases.count(
Base)) {
851 PrimaryBaseIsVirtual =
true;
856 if (!FirstNearlyEmptyVBase)
857 FirstNearlyEmptyVBase =
Base;
860 SelectPrimaryVBase(
Base);
867void ItaniumRecordLayoutBuilder::DeterminePrimaryBase(
const CXXRecordDecl *RD) {
879 for (
const auto &I : RD->
bases()) {
886 if (
Base->isDynamicClass()) {
889 PrimaryBaseIsVirtual =
false;
899 SelectPrimaryVBase(RD);
905 if (FirstNearlyEmptyVBase) {
906 PrimaryBase = FirstNearlyEmptyVBase;
907 PrimaryBaseIsVirtual =
true;
911 assert(!PrimaryBase &&
"Should not get here with a primary base!");
914BaseSubobjectInfo *ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo(
915 const CXXRecordDecl *RD,
bool IsVirtual, BaseSubobjectInfo *Derived) {
916 BaseSubobjectInfo *Info;
922 assert(InfoSlot->Class == RD &&
"Wrong class for virtual base info!");
927 InfoSlot =
new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo;
930 Info =
new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo;
934 Info->IsVirtual = IsVirtual;
935 Info->Derived =
nullptr;
936 Info->PrimaryVirtualBaseInfo =
nullptr;
939 BaseSubobjectInfo *PrimaryVirtualBaseInfo =
nullptr;
947 assert(PrimaryVirtualBase &&
"Didn't have a primary virtual base!");
952 if (PrimaryVirtualBaseInfo) {
953 if (PrimaryVirtualBaseInfo->Derived) {
957 PrimaryVirtualBase =
nullptr;
960 Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;
961 PrimaryVirtualBaseInfo->Derived = Info;
968 for (
const auto &I : RD->
bases()) {
969 bool IsVirtual = I.isVirtual();
971 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
973 Info->Bases.push_back(ComputeBaseSubobjectInfo(BaseDecl, IsVirtual, Info));
976 if (PrimaryVirtualBase && !PrimaryVirtualBaseInfo) {
980 assert(PrimaryVirtualBaseInfo &&
981 "Did not create a primary virtual base!");
984 Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;
985 PrimaryVirtualBaseInfo->Derived = Info;
991void ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo(
993 for (
const auto &I : RD->
bases()) {
994 bool IsVirtual = I.isVirtual();
996 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
999 BaseSubobjectInfo *Info = ComputeBaseSubobjectInfo(BaseDecl, IsVirtual,
1005 "Did not add virtual base!");
1008 assert(!NonVirtualBaseInfo.count(BaseDecl) &&
1009 "Non-virtual base already exists!");
1010 NonVirtualBaseInfo.insert(std::make_pair(BaseDecl, Info));
1015void ItaniumRecordLayoutBuilder::EnsureVTablePointerAlignment(
1020 if (!MaxFieldAlignment.
isZero()) {
1021 BaseAlign = std::min(BaseAlign, MaxFieldAlignment);
1022 UnpackedBaseAlign = std::min(UnpackedBaseAlign, MaxFieldAlignment);
1026 setSize(getSize().alignTo(BaseAlign));
1029 UpdateAlignment(BaseAlign, UnpackedBaseAlign, BaseAlign);
1032void ItaniumRecordLayoutBuilder::LayoutNonVirtualBases(
1035 DeterminePrimaryBase(RD);
1038 ComputeBaseSubobjectInfo(RD);
1042 if (PrimaryBaseIsVirtual) {
1045 BaseSubobjectInfo *PrimaryBaseInfo =
VirtualBaseInfo.lookup(PrimaryBase);
1046 PrimaryBaseInfo->Derived =
nullptr;
1049 IndirectPrimaryBases.insert(PrimaryBase);
1051 assert(!VisitedVirtualBases.count(PrimaryBase) &&
1052 "vbase already visited!");
1053 VisitedVirtualBases.insert(PrimaryBase);
1055 LayoutVirtualBase(PrimaryBaseInfo);
1057 BaseSubobjectInfo *PrimaryBaseInfo =
1058 NonVirtualBaseInfo.lookup(PrimaryBase);
1059 assert(PrimaryBaseInfo &&
1060 "Did not find base info for non-virtual primary base!");
1062 LayoutNonVirtualBase(PrimaryBaseInfo);
1068 assert(DataSize == 0 &&
"Vtable pointer must be at offset zero!");
1073 EnsureVTablePointerAlignment(PtrAlign);
1076 assert(!IsUnion &&
"Unions cannot be dynamic classes.");
1077 HandledFirstNonOverlappingEmptyField =
true;
1079 setSize(getSize() + PtrWidth);
1080 setDataSize(getSize());
1084 for (
const auto &I : RD->
bases()) {
1090 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
1095 if (BaseDecl == PrimaryBase && !PrimaryBaseIsVirtual)
1099 BaseSubobjectInfo *BaseInfo = NonVirtualBaseInfo.
lookup(BaseDecl);
1100 assert(BaseInfo &&
"Did not find base info for non-virtual base!");
1102 LayoutNonVirtualBase(BaseInfo);
1106void ItaniumRecordLayoutBuilder::LayoutNonVirtualBase(
1107 const BaseSubobjectInfo *
Base) {
1112 assert(!Bases.count(
Base->Class) &&
"base offset already exists!");
1113 Bases.insert(std::make_pair(
Base->Class, Offset));
1115 AddPrimaryVirtualBaseOffsets(
Base, Offset);
1118void ItaniumRecordLayoutBuilder::AddPrimaryVirtualBaseOffsets(
1119 const BaseSubobjectInfo *Info,
CharUnits Offset) {
1121 if (!Info->Class->getNumVBases())
1125 if (Info->PrimaryVirtualBaseInfo) {
1126 assert(Info->PrimaryVirtualBaseInfo->IsVirtual &&
1127 "Primary virtual base is not virtual!");
1128 if (Info->PrimaryVirtualBaseInfo->Derived == Info) {
1130 assert(!VBases.count(Info->PrimaryVirtualBaseInfo->Class) &&
1131 "primary vbase offset already exists!");
1132 VBases.insert(std::make_pair(Info->PrimaryVirtualBaseInfo->Class,
1136 AddPrimaryVirtualBaseOffsets(Info->PrimaryVirtualBaseInfo, Offset);
1142 for (
const BaseSubobjectInfo *
Base : Info->Bases) {
1143 if (
Base->IsVirtual)
1147 AddPrimaryVirtualBaseOffsets(
Base, BaseOffset);
1151void ItaniumRecordLayoutBuilder::LayoutVirtualBases(
1154 bool PrimaryBaseIsVirtual;
1156 if (MostDerivedClass == RD) {
1157 PrimaryBase = this->PrimaryBase;
1158 PrimaryBaseIsVirtual = this->PrimaryBaseIsVirtual;
1166 assert(!
Base.getType()->isDependentType() &&
1167 "Cannot layout class with dependent bases.");
1171 if (
Base.isVirtual()) {
1172 if (PrimaryBase != BaseDecl || !PrimaryBaseIsVirtual) {
1173 bool IndirectPrimaryBase = IndirectPrimaryBases.count(BaseDecl);
1176 if (!IndirectPrimaryBase) {
1178 if (!VisitedVirtualBases.insert(BaseDecl).second)
1182 assert(BaseInfo &&
"Did not find virtual base info!");
1183 LayoutVirtualBase(BaseInfo);
1193 LayoutVirtualBases(BaseDecl, MostDerivedClass);
1197void ItaniumRecordLayoutBuilder::LayoutVirtualBase(
1198 const BaseSubobjectInfo *
Base) {
1199 assert(!
Base->Derived &&
"Trying to lay out a primary virtual base!");
1205 assert(!VBases.count(
Base->Class) &&
"vbase offset already exists!");
1206 VBases.insert(std::make_pair(
Base->Class,
1209 AddPrimaryVirtualBaseOffsets(
Base, Offset);
1213ItaniumRecordLayoutBuilder::LayoutBase(
const BaseSubobjectInfo *
Base) {
1214 assert(!IsUnion &&
"Unions cannot have base classes.");
1220 bool HasExternalLayout =
false;
1221 if (UseExternalLayout) {
1222 if (
Base->IsVirtual)
1223 HasExternalLayout =
External.getExternalVBaseOffset(
Base->Class, Offset);
1225 HasExternalLayout =
External.getExternalNVBaseOffset(
Base->Class, Offset);
1228 auto getBaseOrPreferredBaseAlignFromUnpacked = [&](
CharUnits UnpackedAlign) {
1231 return (Packed && ((Context.
getLangOpts().getClangABICompat() <=
1242 getBaseOrPreferredBaseAlignFromUnpacked(UnpackedBaseAlign);
1244 getBaseOrPreferredBaseAlignFromUnpacked(UnpackedPreferredBaseAlign);
1246 const bool DefaultsToAIXPowerAlignment =
1248 if (DefaultsToAIXPowerAlignment) {
1253 if (!
Base->Class->isEmpty() && !HandledFirstNonOverlappingEmptyField) {
1256 HandledFirstNonOverlappingEmptyField =
true;
1257 }
else if (!IsNaturalAlign) {
1258 UnpackedPreferredBaseAlign = UnpackedBaseAlign;
1259 PreferredBaseAlign = BaseAlign;
1263 CharUnits UnpackedAlignTo = !DefaultsToAIXPowerAlignment
1265 : UnpackedPreferredBaseAlign;
1267 if (
Base->Class->isEmpty() &&
1270 setSize(std::max(getSize(), Layout.
getSize()));
1273 UpdateAlignment(BaseAlign, UnpackedAlignTo, PreferredBaseAlign);
1280 if (!MaxFieldAlignment.
isZero()) {
1281 BaseAlign = std::min(BaseAlign, MaxFieldAlignment);
1282 PreferredBaseAlign = std::min(PreferredBaseAlign, MaxFieldAlignment);
1283 UnpackedAlignTo = std::min(UnpackedAlignTo, MaxFieldAlignment);
1287 !DefaultsToAIXPowerAlignment ? BaseAlign : PreferredBaseAlign;
1288 if (!HasExternalLayout) {
1290 Offset = getDataSize().alignTo(AlignTo);
1293 while (!EmptySubobjects->CanPlaceBaseAtOffset(
Base, Offset))
1296 bool Allowed = EmptySubobjects->CanPlaceBaseAtOffset(
Base, Offset);
1298 assert(Allowed &&
"Base subobject externally placed at overlapping offset");
1300 if (InferAlignment && Offset < getDataSize().alignTo(AlignTo)) {
1304 InferAlignment =
false;
1308 if (!
Base->Class->isEmpty()) {
1312 setSize(std::max(getSize(), getDataSize()));
1314 setSize(std::max(getSize(), Offset + Layout.
getSize()));
1317 UpdateAlignment(BaseAlign, UnpackedAlignTo, PreferredBaseAlign);
1322void ItaniumRecordLayoutBuilder::InitializeLayout(
const Decl *
D) {
1323 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(
D)) {
1331 if (
unsigned DefaultMaxFieldAlignment = Context.
getLangOpts().PackStruct) {
1339 if (
D->
hasAttr<AlignMac68kAttr>()) {
1342 "Having both mac68k and natural alignment on a decl is not allowed.");
1343 IsMac68kAlign =
true;
1348 if (
D->
hasAttr<AlignNaturalAttr>())
1349 IsNaturalAlign =
true;
1351 if (
const MaxFieldAlignmentAttr *MFAA =
D->
getAttr<MaxFieldAlignmentAttr>())
1358 HandledFirstNonOverlappingEmptyField =
1362 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(
D))
1364 UseExternalLayout = Source->layoutRecordType(
1369 if (UseExternalLayout) {
1375 InferAlignment =
true;
1381void ItaniumRecordLayoutBuilder::Layout(
const RecordDecl *
D) {
1382 InitializeLayout(
D);
1390void ItaniumRecordLayoutBuilder::Layout(
const CXXRecordDecl *RD) {
1391 InitializeLayout(RD);
1394 LayoutNonVirtualBases(RD);
1400 NonVirtualAlignment = Alignment;
1401 PreferredNVAlignment = PreferredAlignment;
1404 LayoutVirtualBases(RD, RD);
1413 if (
Base.isVirtual())
1418 assert(Bases.count(BaseDecl) &&
"Did not find base offset!");
1425 assert(VBases.count(BaseDecl) &&
"Did not find base offset!");
1439 setSize(getDataSize());
1442 InitializeLayout(
D);
1444 for (
const ObjCIvarDecl *IVD =
D->all_declared_ivar_begin(); IVD;
1445 IVD = IVD->getNextIvar())
1446 LayoutField(IVD,
false);
1453void ItaniumRecordLayoutBuilder::LayoutFields(
const RecordDecl *
D) {
1456 bool InsertExtraPadding =
D->mayInsertExtraPadding(
true);
1457 bool HasFlexibleArrayMember =
D->hasFlexibleArrayMember();
1458 for (
auto I =
D->field_begin(), End =
D->field_end(); I != End; ++I) {
1462 InsertExtraPadding && (Next != End || !HasFlexibleArrayMember));
1471 return llvm::alignTo(Size, CharAlignment);
1474void ItaniumRecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize,
1475 uint64_t StorageUnitSize,
1479 "Can only have wide bit-fields in C++!");
1491 for (
const QualType &QT : IntegralPODTypes) {
1494 if (Size > FieldSize)
1499 assert(!
Type.isNull() &&
"Did not find a type!");
1504 UnfilledBitsInLastUnit = 0;
1505 LastBitfieldStorageUnitSize = 0;
1508 uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;
1513 setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize));
1518 FieldOffset = llvm::alignTo(getDataSizeInBits(), Context.
toBits(TypeAlign));
1520 uint64_t NewSizeInBits = FieldOffset + FieldSize;
1524 UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits;
1528 FieldOffsets.push_back(FieldOffset);
1530 CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, FieldOffset,
1531 Context.
toBits(TypeAlign), FieldPacked,
D);
1534 setSize(std::max(getSizeInBits(), getDataSizeInBits()));
1537 UpdateAlignment(TypeAlign);
1544void ItaniumRecordLayoutBuilder::LayoutBitField(
const FieldDecl *
D) {
1545 bool FieldPacked = Packed ||
D->
hasAttr<PackedAttr>();
1546 uint64_t FieldSize =
D->getBitWidthValue(Context);
1549 unsigned FieldAlign = FieldInfo.
Align;
1612 FieldAlign = StorageUnitSize;
1617 if (LastBitfieldStorageUnitSize != StorageUnitSize ||
1618 UnfilledBitsInLastUnit < FieldSize) {
1620 if (!LastBitfieldStorageUnitSize && !FieldSize)
1623 UnfilledBitsInLastUnit = 0;
1624 LastBitfieldStorageUnitSize = 0;
1638 StorageUnitSize = 32;
1640 if (!AlignIsRequired)
1644 if (FieldAlign < StorageUnitSize) {
1647 FieldAlign = StorageUnitSize;
1654 if (FieldSize > StorageUnitSize && !
isAIXLayout(Context)) {
1655 LayoutWideBitField(FieldSize, StorageUnitSize, FieldPacked,
D);
1661 IsUnion ? 0 : (getDataSizeInBits() - UnfilledBitsInLastUnit);
1666 if (FieldSize == 0 &&
1669 if (!IsUnion && FieldOffset == 0 &&
1675 unsigned ZeroLengthBitfieldBoundary =
1677 FieldAlign = std::max(FieldAlign, ZeroLengthBitfieldBoundary);
1686 unsigned UnpackedFieldAlign = FieldAlign;
1689 if (!IsMsStruct && FieldPacked && FieldSize != 0)
1694 if (ExplicitFieldAlign) {
1695 FieldAlign = std::max(FieldAlign, ExplicitFieldAlign);
1696 UnpackedFieldAlign = std::max(UnpackedFieldAlign, ExplicitFieldAlign);
1701 unsigned MaxFieldAlignmentInBits = Context.
toBits(MaxFieldAlignment);
1702 if (!MaxFieldAlignment.
isZero() && FieldSize) {
1703 UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits);
1705 FieldAlign = UnpackedFieldAlign;
1707 FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits);
1712 if (IsMsStruct && IsUnion) {
1713 FieldAlign = UnpackedFieldAlign = 1;
1719 uint64_t UnpaddedFieldOffset = FieldOffset;
1720 uint64_t UnpackedFieldOffset = FieldOffset;
1730 if (FieldSize == 0 || FieldSize > UnfilledBitsInLastUnit) {
1731 FieldOffset = llvm::alignTo(FieldOffset, FieldAlign);
1732 UnpackedFieldOffset =
1733 llvm::alignTo(UnpackedFieldOffset, UnpackedFieldAlign);
1734 UnfilledBitsInLastUnit = 0;
1739 bool AllowPadding = MaxFieldAlignment.
isZero();
1742 if (FieldSize == 0 ||
1744 (FieldOffset & (FieldAlign - 1)) + FieldSize > StorageUnitSize)) {
1745 FieldOffset = llvm::alignTo(FieldOffset, FieldAlign);
1746 }
else if (ExplicitFieldAlign &&
1747 (MaxFieldAlignmentInBits == 0 ||
1748 ExplicitFieldAlign <= MaxFieldAlignmentInBits) &&
1752 FieldOffset = llvm::alignTo(FieldOffset, ExplicitFieldAlign);
1756 if (FieldSize == 0 ||
1758 (UnpackedFieldOffset & (UnpackedFieldAlign - 1)) + FieldSize >
1760 UnpackedFieldOffset =
1761 llvm::alignTo(UnpackedFieldOffset, UnpackedFieldAlign);
1762 else if (ExplicitFieldAlign &&
1763 (MaxFieldAlignmentInBits == 0 ||
1764 ExplicitFieldAlign <= MaxFieldAlignmentInBits) &&
1766 UnpackedFieldOffset =
1767 llvm::alignTo(UnpackedFieldOffset, ExplicitFieldAlign);
1772 if (UseExternalLayout)
1773 FieldOffset = updateExternalFieldOffset(
D, FieldOffset);
1776 FieldOffsets.push_back(FieldOffset);
1784 !
D->getIdentifier())
1785 FieldAlign = UnpackedFieldAlign = 1;
1793 if (!MaxFieldAlignment.
isZero()) {
1794 UnpackedFieldAlign =
1795 std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits);
1796 FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits);
1801 if (!UseExternalLayout)
1802 CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, UnpackedFieldOffset,
1803 UnpackedFieldAlign, FieldPacked,
D);
1813 RoundedFieldSize = (FieldSize ? StorageUnitSize
1821 setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize));
1825 }
else if (IsMsStruct && FieldSize) {
1828 if (!UnfilledBitsInLastUnit) {
1829 setDataSize(FieldOffset + StorageUnitSize);
1830 UnfilledBitsInLastUnit = StorageUnitSize;
1832 UnfilledBitsInLastUnit -= FieldSize;
1833 LastBitfieldStorageUnitSize = StorageUnitSize;
1839 uint64_t NewSizeInBits = FieldOffset + FieldSize;
1841 setDataSize(llvm::alignTo(NewSizeInBits, CharAlignment));
1842 UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits;
1847 LastBitfieldStorageUnitSize = 0;
1851 setSize(std::max(getSizeInBits(), getDataSizeInBits()));
1854 UnadjustedAlignment =
1860void ItaniumRecordLayoutBuilder::LayoutField(
const FieldDecl *
D,
1861 bool InsertExtraPadding) {
1862 auto *FieldClass =
D->getType()->getAsCXXRecordDecl();
1863 bool IsOverlappingEmptyField =
1864 D->isPotentiallyOverlapping() && FieldClass->isEmpty();
1867 (IsUnion || IsOverlappingEmptyField) ?
CharUnits::Zero() : getDataSize();
1869 const bool DefaultsToAIXPowerAlignment =
1871 bool FoundFirstNonOverlappingEmptyFieldForAIX =
false;
1872 if (DefaultsToAIXPowerAlignment && !HandledFirstNonOverlappingEmptyField) {
1874 "The first non-overlapping empty field should have been handled.");
1876 if (!IsOverlappingEmptyField) {
1877 FoundFirstNonOverlappingEmptyFieldForAIX =
true;
1884 HandledFirstNonOverlappingEmptyField = !IsUnion;
1888 if (
D->isBitField()) {
1893 uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;
1895 UnfilledBitsInLastUnit = 0;
1896 LastBitfieldStorageUnitSize = 0;
1908 auto setDeclInfo = [&](
bool IsIncompleteArrayType) {
1910 FieldAlign = TI.Align;
1913 EffectiveFieldSize = FieldSize =
1915 AlignRequirement = TI.AlignRequirement;
1918 if (
D->getType()->isIncompleteArrayType()) {
1921 setDeclInfo(
false );
1925 if (
D->isPotentiallyOverlapping()) {
1927 EffectiveFieldSize =
1941 if (!llvm::isPowerOf2_64(TypeSize.
getQuantity())) {
1944 "Non PowerOf2 size in MSVC mode");
1966 if (TypeSize > FieldAlign &&
1968 FieldAlign = TypeSize;
1973 bool FieldPacked = (Packed && (!FieldClass || FieldClass->isPOD() ||
1974 FieldClass->hasAttr<PackedAttr>() ||
1985 auto alignedAttrCanDecreaseAIXAlignment = [AlignRequirement, FieldPacked] {
2004 if (DefaultsToAIXPowerAlignment && !alignedAttrCanDecreaseAIXAlignment() &&
2005 (FoundFirstNonOverlappingEmptyFieldForAIX || IsNaturalAlign)) {
2006 auto performBuiltinTypeAlignmentUpgrade = [&](
const BuiltinType *BTy) {
2007 if (BTy->getKind() == BuiltinType::Double ||
2008 BTy->getKind() == BuiltinType::LongDouble) {
2010 "No need to upgrade the alignment value.");
2015 const Type *BaseTy =
D->getType()->getBaseElementTypeUnsafe();
2017 performBuiltinTypeAlignmentUpgrade(
2020 performBuiltinTypeAlignmentUpgrade(BTy);
2023 assert(RD &&
"Expected non-null RecordDecl.");
2031 CharUnits UnpackedFieldAlign = FieldAlign;
2033 CharUnits UnpackedFieldOffset = FieldOffset;
2034 CharUnits OriginalFieldAlign = UnpackedFieldAlign;
2038 PackedFieldAlign = std::max(PackedFieldAlign, MaxAlignmentInChars);
2039 PreferredAlign = std::max(PreferredAlign, MaxAlignmentInChars);
2040 UnpackedFieldAlign = std::max(UnpackedFieldAlign, MaxAlignmentInChars);
2043 if (!MaxFieldAlignment.
isZero()) {
2044 PackedFieldAlign = std::min(PackedFieldAlign, MaxFieldAlignment);
2045 PreferredAlign = std::min(PreferredAlign, MaxFieldAlignment);
2046 UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignment);
2051 FieldAlign = UnpackedFieldAlign;
2052 if (DefaultsToAIXPowerAlignment)
2053 UnpackedFieldAlign = PreferredAlign;
2055 PreferredAlign = PackedFieldAlign;
2056 FieldAlign = PackedFieldAlign;
2060 !DefaultsToAIXPowerAlignment ? FieldAlign : PreferredAlign;
2062 FieldOffset = FieldOffset.
alignTo(AlignTo);
2063 UnpackedFieldOffset = UnpackedFieldOffset.
alignTo(UnpackedFieldAlign);
2065 if (UseExternalLayout) {
2067 updateExternalFieldOffset(
D, Context.
toBits(FieldOffset)));
2069 if (!IsUnion && EmptySubobjects) {
2071 bool Allowed = EmptySubobjects->CanPlaceFieldAtOffset(
D, FieldOffset);
2073 assert(Allowed &&
"Externally-placed field cannot be placed here");
2076 if (!IsUnion && EmptySubobjects) {
2078 while (!EmptySubobjects->CanPlaceFieldAtOffset(
D, FieldOffset)) {
2083 FieldOffset = getDataSize().
alignTo(AlignTo);
2085 FieldOffset += AlignTo;
2091 FieldOffsets.push_back(Context.
toBits(FieldOffset));
2093 if (!UseExternalLayout)
2094 CheckFieldPadding(Context.
toBits(FieldOffset), UnpaddedFieldOffset,
2095 Context.
toBits(UnpackedFieldOffset),
2096 Context.
toBits(UnpackedFieldAlign), FieldPacked,
D);
2098 if (InsertExtraPadding) {
2100 CharUnits ExtraSizeForAsan = ASanAlignment;
2101 if (FieldSize % ASanAlignment)
2104 EffectiveFieldSize = FieldSize = FieldSize + ExtraSizeForAsan;
2108 if (!IsOverlappingEmptyField) {
2109 uint64_t EffectiveFieldSizeInBits = Context.
toBits(EffectiveFieldSize);
2111 setDataSize(std::max(getDataSizeInBits(), EffectiveFieldSizeInBits));
2113 setDataSize(FieldOffset + EffectiveFieldSize);
2115 PaddedFieldSize = std::max(PaddedFieldSize, FieldOffset + FieldSize);
2116 setSize(std::max(getSizeInBits(), getDataSizeInBits()));
2118 setSize(std::max(getSizeInBits(),
2119 (uint64_t)Context.
toBits(FieldOffset + FieldSize)));
2123 UnadjustedAlignment = std::max(UnadjustedAlignment, FieldAlign);
2124 UpdateAlignment(FieldAlign, UnpackedFieldAlign, PreferredAlign);
2130 if (RD->
hasAttr<PackedAttr>() || !MaxFieldAlignment.
isZero())
2131 if (FieldAlign < OriginalFieldAlign)
2132 if (
D->getType()->isRecordType()) {
2136 if (FieldOffset % OriginalFieldAlign != 0)
2142 if (Packed && !FieldPacked && PackedFieldAlign < FieldAlign)
2146void ItaniumRecordLayoutBuilder::FinishLayout(
const NamedDecl *
D) {
2148 if (Context.
getLangOpts().CPlusPlus && getSizeInBits() == 0) {
2162 setSize(std::max(getSizeInBits(), (uint64_t)Context.
toBits(PaddedFieldSize)));
2166 uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastUnit;
2168 llvm::alignTo(getSizeInBits(), Context.
toBits(UnpackedAlignment));
2170 uint64_t RoundedSize = llvm::alignTo(
2174 : PreferredAlignment));
2176 if (UseExternalLayout) {
2180 if (InferAlignment &&
External.Size < RoundedSize) {
2183 InferAlignment =
false;
2190 setSize(RoundedSize);
2193 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(
D)) {
2195 if (getSizeInBits() > UnpaddedSize) {
2196 unsigned PadSize = getSizeInBits() - UnpaddedSize;
2198 if (PadSize % CharBitNum == 0) {
2199 PadSize = PadSize / CharBitNum;
2205 << (InBits ? 1 : 0);
2208 const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD);
2216 if (Packed && UnpackedAlignment <= Alignment &&
2217 UnpackedSizeInBits == getSizeInBits() && !HasPackedField &&
2218 (!CXXRD || CXXRD->isPOD() ||
2226void ItaniumRecordLayoutBuilder::UpdateAlignment(
2231 if (IsMac68kAlign || (UseExternalLayout && !InferAlignment))
2234 if (NewAlignment > Alignment) {
2235 assert(llvm::isPowerOf2_64(NewAlignment.
getQuantity()) &&
2236 "Alignment not a power of 2");
2237 Alignment = NewAlignment;
2240 if (UnpackedNewAlignment > UnpackedAlignment) {
2241 assert(llvm::isPowerOf2_64(UnpackedNewAlignment.
getQuantity()) &&
2242 "Alignment not a power of 2");
2243 UnpackedAlignment = UnpackedNewAlignment;
2246 if (PreferredNewAlignment > PreferredAlignment) {
2247 assert(llvm::isPowerOf2_64(PreferredNewAlignment.
getQuantity()) &&
2248 "Alignment not a power of 2");
2249 PreferredAlignment = PreferredNewAlignment;
2254ItaniumRecordLayoutBuilder::updateExternalFieldOffset(
const FieldDecl *Field,
2255 uint64_t ComputedOffset) {
2258 if (InferAlignment && ExternalFieldOffset < ComputedOffset) {
2263 InferAlignment =
false;
2267 return ExternalFieldOffset;
2283 default: llvm_unreachable(
"Invalid tag kind for field padding diagnostic!");
2287void ItaniumRecordLayoutBuilder::CheckFieldPadding(
2288 uint64_t Offset, uint64_t UnpaddedOffset, uint64_t UnpackedOffset,
2289 unsigned UnpackedAlign,
bool isPacked,
const FieldDecl *
D) {
2292 if (isa<ObjCIvarDecl>(
D))
2303 if (!IsUnion && Offset > UnpaddedOffset) {
2304 unsigned PadSize = Offset - UnpaddedOffset;
2306 if (PadSize % CharBitNum == 0) {
2307 PadSize = PadSize / CharBitNum;
2310 if (
D->getIdentifier()) {
2311 auto Diagnostic =
D->isBitField() ? diag::warn_padded_struct_bitfield
2312 : diag::warn_padded_struct_field;
2317 <<
D->getIdentifier();
2319 auto Diagnostic =
D->isBitField() ? diag::warn_padded_struct_anon_bitfield
2320 : diag::warn_padded_struct_anon_field;
2324 << (InBits ? 1 : 0);
2327 if (isPacked && Offset != UnpackedOffset) {
2328 HasPackedField =
true;
2352 bool allowInlineFunctions =
2356 if (!MD->isVirtual())
2359 if (MD->isPureVirtual())
2364 if (MD->isImplicit())
2367 if (MD->isInlineSpecified() || MD->isConstexpr())
2370 if (MD->hasInlineBody())
2374 if (!MD->isUserProvided())
2378 if (!allowInlineFunctions) {
2390 if (!MD->hasAttr<CUDADeviceAttr>())
2394 if (!MD->hasAttr<CUDAHostAttr>() && MD->hasAttr<CUDADeviceAttr>())
2402 if (MD->hasAttr<DLLImportAttr>() && !RD->
hasAttr<DLLImportAttr>() &&
2457 llvm_unreachable(
"bad tail-padding use kind");
2560struct MicrosoftRecordLayoutBuilder {
2561 struct ElementInfo {
2565 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
2566 MicrosoftRecordLayoutBuilder(
const ASTContext &Context,
2567 EmptySubobjectMap *EmptySubobjects)
2568 : Context(Context), EmptySubobjects(EmptySubobjects) {}
2571 MicrosoftRecordLayoutBuilder(
const MicrosoftRecordLayoutBuilder &) =
delete;
2572 void operator=(
const MicrosoftRecordLayoutBuilder &) =
delete;
2593 void layoutBitField(
const FieldDecl *FD);
2596 void layoutZeroWidthBitField(
const FieldDecl *FD);
2605 ElementInfo getAdjustedElementInfo(
const FieldDecl *FD);
2607 void placeFieldAtOffset(
CharUnits FieldOffset) {
2608 FieldOffsets.push_back(Context.
toBits(FieldOffset));
2611 void placeFieldAtBitOffset(uint64_t FieldOffset) {
2612 FieldOffsets.push_back(FieldOffset);
2615 void computeVtorDispSet(
2616 llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtorDispSet,
2619 EmptySubobjectMap *EmptySubobjects;
2643 ElementInfo PointerInfo;
2651 BaseOffsetsMapTy Bases;
2657 unsigned RemainingBitsInField;
2661 bool LastFieldIsNonZeroWidthBitfield : 1;
2663 bool HasOwnVFPtr : 1;
2669 bool EndsWithZeroSizedObject : 1;
2672 bool LeadsWithZeroSizedBase : 1;
2675 bool UseExternalLayout : 1;
2683MicrosoftRecordLayoutBuilder::ElementInfo
2684MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
2689 if (!MaxFieldAlignment.
isZero())
2690 Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment);
2696 Alignment = std::max(Alignment, Info.Alignment);
2703MicrosoftRecordLayoutBuilder::ElementInfo
2704MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
2710 ElementInfo Info{TInfo.
Width, TInfo.Align};
2716 FieldRequiredAlignment = std::max(
2722 Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment);
2728 FieldRequiredAlignment = std::max(FieldRequiredAlignment,
2732 RequiredAlignment = std::max(RequiredAlignment, FieldRequiredAlignment);
2735 if (!MaxFieldAlignment.
isZero())
2736 Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment);
2737 if (FD->
hasAttr<PackedAttr>())
2739 Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment);
2743void MicrosoftRecordLayoutBuilder::layout(
const RecordDecl *RD) {
2746 initializeLayout(RD);
2748 DataSize =
Size =
Size.alignTo(Alignment);
2749 RequiredAlignment = std::max(
2754void MicrosoftRecordLayoutBuilder::cxxLayout(
const CXXRecordDecl *RD) {
2757 initializeLayout(RD);
2758 initializeCXXLayout(RD);
2759 layoutNonVirtualBases(RD);
2763 if (HasOwnVFPtr || (HasVBPtr && !SharedVBPtrBase))
2764 Alignment = std::max(Alignment, PointerInfo.Alignment);
2765 auto RoundingAlignment = Alignment;
2766 if (!MaxFieldAlignment.
isZero())
2767 RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment);
2768 if (!UseExternalLayout)
2769 Size =
Size.alignTo(RoundingAlignment);
2770 NonVirtualSize =
Size;
2771 RequiredAlignment = std::max(
2773 layoutVirtualBases(RD);
2777void MicrosoftRecordLayoutBuilder::initializeLayout(
const RecordDecl *RD) {
2790 if (
unsigned DefaultMaxFieldAlignment = Context.
getLangOpts().PackStruct)
2794 if (
const MaxFieldAlignmentAttr *MFAA = RD->
getAttr<MaxFieldAlignmentAttr>()){
2795 unsigned PackedAlignment = MFAA->getAlignment();
2796 if (PackedAlignment <=
2801 if (RD->
hasAttr<PackedAttr>())
2805 UseExternalLayout =
false;
2807 UseExternalLayout = Source->layoutRecordType(
2813MicrosoftRecordLayoutBuilder::initializeCXXLayout(
const CXXRecordDecl *RD) {
2814 EndsWithZeroSizedObject =
false;
2815 LeadsWithZeroSizedBase =
false;
2816 HasOwnVFPtr =
false;
2818 PrimaryBase =
nullptr;
2819 SharedVBPtrBase =
nullptr;
2827 if (!MaxFieldAlignment.
isZero())
2828 PointerInfo.Alignment = std::min(PointerInfo.Alignment, MaxFieldAlignment);
2832MicrosoftRecordLayoutBuilder::layoutNonVirtualBases(
const CXXRecordDecl *RD) {
2840 bool HasPolymorphicBaseClass =
false;
2847 if (
Base.isVirtual()) {
2852 if (!SharedVBPtrBase && BaseLayout.
hasVBPtr()) {
2853 SharedVBPtrBase = BaseDecl;
2861 PrimaryBase = BaseDecl;
2865 layoutNonVirtualBase(RD, BaseDecl, BaseLayout, PreviousBaseLayout);
2869 if (!HasPolymorphicBaseClass)
2873 else if (!PrimaryBase) {
2877 if (MicrosoftVTableContext::hasVtableSlot(M) &&
2878 M->size_overridden_methods() == 0) {
2887 bool CheckLeadingLayout = !PrimaryBase;
2890 if (
Base.isVirtual())
2901 if (CheckLeadingLayout) {
2902 CheckLeadingLayout =
false;
2906 layoutNonVirtualBase(RD, BaseDecl, BaseLayout, PreviousBaseLayout);
2912 else if (SharedVBPtrBase) {
2919 if (!isa<CXXRecordDecl>(RD))
2921 if (RD->
hasAttr<EmptyBasesAttr>())
2923 if (
auto *LVA = RD->
getAttr<LayoutVersionAttr>())
2925 if (LVA->getVersion() <= LangOptions::MSVC2015)
2933void MicrosoftRecordLayoutBuilder::layoutNonVirtualBase(
2944 ElementInfo Info = getAdjustedElementInfo(BaseLayout);
2948 bool FoundBase =
false;
2949 if (UseExternalLayout) {
2950 FoundBase =
External.getExternalNVBaseOffset(BaseDecl, BaseOffset);
2951 if (BaseOffset > Size) {
2957 if (MDCUsesEBO && BaseDecl->
isEmpty() &&
2962 BaseOffset =
Size =
Size.alignTo(Info.Alignment);
2965 Bases.insert(std::make_pair(BaseDecl, BaseOffset));
2968 PreviousBaseLayout = &BaseLayout;
2971void MicrosoftRecordLayoutBuilder::layoutFields(
const RecordDecl *RD) {
2972 LastFieldIsNonZeroWidthBitfield =
false;
2977void MicrosoftRecordLayoutBuilder::layoutField(
const FieldDecl *FD) {
2982 LastFieldIsNonZeroWidthBitfield =
false;
2983 ElementInfo Info = getAdjustedElementInfo(FD);
2984 Alignment = std::max(Alignment, Info.Alignment);
2989 FieldClass->
fields().empty();
2992 if (UseExternalLayout) {
2995 }
else if (IsUnion) {
2997 }
else if (EmptySubobjects) {
2998 if (!IsOverlappingEmptyField)
2999 FieldOffset = DataSize.
alignTo(Info.Alignment);
3001 while (!EmptySubobjects->CanPlaceFieldAtOffset(FD, FieldOffset)) {
3003 bool HasBases = ParentClass && (!ParentClass->
bases().empty() ||
3004 !ParentClass->
vbases().empty());
3009 FieldOffset = DataSize.
alignTo(Info.Alignment);
3011 FieldOffset += Info.Alignment;
3015 FieldOffset =
Size.alignTo(Info.Alignment);
3017 placeFieldAtOffset(FieldOffset);
3019 if (!IsOverlappingEmptyField)
3020 DataSize = std::max(DataSize, FieldOffset + Info.Size);
3022 Size = std::max(Size, FieldOffset + Info.Size);
3025void MicrosoftRecordLayoutBuilder::layoutBitField(
const FieldDecl *FD) {
3028 layoutZeroWidthBitField(FD);
3031 ElementInfo Info = getAdjustedElementInfo(FD);
3034 if (Width > Context.
toBits(Info.Size))
3035 Width = Context.
toBits(Info.Size);
3039 if (!UseExternalLayout && !IsUnion && LastFieldIsNonZeroWidthBitfield &&
3040 CurrentBitfieldSize == Info.Size && Width <= RemainingBitsInField) {
3041 placeFieldAtBitOffset(Context.
toBits(Size) - RemainingBitsInField);
3042 RemainingBitsInField -= Width;
3045 LastFieldIsNonZeroWidthBitfield =
true;
3046 CurrentBitfieldSize = Info.Size;
3047 if (UseExternalLayout) {
3048 auto FieldBitOffset =
External.getExternalFieldOffset(FD);
3049 placeFieldAtBitOffset(FieldBitOffset);
3051 llvm::alignDown(FieldBitOffset, Context.
toBits(Info.Alignment)) +
3052 Context.
toBits(Info.Size));
3053 Size = std::max(Size, NewSize);
3054 Alignment = std::max(Alignment, Info.Alignment);
3055 }
else if (IsUnion) {
3057 Size = std::max(Size, Info.Size);
3062 placeFieldAtOffset(FieldOffset);
3063 Size = FieldOffset + Info.Size;
3064 Alignment = std::max(Alignment, Info.Alignment);
3065 RemainingBitsInField = Context.
toBits(Info.Size) - Width;
3071MicrosoftRecordLayoutBuilder::layoutZeroWidthBitField(
const FieldDecl *FD) {
3074 if (!LastFieldIsNonZeroWidthBitfield) {
3080 LastFieldIsNonZeroWidthBitfield =
false;
3081 ElementInfo Info = getAdjustedElementInfo(FD);
3084 Size = std::max(Size, Info.Size);
3089 placeFieldAtOffset(FieldOffset);
3091 Alignment = std::max(Alignment, Info.Alignment);
3096void MicrosoftRecordLayoutBuilder::injectVBPtr(
const CXXRecordDecl *RD) {
3097 if (!HasVBPtr || SharedVBPtrBase)
3102 VBPtrOffset = VBPtrOffset.
alignTo(PointerInfo.Alignment);
3104 CharUnits FieldStart = VBPtrOffset + PointerInfo.Size;
3107 if (UseExternalLayout) {
3110 if (Size < FieldStart)
3116 CharUnits Offset = (FieldStart - InjectionSite)
3117 .alignTo(std::max(RequiredAlignment, Alignment));
3119 for (uint64_t &FieldOffset : FieldOffsets)
3120 FieldOffset += Context.
toBits(Offset);
3121 for (BaseOffsetsMapTy::value_type &
Base : Bases)
3122 if (
Base.second >= InjectionSite)
3123 Base.second += Offset;
3126void MicrosoftRecordLayoutBuilder::injectVFPtr(
const CXXRecordDecl *RD) {
3132 PointerInfo.Size.alignTo(std::max(RequiredAlignment, Alignment));
3136 VBPtrOffset += Offset;
3138 if (UseExternalLayout) {
3150 for (uint64_t &FieldOffset : FieldOffsets)
3151 FieldOffset += Context.
toBits(Offset);
3152 for (BaseOffsetsMapTy::value_type &
Base : Bases)
3153 Base.second += Offset;
3156void MicrosoftRecordLayoutBuilder::layoutVirtualBases(
const CXXRecordDecl *RD) {
3161 CharUnits VtorDispAlignment = VtorDispSize;
3163 if (!MaxFieldAlignment.
isZero())
3164 VtorDispAlignment = std::min(VtorDispAlignment, MaxFieldAlignment);
3169 const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl();
3174 VtorDispAlignment = std::max(VtorDispAlignment, RequiredAlignment);
3177 computeVtorDispSet(HasVtorDispSet, RD);
3181 const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl();
3183 bool HasVtordisp = HasVtorDispSet.contains(BaseDecl);
3192 Size =
Size.alignTo(VtorDispAlignment) + VtorDispSize;
3193 Alignment = std::max(VtorDispAlignment, Alignment);
3196 ElementInfo Info = getAdjustedElementInfo(BaseLayout);
3200 if (UseExternalLayout) {
3201 if (!
External.getExternalVBaseOffset(BaseDecl, BaseOffset))
3204 BaseOffset =
Size.alignTo(Info.Alignment);
3206 assert(BaseOffset >= Size &&
"base offset already allocated");
3208 VBases.insert(std::make_pair(BaseDecl,
3211 PreviousBaseLayout = &BaseLayout;
3215void MicrosoftRecordLayoutBuilder::finalizeLayout(
const RecordDecl *RD) {
3219 if (!RequiredAlignment.isZero()) {
3220 Alignment = std::max(Alignment, RequiredAlignment);
3221 auto RoundingAlignment = Alignment;
3222 if (!MaxFieldAlignment.
isZero())
3223 RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment);
3224 RoundingAlignment = std::max(RoundingAlignment, RequiredAlignment);
3225 Size =
Size.alignTo(RoundingAlignment);
3227 if (
Size.isZero()) {
3228 if (!
recordUsesEBO(RD) || !cast<CXXRecordDecl>(RD)->isEmpty()) {
3229 EndsWithZeroSizedObject =
true;
3230 LeadsWithZeroSizedBase =
true;
3234 if (RequiredAlignment >= MinEmptyStructSize)
3237 Size = MinEmptyStructSize;
3240 if (UseExternalLayout) {
3251 BasesWithOverriddenMethods,
3253 if (BasesWithOverriddenMethods.count(RD))
3258 if (!
Base.isVirtual() &&
3260 Base.getType()->getAsCXXRecordDecl()))
3265void MicrosoftRecordLayoutBuilder::computeVtorDispSet(
3266 llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtordispSet,
3275 HasVtordispSet.insert(BaseDecl);
3286 if (bi.second.hasVtorDisp())
3287 HasVtordispSet.insert(bi.first);
3307 if (MicrosoftVTableContext::hasVtableSlot(MD) &&
3308 !isa<CXXDestructorDecl>(MD) && !MD->isPureVirtual())
3310 while (!Work.empty()) {
3314 if (MethodRange.begin() == MethodRange.end())
3315 BasesWithOverriddenMethods.insert(MD->
getParent());
3317 Work.insert(MethodRange.begin(), MethodRange.end());
3325 if (!HasVtordispSet.count(BaseDecl) &&
3327 HasVtordispSet.insert(BaseDecl);
3341 if (
D->hasExternalLexicalStorage() && !
D->getDefinition())
3346 D =
D->getDefinition();
3347 assert(
D &&
"Cannot get layout of forward declarations!");
3348 assert(!
D->
isInvalidDecl() &&
"Cannot get layout of invalid decl!");
3349 assert(
D->isCompleteDefinition() &&
"Cannot layout type before complete!");
3355 if (Entry)
return *Entry;
3360 if (
const auto *RD = dyn_cast<CXXRecordDecl>(
D)) {
3361 EmptySubobjectMap EmptySubobjects(*
this, RD);
3362 MicrosoftRecordLayoutBuilder Builder(*
this, &EmptySubobjects);
3363 Builder.cxxLayout(RD);
3365 *
this, Builder.Size, Builder.Alignment, Builder.Alignment,
3366 Builder.Alignment, Builder.RequiredAlignment, Builder.HasOwnVFPtr,
3367 Builder.HasOwnVFPtr || Builder.PrimaryBase, Builder.VBPtrOffset,
3368 Builder.DataSize, Builder.FieldOffsets, Builder.NonVirtualSize,
3370 Builder.PrimaryBase,
false, Builder.SharedVBPtrBase,
3371 Builder.EndsWithZeroSizedObject, Builder.LeadsWithZeroSizedBase,
3372 Builder.Bases, Builder.VBases);
3374 MicrosoftRecordLayoutBuilder Builder(*
this,
nullptr);
3377 *
this, Builder.Size, Builder.Alignment, Builder.Alignment,
3378 Builder.Alignment, Builder.RequiredAlignment, Builder.Size,
3379 Builder.FieldOffsets);
3382 if (
const auto *RD = dyn_cast<CXXRecordDecl>(
D)) {
3383 EmptySubobjectMap EmptySubobjects(*
this, RD);
3384 ItaniumRecordLayoutBuilder Builder(*
this, &EmptySubobjects);
3390 bool skipTailPadding =
3395 skipTailPadding ? Builder.getSize() : Builder.getDataSize();
3397 skipTailPadding ? DataSize : Builder.NonVirtualSize;
3399 *
this, Builder.getSize(), Builder.Alignment,
3400 Builder.PreferredAlignment, Builder.UnadjustedAlignment,
3404 NonVirtualSize, Builder.NonVirtualAlignment,
3405 Builder.PreferredNVAlignment,
3406 EmptySubobjects.SizeOfLargestEmptySubobject, Builder.PrimaryBase,
3407 Builder.PrimaryBaseIsVirtual,
nullptr,
false,
false, Builder.Bases,
3410 ItaniumRecordLayoutBuilder Builder(*
this,
nullptr);
3414 *
this, Builder.getSize(), Builder.Alignment,
3415 Builder.PreferredAlignment, Builder.UnadjustedAlignment,
3417 Builder.Alignment, Builder.getSize(), Builder.FieldOffsets);
3421 ASTRecordLayouts[
D] = NewEntry;
3424 llvm::outs() <<
"\n*** Dumping AST Record Layout\n";
3435 assert(RD->
getDefinition() &&
"Cannot get key function for forward decl!");
3449 KeyFunctions[RD] =
const_cast<Decl*
>(
Result);
3451 return cast_or_null<CXXMethodDecl>(
Result);
3456 "not working with method declaration from class definition");
3461 const auto &Map = KeyFunctions;
3465 if (I == Map.end())
return;
3473 KeyFunctions.erase(Method->
getParent());
3483 uint64_t OffsetInBits;
3484 if (
const FieldDecl *FD = dyn_cast<FieldDecl>(VD)) {
3494 return OffsetInBits;
3522 for (
const ObjCIvarDecl *IVD = Container->all_declared_ivar_begin();
3523 IVD; IVD = IVD->getNextIvar()) {
3528 assert(Index < RL->getFieldCount() &&
"Ivar is not inside record layout!");
3542 if (
D->hasExternalLexicalStorage() && !
D->getDefinition())
3544 D =
D->getDefinition();
3546 "Invalid interface decl!");
3561 if (SynthCount == 0)
3562 return getObjCLayout(
D,
nullptr);
3565 ItaniumRecordLayoutBuilder Builder(*
this,
nullptr);
3569 *
this, Builder.getSize(), Builder.Alignment, Builder.PreferredAlignment,
3570 Builder.UnadjustedAlignment,
3572 Builder.Alignment, Builder.getDataSize(), Builder.FieldOffsets);
3574 ObjCLayouts[Key] = NewEntry;
3580 CharUnits Offset,
unsigned IndentLevel) {
3581 OS << llvm::format(
"%10" PRId64
" | ", (int64_t)Offset.getQuantity());
3582 OS.indent(IndentLevel * 2);
3586 unsigned Begin,
unsigned Width,
3587 unsigned IndentLevel) {
3590 llvm::raw_svector_ostream BufferOS(Buffer);
3591 BufferOS << Offset.getQuantity() <<
':';
3595 BufferOS <<
Begin <<
'-' << (
Begin + Width - 1);
3599 OS << llvm::right_justify(Buffer, 10) <<
" | ";
3600 OS.indent(IndentLevel * 2);
3605 OS.indent(IndentLevel * 2);
3611 unsigned IndentLevel,
3612 const char* Description,
3614 bool IncludeVirtualBases) {
3616 auto CXXRD = dyn_cast<CXXRecordDecl>(RD);
3619 OS <<
C.getTypeDeclType(
const_cast<RecordDecl *
>(RD));
3621 OS <<
' ' << Description;
3622 if (CXXRD && CXXRD->isEmpty())
3635 if (CXXRD->isDynamicClass() && !PrimaryBase && !
isMsLayout(
C)) {
3637 OS <<
'(' << *RD <<
" vtable pointer)\n";
3638 }
else if (HasOwnVFPtr) {
3641 OS <<
'(' << *RD <<
" vftable pointer)\n";
3647 assert(!
Base.getType()->isDependentType() &&
3648 "Cannot layout class with dependent bases.");
3649 if (!
Base.isVirtual())
3650 Bases.push_back(
Base.getType()->getAsCXXRecordDecl());
3663 Base == PrimaryBase ?
"(primary base)" :
"(base)",
3671 OS <<
'(' << *RD <<
" vbtable pointer)\n";
3676 uint64_t FieldNo = 0;
3680 uint64_t LocalFieldOffsetInBits = Layout.
getFieldOffset(FieldNo);
3682 Offset +
C.toCharUnitsFromBits(LocalFieldOffsetInBits);
3685 if (
auto RT = Field.getType()->getAs<
RecordType>()) {
3687 Field.getName().data(),
3693 if (Field.isBitField()) {
3694 uint64_t LocalFieldByteOffsetInBits =
C.toBits(FieldOffset - Offset);
3695 unsigned Begin = LocalFieldOffsetInBits - LocalFieldByteOffsetInBits;
3696 unsigned Width = Field.getBitWidthValue(
C);
3701 const QualType &FieldType =
C.getLangOpts().DumpRecordLayoutsCanonical
3702 ? Field.getType().getCanonicalType()
3704 OS << FieldType <<
' ' << Field <<
'\n';
3708 if (CXXRD && IncludeVirtualBases) {
3713 assert(
Base.isVirtual() &&
"Found non-virtual class!");
3718 if (VtorDisps.find(VBase)->second.hasVtorDisp()) {
3720 OS <<
"(vtordisp for vbase " << *VBase <<
")\n";
3725 "(primary virtual base)" :
"(virtual base)",
3731 if (!PrintSizeInfo)
return;
3738 if (
C.getTargetInfo().defaultsToAIXPowerAlignment())
3746 if (
C.getTargetInfo().defaultsToAIXPowerAlignment())
3747 OS <<
", preferrednvalign="
3754 bool Simple)
const {
3772 OS <<
"<ASTRecordLayout\n";
3777 if (
Target->defaultsToAIXPowerAlignment())
3780 if (
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
3781 OS <<
" BaseOffsets: [";
3783 for (
auto I : CXXRD->bases()) {
3788 Base = I.getType()->getAsCXXRecordDecl();
3789 OS << Info.CXXInfo->BaseOffsets[
Base].getQuantity();
3792 OS <<
" VBaseOffsets: [";
3794 for (
auto I : CXXRD->vbases()) {
3797 VBase = I.getType()->getAsCXXRecordDecl();
3798 OS << Info.CXXInfo->VBaseOffsets[VBase].VBaseOffset.getQuantity();
3802 OS <<
" FieldOffsets: [";
3803 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.
specific_decl_iterator - Iterates over a subrange of declarations stored in a DeclContext,...
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) ...
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 getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
unsigned getBitWidthValue(const ASTContext &Ctx) const
Computes the bit width of this field, if this is a bit field.
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_iterator field_end() const
field_range fields() const
field_iterator field_begin() 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.