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 unsigned FieldNo = 0;
303 E = Info->Class->field_end(); I !=
E; ++I, ++FieldNo) {
308 if (!CanPlaceFieldSubobjectAtOffset(*I, FieldOffset))
315void EmptySubobjectMap::UpdateEmptyBaseSubobjects(
const BaseSubobjectInfo *Info,
317 bool PlacingEmptyBase) {
318 if (!PlacingEmptyBase && Offset >= SizeOfLargestEmptySubobject) {
327 AddSubobjectAtOffset(Info->Class, Offset);
331 for (
const BaseSubobjectInfo *
Base : Info->Bases) {
336 UpdateEmptyBaseSubobjects(
Base, BaseOffset, PlacingEmptyBase);
339 if (Info->PrimaryVirtualBaseInfo) {
340 BaseSubobjectInfo *PrimaryVirtualBaseInfo = Info->PrimaryVirtualBaseInfo;
342 if (Info == PrimaryVirtualBaseInfo->Derived)
343 UpdateEmptyBaseSubobjects(PrimaryVirtualBaseInfo, Offset,
348 unsigned FieldNo = 0;
350 E = Info->Class->field_end(); I !=
E; ++I, ++FieldNo) {
355 UpdateEmptyFieldSubobjects(*I, FieldOffset, PlacingEmptyBase);
359bool EmptySubobjectMap::CanPlaceBaseAtOffset(
const BaseSubobjectInfo *Info,
363 if (SizeOfLargestEmptySubobject.isZero())
366 if (!CanPlaceBaseSubobjectAtOffset(Info, Offset))
371 UpdateEmptyBaseSubobjects(Info, Offset, Info->Class->isEmpty());
376EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(
const CXXRecordDecl *RD,
381 if (!AnyEmptySubobjectsBeyondOffset(Offset))
384 if (!CanPlaceSubobjectAtOffset(RD, Offset))
391 if (
Base.isVirtual())
397 if (!CanPlaceFieldSubobjectAtOffset(BaseDecl, Class, BaseOffset))
407 if (!CanPlaceFieldSubobjectAtOffset(VBaseDecl, Class, VBaseOffset))
413 unsigned FieldNo = 0;
415 I !=
E; ++I, ++FieldNo) {
421 if (!CanPlaceFieldSubobjectAtOffset(*I, FieldOffset))
429EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(
const FieldDecl *FD,
433 if (!AnyEmptySubobjectsBeyondOffset(Offset))
438 return CanPlaceFieldSubobjectAtOffset(RD, RD, Offset);
452 for (uint64_t I = 0; I != NumElements; ++I) {
455 if (!AnyEmptySubobjectsBeyondOffset(ElementOffset))
458 if (!CanPlaceFieldSubobjectAtOffset(RD, RD, ElementOffset))
461 ElementOffset += Layout.
getSize();
469EmptySubobjectMap::CanPlaceFieldAtOffset(
const FieldDecl *FD,
471 if (!CanPlaceFieldSubobjectAtOffset(FD, Offset))
476 UpdateEmptyFieldSubobjects(FD, Offset, FD->
hasAttr<NoUniqueAddressAttr>());
480void EmptySubobjectMap::UpdateEmptyFieldSubobjects(
482 bool PlacingOverlappingField) {
493 if (!PlacingOverlappingField && Offset >= SizeOfLargestEmptySubobject)
496 AddSubobjectAtOffset(RD, Offset);
502 if (
Base.isVirtual())
508 UpdateEmptyFieldSubobjects(BaseDecl, Class, BaseOffset,
509 PlacingOverlappingField);
518 UpdateEmptyFieldSubobjects(VBaseDecl, Class, VBaseOffset,
519 PlacingOverlappingField);
524 unsigned FieldNo = 0;
526 I !=
E; ++I, ++FieldNo) {
532 UpdateEmptyFieldSubobjects(*I, FieldOffset, PlacingOverlappingField);
536void EmptySubobjectMap::UpdateEmptyFieldSubobjects(
540 UpdateEmptyFieldSubobjects(RD, RD, Offset, PlacingOverlappingField);
557 for (uint64_t I = 0; I != NumElements; ++I) {
563 if (!PlacingOverlappingField &&
564 ElementOffset >= SizeOfLargestEmptySubobject)
567 UpdateEmptyFieldSubobjects(RD, RD, ElementOffset,
568 PlacingOverlappingField);
569 ElementOffset += Layout.
getSize();
576class ItaniumRecordLayoutBuilder {
583 EmptySubobjectMap *EmptySubobjects;
604 LLVM_PREFERRED_TYPE(
bool)
605 unsigned UseExternalLayout : 1;
609 LLVM_PREFERRED_TYPE(
bool)
610 unsigned InferAlignment : 1;
613 LLVM_PREFERRED_TYPE(
bool)
616 LLVM_PREFERRED_TYPE(
bool)
617 unsigned IsUnion : 1;
619 LLVM_PREFERRED_TYPE(
bool)
620 unsigned IsMac68kAlign : 1;
622 LLVM_PREFERRED_TYPE(
bool)
623 unsigned IsNaturalAlign : 1;
625 LLVM_PREFERRED_TYPE(
bool)
626 unsigned IsMsStruct : 1;
632 unsigned char UnfilledBitsInLastUnit;
636 unsigned char LastBitfieldStorageUnitSize;
659 bool PrimaryBaseIsVirtual;
672 bool HandledFirstNonOverlappingEmptyField;
674 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
677 BaseOffsetsMapTy Bases;
697 ItaniumRecordLayoutBuilder(
const ASTContext &Context,
698 EmptySubobjectMap *EmptySubobjects)
699 : Context(Context), EmptySubobjects(EmptySubobjects),
Size(0),
704 IsMac68kAlign(
false),
705 IsNaturalAlign(!Context.getTargetInfo().getTriple().isOSAIX()),
706 IsMsStruct(
false), UnfilledBitsInLastUnit(0),
707 LastBitfieldStorageUnitSize(0), MaxFieldAlignment(
CharUnits::
Zero()),
712 PrimaryBaseIsVirtual(
false), HasOwnVFPtr(
false), HasPackedField(
false),
713 HandledFirstNonOverlappingEmptyField(
false),
714 FirstNearlyEmptyVBase(nullptr) {}
721 void LayoutField(
const FieldDecl *
D,
bool InsertExtraPadding);
722 void LayoutWideBitField(uint64_t FieldSize, uint64_t StorageUnitSize,
731 llvm::SpecificBumpPtrAllocator<BaseSubobjectInfo> BaseSubobjectInfoAllocator;
733 typedef llvm::DenseMap<const CXXRecordDecl *, BaseSubobjectInfo *>
734 BaseSubobjectInfoMapTy;
742 BaseSubobjectInfoMapTy NonVirtualBaseInfo;
750 BaseSubobjectInfo *ComputeBaseSubobjectInfo(
const CXXRecordDecl *RD,
752 BaseSubobjectInfo *Derived);
759 void EnsureVTablePointerAlignment(
CharUnits UnpackedBaseAlign);
766 void LayoutNonVirtualBase(
const BaseSubobjectInfo *
Base);
768 void AddPrimaryVirtualBaseOffsets(
const BaseSubobjectInfo *Info,
776 void LayoutVirtualBase(
const BaseSubobjectInfo *
Base);
783 void InitializeLayout(
const Decl *
D);
792 UpdateAlignment(NewAlignment, UnpackedNewAlignment, NewAlignment);
794 void UpdateAlignment(
CharUnits NewAlignment) {
795 UpdateAlignment(NewAlignment, NewAlignment, NewAlignment);
804 uint64_t ComputedOffset);
806 void CheckFieldPadding(uint64_t Offset, uint64_t UnpaddedOffset,
807 uint64_t UnpackedOffset,
unsigned UnpackedAlign,
819 void setSize(uint64_t NewSize) {
Size = NewSize; }
821 CharUnits getAlignment()
const {
return Alignment; }
827 uint64_t getDataSizeInBits()
const {
return DataSize; }
829 void setDataSize(
CharUnits NewSize) { DataSize = Context.
toBits(NewSize); }
830 void setDataSize(uint64_t NewSize) { DataSize = NewSize; }
832 ItaniumRecordLayoutBuilder(
const ItaniumRecordLayoutBuilder &) =
delete;
833 void operator=(
const ItaniumRecordLayoutBuilder &) =
delete;
837void ItaniumRecordLayoutBuilder::SelectPrimaryVBase(
const CXXRecordDecl *RD) {
838 for (
const auto &I : RD->
bases()) {
839 assert(!I.getType()->isDependentType() &&
840 "Cannot layout class with dependent bases.");
848 if (!IndirectPrimaryBases.count(
Base)) {
850 PrimaryBaseIsVirtual =
true;
855 if (!FirstNearlyEmptyVBase)
856 FirstNearlyEmptyVBase =
Base;
859 SelectPrimaryVBase(
Base);
866void ItaniumRecordLayoutBuilder::DeterminePrimaryBase(
const CXXRecordDecl *RD) {
878 for (
const auto &I : RD->
bases()) {
885 if (
Base->isDynamicClass()) {
888 PrimaryBaseIsVirtual =
false;
898 SelectPrimaryVBase(RD);
904 if (FirstNearlyEmptyVBase) {
905 PrimaryBase = FirstNearlyEmptyVBase;
906 PrimaryBaseIsVirtual =
true;
910 assert(!PrimaryBase &&
"Should not get here with a primary base!");
913BaseSubobjectInfo *ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo(
914 const CXXRecordDecl *RD,
bool IsVirtual, BaseSubobjectInfo *Derived) {
915 BaseSubobjectInfo *Info;
921 assert(InfoSlot->Class == RD &&
"Wrong class for virtual base info!");
926 InfoSlot =
new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo;
929 Info =
new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo;
933 Info->IsVirtual = IsVirtual;
934 Info->Derived =
nullptr;
935 Info->PrimaryVirtualBaseInfo =
nullptr;
938 BaseSubobjectInfo *PrimaryVirtualBaseInfo =
nullptr;
946 assert(PrimaryVirtualBase &&
"Didn't have a primary virtual base!");
951 if (PrimaryVirtualBaseInfo) {
952 if (PrimaryVirtualBaseInfo->Derived) {
956 PrimaryVirtualBase =
nullptr;
959 Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;
960 PrimaryVirtualBaseInfo->Derived = Info;
967 for (
const auto &I : RD->
bases()) {
968 bool IsVirtual = I.isVirtual();
970 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
972 Info->Bases.push_back(ComputeBaseSubobjectInfo(BaseDecl, IsVirtual, Info));
975 if (PrimaryVirtualBase && !PrimaryVirtualBaseInfo) {
979 assert(PrimaryVirtualBaseInfo &&
980 "Did not create a primary virtual base!");
983 Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;
984 PrimaryVirtualBaseInfo->Derived = Info;
990void ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo(
992 for (
const auto &I : RD->
bases()) {
993 bool IsVirtual = I.isVirtual();
995 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
998 BaseSubobjectInfo *Info = ComputeBaseSubobjectInfo(BaseDecl, IsVirtual,
1004 "Did not add virtual base!");
1007 assert(!NonVirtualBaseInfo.count(BaseDecl) &&
1008 "Non-virtual base already exists!");
1009 NonVirtualBaseInfo.insert(std::make_pair(BaseDecl, Info));
1014void ItaniumRecordLayoutBuilder::EnsureVTablePointerAlignment(
1019 if (!MaxFieldAlignment.
isZero()) {
1020 BaseAlign = std::min(BaseAlign, MaxFieldAlignment);
1021 UnpackedBaseAlign = std::min(UnpackedBaseAlign, MaxFieldAlignment);
1025 setSize(getSize().alignTo(BaseAlign));
1028 UpdateAlignment(BaseAlign, UnpackedBaseAlign, BaseAlign);
1031void ItaniumRecordLayoutBuilder::LayoutNonVirtualBases(
1034 DeterminePrimaryBase(RD);
1037 ComputeBaseSubobjectInfo(RD);
1041 if (PrimaryBaseIsVirtual) {
1044 BaseSubobjectInfo *PrimaryBaseInfo =
VirtualBaseInfo.lookup(PrimaryBase);
1045 PrimaryBaseInfo->Derived =
nullptr;
1048 IndirectPrimaryBases.insert(PrimaryBase);
1050 assert(!VisitedVirtualBases.count(PrimaryBase) &&
1051 "vbase already visited!");
1052 VisitedVirtualBases.insert(PrimaryBase);
1054 LayoutVirtualBase(PrimaryBaseInfo);
1056 BaseSubobjectInfo *PrimaryBaseInfo =
1057 NonVirtualBaseInfo.lookup(PrimaryBase);
1058 assert(PrimaryBaseInfo &&
1059 "Did not find base info for non-virtual primary base!");
1061 LayoutNonVirtualBase(PrimaryBaseInfo);
1067 assert(DataSize == 0 &&
"Vtable pointer must be at offset zero!");
1072 EnsureVTablePointerAlignment(PtrAlign);
1075 assert(!IsUnion &&
"Unions cannot be dynamic classes.");
1076 HandledFirstNonOverlappingEmptyField =
true;
1078 setSize(getSize() + PtrWidth);
1079 setDataSize(getSize());
1083 for (
const auto &I : RD->
bases()) {
1089 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
1094 if (BaseDecl == PrimaryBase && !PrimaryBaseIsVirtual)
1098 BaseSubobjectInfo *BaseInfo = NonVirtualBaseInfo.
lookup(BaseDecl);
1099 assert(BaseInfo &&
"Did not find base info for non-virtual base!");
1101 LayoutNonVirtualBase(BaseInfo);
1105void ItaniumRecordLayoutBuilder::LayoutNonVirtualBase(
1106 const BaseSubobjectInfo *
Base) {
1111 assert(!Bases.count(
Base->Class) &&
"base offset already exists!");
1112 Bases.insert(std::make_pair(
Base->Class, Offset));
1114 AddPrimaryVirtualBaseOffsets(
Base, Offset);
1117void ItaniumRecordLayoutBuilder::AddPrimaryVirtualBaseOffsets(
1118 const BaseSubobjectInfo *Info,
CharUnits Offset) {
1120 if (!Info->Class->getNumVBases())
1124 if (Info->PrimaryVirtualBaseInfo) {
1125 assert(Info->PrimaryVirtualBaseInfo->IsVirtual &&
1126 "Primary virtual base is not virtual!");
1127 if (Info->PrimaryVirtualBaseInfo->Derived == Info) {
1129 assert(!VBases.count(Info->PrimaryVirtualBaseInfo->Class) &&
1130 "primary vbase offset already exists!");
1131 VBases.insert(std::make_pair(Info->PrimaryVirtualBaseInfo->Class,
1135 AddPrimaryVirtualBaseOffsets(Info->PrimaryVirtualBaseInfo, Offset);
1141 for (
const BaseSubobjectInfo *
Base : Info->Bases) {
1142 if (
Base->IsVirtual)
1146 AddPrimaryVirtualBaseOffsets(
Base, BaseOffset);
1150void ItaniumRecordLayoutBuilder::LayoutVirtualBases(
1153 bool PrimaryBaseIsVirtual;
1155 if (MostDerivedClass == RD) {
1156 PrimaryBase = this->PrimaryBase;
1157 PrimaryBaseIsVirtual = this->PrimaryBaseIsVirtual;
1165 assert(!
Base.getType()->isDependentType() &&
1166 "Cannot layout class with dependent bases.");
1170 if (
Base.isVirtual()) {
1171 if (PrimaryBase != BaseDecl || !PrimaryBaseIsVirtual) {
1172 bool IndirectPrimaryBase = IndirectPrimaryBases.count(BaseDecl);
1175 if (!IndirectPrimaryBase) {
1177 if (!VisitedVirtualBases.insert(BaseDecl).second)
1181 assert(BaseInfo &&
"Did not find virtual base info!");
1182 LayoutVirtualBase(BaseInfo);
1192 LayoutVirtualBases(BaseDecl, MostDerivedClass);
1196void ItaniumRecordLayoutBuilder::LayoutVirtualBase(
1197 const BaseSubobjectInfo *
Base) {
1198 assert(!
Base->Derived &&
"Trying to lay out a primary virtual base!");
1204 assert(!VBases.count(
Base->Class) &&
"vbase offset already exists!");
1205 VBases.insert(std::make_pair(
Base->Class,
1208 AddPrimaryVirtualBaseOffsets(
Base, Offset);
1212ItaniumRecordLayoutBuilder::LayoutBase(
const BaseSubobjectInfo *
Base) {
1213 assert(!IsUnion &&
"Unions cannot have base classes.");
1219 bool HasExternalLayout =
false;
1220 if (UseExternalLayout) {
1221 if (
Base->IsVirtual)
1222 HasExternalLayout =
External.getExternalVBaseOffset(
Base->Class, Offset);
1224 HasExternalLayout =
External.getExternalNVBaseOffset(
Base->Class, Offset);
1227 auto getBaseOrPreferredBaseAlignFromUnpacked = [&](
CharUnits UnpackedAlign) {
1230 return (Packed && ((Context.
getLangOpts().getClangABICompat() <=
1241 getBaseOrPreferredBaseAlignFromUnpacked(UnpackedBaseAlign);
1243 getBaseOrPreferredBaseAlignFromUnpacked(UnpackedPreferredBaseAlign);
1245 const bool DefaultsToAIXPowerAlignment =
1247 if (DefaultsToAIXPowerAlignment) {
1252 if (!
Base->Class->isEmpty() && !HandledFirstNonOverlappingEmptyField) {
1255 HandledFirstNonOverlappingEmptyField =
true;
1256 }
else if (!IsNaturalAlign) {
1257 UnpackedPreferredBaseAlign = UnpackedBaseAlign;
1258 PreferredBaseAlign = BaseAlign;
1262 CharUnits UnpackedAlignTo = !DefaultsToAIXPowerAlignment
1264 : UnpackedPreferredBaseAlign;
1266 if (
Base->Class->isEmpty() &&
1269 setSize(std::max(getSize(), Layout.
getSize()));
1272 UpdateAlignment(BaseAlign, UnpackedAlignTo, PreferredBaseAlign);
1279 if (!MaxFieldAlignment.
isZero()) {
1280 BaseAlign = std::min(BaseAlign, MaxFieldAlignment);
1281 PreferredBaseAlign = std::min(PreferredBaseAlign, MaxFieldAlignment);
1282 UnpackedAlignTo = std::min(UnpackedAlignTo, MaxFieldAlignment);
1286 !DefaultsToAIXPowerAlignment ? BaseAlign : PreferredBaseAlign;
1287 if (!HasExternalLayout) {
1289 Offset = getDataSize().alignTo(AlignTo);
1292 while (!EmptySubobjects->CanPlaceBaseAtOffset(
Base, Offset))
1295 bool Allowed = EmptySubobjects->CanPlaceBaseAtOffset(
Base, Offset);
1297 assert(Allowed &&
"Base subobject externally placed at overlapping offset");
1299 if (InferAlignment && Offset < getDataSize().alignTo(AlignTo)) {
1303 InferAlignment =
false;
1307 if (!
Base->Class->isEmpty()) {
1311 setSize(std::max(getSize(), getDataSize()));
1313 setSize(std::max(getSize(), Offset + Layout.
getSize()));
1316 UpdateAlignment(BaseAlign, UnpackedAlignTo, PreferredBaseAlign);
1321void ItaniumRecordLayoutBuilder::InitializeLayout(
const Decl *
D) {
1322 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(
D)) {
1330 if (
unsigned DefaultMaxFieldAlignment = Context.
getLangOpts().PackStruct) {
1338 if (
D->
hasAttr<AlignMac68kAttr>()) {
1341 "Having both mac68k and natural alignment on a decl is not allowed.");
1342 IsMac68kAlign =
true;
1347 if (
D->
hasAttr<AlignNaturalAttr>())
1348 IsNaturalAlign =
true;
1350 if (
const MaxFieldAlignmentAttr *MFAA =
D->
getAttr<MaxFieldAlignmentAttr>())
1357 HandledFirstNonOverlappingEmptyField =
1361 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(
D))
1363 UseExternalLayout = Source->layoutRecordType(
1368 if (UseExternalLayout) {
1374 InferAlignment =
true;
1380void ItaniumRecordLayoutBuilder::Layout(
const RecordDecl *
D) {
1381 InitializeLayout(
D);
1389void ItaniumRecordLayoutBuilder::Layout(
const CXXRecordDecl *RD) {
1390 InitializeLayout(RD);
1393 LayoutNonVirtualBases(RD);
1399 NonVirtualAlignment = Alignment;
1400 PreferredNVAlignment = PreferredAlignment;
1403 LayoutVirtualBases(RD, RD);
1412 if (
Base.isVirtual())
1417 assert(Bases.count(BaseDecl) &&
"Did not find base offset!");
1424 assert(VBases.count(BaseDecl) &&
"Did not find base offset!");
1438 setSize(getDataSize());
1441 InitializeLayout(
D);
1443 for (
const ObjCIvarDecl *IVD =
D->all_declared_ivar_begin(); IVD;
1444 IVD = IVD->getNextIvar())
1445 LayoutField(IVD,
false);
1452void ItaniumRecordLayoutBuilder::LayoutFields(
const RecordDecl *
D) {
1455 bool InsertExtraPadding =
D->mayInsertExtraPadding(
true);
1456 bool HasFlexibleArrayMember =
D->hasFlexibleArrayMember();
1457 for (
auto I =
D->field_begin(), End =
D->field_end(); I != End; ++I) {
1461 InsertExtraPadding && (Next != End || !HasFlexibleArrayMember));
1470 return llvm::alignTo(Size, CharAlignment);
1473void ItaniumRecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize,
1474 uint64_t StorageUnitSize,
1478 "Can only have wide bit-fields in C++!");
1490 for (
const QualType &QT : IntegralPODTypes) {
1493 if (Size > FieldSize)
1498 assert(!
Type.isNull() &&
"Did not find a type!");
1503 UnfilledBitsInLastUnit = 0;
1504 LastBitfieldStorageUnitSize = 0;
1507 uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;
1512 setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize));
1517 FieldOffset = llvm::alignTo(getDataSizeInBits(), Context.
toBits(TypeAlign));
1519 uint64_t NewSizeInBits = FieldOffset + FieldSize;
1523 UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits;
1527 FieldOffsets.push_back(FieldOffset);
1529 CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, FieldOffset,
1530 Context.
toBits(TypeAlign), FieldPacked,
D);
1533 setSize(std::max(getSizeInBits(), getDataSizeInBits()));
1536 UpdateAlignment(TypeAlign);
1543void ItaniumRecordLayoutBuilder::LayoutBitField(
const FieldDecl *
D) {
1544 bool FieldPacked = Packed ||
D->
hasAttr<PackedAttr>();
1545 uint64_t FieldSize =
D->getBitWidthValue(Context);
1548 unsigned FieldAlign = FieldInfo.
Align;
1611 FieldAlign = StorageUnitSize;
1616 if (LastBitfieldStorageUnitSize != StorageUnitSize ||
1617 UnfilledBitsInLastUnit < FieldSize) {
1619 if (!LastBitfieldStorageUnitSize && !FieldSize)
1622 UnfilledBitsInLastUnit = 0;
1623 LastBitfieldStorageUnitSize = 0;
1637 StorageUnitSize = 32;
1639 if (!AlignIsRequired)
1643 if (FieldAlign < StorageUnitSize) {
1646 FieldAlign = StorageUnitSize;
1653 if (FieldSize > StorageUnitSize && !
isAIXLayout(Context)) {
1654 LayoutWideBitField(FieldSize, StorageUnitSize, FieldPacked,
D);
1660 IsUnion ? 0 : (getDataSizeInBits() - UnfilledBitsInLastUnit);
1665 if (FieldSize == 0 &&
1668 if (!IsUnion && FieldOffset == 0 &&
1674 unsigned ZeroLengthBitfieldBoundary =
1676 FieldAlign = std::max(FieldAlign, ZeroLengthBitfieldBoundary);
1685 unsigned UnpackedFieldAlign = FieldAlign;
1688 if (!IsMsStruct && FieldPacked && FieldSize != 0)
1693 if (ExplicitFieldAlign) {
1694 FieldAlign = std::max(FieldAlign, ExplicitFieldAlign);
1695 UnpackedFieldAlign = std::max(UnpackedFieldAlign, ExplicitFieldAlign);
1700 unsigned MaxFieldAlignmentInBits = Context.
toBits(MaxFieldAlignment);
1701 if (!MaxFieldAlignment.
isZero() && FieldSize) {
1702 UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits);
1704 FieldAlign = UnpackedFieldAlign;
1706 FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits);
1711 if (IsMsStruct && IsUnion) {
1712 FieldAlign = UnpackedFieldAlign = 1;
1718 uint64_t UnpaddedFieldOffset = FieldOffset;
1719 uint64_t UnpackedFieldOffset = FieldOffset;
1729 if (FieldSize == 0 || FieldSize > UnfilledBitsInLastUnit) {
1730 FieldOffset = llvm::alignTo(FieldOffset, FieldAlign);
1731 UnpackedFieldOffset =
1732 llvm::alignTo(UnpackedFieldOffset, UnpackedFieldAlign);
1733 UnfilledBitsInLastUnit = 0;
1738 bool AllowPadding = MaxFieldAlignment.
isZero();
1741 if (FieldSize == 0 ||
1743 (FieldOffset & (FieldAlign - 1)) + FieldSize > StorageUnitSize)) {
1744 FieldOffset = llvm::alignTo(FieldOffset, FieldAlign);
1745 }
else if (ExplicitFieldAlign &&
1746 (MaxFieldAlignmentInBits == 0 ||
1747 ExplicitFieldAlign <= MaxFieldAlignmentInBits) &&
1751 FieldOffset = llvm::alignTo(FieldOffset, ExplicitFieldAlign);
1755 if (FieldSize == 0 ||
1757 (UnpackedFieldOffset & (UnpackedFieldAlign - 1)) + FieldSize >
1759 UnpackedFieldOffset =
1760 llvm::alignTo(UnpackedFieldOffset, UnpackedFieldAlign);
1761 else if (ExplicitFieldAlign &&
1762 (MaxFieldAlignmentInBits == 0 ||
1763 ExplicitFieldAlign <= MaxFieldAlignmentInBits) &&
1765 UnpackedFieldOffset =
1766 llvm::alignTo(UnpackedFieldOffset, ExplicitFieldAlign);
1771 if (UseExternalLayout)
1772 FieldOffset = updateExternalFieldOffset(
D, FieldOffset);
1775 FieldOffsets.push_back(FieldOffset);
1783 !
D->getIdentifier())
1784 FieldAlign = UnpackedFieldAlign = 1;
1792 if (!MaxFieldAlignment.
isZero()) {
1793 UnpackedFieldAlign =
1794 std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits);
1795 FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits);
1800 if (!UseExternalLayout)
1801 CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, UnpackedFieldOffset,
1802 UnpackedFieldAlign, FieldPacked,
D);
1812 RoundedFieldSize = (FieldSize ? StorageUnitSize
1820 setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize));
1824 }
else if (IsMsStruct && FieldSize) {
1827 if (!UnfilledBitsInLastUnit) {
1828 setDataSize(FieldOffset + StorageUnitSize);
1829 UnfilledBitsInLastUnit = StorageUnitSize;
1831 UnfilledBitsInLastUnit -= FieldSize;
1832 LastBitfieldStorageUnitSize = StorageUnitSize;
1838 uint64_t NewSizeInBits = FieldOffset + FieldSize;
1840 setDataSize(llvm::alignTo(NewSizeInBits, CharAlignment));
1841 UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits;
1846 LastBitfieldStorageUnitSize = 0;
1850 setSize(std::max(getSizeInBits(), getDataSizeInBits()));
1853 UnadjustedAlignment =
1859void ItaniumRecordLayoutBuilder::LayoutField(
const FieldDecl *
D,
1860 bool InsertExtraPadding) {
1861 auto *FieldClass =
D->getType()->getAsCXXRecordDecl();
1862 bool IsOverlappingEmptyField =
1863 D->isPotentiallyOverlapping() && FieldClass->isEmpty();
1866 (IsUnion || IsOverlappingEmptyField) ?
CharUnits::Zero() : getDataSize();
1868 const bool DefaultsToAIXPowerAlignment =
1870 bool FoundFirstNonOverlappingEmptyFieldForAIX =
false;
1871 if (DefaultsToAIXPowerAlignment && !HandledFirstNonOverlappingEmptyField) {
1873 "The first non-overlapping empty field should have been handled.");
1875 if (!IsOverlappingEmptyField) {
1876 FoundFirstNonOverlappingEmptyFieldForAIX =
true;
1883 HandledFirstNonOverlappingEmptyField = !IsUnion;
1887 if (
D->isBitField()) {
1892 uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;
1894 UnfilledBitsInLastUnit = 0;
1895 LastBitfieldStorageUnitSize = 0;
1907 auto setDeclInfo = [&](
bool IsIncompleteArrayType) {
1909 FieldAlign = TI.Align;
1912 EffectiveFieldSize = FieldSize =
1914 AlignRequirement = TI.AlignRequirement;
1917 if (
D->getType()->isIncompleteArrayType()) {
1920 setDeclInfo(
false );
1924 if (
D->isPotentiallyOverlapping()) {
1926 EffectiveFieldSize =
1940 if (!llvm::isPowerOf2_64(TypeSize.
getQuantity())) {
1943 "Non PowerOf2 size in MSVC mode");
1965 if (TypeSize > FieldAlign &&
1967 FieldAlign = TypeSize;
1972 bool FieldPacked = (Packed && (!FieldClass || FieldClass->isPOD() ||
1973 FieldClass->hasAttr<PackedAttr>() ||
1984 auto alignedAttrCanDecreaseAIXAlignment = [AlignRequirement, FieldPacked] {
2003 if (DefaultsToAIXPowerAlignment && !alignedAttrCanDecreaseAIXAlignment() &&
2004 (FoundFirstNonOverlappingEmptyFieldForAIX || IsNaturalAlign)) {
2005 auto performBuiltinTypeAlignmentUpgrade = [&](
const BuiltinType *BTy) {
2006 if (BTy->getKind() == BuiltinType::Double ||
2007 BTy->getKind() == BuiltinType::LongDouble) {
2009 "No need to upgrade the alignment value.");
2014 const Type *BaseTy =
D->getType()->getBaseElementTypeUnsafe();
2016 performBuiltinTypeAlignmentUpgrade(
2019 performBuiltinTypeAlignmentUpgrade(BTy);
2022 assert(RD &&
"Expected non-null RecordDecl.");
2030 CharUnits UnpackedFieldAlign = FieldAlign;
2032 CharUnits UnpackedFieldOffset = FieldOffset;
2033 CharUnits OriginalFieldAlign = UnpackedFieldAlign;
2037 PackedFieldAlign = std::max(PackedFieldAlign, MaxAlignmentInChars);
2038 PreferredAlign = std::max(PreferredAlign, MaxAlignmentInChars);
2039 UnpackedFieldAlign = std::max(UnpackedFieldAlign, MaxAlignmentInChars);
2042 if (!MaxFieldAlignment.
isZero()) {
2043 PackedFieldAlign = std::min(PackedFieldAlign, MaxFieldAlignment);
2044 PreferredAlign = std::min(PreferredAlign, MaxFieldAlignment);
2045 UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignment);
2050 FieldAlign = UnpackedFieldAlign;
2051 if (DefaultsToAIXPowerAlignment)
2052 UnpackedFieldAlign = PreferredAlign;
2054 PreferredAlign = PackedFieldAlign;
2055 FieldAlign = PackedFieldAlign;
2059 !DefaultsToAIXPowerAlignment ? FieldAlign : PreferredAlign;
2061 FieldOffset = FieldOffset.
alignTo(AlignTo);
2062 UnpackedFieldOffset = UnpackedFieldOffset.
alignTo(UnpackedFieldAlign);
2064 if (UseExternalLayout) {
2066 updateExternalFieldOffset(
D, Context.
toBits(FieldOffset)));
2068 if (!IsUnion && EmptySubobjects) {
2070 bool Allowed = EmptySubobjects->CanPlaceFieldAtOffset(
D, FieldOffset);
2072 assert(Allowed &&
"Externally-placed field cannot be placed here");
2075 if (!IsUnion && EmptySubobjects) {
2077 while (!EmptySubobjects->CanPlaceFieldAtOffset(
D, FieldOffset)) {
2082 FieldOffset = getDataSize().
alignTo(AlignTo);
2084 FieldOffset += AlignTo;
2090 FieldOffsets.push_back(Context.
toBits(FieldOffset));
2092 if (!UseExternalLayout)
2093 CheckFieldPadding(Context.
toBits(FieldOffset), UnpaddedFieldOffset,
2094 Context.
toBits(UnpackedFieldOffset),
2095 Context.
toBits(UnpackedFieldAlign), FieldPacked,
D);
2097 if (InsertExtraPadding) {
2099 CharUnits ExtraSizeForAsan = ASanAlignment;
2100 if (FieldSize % ASanAlignment)
2103 EffectiveFieldSize = FieldSize = FieldSize + ExtraSizeForAsan;
2107 if (!IsOverlappingEmptyField) {
2108 uint64_t EffectiveFieldSizeInBits = Context.
toBits(EffectiveFieldSize);
2110 setDataSize(std::max(getDataSizeInBits(), EffectiveFieldSizeInBits));
2112 setDataSize(FieldOffset + EffectiveFieldSize);
2114 PaddedFieldSize = std::max(PaddedFieldSize, FieldOffset + FieldSize);
2115 setSize(std::max(getSizeInBits(), getDataSizeInBits()));
2117 setSize(std::max(getSizeInBits(),
2118 (uint64_t)Context.
toBits(FieldOffset + FieldSize)));
2122 UnadjustedAlignment = std::max(UnadjustedAlignment, FieldAlign);
2123 UpdateAlignment(FieldAlign, UnpackedFieldAlign, PreferredAlign);
2129 if (RD->
hasAttr<PackedAttr>() || !MaxFieldAlignment.
isZero())
2130 if (FieldAlign < OriginalFieldAlign)
2131 if (
D->getType()->isRecordType()) {
2135 if (FieldOffset % OriginalFieldAlign != 0)
2141 if (Packed && !FieldPacked && PackedFieldAlign < FieldAlign)
2145void ItaniumRecordLayoutBuilder::FinishLayout(
const NamedDecl *
D) {
2147 if (Context.
getLangOpts().CPlusPlus && getSizeInBits() == 0) {
2161 setSize(std::max(getSizeInBits(), (uint64_t)Context.
toBits(PaddedFieldSize)));
2165 uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastUnit;
2167 llvm::alignTo(getSizeInBits(), Context.
toBits(UnpackedAlignment));
2169 uint64_t RoundedSize = llvm::alignTo(
2173 : PreferredAlignment));
2175 if (UseExternalLayout) {
2179 if (InferAlignment &&
External.Size < RoundedSize) {
2182 InferAlignment =
false;
2189 setSize(RoundedSize);
2192 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(
D)) {
2194 if (getSizeInBits() > UnpaddedSize) {
2195 unsigned PadSize = getSizeInBits() - UnpaddedSize;
2197 if (PadSize % CharBitNum == 0) {
2198 PadSize = PadSize / CharBitNum;
2204 << (InBits ? 1 : 0);
2207 const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD);
2215 if (Packed && UnpackedAlignment <= Alignment &&
2216 UnpackedSizeInBits == getSizeInBits() && !HasPackedField &&
2217 (!CXXRD || CXXRD->isPOD() ||
2225void ItaniumRecordLayoutBuilder::UpdateAlignment(
2230 if (IsMac68kAlign || (UseExternalLayout && !InferAlignment))
2233 if (NewAlignment > Alignment) {
2234 assert(llvm::isPowerOf2_64(NewAlignment.
getQuantity()) &&
2235 "Alignment not a power of 2");
2236 Alignment = NewAlignment;
2239 if (UnpackedNewAlignment > UnpackedAlignment) {
2240 assert(llvm::isPowerOf2_64(UnpackedNewAlignment.
getQuantity()) &&
2241 "Alignment not a power of 2");
2242 UnpackedAlignment = UnpackedNewAlignment;
2245 if (PreferredNewAlignment > PreferredAlignment) {
2246 assert(llvm::isPowerOf2_64(PreferredNewAlignment.
getQuantity()) &&
2247 "Alignment not a power of 2");
2248 PreferredAlignment = PreferredNewAlignment;
2253ItaniumRecordLayoutBuilder::updateExternalFieldOffset(
const FieldDecl *Field,
2254 uint64_t ComputedOffset) {
2257 if (InferAlignment && ExternalFieldOffset < ComputedOffset) {
2262 InferAlignment =
false;
2266 return ExternalFieldOffset;
2282 default: llvm_unreachable(
"Invalid tag kind for field padding diagnostic!");
2286void ItaniumRecordLayoutBuilder::CheckFieldPadding(
2287 uint64_t Offset, uint64_t UnpaddedOffset, uint64_t UnpackedOffset,
2288 unsigned UnpackedAlign,
bool isPacked,
const FieldDecl *
D) {
2291 if (isa<ObjCIvarDecl>(
D))
2302 if (!IsUnion && Offset > UnpaddedOffset) {
2303 unsigned PadSize = Offset - UnpaddedOffset;
2305 if (PadSize % CharBitNum == 0) {
2306 PadSize = PadSize / CharBitNum;
2309 if (
D->getIdentifier()) {
2310 auto Diagnostic =
D->isBitField() ? diag::warn_padded_struct_bitfield
2311 : diag::warn_padded_struct_field;
2316 <<
D->getIdentifier();
2318 auto Diagnostic =
D->isBitField() ? diag::warn_padded_struct_anon_bitfield
2319 : diag::warn_padded_struct_anon_field;
2323 << (InBits ? 1 : 0);
2326 if (isPacked && Offset != UnpackedOffset) {
2327 HasPackedField =
true;
2351 bool allowInlineFunctions =
2355 if (!MD->isVirtual())
2358 if (MD->isPureVirtual())
2363 if (MD->isImplicit())
2366 if (MD->isInlineSpecified() || MD->isConstexpr())
2369 if (MD->hasInlineBody())
2373 if (!MD->isUserProvided())
2377 if (!allowInlineFunctions) {
2389 if (!MD->hasAttr<CUDADeviceAttr>())
2393 if (!MD->hasAttr<CUDAHostAttr>() && MD->hasAttr<CUDADeviceAttr>())
2401 if (MD->hasAttr<DLLImportAttr>() && !RD->
hasAttr<DLLImportAttr>() &&
2456 llvm_unreachable(
"bad tail-padding use kind");
2559struct MicrosoftRecordLayoutBuilder {
2560 struct ElementInfo {
2564 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
2565 MicrosoftRecordLayoutBuilder(
const ASTContext &Context,
2566 EmptySubobjectMap *EmptySubobjects)
2567 : Context(Context), EmptySubobjects(EmptySubobjects) {}
2570 MicrosoftRecordLayoutBuilder(
const MicrosoftRecordLayoutBuilder &) =
delete;
2571 void operator=(
const MicrosoftRecordLayoutBuilder &) =
delete;
2592 void layoutBitField(
const FieldDecl *FD);
2595 void layoutZeroWidthBitField(
const FieldDecl *FD);
2604 ElementInfo getAdjustedElementInfo(
const FieldDecl *FD);
2606 void placeFieldAtOffset(
CharUnits FieldOffset) {
2607 FieldOffsets.push_back(Context.
toBits(FieldOffset));
2610 void placeFieldAtBitOffset(uint64_t FieldOffset) {
2611 FieldOffsets.push_back(FieldOffset);
2614 void computeVtorDispSet(
2615 llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtorDispSet,
2618 EmptySubobjectMap *EmptySubobjects;
2642 ElementInfo PointerInfo;
2650 BaseOffsetsMapTy Bases;
2656 unsigned RemainingBitsInField;
2660 bool LastFieldIsNonZeroWidthBitfield : 1;
2662 bool HasOwnVFPtr : 1;
2668 bool EndsWithZeroSizedObject : 1;
2671 bool LeadsWithZeroSizedBase : 1;
2674 bool UseExternalLayout : 1;
2682MicrosoftRecordLayoutBuilder::ElementInfo
2683MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
2688 if (!MaxFieldAlignment.
isZero())
2689 Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment);
2695 Alignment = std::max(Alignment, Info.Alignment);
2702MicrosoftRecordLayoutBuilder::ElementInfo
2703MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
2709 ElementInfo Info{TInfo.
Width, TInfo.Align};
2715 FieldRequiredAlignment = std::max(
2721 Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment);
2727 FieldRequiredAlignment = std::max(FieldRequiredAlignment,
2731 RequiredAlignment = std::max(RequiredAlignment, FieldRequiredAlignment);
2734 if (!MaxFieldAlignment.
isZero())
2735 Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment);
2736 if (FD->
hasAttr<PackedAttr>())
2738 Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment);
2742void MicrosoftRecordLayoutBuilder::layout(
const RecordDecl *RD) {
2745 initializeLayout(RD);
2747 DataSize =
Size =
Size.alignTo(Alignment);
2748 RequiredAlignment = std::max(
2753void MicrosoftRecordLayoutBuilder::cxxLayout(
const CXXRecordDecl *RD) {
2756 initializeLayout(RD);
2757 initializeCXXLayout(RD);
2758 layoutNonVirtualBases(RD);
2762 if (HasOwnVFPtr || (HasVBPtr && !SharedVBPtrBase))
2763 Alignment = std::max(Alignment, PointerInfo.Alignment);
2764 auto RoundingAlignment = Alignment;
2765 if (!MaxFieldAlignment.
isZero())
2766 RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment);
2767 if (!UseExternalLayout)
2768 Size =
Size.alignTo(RoundingAlignment);
2769 NonVirtualSize =
Size;
2770 RequiredAlignment = std::max(
2772 layoutVirtualBases(RD);
2776void MicrosoftRecordLayoutBuilder::initializeLayout(
const RecordDecl *RD) {
2789 if (
unsigned DefaultMaxFieldAlignment = Context.
getLangOpts().PackStruct)
2793 if (
const MaxFieldAlignmentAttr *MFAA = RD->
getAttr<MaxFieldAlignmentAttr>()){
2794 unsigned PackedAlignment = MFAA->getAlignment();
2795 if (PackedAlignment <=
2800 if (RD->
hasAttr<PackedAttr>())
2804 UseExternalLayout =
false;
2806 UseExternalLayout = Source->layoutRecordType(
2812MicrosoftRecordLayoutBuilder::initializeCXXLayout(
const CXXRecordDecl *RD) {
2813 EndsWithZeroSizedObject =
false;
2814 LeadsWithZeroSizedBase =
false;
2815 HasOwnVFPtr =
false;
2817 PrimaryBase =
nullptr;
2818 SharedVBPtrBase =
nullptr;
2826 if (!MaxFieldAlignment.
isZero())
2827 PointerInfo.Alignment = std::min(PointerInfo.Alignment, MaxFieldAlignment);
2831MicrosoftRecordLayoutBuilder::layoutNonVirtualBases(
const CXXRecordDecl *RD) {
2839 bool HasPolymorphicBaseClass =
false;
2846 if (
Base.isVirtual()) {
2851 if (!SharedVBPtrBase && BaseLayout.
hasVBPtr()) {
2852 SharedVBPtrBase = BaseDecl;
2860 PrimaryBase = BaseDecl;
2864 layoutNonVirtualBase(RD, BaseDecl, BaseLayout, PreviousBaseLayout);
2868 if (!HasPolymorphicBaseClass)
2872 else if (!PrimaryBase) {
2876 if (MicrosoftVTableContext::hasVtableSlot(M) &&
2877 M->size_overridden_methods() == 0) {
2886 bool CheckLeadingLayout = !PrimaryBase;
2889 if (
Base.isVirtual())
2900 if (CheckLeadingLayout) {
2901 CheckLeadingLayout =
false;
2905 layoutNonVirtualBase(RD, BaseDecl, BaseLayout, PreviousBaseLayout);
2911 else if (SharedVBPtrBase) {
2918 if (!isa<CXXRecordDecl>(RD))
2920 if (RD->
hasAttr<EmptyBasesAttr>())
2922 if (
auto *LVA = RD->
getAttr<LayoutVersionAttr>())
2924 if (LVA->getVersion() <= LangOptions::MSVC2015)
2932void MicrosoftRecordLayoutBuilder::layoutNonVirtualBase(
2943 ElementInfo Info = getAdjustedElementInfo(BaseLayout);
2947 bool FoundBase =
false;
2948 if (UseExternalLayout) {
2949 FoundBase =
External.getExternalNVBaseOffset(BaseDecl, BaseOffset);
2950 if (BaseOffset > Size) {
2956 if (MDCUsesEBO && BaseDecl->
isEmpty() &&
2961 BaseOffset =
Size =
Size.alignTo(Info.Alignment);
2964 Bases.insert(std::make_pair(BaseDecl, BaseOffset));
2967 PreviousBaseLayout = &BaseLayout;
2970void MicrosoftRecordLayoutBuilder::layoutFields(
const RecordDecl *RD) {
2971 LastFieldIsNonZeroWidthBitfield =
false;
2976void MicrosoftRecordLayoutBuilder::layoutField(
const FieldDecl *FD) {
2981 LastFieldIsNonZeroWidthBitfield =
false;
2982 ElementInfo Info = getAdjustedElementInfo(FD);
2983 Alignment = std::max(Alignment, Info.Alignment);
2988 FieldClass->
fields().empty();
2991 if (UseExternalLayout) {
2994 }
else if (IsUnion) {
2996 }
else if (EmptySubobjects) {
2997 if (!IsOverlappingEmptyField)
2998 FieldOffset = DataSize.
alignTo(Info.Alignment);
3000 while (!EmptySubobjects->CanPlaceFieldAtOffset(FD, FieldOffset)) {
3002 bool HasBases = ParentClass && (!ParentClass->
bases().empty() ||
3003 !ParentClass->
vbases().empty());
3008 FieldOffset = DataSize.
alignTo(Info.Alignment);
3010 FieldOffset += Info.Alignment;
3014 FieldOffset =
Size.alignTo(Info.Alignment);
3016 placeFieldAtOffset(FieldOffset);
3018 if (!IsOverlappingEmptyField)
3019 DataSize = std::max(DataSize, FieldOffset + Info.Size);
3021 Size = std::max(Size, FieldOffset + Info.Size);
3024void MicrosoftRecordLayoutBuilder::layoutBitField(
const FieldDecl *FD) {
3027 layoutZeroWidthBitField(FD);
3030 ElementInfo Info = getAdjustedElementInfo(FD);
3033 if (Width > Context.
toBits(Info.Size))
3034 Width = Context.
toBits(Info.Size);
3038 if (!UseExternalLayout && !IsUnion && LastFieldIsNonZeroWidthBitfield &&
3039 CurrentBitfieldSize == Info.Size && Width <= RemainingBitsInField) {
3040 placeFieldAtBitOffset(Context.
toBits(Size) - RemainingBitsInField);
3041 RemainingBitsInField -= Width;
3044 LastFieldIsNonZeroWidthBitfield =
true;
3045 CurrentBitfieldSize = Info.Size;
3046 if (UseExternalLayout) {
3047 auto FieldBitOffset =
External.getExternalFieldOffset(FD);
3048 placeFieldAtBitOffset(FieldBitOffset);
3050 llvm::alignDown(FieldBitOffset, Context.
toBits(Info.Alignment)) +
3051 Context.
toBits(Info.Size));
3052 Size = std::max(Size, NewSize);
3053 Alignment = std::max(Alignment, Info.Alignment);
3054 }
else if (IsUnion) {
3056 Size = std::max(Size, Info.Size);
3061 placeFieldAtOffset(FieldOffset);
3062 Size = FieldOffset + Info.Size;
3063 Alignment = std::max(Alignment, Info.Alignment);
3064 RemainingBitsInField = Context.
toBits(Info.Size) - Width;
3070MicrosoftRecordLayoutBuilder::layoutZeroWidthBitField(
const FieldDecl *FD) {
3073 if (!LastFieldIsNonZeroWidthBitfield) {
3079 LastFieldIsNonZeroWidthBitfield =
false;
3080 ElementInfo Info = getAdjustedElementInfo(FD);
3083 Size = std::max(Size, Info.Size);
3088 placeFieldAtOffset(FieldOffset);
3090 Alignment = std::max(Alignment, Info.Alignment);
3095void MicrosoftRecordLayoutBuilder::injectVBPtr(
const CXXRecordDecl *RD) {
3096 if (!HasVBPtr || SharedVBPtrBase)
3101 VBPtrOffset = VBPtrOffset.
alignTo(PointerInfo.Alignment);
3103 CharUnits FieldStart = VBPtrOffset + PointerInfo.Size;
3106 if (UseExternalLayout) {
3109 if (Size < FieldStart)
3115 CharUnits Offset = (FieldStart - InjectionSite)
3116 .alignTo(std::max(RequiredAlignment, Alignment));
3118 for (uint64_t &FieldOffset : FieldOffsets)
3119 FieldOffset += Context.
toBits(Offset);
3120 for (BaseOffsetsMapTy::value_type &
Base : Bases)
3121 if (
Base.second >= InjectionSite)
3122 Base.second += Offset;
3125void MicrosoftRecordLayoutBuilder::injectVFPtr(
const CXXRecordDecl *RD) {
3131 PointerInfo.Size.alignTo(std::max(RequiredAlignment, Alignment));
3135 VBPtrOffset += Offset;
3137 if (UseExternalLayout) {
3149 for (uint64_t &FieldOffset : FieldOffsets)
3150 FieldOffset += Context.
toBits(Offset);
3151 for (BaseOffsetsMapTy::value_type &
Base : Bases)
3152 Base.second += Offset;
3155void MicrosoftRecordLayoutBuilder::layoutVirtualBases(
const CXXRecordDecl *RD) {
3160 CharUnits VtorDispAlignment = VtorDispSize;
3162 if (!MaxFieldAlignment.
isZero())
3163 VtorDispAlignment = std::min(VtorDispAlignment, MaxFieldAlignment);
3168 const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl();
3173 VtorDispAlignment = std::max(VtorDispAlignment, RequiredAlignment);
3176 computeVtorDispSet(HasVtorDispSet, RD);
3180 const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl();
3182 bool HasVtordisp = HasVtorDispSet.contains(BaseDecl);
3191 Size =
Size.alignTo(VtorDispAlignment) + VtorDispSize;
3192 Alignment = std::max(VtorDispAlignment, Alignment);
3195 ElementInfo Info = getAdjustedElementInfo(BaseLayout);
3199 if (UseExternalLayout) {
3200 if (!
External.getExternalVBaseOffset(BaseDecl, BaseOffset))
3203 BaseOffset =
Size.alignTo(Info.Alignment);
3205 assert(BaseOffset >= Size &&
"base offset already allocated");
3207 VBases.insert(std::make_pair(BaseDecl,
3210 PreviousBaseLayout = &BaseLayout;
3214void MicrosoftRecordLayoutBuilder::finalizeLayout(
const RecordDecl *RD) {
3218 if (!RequiredAlignment.isZero()) {
3219 Alignment = std::max(Alignment, RequiredAlignment);
3220 auto RoundingAlignment = Alignment;
3221 if (!MaxFieldAlignment.
isZero())
3222 RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment);
3223 RoundingAlignment = std::max(RoundingAlignment, RequiredAlignment);
3224 Size =
Size.alignTo(RoundingAlignment);
3226 if (
Size.isZero()) {
3227 if (!
recordUsesEBO(RD) || !cast<CXXRecordDecl>(RD)->isEmpty()) {
3228 EndsWithZeroSizedObject =
true;
3229 LeadsWithZeroSizedBase =
true;
3233 if (RequiredAlignment >= MinEmptyStructSize)
3236 Size = MinEmptyStructSize;
3239 if (UseExternalLayout) {
3250 BasesWithOverriddenMethods,
3252 if (BasesWithOverriddenMethods.count(RD))
3257 if (!
Base.isVirtual() &&
3259 Base.getType()->getAsCXXRecordDecl()))
3264void MicrosoftRecordLayoutBuilder::computeVtorDispSet(
3265 llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtordispSet,
3274 HasVtordispSet.insert(BaseDecl);
3285 if (bi.second.hasVtorDisp())
3286 HasVtordispSet.insert(bi.first);
3306 if (MicrosoftVTableContext::hasVtableSlot(MD) &&
3307 !isa<CXXDestructorDecl>(MD) && !MD->isPureVirtual())
3309 while (!Work.empty()) {
3313 if (MethodRange.begin() == MethodRange.end())
3314 BasesWithOverriddenMethods.insert(MD->
getParent());
3316 Work.insert(MethodRange.begin(), MethodRange.end());
3324 if (!HasVtordispSet.count(BaseDecl) &&
3326 HasVtordispSet.insert(BaseDecl);
3340 if (
D->hasExternalLexicalStorage() && !
D->getDefinition())
3345 D =
D->getDefinition();
3346 assert(
D &&
"Cannot get layout of forward declarations!");
3347 assert(!
D->
isInvalidDecl() &&
"Cannot get layout of invalid decl!");
3348 assert(
D->isCompleteDefinition() &&
"Cannot layout type before complete!");
3354 if (Entry)
return *Entry;
3359 if (
const auto *RD = dyn_cast<CXXRecordDecl>(
D)) {
3360 EmptySubobjectMap EmptySubobjects(*
this, RD);
3361 MicrosoftRecordLayoutBuilder Builder(*
this, &EmptySubobjects);
3362 Builder.cxxLayout(RD);
3364 *
this, Builder.Size, Builder.Alignment, Builder.Alignment,
3365 Builder.Alignment, Builder.RequiredAlignment, Builder.HasOwnVFPtr,
3366 Builder.HasOwnVFPtr || Builder.PrimaryBase, Builder.VBPtrOffset,
3367 Builder.DataSize, Builder.FieldOffsets, Builder.NonVirtualSize,
3369 Builder.PrimaryBase,
false, Builder.SharedVBPtrBase,
3370 Builder.EndsWithZeroSizedObject, Builder.LeadsWithZeroSizedBase,
3371 Builder.Bases, Builder.VBases);
3373 MicrosoftRecordLayoutBuilder Builder(*
this,
nullptr);
3376 *
this, Builder.Size, Builder.Alignment, Builder.Alignment,
3377 Builder.Alignment, Builder.RequiredAlignment, Builder.Size,
3378 Builder.FieldOffsets);
3381 if (
const auto *RD = dyn_cast<CXXRecordDecl>(
D)) {
3382 EmptySubobjectMap EmptySubobjects(*
this, RD);
3383 ItaniumRecordLayoutBuilder Builder(*
this, &EmptySubobjects);
3389 bool skipTailPadding =
3394 skipTailPadding ? Builder.getSize() : Builder.getDataSize();
3396 skipTailPadding ? DataSize : Builder.NonVirtualSize;
3398 *
this, Builder.getSize(), Builder.Alignment,
3399 Builder.PreferredAlignment, Builder.UnadjustedAlignment,
3403 NonVirtualSize, Builder.NonVirtualAlignment,
3404 Builder.PreferredNVAlignment,
3405 EmptySubobjects.SizeOfLargestEmptySubobject, Builder.PrimaryBase,
3406 Builder.PrimaryBaseIsVirtual,
nullptr,
false,
false, Builder.Bases,
3409 ItaniumRecordLayoutBuilder Builder(*
this,
nullptr);
3413 *
this, Builder.getSize(), Builder.Alignment,
3414 Builder.PreferredAlignment, Builder.UnadjustedAlignment,
3416 Builder.Alignment, Builder.getSize(), Builder.FieldOffsets);
3420 ASTRecordLayouts[
D] = NewEntry;
3423 llvm::outs() <<
"\n*** Dumping AST Record Layout\n";
3434 assert(RD->
getDefinition() &&
"Cannot get key function for forward decl!");
3448 KeyFunctions[RD] =
const_cast<Decl*
>(
Result);
3450 return cast_or_null<CXXMethodDecl>(
Result);
3455 "not working with method declaration from class definition");
3460 const auto &Map = KeyFunctions;
3464 if (I == Map.end())
return;
3472 KeyFunctions.erase(Method->
getParent());
3482 uint64_t OffsetInBits;
3483 if (
const FieldDecl *FD = dyn_cast<FieldDecl>(VD)) {
3493 return OffsetInBits;
3521 for (
const ObjCIvarDecl *IVD = Container->all_declared_ivar_begin();
3522 IVD; IVD = IVD->getNextIvar()) {
3527 assert(Index < RL->getFieldCount() &&
"Ivar is not inside record layout!");
3541 if (
D->hasExternalLexicalStorage() && !
D->getDefinition())
3543 D =
D->getDefinition();
3545 "Invalid interface decl!");
3560 if (SynthCount == 0)
3561 return getObjCLayout(
D,
nullptr);
3564 ItaniumRecordLayoutBuilder Builder(*
this,
nullptr);
3568 *
this, Builder.getSize(), Builder.Alignment, Builder.PreferredAlignment,
3569 Builder.UnadjustedAlignment,
3571 Builder.Alignment, Builder.getDataSize(), Builder.FieldOffsets);
3573 ObjCLayouts[Key] = NewEntry;
3579 CharUnits Offset,
unsigned IndentLevel) {
3580 OS << llvm::format(
"%10" PRId64
" | ", (int64_t)Offset.getQuantity());
3581 OS.indent(IndentLevel * 2);
3585 unsigned Begin,
unsigned Width,
3586 unsigned IndentLevel) {
3589 llvm::raw_svector_ostream BufferOS(Buffer);
3590 BufferOS << Offset.getQuantity() <<
':';
3594 BufferOS <<
Begin <<
'-' << (
Begin + Width - 1);
3598 OS << llvm::right_justify(Buffer, 10) <<
" | ";
3599 OS.indent(IndentLevel * 2);
3604 OS.indent(IndentLevel * 2);
3610 unsigned IndentLevel,
3611 const char* Description,
3613 bool IncludeVirtualBases) {
3615 auto CXXRD = dyn_cast<CXXRecordDecl>(RD);
3618 OS <<
C.getTypeDeclType(
const_cast<RecordDecl *
>(RD));
3620 OS <<
' ' << Description;
3621 if (CXXRD && CXXRD->isEmpty())
3634 if (CXXRD->isDynamicClass() && !PrimaryBase && !
isMsLayout(
C)) {
3636 OS <<
'(' << *RD <<
" vtable pointer)\n";
3637 }
else if (HasOwnVFPtr) {
3640 OS <<
'(' << *RD <<
" vftable pointer)\n";
3646 assert(!
Base.getType()->isDependentType() &&
3647 "Cannot layout class with dependent bases.");
3648 if (!
Base.isVirtual())
3649 Bases.push_back(
Base.getType()->getAsCXXRecordDecl());
3662 Base == PrimaryBase ?
"(primary base)" :
"(base)",
3670 OS <<
'(' << *RD <<
" vbtable pointer)\n";
3675 uint64_t FieldNo = 0;
3679 uint64_t LocalFieldOffsetInBits = Layout.
getFieldOffset(FieldNo);
3681 Offset +
C.toCharUnitsFromBits(LocalFieldOffsetInBits);
3684 if (
auto RT = Field.getType()->getAs<
RecordType>()) {
3686 Field.getName().data(),
3692 if (Field.isBitField()) {
3693 uint64_t LocalFieldByteOffsetInBits =
C.toBits(FieldOffset - Offset);
3694 unsigned Begin = LocalFieldOffsetInBits - LocalFieldByteOffsetInBits;
3695 unsigned Width = Field.getBitWidthValue(
C);
3700 const QualType &FieldType =
C.getLangOpts().DumpRecordLayoutsCanonical
3701 ? Field.getType().getCanonicalType()
3703 OS << FieldType <<
' ' << Field <<
'\n';
3707 if (CXXRD && IncludeVirtualBases) {
3712 assert(
Base.isVirtual() &&
"Found non-virtual class!");
3717 if (VtorDisps.find(VBase)->second.hasVtorDisp()) {
3719 OS <<
"(vtordisp for vbase " << *VBase <<
")\n";
3724 "(primary virtual base)" :
"(virtual base)",
3730 if (!PrintSizeInfo)
return;
3737 if (
C.getTargetInfo().defaultsToAIXPowerAlignment())
3745 if (
C.getTargetInfo().defaultsToAIXPowerAlignment())
3746 OS <<
", preferrednvalign="
3753 bool Simple)
const {
3771 OS <<
"<ASTRecordLayout\n";
3776 if (
Target->defaultsToAIXPowerAlignment())
3779 if (
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
3780 OS <<
" BaseOffsets: [";
3782 for (
auto I : CXXRD->bases()) {
3787 Base = I.getType()->getAsCXXRecordDecl();
3788 OS << Info.CXXInfo->BaseOffsets[
Base].getQuantity();
3791 OS <<
" VBaseOffsets: [";
3793 for (
auto I : CXXRD->vbases()) {
3796 VBase = I.getType()->getAsCXXRecordDecl();
3797 OS << Info.CXXInfo->VBaseOffsets[VBase].VBaseOffset.getQuantity();
3801 OS <<
" FieldOffsets: [";
3802 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 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 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.