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;
208 const auto *MemberDecl =
215 if (MemberDecl->isEmpty()) {
223 if (EmptySize > SizeOfLargestEmptySubobject)
224 SizeOfLargestEmptySubobject = EmptySize;
229EmptySubobjectMap::CanPlaceSubobjectAtOffset(
const CXXRecordDecl *RD,
235 EmptyClassOffsetsMapTy::const_iterator I = EmptyClassOffsets.find(Offset);
236 if (I == EmptyClassOffsets.end())
239 const ClassVectorTy &Classes = I->second;
240 if (!llvm::is_contained(Classes, RD))
247void EmptySubobjectMap::AddSubobjectAtOffset(
const CXXRecordDecl *RD,
255 ClassVectorTy &Classes = EmptyClassOffsets[Offset];
256 if (llvm::is_contained(Classes, RD))
259 Classes.push_back(RD);
262 if (Offset > MaxEmptyClassOffset)
263 MaxEmptyClassOffset = Offset;
267EmptySubobjectMap::CanPlaceBaseSubobjectAtOffset(
const BaseSubobjectInfo *Info,
271 if (!AnyEmptySubobjectsBeyondOffset(Offset))
274 if (!CanPlaceSubobjectAtOffset(Info->Class, Offset))
279 for (
const BaseSubobjectInfo *
Base : Info->Bases) {
285 if (!CanPlaceBaseSubobjectAtOffset(
Base, BaseOffset))
289 if (Info->PrimaryVirtualBaseInfo) {
290 BaseSubobjectInfo *PrimaryVirtualBaseInfo = Info->PrimaryVirtualBaseInfo;
292 if (Info == PrimaryVirtualBaseInfo->Derived) {
293 if (!CanPlaceBaseSubobjectAtOffset(PrimaryVirtualBaseInfo, Offset))
299 for (
const FieldDecl *Field : Info->Class->fields()) {
300 if (
Field->isBitField())
304 if (!CanPlaceFieldSubobjectAtOffset(Field, FieldOffset))
311void EmptySubobjectMap::UpdateEmptyBaseSubobjects(
const BaseSubobjectInfo *Info,
313 bool PlacingEmptyBase) {
314 if (!PlacingEmptyBase && Offset >= SizeOfLargestEmptySubobject) {
323 AddSubobjectAtOffset(Info->Class, Offset);
327 for (
const BaseSubobjectInfo *
Base : Info->Bases) {
332 UpdateEmptyBaseSubobjects(
Base, BaseOffset, PlacingEmptyBase);
335 if (Info->PrimaryVirtualBaseInfo) {
336 BaseSubobjectInfo *PrimaryVirtualBaseInfo = Info->PrimaryVirtualBaseInfo;
338 if (Info == PrimaryVirtualBaseInfo->Derived)
339 UpdateEmptyBaseSubobjects(PrimaryVirtualBaseInfo, Offset,
344 for (
const FieldDecl *Field : Info->Class->fields()) {
345 if (
Field->isBitField())
349 UpdateEmptyFieldSubobjects(Field, FieldOffset, PlacingEmptyBase);
353bool EmptySubobjectMap::CanPlaceBaseAtOffset(
const BaseSubobjectInfo *Info,
357 if (SizeOfLargestEmptySubobject.isZero())
360 if (!CanPlaceBaseSubobjectAtOffset(Info, Offset))
365 UpdateEmptyBaseSubobjects(Info, Offset, Info->Class->isEmpty());
370EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(
const CXXRecordDecl *RD,
375 if (!AnyEmptySubobjectsBeyondOffset(Offset))
378 if (!CanPlaceSubobjectAtOffset(RD, Offset))
385 if (
Base.isVirtual())
391 if (!CanPlaceFieldSubobjectAtOffset(BaseDecl, Class, BaseOffset))
401 if (!CanPlaceFieldSubobjectAtOffset(VBaseDecl, Class, VBaseOffset))
408 if (
Field->isBitField())
412 if (!CanPlaceFieldSubobjectAtOffset(Field, FieldOffset))
420EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(
const FieldDecl *FD,
424 if (!AnyEmptySubobjectsBeyondOffset(Offset))
429 return CanPlaceFieldSubobjectAtOffset(RD, RD, Offset);
442 for (uint64_t I = 0; I != NumElements; ++I) {
445 if (!AnyEmptySubobjectsBeyondOffset(ElementOffset))
448 if (!CanPlaceFieldSubobjectAtOffset(RD, RD, ElementOffset))
451 ElementOffset += Layout.
getSize();
458bool EmptySubobjectMap::CanPlaceFieldAtOffset(
const FieldDecl *FD,
460 if (!CanPlaceFieldSubobjectAtOffset(FD, Offset))
465 UpdateEmptyFieldSubobjects(FD, Offset, FD->
hasAttr<NoUniqueAddressAttr>());
469void EmptySubobjectMap::UpdateEmptyFieldSubobjects(
471 bool PlacingOverlappingField) {
482 if (!PlacingOverlappingField && Offset >= SizeOfLargestEmptySubobject)
485 AddSubobjectAtOffset(RD, Offset);
491 if (
Base.isVirtual())
497 UpdateEmptyFieldSubobjects(BaseDecl, Class, BaseOffset,
498 PlacingOverlappingField);
507 UpdateEmptyFieldSubobjects(VBaseDecl, Class, VBaseOffset,
508 PlacingOverlappingField);
514 if (
Field->isBitField())
518 UpdateEmptyFieldSubobjects(Field, FieldOffset, PlacingOverlappingField);
522void EmptySubobjectMap::UpdateEmptyFieldSubobjects(
526 UpdateEmptyFieldSubobjects(RD, RD, Offset, PlacingOverlappingField);
542 for (uint64_t I = 0; I != NumElements; ++I) {
548 if (!PlacingOverlappingField &&
549 ElementOffset >= SizeOfLargestEmptySubobject)
552 UpdateEmptyFieldSubobjects(RD, RD, ElementOffset,
553 PlacingOverlappingField);
554 ElementOffset += Layout.
getSize();
561class ItaniumRecordLayoutBuilder {
568 EmptySubobjectMap *EmptySubobjects;
589 LLVM_PREFERRED_TYPE(
bool)
590 unsigned UseExternalLayout : 1;
594 LLVM_PREFERRED_TYPE(
bool)
595 unsigned InferAlignment : 1;
598 LLVM_PREFERRED_TYPE(
bool)
601 LLVM_PREFERRED_TYPE(
bool)
602 unsigned IsUnion : 1;
604 LLVM_PREFERRED_TYPE(
bool)
605 unsigned IsMac68kAlign : 1;
607 LLVM_PREFERRED_TYPE(
bool)
608 unsigned IsNaturalAlign : 1;
610 LLVM_PREFERRED_TYPE(
bool)
611 unsigned IsMsStruct : 1;
617 unsigned char UnfilledBitsInLastUnit;
621 unsigned char LastBitfieldStorageUnitSize;
644 bool PrimaryBaseIsVirtual;
657 bool HandledFirstNonOverlappingEmptyField;
659 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
662 BaseOffsetsMapTy Bases;
682 ItaniumRecordLayoutBuilder(
const ASTContext &Context,
683 EmptySubobjectMap *EmptySubobjects)
684 : Context(Context), EmptySubobjects(EmptySubobjects),
Size(0),
689 IsMac68kAlign(
false),
690 IsNaturalAlign(!Context.getTargetInfo().getTriple().isOSAIX()),
691 IsMsStruct(
false), UnfilledBitsInLastUnit(0),
692 LastBitfieldStorageUnitSize(0), MaxFieldAlignment(
CharUnits::
Zero()),
697 PrimaryBaseIsVirtual(
false), HasOwnVFPtr(
false), HasPackedField(
false),
698 HandledFirstNonOverlappingEmptyField(
false),
699 FirstNearlyEmptyVBase(nullptr) {}
706 void LayoutField(
const FieldDecl *
D,
bool InsertExtraPadding);
707 void LayoutWideBitField(uint64_t FieldSize, uint64_t StorageUnitSize,
716 llvm::SpecificBumpPtrAllocator<BaseSubobjectInfo> BaseSubobjectInfoAllocator;
718 typedef llvm::DenseMap<const CXXRecordDecl *, BaseSubobjectInfo *>
719 BaseSubobjectInfoMapTy;
727 BaseSubobjectInfoMapTy NonVirtualBaseInfo;
735 BaseSubobjectInfo *ComputeBaseSubobjectInfo(
const CXXRecordDecl *RD,
737 BaseSubobjectInfo *Derived);
744 void EnsureVTablePointerAlignment(
CharUnits UnpackedBaseAlign);
751 void LayoutNonVirtualBase(
const BaseSubobjectInfo *
Base);
753 void AddPrimaryVirtualBaseOffsets(
const BaseSubobjectInfo *Info,
761 void LayoutVirtualBase(
const BaseSubobjectInfo *
Base);
768 void InitializeLayout(
const Decl *
D);
777 UpdateAlignment(NewAlignment, UnpackedNewAlignment, NewAlignment);
779 void UpdateAlignment(
CharUnits NewAlignment) {
780 UpdateAlignment(NewAlignment, NewAlignment, NewAlignment);
789 uint64_t ComputedOffset);
792 uint64_t UnpackedOffset,
unsigned UnpackedAlign,
804 void setSize(uint64_t NewSize) {
Size = NewSize; }
806 CharUnits getAlignment()
const {
return Alignment; }
812 uint64_t getDataSizeInBits()
const {
return DataSize; }
814 void setDataSize(
CharUnits NewSize) { DataSize = Context.
toBits(NewSize); }
815 void setDataSize(uint64_t NewSize) { DataSize = NewSize; }
817 ItaniumRecordLayoutBuilder(
const ItaniumRecordLayoutBuilder &) =
delete;
818 void operator=(
const ItaniumRecordLayoutBuilder &) =
delete;
822void ItaniumRecordLayoutBuilder::SelectPrimaryVBase(
const CXXRecordDecl *RD) {
823 for (
const auto &I : RD->
bases()) {
824 assert(!I.getType()->isDependentType() &&
825 "Cannot layout class with dependent bases.");
833 if (!IndirectPrimaryBases.count(
Base)) {
835 PrimaryBaseIsVirtual =
true;
840 if (!FirstNearlyEmptyVBase)
841 FirstNearlyEmptyVBase =
Base;
844 SelectPrimaryVBase(
Base);
851void ItaniumRecordLayoutBuilder::DeterminePrimaryBase(
const CXXRecordDecl *RD) {
863 for (
const auto &I : RD->
bases()) {
870 if (
Base->isDynamicClass()) {
873 PrimaryBaseIsVirtual =
false;
883 SelectPrimaryVBase(RD);
889 if (FirstNearlyEmptyVBase) {
890 PrimaryBase = FirstNearlyEmptyVBase;
891 PrimaryBaseIsVirtual =
true;
895 assert(!PrimaryBase &&
"Should not get here with a primary base!");
898BaseSubobjectInfo *ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo(
899 const CXXRecordDecl *RD,
bool IsVirtual, BaseSubobjectInfo *Derived) {
900 BaseSubobjectInfo *Info;
906 assert(InfoSlot->Class == RD &&
"Wrong class for virtual base info!");
911 InfoSlot =
new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo;
914 Info =
new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo;
918 Info->IsVirtual = IsVirtual;
919 Info->Derived =
nullptr;
920 Info->PrimaryVirtualBaseInfo =
nullptr;
923 BaseSubobjectInfo *PrimaryVirtualBaseInfo =
nullptr;
931 assert(PrimaryVirtualBase &&
"Didn't have a primary virtual base!");
936 if (PrimaryVirtualBaseInfo) {
937 if (PrimaryVirtualBaseInfo->Derived) {
941 PrimaryVirtualBase =
nullptr;
944 Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;
945 PrimaryVirtualBaseInfo->Derived = Info;
952 for (
const auto &I : RD->
bases()) {
953 bool IsVirtual = I.isVirtual();
955 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
957 Info->Bases.push_back(ComputeBaseSubobjectInfo(BaseDecl, IsVirtual, Info));
960 if (PrimaryVirtualBase && !PrimaryVirtualBaseInfo) {
964 assert(PrimaryVirtualBaseInfo &&
965 "Did not create a primary virtual base!");
968 Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;
969 PrimaryVirtualBaseInfo->Derived = Info;
975void ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo(
977 for (
const auto &I : RD->
bases()) {
978 bool IsVirtual = I.isVirtual();
980 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
983 BaseSubobjectInfo *Info = ComputeBaseSubobjectInfo(BaseDecl, IsVirtual,
989 "Did not add virtual base!");
992 assert(!NonVirtualBaseInfo.count(BaseDecl) &&
993 "Non-virtual base already exists!");
994 NonVirtualBaseInfo.insert(std::make_pair(BaseDecl, Info));
999void ItaniumRecordLayoutBuilder::EnsureVTablePointerAlignment(
1004 if (!MaxFieldAlignment.
isZero()) {
1005 BaseAlign = std::min(BaseAlign, MaxFieldAlignment);
1006 UnpackedBaseAlign = std::min(UnpackedBaseAlign, MaxFieldAlignment);
1010 setSize(getSize().alignTo(BaseAlign));
1013 UpdateAlignment(BaseAlign, UnpackedBaseAlign, BaseAlign);
1016void ItaniumRecordLayoutBuilder::LayoutNonVirtualBases(
1019 DeterminePrimaryBase(RD);
1022 ComputeBaseSubobjectInfo(RD);
1026 if (PrimaryBaseIsVirtual) {
1029 BaseSubobjectInfo *PrimaryBaseInfo =
VirtualBaseInfo.lookup(PrimaryBase);
1030 PrimaryBaseInfo->Derived =
nullptr;
1033 IndirectPrimaryBases.insert(PrimaryBase);
1035 assert(!VisitedVirtualBases.count(PrimaryBase) &&
1036 "vbase already visited!");
1037 VisitedVirtualBases.insert(PrimaryBase);
1039 LayoutVirtualBase(PrimaryBaseInfo);
1041 BaseSubobjectInfo *PrimaryBaseInfo =
1042 NonVirtualBaseInfo.lookup(PrimaryBase);
1043 assert(PrimaryBaseInfo &&
1044 "Did not find base info for non-virtual primary base!");
1046 LayoutNonVirtualBase(PrimaryBaseInfo);
1052 assert(DataSize == 0 &&
"Vtable pointer must be at offset zero!");
1057 EnsureVTablePointerAlignment(PtrAlign);
1060 assert(!IsUnion &&
"Unions cannot be dynamic classes.");
1061 HandledFirstNonOverlappingEmptyField =
true;
1063 setSize(getSize() + PtrWidth);
1064 setDataSize(getSize());
1068 for (
const auto &I : RD->
bases()) {
1074 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
1079 if (BaseDecl == PrimaryBase && !PrimaryBaseIsVirtual)
1083 BaseSubobjectInfo *BaseInfo = NonVirtualBaseInfo.
lookup(BaseDecl);
1084 assert(BaseInfo &&
"Did not find base info for non-virtual base!");
1086 LayoutNonVirtualBase(BaseInfo);
1090void ItaniumRecordLayoutBuilder::LayoutNonVirtualBase(
1091 const BaseSubobjectInfo *
Base) {
1096 assert(!Bases.count(
Base->Class) &&
"base offset already exists!");
1097 Bases.insert(std::make_pair(
Base->Class, Offset));
1099 AddPrimaryVirtualBaseOffsets(
Base, Offset);
1102void ItaniumRecordLayoutBuilder::AddPrimaryVirtualBaseOffsets(
1103 const BaseSubobjectInfo *Info,
CharUnits Offset) {
1105 if (!Info->Class->getNumVBases())
1109 if (Info->PrimaryVirtualBaseInfo) {
1110 assert(Info->PrimaryVirtualBaseInfo->IsVirtual &&
1111 "Primary virtual base is not virtual!");
1112 if (Info->PrimaryVirtualBaseInfo->Derived == Info) {
1114 assert(!VBases.count(Info->PrimaryVirtualBaseInfo->Class) &&
1115 "primary vbase offset already exists!");
1116 VBases.insert(std::make_pair(Info->PrimaryVirtualBaseInfo->Class,
1120 AddPrimaryVirtualBaseOffsets(Info->PrimaryVirtualBaseInfo, Offset);
1126 for (
const BaseSubobjectInfo *
Base : Info->Bases) {
1127 if (
Base->IsVirtual)
1131 AddPrimaryVirtualBaseOffsets(
Base, BaseOffset);
1135void ItaniumRecordLayoutBuilder::LayoutVirtualBases(
1138 bool PrimaryBaseIsVirtual;
1140 if (MostDerivedClass == RD) {
1141 PrimaryBase = this->PrimaryBase;
1142 PrimaryBaseIsVirtual = this->PrimaryBaseIsVirtual;
1150 assert(!
Base.getType()->isDependentType() &&
1151 "Cannot layout class with dependent bases.");
1155 if (
Base.isVirtual()) {
1156 if (PrimaryBase != BaseDecl || !PrimaryBaseIsVirtual) {
1157 bool IndirectPrimaryBase = IndirectPrimaryBases.count(BaseDecl);
1160 if (!IndirectPrimaryBase) {
1162 if (!VisitedVirtualBases.insert(BaseDecl).second)
1166 assert(BaseInfo &&
"Did not find virtual base info!");
1167 LayoutVirtualBase(BaseInfo);
1177 LayoutVirtualBases(BaseDecl, MostDerivedClass);
1181void ItaniumRecordLayoutBuilder::LayoutVirtualBase(
1182 const BaseSubobjectInfo *
Base) {
1183 assert(!
Base->Derived &&
"Trying to lay out a primary virtual base!");
1189 assert(!VBases.count(
Base->Class) &&
"vbase offset already exists!");
1190 VBases.insert(std::make_pair(
Base->Class,
1193 AddPrimaryVirtualBaseOffsets(
Base, Offset);
1197ItaniumRecordLayoutBuilder::LayoutBase(
const BaseSubobjectInfo *
Base) {
1198 assert(!IsUnion &&
"Unions cannot have base classes.");
1204 bool HasExternalLayout =
false;
1205 if (UseExternalLayout) {
1206 if (
Base->IsVirtual)
1207 HasExternalLayout =
External.getExternalVBaseOffset(
Base->Class, Offset);
1209 HasExternalLayout =
External.getExternalNVBaseOffset(
Base->Class, Offset);
1212 auto getBaseOrPreferredBaseAlignFromUnpacked = [&](
CharUnits UnpackedAlign) {
1216 LangOptions::ClangABI::Ver6) ||
1226 getBaseOrPreferredBaseAlignFromUnpacked(UnpackedBaseAlign);
1228 getBaseOrPreferredBaseAlignFromUnpacked(UnpackedPreferredBaseAlign);
1230 const bool DefaultsToAIXPowerAlignment =
1232 if (DefaultsToAIXPowerAlignment) {
1237 if (!
Base->Class->isEmpty() && !HandledFirstNonOverlappingEmptyField) {
1240 HandledFirstNonOverlappingEmptyField =
true;
1241 }
else if (!IsNaturalAlign) {
1242 UnpackedPreferredBaseAlign = UnpackedBaseAlign;
1243 PreferredBaseAlign = BaseAlign;
1247 CharUnits UnpackedAlignTo = !DefaultsToAIXPowerAlignment
1249 : UnpackedPreferredBaseAlign;
1251 if (
Base->Class->isEmpty() &&
1254 setSize(std::max(getSize(), Layout.
getSize()));
1257 UpdateAlignment(BaseAlign, UnpackedAlignTo, PreferredBaseAlign);
1264 if (!MaxFieldAlignment.
isZero()) {
1265 BaseAlign = std::min(BaseAlign, MaxFieldAlignment);
1266 PreferredBaseAlign = std::min(PreferredBaseAlign, MaxFieldAlignment);
1267 UnpackedAlignTo = std::min(UnpackedAlignTo, MaxFieldAlignment);
1271 !DefaultsToAIXPowerAlignment ? BaseAlign : PreferredBaseAlign;
1272 if (!HasExternalLayout) {
1274 Offset = getDataSize().alignTo(AlignTo);
1277 while (!EmptySubobjects->CanPlaceBaseAtOffset(
Base, Offset))
1280 bool Allowed = EmptySubobjects->CanPlaceBaseAtOffset(
Base, Offset);
1282 assert(Allowed &&
"Base subobject externally placed at overlapping offset");
1284 if (InferAlignment && Offset < getDataSize().alignTo(AlignTo)) {
1288 InferAlignment =
false;
1292 if (!
Base->Class->isEmpty()) {
1296 setSize(std::max(getSize(), getDataSize()));
1298 setSize(std::max(getSize(), Offset + Layout.
getSize()));
1301 UnadjustedAlignment = std::max(UnadjustedAlignment, BaseAlign);
1302 UpdateAlignment(BaseAlign, UnpackedAlignTo, PreferredBaseAlign);
1307void ItaniumRecordLayoutBuilder::InitializeLayout(
const Decl *
D) {
1308 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(
D)) {
1316 if (
unsigned DefaultMaxFieldAlignment = Context.
getLangOpts().PackStruct) {
1324 if (
D->
hasAttr<AlignMac68kAttr>()) {
1327 "Having both mac68k and natural alignment on a decl is not allowed.");
1328 IsMac68kAlign =
true;
1333 if (
D->
hasAttr<AlignNaturalAttr>())
1334 IsNaturalAlign =
true;
1336 if (
const MaxFieldAlignmentAttr *MFAA =
D->
getAttr<MaxFieldAlignmentAttr>())
1343 HandledFirstNonOverlappingEmptyField =
1347 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(
D))
1349 UseExternalLayout = Source->layoutRecordType(
1354 if (UseExternalLayout) {
1360 InferAlignment =
true;
1366void ItaniumRecordLayoutBuilder::Layout(
const RecordDecl *
D) {
1367 InitializeLayout(
D);
1375void ItaniumRecordLayoutBuilder::Layout(
const CXXRecordDecl *RD) {
1376 InitializeLayout(RD);
1379 LayoutNonVirtualBases(RD);
1385 NonVirtualAlignment = Alignment;
1386 PreferredNVAlignment = PreferredAlignment;
1389 LayoutVirtualBases(RD, RD);
1398 if (
Base.isVirtual())
1403 assert(Bases.count(BaseDecl) &&
"Did not find base offset!");
1410 assert(VBases.count(BaseDecl) &&
"Did not find base offset!");
1424 setSize(getDataSize());
1427 InitializeLayout(
D);
1429 for (
const ObjCIvarDecl *IVD =
D->all_declared_ivar_begin(); IVD;
1430 IVD = IVD->getNextIvar())
1431 LayoutField(IVD,
false);
1438void ItaniumRecordLayoutBuilder::LayoutFields(
const RecordDecl *
D) {
1441 bool InsertExtraPadding =
D->mayInsertExtraPadding(
true);
1442 bool HasFlexibleArrayMember =
D->hasFlexibleArrayMember();
1443 for (
auto I =
D->field_begin(), End =
D->field_end(); I != End; ++I) {
1444 LayoutField(*I, InsertExtraPadding &&
1445 (std::next(I) != End || !HasFlexibleArrayMember));
1454 return llvm::alignTo(Size, CharAlignment);
1457void ItaniumRecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize,
1458 uint64_t StorageUnitSize,
1462 "Can only have wide bit-fields in C++!");
1477 for (
const QualType &QT : IntegralPODTypes) {
1480 if (Size > FieldSize || Size > MaxSize)
1485 assert(!
Type.isNull() &&
"Did not find a type!");
1490 UnfilledBitsInLastUnit = 0;
1491 LastBitfieldStorageUnitSize = 0;
1494 uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;
1499 setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize));
1504 FieldOffset = llvm::alignTo(getDataSizeInBits(), Context.
toBits(TypeAlign));
1506 uint64_t NewSizeInBits = FieldOffset + FieldSize;
1510 UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits;
1514 FieldOffsets.push_back(FieldOffset);
1517 Context.
toBits(TypeAlign), FieldPacked,
D);
1520 setSize(std::max(getSizeInBits(), getDataSizeInBits()));
1523 UnadjustedAlignment = std::max(UnadjustedAlignment, TypeAlign);
1524 UpdateAlignment(TypeAlign);
1531void ItaniumRecordLayoutBuilder::LayoutBitField(
const FieldDecl *
D) {
1533 uint64_t FieldSize =
D->getBitWidthValue();
1536 unsigned FieldAlign = FieldInfo.
Align;
1538 unsigned char PaddingInLastUnit = 0;
1600 FieldAlign = StorageUnitSize;
1605 if (LastBitfieldStorageUnitSize != StorageUnitSize ||
1606 UnfilledBitsInLastUnit < FieldSize) {
1608 if (!LastBitfieldStorageUnitSize && !FieldSize)
1611 PaddingInLastUnit = UnfilledBitsInLastUnit;
1612 UnfilledBitsInLastUnit = 0;
1613 LastBitfieldStorageUnitSize = 0;
1627 StorageUnitSize = 32;
1629 if (!AlignIsRequired)
1633 if (FieldAlign < StorageUnitSize) {
1636 FieldAlign = StorageUnitSize;
1643 if (FieldSize > StorageUnitSize && !
isAIXLayout(Context)) {
1644 LayoutWideBitField(FieldSize, StorageUnitSize, FieldPacked,
D);
1650 IsUnion ? 0 : (getDataSizeInBits() - UnfilledBitsInLastUnit);
1655 if (FieldSize == 0 &&
1658 if (!IsUnion && FieldOffset == 0 &&
1664 unsigned ZeroLengthBitfieldBoundary =
1666 FieldAlign = std::max(FieldAlign, ZeroLengthBitfieldBoundary);
1675 unsigned UnpackedFieldAlign = FieldAlign;
1678 if (!IsMsStruct && FieldPacked && FieldSize != 0)
1683 if (ExplicitFieldAlign) {
1684 FieldAlign = std::max(FieldAlign, ExplicitFieldAlign);
1685 UnpackedFieldAlign = std::max(UnpackedFieldAlign, ExplicitFieldAlign);
1690 unsigned MaxFieldAlignmentInBits = Context.
toBits(MaxFieldAlignment);
1691 if (!MaxFieldAlignment.
isZero() && FieldSize) {
1692 UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits);
1694 FieldAlign = UnpackedFieldAlign;
1696 FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits);
1701 if (IsMsStruct && IsUnion) {
1702 FieldAlign = UnpackedFieldAlign = 1;
1708 uint64_t UnpaddedFieldOffset = FieldOffset - PaddingInLastUnit;
1709 uint64_t UnpackedFieldOffset = FieldOffset;
1719 if (FieldSize == 0 || FieldSize > UnfilledBitsInLastUnit) {
1720 FieldOffset = llvm::alignTo(FieldOffset, FieldAlign);
1721 UnpackedFieldOffset =
1722 llvm::alignTo(UnpackedFieldOffset, UnpackedFieldAlign);
1723 UnfilledBitsInLastUnit = 0;
1728 bool AllowPadding = MaxFieldAlignment.
isZero();
1731 if (FieldSize == 0 ||
1733 (FieldOffset & (FieldAlign - 1)) + FieldSize > StorageUnitSize)) {
1734 FieldOffset = llvm::alignTo(FieldOffset, FieldAlign);
1735 }
else if (ExplicitFieldAlign &&
1736 (MaxFieldAlignmentInBits == 0 ||
1737 ExplicitFieldAlign <= MaxFieldAlignmentInBits) &&
1741 FieldOffset = llvm::alignTo(FieldOffset, ExplicitFieldAlign);
1745 if (FieldSize == 0 ||
1747 (UnpackedFieldOffset & (UnpackedFieldAlign - 1)) + FieldSize >
1749 UnpackedFieldOffset =
1750 llvm::alignTo(UnpackedFieldOffset, UnpackedFieldAlign);
1751 else if (ExplicitFieldAlign &&
1752 (MaxFieldAlignmentInBits == 0 ||
1753 ExplicitFieldAlign <= MaxFieldAlignmentInBits) &&
1755 UnpackedFieldOffset =
1756 llvm::alignTo(UnpackedFieldOffset, ExplicitFieldAlign);
1761 if (UseExternalLayout)
1762 FieldOffset = updateExternalFieldOffset(
D, FieldOffset);
1765 FieldOffsets.push_back(FieldOffset);
1773 !
D->getIdentifier())
1774 FieldAlign = UnpackedFieldAlign = 1;
1782 if (!MaxFieldAlignment.
isZero()) {
1783 UnpackedFieldAlign =
1784 std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits);
1785 FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits);
1790 if (!UseExternalLayout)
1792 UnpackedFieldAlign, FieldPacked,
D);
1802 RoundedFieldSize = (FieldSize ? StorageUnitSize
1810 setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize));
1814 }
else if (IsMsStruct && FieldSize) {
1817 if (!UnfilledBitsInLastUnit) {
1818 setDataSize(FieldOffset + StorageUnitSize);
1819 UnfilledBitsInLastUnit = StorageUnitSize;
1821 UnfilledBitsInLastUnit -= FieldSize;
1822 LastBitfieldStorageUnitSize = StorageUnitSize;
1828 uint64_t NewSizeInBits = FieldOffset + FieldSize;
1830 setDataSize(llvm::alignTo(NewSizeInBits, CharAlignment));
1831 UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits;
1836 LastBitfieldStorageUnitSize = 0;
1840 setSize(std::max(getSizeInBits(), getDataSizeInBits()));
1843 UnadjustedAlignment =
1849void ItaniumRecordLayoutBuilder::LayoutField(
const FieldDecl *
D,
1850 bool InsertExtraPadding) {
1851 auto *FieldClass =
D->getType()->getAsCXXRecordDecl();
1852 bool IsOverlappingEmptyField =
1853 D->isPotentiallyOverlapping() && FieldClass->isEmpty();
1856 (IsUnion || IsOverlappingEmptyField) ?
CharUnits::Zero() : getDataSize();
1858 const bool DefaultsToAIXPowerAlignment =
1860 bool FoundFirstNonOverlappingEmptyFieldForAIX =
false;
1861 if (DefaultsToAIXPowerAlignment && !HandledFirstNonOverlappingEmptyField) {
1863 "The first non-overlapping empty field should have been handled.");
1865 if (!IsOverlappingEmptyField) {
1866 FoundFirstNonOverlappingEmptyFieldForAIX =
true;
1873 HandledFirstNonOverlappingEmptyField = !IsUnion;
1877 if (
D->isBitField()) {
1882 uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;
1884 UnfilledBitsInLastUnit = 0;
1885 LastBitfieldStorageUnitSize = 0;
1897 auto setDeclInfo = [&](
bool IsIncompleteArrayType) {
1899 FieldAlign = TI.Align;
1902 EffectiveFieldSize = FieldSize =
1904 AlignRequirement = TI.AlignRequirement;
1907 if (
D->getType()->isIncompleteArrayType()) {
1910 setDeclInfo(
false );
1914 if (
D->isPotentiallyOverlapping()) {
1916 EffectiveFieldSize =
1930 if (!llvm::isPowerOf2_64(TypeSize.
getQuantity())) {
1933 "Non PowerOf2 size in MSVC mode");
1955 if (TypeSize > FieldAlign &&
1957 FieldAlign = TypeSize;
1962 bool FieldPacked = (
Packed && (!FieldClass || FieldClass->isPOD() ||
1963 FieldClass->hasAttr<PackedAttr>() ||
1965 LangOptions::ClangABI::Ver15 ||
1974 auto alignedAttrCanDecreaseAIXAlignment = [AlignRequirement, FieldPacked] {
1993 if (DefaultsToAIXPowerAlignment && !alignedAttrCanDecreaseAIXAlignment() &&
1994 (FoundFirstNonOverlappingEmptyFieldForAIX || IsNaturalAlign)) {
1995 auto performBuiltinTypeAlignmentUpgrade = [&](
const BuiltinType *BTy) {
1996 if (BTy->getKind() == BuiltinType::Double ||
1997 BTy->getKind() == BuiltinType::LongDouble) {
1999 "No need to upgrade the alignment value.");
2004 const Type *BaseTy =
D->getType()->getBaseElementTypeUnsafe();
2006 performBuiltinTypeAlignmentUpgrade(
2009 performBuiltinTypeAlignmentUpgrade(BTy);
2011 const RecordDecl *RD = RT->getOriginalDecl();
2019 CharUnits UnpackedFieldAlign = FieldAlign;
2021 CharUnits UnpackedFieldOffset = FieldOffset;
2022 CharUnits OriginalFieldAlign = UnpackedFieldAlign;
2026 PackedFieldAlign = std::max(PackedFieldAlign, MaxAlignmentInChars);
2027 PreferredAlign = std::max(PreferredAlign, MaxAlignmentInChars);
2028 UnpackedFieldAlign = std::max(UnpackedFieldAlign, MaxAlignmentInChars);
2031 if (!MaxFieldAlignment.
isZero()) {
2032 PackedFieldAlign = std::min(PackedFieldAlign, MaxFieldAlignment);
2033 PreferredAlign = std::min(PreferredAlign, MaxFieldAlignment);
2034 UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignment);
2039 FieldAlign = UnpackedFieldAlign;
2040 if (DefaultsToAIXPowerAlignment)
2041 UnpackedFieldAlign = PreferredAlign;
2043 PreferredAlign = PackedFieldAlign;
2044 FieldAlign = PackedFieldAlign;
2048 !DefaultsToAIXPowerAlignment ? FieldAlign : PreferredAlign;
2050 FieldOffset = FieldOffset.
alignTo(AlignTo);
2051 UnpackedFieldOffset = UnpackedFieldOffset.
alignTo(UnpackedFieldAlign);
2053 if (UseExternalLayout) {
2055 updateExternalFieldOffset(
D, Context.
toBits(FieldOffset)));
2057 if (!IsUnion && EmptySubobjects) {
2059 bool Allowed = EmptySubobjects->CanPlaceFieldAtOffset(
D, FieldOffset);
2061 assert(Allowed &&
"Externally-placed field cannot be placed here");
2064 if (!IsUnion && EmptySubobjects) {
2066 while (!EmptySubobjects->CanPlaceFieldAtOffset(
D, FieldOffset)) {
2071 FieldOffset = getDataSize().
alignTo(AlignTo);
2073 FieldOffset += AlignTo;
2079 FieldOffsets.push_back(Context.
toBits(FieldOffset));
2081 if (!UseExternalLayout)
2083 Context.
toBits(UnpackedFieldOffset),
2084 Context.
toBits(UnpackedFieldAlign), FieldPacked,
D);
2086 if (InsertExtraPadding) {
2088 CharUnits ExtraSizeForAsan = ASanAlignment;
2089 if (FieldSize % ASanAlignment)
2092 EffectiveFieldSize = FieldSize = FieldSize + ExtraSizeForAsan;
2096 if (!IsOverlappingEmptyField) {
2097 uint64_t EffectiveFieldSizeInBits = Context.
toBits(EffectiveFieldSize);
2099 setDataSize(std::max(getDataSizeInBits(), EffectiveFieldSizeInBits));
2101 setDataSize(FieldOffset + EffectiveFieldSize);
2103 PaddedFieldSize = std::max(PaddedFieldSize, FieldOffset + FieldSize);
2104 setSize(std::max(getSizeInBits(), getDataSizeInBits()));
2106 setSize(std::max(getSizeInBits(),
2107 (uint64_t)Context.
toBits(FieldOffset + FieldSize)));
2111 UnadjustedAlignment = std::max(UnadjustedAlignment, FieldAlign);
2112 UpdateAlignment(FieldAlign, UnpackedFieldAlign, PreferredAlign);
2118 if (RD->
hasAttr<PackedAttr>() || !MaxFieldAlignment.
isZero())
2119 if (FieldAlign < OriginalFieldAlign)
2120 if (
D->getType()->isRecordType()) {
2124 if (FieldOffset % OriginalFieldAlign != 0)
2131 if (
Packed && !FieldPacked && PackedFieldAlign < FieldAlign)
2135void ItaniumRecordLayoutBuilder::FinishLayout(
const NamedDecl *
D) {
2137 if (Context.
getLangOpts().CPlusPlus && getSizeInBits() == 0) {
2151 setSize(std::max(getSizeInBits(), (uint64_t)Context.
toBits(PaddedFieldSize)));
2155 uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastUnit;
2157 llvm::alignTo(getSizeInBits(), Context.
toBits(UnpackedAlignment));
2159 uint64_t RoundedSize = llvm::alignTo(
2163 : PreferredAlignment));
2165 if (UseExternalLayout) {
2169 if (InferAlignment &&
External.Size < RoundedSize) {
2172 InferAlignment =
false;
2179 setSize(RoundedSize);
2182 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(
D)) {
2184 if (getSizeInBits() > UnpaddedSize) {
2185 unsigned PadSize = getSizeInBits() - UnpaddedSize;
2187 if (PadSize % CharBitNum == 0) {
2188 PadSize = PadSize / CharBitNum;
2193 << (InBits ? 1 : 0);
2196 const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD);
2204 if (
Packed && UnpackedAlignment <= Alignment &&
2205 UnpackedSizeInBits == getSizeInBits() && !HasPackedField &&
2206 (!CXXRD || CXXRD->isPOD() ||
2208 LangOptions::ClangABI::Ver15))
2214void ItaniumRecordLayoutBuilder::UpdateAlignment(
2219 if (IsMac68kAlign || (UseExternalLayout && !InferAlignment))
2222 if (NewAlignment > Alignment) {
2223 assert(llvm::isPowerOf2_64(NewAlignment.
getQuantity()) &&
2224 "Alignment not a power of 2");
2225 Alignment = NewAlignment;
2228 if (UnpackedNewAlignment > UnpackedAlignment) {
2229 assert(llvm::isPowerOf2_64(UnpackedNewAlignment.
getQuantity()) &&
2230 "Alignment not a power of 2");
2231 UnpackedAlignment = UnpackedNewAlignment;
2234 if (PreferredNewAlignment > PreferredAlignment) {
2235 assert(llvm::isPowerOf2_64(PreferredNewAlignment.
getQuantity()) &&
2236 "Alignment not a power of 2");
2237 PreferredAlignment = PreferredNewAlignment;
2242ItaniumRecordLayoutBuilder::updateExternalFieldOffset(
const FieldDecl *Field,
2243 uint64_t ComputedOffset) {
2246 if (InferAlignment && ExternalFieldOffset < ComputedOffset) {
2251 InferAlignment =
false;
2255 return ExternalFieldOffset;
2271 default: llvm_unreachable(
"Invalid tag kind for field padding diagnostic!");
2276 uint64_t Offset, uint64_t UnpaddedOffset,
2280 if (isa<ObjCIvarDecl>(
D))
2291 if (!IsUnion && Offset > UnpaddedOffset) {
2292 unsigned PadSize = Offset - UnpaddedOffset;
2294 if (PadSize % CharBitNum == 0) {
2295 PadSize = PadSize / CharBitNum;
2298 if (
D->getIdentifier()) {
2299 auto Diagnostic =
D->isBitField() ? diag::warn_padded_struct_bitfield
2300 : diag::warn_padded_struct_field;
2306 <<
D->getIdentifier();
2308 auto Diagnostic =
D->isBitField() ? diag::warn_padded_struct_anon_bitfield
2309 : diag::warn_padded_struct_anon_field;
2314 << (InBits ? 1 : 0);
2319void ItaniumRecordLayoutBuilder::CheckFieldPadding(
2320 uint64_t Offset, uint64_t UnpaddedOffset, uint64_t UnpackedOffset,
2321 unsigned UnpackedAlign,
bool isPacked,
const FieldDecl *
D) {
2323 if (isPacked && Offset != UnpackedOffset) {
2324 HasPackedField =
true;
2348 bool allowInlineFunctions =
2352 if (!MD->isVirtual())
2355 if (MD->isPureVirtual())
2360 if (MD->isImplicit())
2363 if (MD->isInlineSpecified() || MD->isConstexpr())
2366 if (MD->hasInlineBody())
2370 if (!MD->isUserProvided())
2374 if (!allowInlineFunctions) {
2386 if (!MD->hasAttr<CUDADeviceAttr>())
2390 if (!MD->hasAttr<CUDAHostAttr>() && MD->hasAttr<CUDADeviceAttr>())
2398 if (MD->hasAttr<DLLImportAttr>() && !RD->
hasAttr<DLLImportAttr>() &&
2453 llvm_unreachable(
"bad tail-padding use kind");
2547struct MicrosoftRecordLayoutBuilder {
2548 struct ElementInfo {
2552 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
2553 MicrosoftRecordLayoutBuilder(
const ASTContext &Context,
2554 EmptySubobjectMap *EmptySubobjects)
2555 : Context(Context), EmptySubobjects(EmptySubobjects),
2556 RemainingBitsInField(0) {}
2559 MicrosoftRecordLayoutBuilder(
const MicrosoftRecordLayoutBuilder &) =
delete;
2560 void operator=(
const MicrosoftRecordLayoutBuilder &) =
delete;
2581 void layoutBitField(
const FieldDecl *FD);
2584 void layoutZeroWidthBitField(
const FieldDecl *FD);
2593 ElementInfo getAdjustedElementInfo(
const FieldDecl *FD);
2595 void placeFieldAtOffset(
CharUnits FieldOffset) {
2596 FieldOffsets.push_back(Context.
toBits(FieldOffset));
2599 void placeFieldAtBitOffset(uint64_t FieldOffset) {
2600 FieldOffsets.push_back(FieldOffset);
2603 void computeVtorDispSet(
2604 llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtorDispSet,
2607 EmptySubobjectMap *EmptySubobjects;
2631 ElementInfo PointerInfo;
2639 BaseOffsetsMapTy Bases;
2643 unsigned RemainingBitsInField;
2647 bool LastFieldIsNonZeroWidthBitfield : 1;
2649 bool HasOwnVFPtr : 1;
2655 bool EndsWithZeroSizedObject : 1;
2658 bool LeadsWithZeroSizedBase : 1;
2661 bool UseExternalLayout : 1;
2669MicrosoftRecordLayoutBuilder::ElementInfo
2670MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
2675 if (!MaxFieldAlignment.
isZero())
2676 Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment);
2682 Alignment = std::max(Alignment, Info.Alignment);
2689MicrosoftRecordLayoutBuilder::ElementInfo
2690MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
2696 ElementInfo Info{TInfo.
Width, TInfo.Align};
2702 FieldRequiredAlignment = std::max(
2708 Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment);
2710 if (
const auto *RT = FD->
getType()
2715 FieldRequiredAlignment = std::max(FieldRequiredAlignment,
2719 RequiredAlignment = std::max(RequiredAlignment, FieldRequiredAlignment);
2722 if (!MaxFieldAlignment.
isZero())
2723 Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment);
2724 if (FD->
hasAttr<PackedAttr>())
2726 Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment);
2730void MicrosoftRecordLayoutBuilder::layout(
const RecordDecl *RD) {
2733 initializeLayout(RD);
2735 DataSize =
Size =
Size.alignTo(Alignment);
2736 RequiredAlignment = std::max(
2741void MicrosoftRecordLayoutBuilder::cxxLayout(
const CXXRecordDecl *RD) {
2744 initializeLayout(RD);
2745 initializeCXXLayout(RD);
2746 layoutNonVirtualBases(RD);
2750 if (HasOwnVFPtr || (HasVBPtr && !SharedVBPtrBase))
2751 Alignment = std::max(Alignment, PointerInfo.Alignment);
2752 auto RoundingAlignment = Alignment;
2753 if (!MaxFieldAlignment.
isZero())
2754 RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment);
2755 if (!UseExternalLayout)
2756 Size =
Size.alignTo(RoundingAlignment);
2757 NonVirtualSize =
Size;
2758 RequiredAlignment = std::max(
2760 layoutVirtualBases(RD);
2764void MicrosoftRecordLayoutBuilder::initializeLayout(
const RecordDecl *RD) {
2777 if (
unsigned DefaultMaxFieldAlignment = Context.
getLangOpts().PackStruct)
2781 if (
const MaxFieldAlignmentAttr *MFAA = RD->
getAttr<MaxFieldAlignmentAttr>()){
2782 unsigned PackedAlignment = MFAA->getAlignment();
2783 if (PackedAlignment <=
2788 if (RD->
hasAttr<PackedAttr>())
2792 UseExternalLayout =
false;
2794 UseExternalLayout = Source->layoutRecordType(
2800MicrosoftRecordLayoutBuilder::initializeCXXLayout(
const CXXRecordDecl *RD) {
2801 EndsWithZeroSizedObject =
false;
2802 LeadsWithZeroSizedBase =
false;
2803 HasOwnVFPtr =
false;
2805 PrimaryBase =
nullptr;
2806 SharedVBPtrBase =
nullptr;
2814 if (!MaxFieldAlignment.
isZero())
2815 PointerInfo.Alignment = std::min(PointerInfo.Alignment, MaxFieldAlignment);
2819MicrosoftRecordLayoutBuilder::layoutNonVirtualBases(
const CXXRecordDecl *RD) {
2827 bool HasPolymorphicBaseClass =
false;
2834 if (
Base.isVirtual()) {
2839 if (!SharedVBPtrBase && BaseLayout.
hasVBPtr()) {
2840 SharedVBPtrBase = BaseDecl;
2848 PrimaryBase = BaseDecl;
2852 layoutNonVirtualBase(RD, BaseDecl, BaseLayout, PreviousBaseLayout);
2856 if (!HasPolymorphicBaseClass)
2860 else if (!PrimaryBase) {
2864 if (MicrosoftVTableContext::hasVtableSlot(M) &&
2865 M->size_overridden_methods() == 0) {
2874 bool CheckLeadingLayout = !PrimaryBase;
2877 if (
Base.isVirtual())
2888 if (CheckLeadingLayout) {
2889 CheckLeadingLayout =
false;
2893 layoutNonVirtualBase(RD, BaseDecl, BaseLayout, PreviousBaseLayout);
2899 else if (SharedVBPtrBase) {
2906 if (!isa<CXXRecordDecl>(RD))
2908 if (RD->
hasAttr<EmptyBasesAttr>())
2910 if (
auto *LVA = RD->
getAttr<LayoutVersionAttr>())
2912 if (LVA->getVersion() <= LangOptions::MSVC2015)
2920void MicrosoftRecordLayoutBuilder::layoutNonVirtualBase(
2931 ElementInfo Info = getAdjustedElementInfo(BaseLayout);
2935 bool FoundBase =
false;
2936 if (UseExternalLayout) {
2937 FoundBase =
External.getExternalNVBaseOffset(BaseDecl, BaseOffset);
2938 if (BaseOffset > Size) {
2944 if (MDCUsesEBO && BaseDecl->
isEmpty() &&
2949 BaseOffset =
Size =
Size.alignTo(Info.Alignment);
2952 Bases.insert(std::make_pair(BaseDecl, BaseOffset));
2955 PreviousBaseLayout = &BaseLayout;
2958void MicrosoftRecordLayoutBuilder::layoutFields(
const RecordDecl *RD) {
2959 LastFieldIsNonZeroWidthBitfield =
false;
2964void MicrosoftRecordLayoutBuilder::layoutField(
const FieldDecl *FD) {
2969 LastFieldIsNonZeroWidthBitfield =
false;
2970 ElementInfo Info = getAdjustedElementInfo(FD);
2971 Alignment = std::max(Alignment, Info.Alignment);
2976 FieldClass->
fields().empty();
2979 if (UseExternalLayout) {
2982 }
else if (IsUnion) {
2984 }
else if (EmptySubobjects) {
2985 if (!IsOverlappingEmptyField)
2986 FieldOffset = DataSize.
alignTo(Info.Alignment);
2988 while (!EmptySubobjects->CanPlaceFieldAtOffset(FD, FieldOffset)) {
2990 bool HasBases = ParentClass && (!ParentClass->
bases().empty() ||
2991 !ParentClass->
vbases().empty());
2996 FieldOffset = DataSize.
alignTo(Info.Alignment);
2998 FieldOffset += Info.Alignment;
3002 FieldOffset =
Size.alignTo(Info.Alignment);
3005 uint64_t UnpaddedFielddOffsetInBits =
3006 Context.
toBits(DataSize) - RemainingBitsInField;
3009 UnpaddedFielddOffsetInBits, FD);
3011 RemainingBitsInField = 0;
3013 placeFieldAtOffset(FieldOffset);
3015 if (!IsOverlappingEmptyField)
3016 DataSize = std::max(DataSize, FieldOffset + Info.Size);
3018 Size = std::max(Size, FieldOffset + Info.Size);
3021void MicrosoftRecordLayoutBuilder::layoutBitField(
const FieldDecl *FD) {
3024 layoutZeroWidthBitField(FD);
3027 ElementInfo Info = getAdjustedElementInfo(FD);
3030 if (Width > Context.
toBits(Info.Size))
3031 Width = Context.
toBits(Info.Size);
3035 if (!UseExternalLayout && !IsUnion && LastFieldIsNonZeroWidthBitfield &&
3036 CurrentBitfieldSize == Info.Size && Width <= RemainingBitsInField) {
3037 placeFieldAtBitOffset(Context.
toBits(Size) - RemainingBitsInField);
3038 RemainingBitsInField -= Width;
3041 LastFieldIsNonZeroWidthBitfield =
true;
3042 CurrentBitfieldSize = Info.Size;
3043 if (UseExternalLayout) {
3044 auto FieldBitOffset =
External.getExternalFieldOffset(FD);
3045 placeFieldAtBitOffset(FieldBitOffset);
3047 llvm::alignDown(FieldBitOffset, Context.
toBits(Info.Alignment)) +
3048 Context.
toBits(Info.Size));
3049 Size = std::max(Size, NewSize);
3050 Alignment = std::max(Alignment, Info.Alignment);
3051 }
else if (IsUnion) {
3053 Size = std::max(Size, Info.Size);
3058 uint64_t UnpaddedFieldOffsetInBits =
3059 Context.
toBits(DataSize) - RemainingBitsInField;
3060 placeFieldAtOffset(FieldOffset);
3061 Size = FieldOffset + Info.Size;
3062 Alignment = std::max(Alignment, Info.Alignment);
3063 RemainingBitsInField = Context.
toBits(Info.Size) - Width;
3065 UnpaddedFieldOffsetInBits, FD);
3071MicrosoftRecordLayoutBuilder::layoutZeroWidthBitField(
const FieldDecl *FD) {
3074 if (!LastFieldIsNonZeroWidthBitfield) {
3080 LastFieldIsNonZeroWidthBitfield =
false;
3081 ElementInfo Info = getAdjustedElementInfo(FD);
3084 Size = std::max(Size, Info.Size);
3089 uint64_t UnpaddedFieldOffsetInBits =
3090 Context.
toBits(DataSize) - RemainingBitsInField;
3091 placeFieldAtOffset(FieldOffset);
3092 RemainingBitsInField = 0;
3094 Alignment = std::max(Alignment, Info.Alignment);
3096 UnpaddedFieldOffsetInBits, FD);
3101void MicrosoftRecordLayoutBuilder::injectVBPtr(
const CXXRecordDecl *RD) {
3102 if (!HasVBPtr || SharedVBPtrBase)
3107 VBPtrOffset = VBPtrOffset.
alignTo(PointerInfo.Alignment);
3109 CharUnits FieldStart = VBPtrOffset + PointerInfo.Size;
3112 if (UseExternalLayout) {
3115 if (Size < FieldStart)
3121 CharUnits Offset = (FieldStart - InjectionSite)
3122 .alignTo(std::max(RequiredAlignment, Alignment));
3124 for (uint64_t &FieldOffset : FieldOffsets)
3125 FieldOffset += Context.
toBits(Offset);
3126 for (BaseOffsetsMapTy::value_type &
Base : Bases)
3127 if (
Base.second >= InjectionSite)
3128 Base.second += Offset;
3131void MicrosoftRecordLayoutBuilder::injectVFPtr(
const CXXRecordDecl *RD) {
3137 PointerInfo.Size.alignTo(std::max(RequiredAlignment, Alignment));
3141 VBPtrOffset += Offset;
3143 if (UseExternalLayout) {
3155 for (uint64_t &FieldOffset : FieldOffsets)
3156 FieldOffset += Context.
toBits(Offset);
3157 for (BaseOffsetsMapTy::value_type &
Base : Bases)
3158 Base.second += Offset;
3161void MicrosoftRecordLayoutBuilder::layoutVirtualBases(
const CXXRecordDecl *RD) {
3166 CharUnits VtorDispAlignment = VtorDispSize;
3168 if (!MaxFieldAlignment.
isZero())
3169 VtorDispAlignment = std::min(VtorDispAlignment, MaxFieldAlignment);
3174 const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl();
3179 VtorDispAlignment = std::max(VtorDispAlignment, RequiredAlignment);
3182 computeVtorDispSet(HasVtorDispSet, RD);
3186 const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl();
3188 bool HasVtordisp = HasVtorDispSet.contains(BaseDecl);
3197 Size =
Size.alignTo(VtorDispAlignment) + VtorDispSize;
3198 Alignment = std::max(VtorDispAlignment, Alignment);
3201 ElementInfo Info = getAdjustedElementInfo(BaseLayout);
3205 if (UseExternalLayout) {
3206 if (!
External.getExternalVBaseOffset(BaseDecl, BaseOffset))
3209 BaseOffset =
Size.alignTo(Info.Alignment);
3211 assert(BaseOffset >= Size &&
"base offset already allocated");
3213 VBases.insert(std::make_pair(BaseDecl,
3216 PreviousBaseLayout = &BaseLayout;
3220void MicrosoftRecordLayoutBuilder::finalizeLayout(
const RecordDecl *RD) {
3222 UnpaddedSizeInBits -= RemainingBitsInField;
3227 UnpaddedSizeInBits += 8;
3232 if (!RequiredAlignment.isZero()) {
3233 Alignment = std::max(Alignment, RequiredAlignment);
3234 auto RoundingAlignment = Alignment;
3235 if (!MaxFieldAlignment.
isZero())
3236 RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment);
3237 RoundingAlignment = std::max(RoundingAlignment, RequiredAlignment);
3238 Size =
Size.alignTo(RoundingAlignment);
3240 if (
Size.isZero()) {
3241 if (!
recordUsesEBO(RD) || !cast<CXXRecordDecl>(RD)->isEmpty()) {
3242 EndsWithZeroSizedObject =
true;
3243 LeadsWithZeroSizedBase =
true;
3247 if (RequiredAlignment >= MinEmptyStructSize)
3250 Size = MinEmptyStructSize;
3253 if (UseExternalLayout) {
3262 if (SizeInBits > UnpaddedSizeInBits) {
3263 unsigned int PadSize = SizeInBits - UnpaddedSizeInBits;
3265 if (PadSize % CharBitNum == 0) {
3266 PadSize = PadSize / CharBitNum;
3271 diag::warn_padded_struct_size)
3273 << (InBits ? 1 : 0);
3281 BasesWithOverriddenMethods,
3283 if (BasesWithOverriddenMethods.count(RD))
3288 if (!
Base.isVirtual() &&
3290 Base.getType()->getAsCXXRecordDecl()))
3295void MicrosoftRecordLayoutBuilder::computeVtorDispSet(
3296 llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtordispSet,
3305 HasVtordispSet.insert(BaseDecl);
3316 if (bi.second.hasVtorDisp())
3317 HasVtordispSet.insert(bi.first);
3337 if (MicrosoftVTableContext::hasVtableSlot(MD) &&
3338 !isa<CXXDestructorDecl>(MD) && !MD->isPureVirtual())
3340 while (!Work.empty()) {
3344 if (MethodRange.begin() == MethodRange.end())
3345 BasesWithOverriddenMethods.insert(MD->
getParent());
3347 Work.insert_range(MethodRange);
3355 if (!HasVtordispSet.count(BaseDecl) &&
3357 HasVtordispSet.insert(BaseDecl);
3371 if (
D->hasExternalLexicalStorage() && !
D->getDefinition())
3376 D =
D->getDefinition();
3377 assert(
D &&
"Cannot get layout of forward declarations!");
3378 assert(!
D->
isInvalidDecl() &&
"Cannot get layout of invalid decl!");
3379 assert(
D->isCompleteDefinition() &&
"Cannot layout type before complete!");
3385 if (Entry)
return *Entry;
3390 if (
const auto *RD = dyn_cast<CXXRecordDecl>(
D)) {
3391 EmptySubobjectMap EmptySubobjects(*
this, RD);
3392 MicrosoftRecordLayoutBuilder Builder(*
this, &EmptySubobjects);
3393 Builder.cxxLayout(RD);
3395 *
this, Builder.Size, Builder.Alignment, Builder.Alignment,
3396 Builder.Alignment, Builder.RequiredAlignment, Builder.HasOwnVFPtr,
3397 Builder.HasOwnVFPtr || Builder.PrimaryBase, Builder.VBPtrOffset,
3398 Builder.DataSize, Builder.FieldOffsets, Builder.NonVirtualSize,
3400 Builder.PrimaryBase,
false, Builder.SharedVBPtrBase,
3401 Builder.EndsWithZeroSizedObject, Builder.LeadsWithZeroSizedBase,
3402 Builder.Bases, Builder.VBases);
3404 MicrosoftRecordLayoutBuilder Builder(*
this,
nullptr);
3407 *
this, Builder.Size, Builder.Alignment, Builder.Alignment,
3408 Builder.Alignment, Builder.RequiredAlignment, Builder.Size,
3409 Builder.FieldOffsets);
3412 if (
const auto *RD = dyn_cast<CXXRecordDecl>(
D)) {
3413 EmptySubobjectMap EmptySubobjects(*
this, RD);
3414 ItaniumRecordLayoutBuilder Builder(*
this, &EmptySubobjects);
3420 bool skipTailPadding =
3425 skipTailPadding ? Builder.getSize() : Builder.getDataSize();
3427 skipTailPadding ? DataSize : Builder.NonVirtualSize;
3429 *
this, Builder.getSize(), Builder.Alignment,
3430 Builder.PreferredAlignment, Builder.UnadjustedAlignment,
3434 NonVirtualSize, Builder.NonVirtualAlignment,
3435 Builder.PreferredNVAlignment,
3436 EmptySubobjects.SizeOfLargestEmptySubobject, Builder.PrimaryBase,
3437 Builder.PrimaryBaseIsVirtual,
nullptr,
false,
false, Builder.Bases,
3440 ItaniumRecordLayoutBuilder Builder(*
this,
nullptr);
3444 *
this, Builder.getSize(), Builder.Alignment,
3445 Builder.PreferredAlignment, Builder.UnadjustedAlignment,
3447 Builder.Alignment, Builder.getSize(), Builder.FieldOffsets);
3451 ASTRecordLayouts[
D] = NewEntry;
3453 constexpr uint64_t MaxStructSizeInBytes = 1ULL << 60;
3455 if (
static_cast<uint64_t
>(StructSize.
getQuantity()) >= MaxStructSizeInBytes) {
3457 <<
D->getName() << MaxStructSizeInBytes;
3461 llvm::outs() <<
"\n*** Dumping AST Record Layout\n";
3472 assert(RD->
getDefinition() &&
"Cannot get key function for forward decl!");
3486 KeyFunctions[RD] =
const_cast<Decl*
>(
Result);
3488 return cast_or_null<CXXMethodDecl>(
Result);
3493 "not working with method declaration from class definition");
3498 const auto &Map = KeyFunctions;
3499 auto I = Map.find(
Method->getParent());
3502 if (I == Map.end())
return;
3510 KeyFunctions.erase(
Method->getParent());
3520 uint64_t OffsetInBits;
3521 if (
const FieldDecl *FD = dyn_cast<FieldDecl>(VD)) {
3531 return OffsetInBits;
3547 for (
const ObjCIvarDecl *IVD = Container->all_declared_ivar_begin();
3548 IVD; IVD = IVD->getNextIvar()) {
3553 assert(Index < RL->getFieldCount() &&
"Ivar is not inside record layout!");
3566 if (
D->hasExternalLexicalStorage() && !
D->getDefinition())
3568 D =
D->getDefinition();
3570 "Invalid interface decl!");
3576 ItaniumRecordLayoutBuilder Builder(*
this,
nullptr);
3580 *
this, Builder.getSize(), Builder.Alignment, Builder.PreferredAlignment,
3581 Builder.UnadjustedAlignment,
3583 Builder.Alignment, Builder.getDataSize(), Builder.FieldOffsets);
3585 ObjCLayouts[
D] = NewEntry;
3591 CharUnits Offset,
unsigned IndentLevel) {
3592 OS << llvm::format(
"%10" PRId64
" | ", (int64_t)Offset.getQuantity());
3593 OS.indent(IndentLevel * 2);
3597 unsigned Begin,
unsigned Width,
3598 unsigned IndentLevel) {
3601 llvm::raw_svector_ostream BufferOS(Buffer);
3602 BufferOS << Offset.getQuantity() <<
':';
3606 BufferOS <<
Begin <<
'-' << (
Begin + Width - 1);
3610 OS << llvm::right_justify(Buffer, 10) <<
" | ";
3611 OS.indent(IndentLevel * 2);
3616 OS.indent(IndentLevel * 2);
3622 unsigned IndentLevel,
3623 const char* Description,
3625 bool IncludeVirtualBases) {
3627 auto CXXRD = dyn_cast<CXXRecordDecl>(RD);
3630 OS <<
C.getCanonicalTagType(
const_cast<RecordDecl *
>(RD));
3632 OS <<
' ' << Description;
3633 if (CXXRD && CXXRD->isEmpty())
3646 if (CXXRD->isDynamicClass() && !PrimaryBase &&
3647 !
C.getTargetInfo().hasMicrosoftRecordLayout()) {
3649 OS <<
'(' << *RD <<
" vtable pointer)\n";
3650 }
else if (HasOwnVFPtr) {
3653 OS <<
'(' << *RD <<
" vftable pointer)\n";
3659 assert(!
Base.getType()->isDependentType() &&
3660 "Cannot layout class with dependent bases.");
3661 if (!
Base.isVirtual())
3662 Bases.push_back(
Base.getType()->getAsCXXRecordDecl());
3675 Base == PrimaryBase ?
"(primary base)" :
"(base)",
3683 OS <<
'(' << *RD <<
" vbtable pointer)\n";
3689 uint64_t LocalFieldOffsetInBits =
3692 Offset +
C.toCharUnitsFromBits(LocalFieldOffsetInBits);
3695 if (
const auto *RD = Field->getType()->getAsRecordDecl()) {
3697 Field->getName().data(),
3703 if (Field->isBitField()) {
3704 uint64_t LocalFieldByteOffsetInBits =
C.toBits(FieldOffset - Offset);
3705 unsigned Begin = LocalFieldOffsetInBits - LocalFieldByteOffsetInBits;
3706 unsigned Width = Field->getBitWidthValue();
3711 const QualType &FieldType =
C.getLangOpts().DumpRecordLayoutsCanonical
3712 ? Field->getType().getCanonicalType()
3714 OS << FieldType <<
' ' << *Field <<
'\n';
3718 if (CXXRD && IncludeVirtualBases) {
3723 assert(
Base.isVirtual() &&
"Found non-virtual class!");
3728 if (VtorDisps.find(VBase)->second.hasVtorDisp()) {
3730 OS <<
"(vtordisp for vbase " << *VBase <<
")\n";
3735 "(primary virtual base)" :
"(virtual base)",
3741 if (!PrintSizeInfo)
return;
3745 if (CXXRD && !
C.getTargetInfo().hasMicrosoftRecordLayout())
3748 if (
C.getTargetInfo().defaultsToAIXPowerAlignment())
3756 if (
C.getTargetInfo().defaultsToAIXPowerAlignment())
3757 OS <<
", preferrednvalign="
3764 bool Simple)
const {
3782 OS <<
"<ASTRecordLayout\n";
3787 if (
Target->defaultsToAIXPowerAlignment())
3790 if (
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
3791 OS <<
" BaseOffsets: [";
3793 for (
auto I : CXXRD->bases()) {
3798 Base = I.getType()->getAsCXXRecordDecl();
3799 OS << Info.CXXInfo->BaseOffsets[
Base].getQuantity();
3802 OS <<
" VBaseOffsets: [";
3804 for (
auto I : CXXRD->vbases()) {
3807 VBase = I.getType()->getAsCXXRecordDecl();
3808 OS << Info.CXXInfo->VBaseOffsets[VBase].VBaseOffset.getQuantity();
3812 OS <<
" FieldOffsets: [";
3813 for (
unsigned i = 0, e = Info.
getFieldCount(); i != e; ++i) {
Defines the clang::ASTContext interface.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
static unsigned getCharWidth(tok::TokenKind kind, const TargetInfo &Target)
llvm::MachO::Target Target
static const CXXMethodDecl * computeKeyFunction(ASTContext &Context, const CXXRecordDecl *RD)
static bool mustSkipTailPadding(TargetCXXABI ABI, const CXXRecordDecl *RD)
Does the target C++ ABI require us to skip over the tail-padding of the given class (considering it a...
static bool isAIXLayout(const ASTContext &Context)
static void PrintIndentNoOffset(raw_ostream &OS, unsigned IndentLevel)
static uint64_t roundUpSizeToCharAlignment(uint64_t Size, const ASTContext &Context)
static void PrintOffset(raw_ostream &OS, CharUnits Offset, unsigned IndentLevel)
static unsigned getPaddingDiagFromTagKind(TagTypeKind Tag)
Get diagnostic select index for tag kind for field padding diagnostic message.
static void DumpRecordLayout(raw_ostream &OS, const RecordDecl *RD, const ASTContext &C, CharUnits Offset, unsigned IndentLevel, const char *Description, bool PrintSizeInfo, bool IncludeVirtualBases)
static void CheckFieldPadding(const ASTContext &Context, bool IsUnion, uint64_t Offset, uint64_t UnpaddedOffset, const FieldDecl *D)
static uint64_t getFieldOffset(const ASTContext &C, const FieldDecl *FD)
static bool RequiresVtordisp(const llvm::SmallPtrSetImpl< const CXXRecordDecl * > &BasesWithOverriddenMethods, const CXXRecordDecl *RD)
static void PrintBitFieldOffset(raw_ostream &OS, CharUnits Offset, unsigned Begin, unsigned Width, unsigned IndentLevel)
static bool recordUsesEBO(const RecordDecl *RD)
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 LangOptions & getLangOpts() const
uint64_t lookupFieldBitOffset(const ObjCInterfaceDecl *OID, const ObjCIvarDecl *Ivar) const
Get the offset of an ObjCIvarDecl in bits.
const ASTRecordLayout & getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D) const
Get or compute information about the layout of the specified Objective-C interface.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
bool isNearlyEmpty(const CXXRecordDecl *RD) const
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 getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CanQualType UnsignedInt128Ty
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CanQualType UnsignedCharTy
CanQualType UnsignedIntTy
CanQualType UnsignedLongLongTy
CanQualType UnsignedShortTy
DiagnosticsEngine & getDiagnostics() const
const TargetInfo & getTargetInfo() const
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
ExternalASTSource * getExternalSource() const
Retrieve a pointer to the external AST source associated with this AST context, if any.
uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const
Return number of constant array elements.
CanQualType getCanonicalTagType(const TagDecl *TD) const
uint64_t getCharWidth() const
Return the size of the character type, in bits.
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
bool endsWithZeroSizedObject() const
bool hasOwnVFPtr() const
hasOwnVFPtr - Does this class provide its own virtual-function table pointer, rather than inheriting ...
CharUnits getAlignment() const
getAlignment - Get the record alignment in characters.
CharUnits getPreferredAlignment() const
getPreferredFieldAlignment - Get the record preferred alignment in characters.
bool hasOwnVBPtr() const
hasOwnVBPtr - Does this class provide its own virtual-base table pointer, rather than inheriting one ...
llvm::DenseMap< const CXXRecordDecl *, VBaseInfo > VBaseOffsetsMapTy
CharUnits getSize() const
getSize - Get the record size in characters.
unsigned getFieldCount() const
getFieldCount - Get the number of fields in the layout.
bool hasVBPtr() const
hasVBPtr - Does this class have a virtual function table pointer.
bool leadsWithZeroSizedBase() const
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
CharUnits getNonVirtualAlignment() const
getNonVirtualAlignment - Get the non-virtual alignment (in chars) of an object, which is the alignmen...
CharUnits getVBPtrOffset() const
getVBPtrOffset - Get the offset for virtual base table pointer.
CharUnits getDataSize() const
getDataSize() - Get the record data size, which is the record size without tail padding,...
CharUnits getRequiredAlignment() const
CharUnits getSizeOfLargestEmptySubobject() const
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
CharUnits getPreferredNVAlignment() const
getPreferredNVAlignment - Get the preferred non-virtual alignment (in chars) of an object,...
CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const
getVBaseClassOffset - Get the offset, in chars, for the given base class.
const VBaseOffsetsMapTy & getVBaseOffsetsMap() const
const CXXRecordDecl * getPrimaryBase() const
getPrimaryBase - Get the primary base for this record.
bool hasExtendableVFPtr() const
hasVFPtr - Does this class have a virtual function table pointer that can be extended by a derived cl...
bool isPrimaryBaseVirtual() const
isPrimaryBaseVirtual - Get whether the primary base for this record is virtual or not.
CharUnits getNonVirtualSize() const
getNonVirtualSize - Get the non-virtual size (in chars) of an object, which is the size of the object...
This class is used for builtin types like 'int'.
Represents a base class of a C++ class.
A set of all the primary bases for a class.
Represents a static or instance method of a struct/union/class.
overridden_method_range overridden_methods() const
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Represents a C++ struct/union/class.
void getIndirectPrimaryBases(CXXIndirectPrimaryBaseSet &Bases) const
Get the indirect primary bases for this class.
bool hasUserDeclaredDestructor() const
Determine whether this class has a user-declared destructor.
method_range methods() const
CXXRecordDecl * getDefinition() const
bool isPolymorphic() const
Whether this class is polymorphic (C++ [class.virtual]), which means that the class contains or inher...
TemplateSpecializationKind getTemplateSpecializationKind() const
Determine whether this particular class is a specialization or instantiation of a class template or m...
base_class_range vbases()
bool isDynamicClass() const
bool isCXX11StandardLayout() const
Determine whether this class was standard-layout per C++11 [class]p7, specifically using the C++11 ru...
bool hasUserDeclaredConstructor() const
Determine whether this class has any user-declared constructors.
bool isPOD() const
Whether this class is a POD-type (C++ [class]p4)
MSVtorDispMode getMSVtorDispMode() const
Controls when vtordisps will be emitted if this record is used as a virtual base.
bool isEmpty() const
Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).
bool isTrivial() const
Determine whether this class is considered trivial.
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
CharUnits - This is an opaque type for sizes expressed in character units.
bool isZero() const
isZero - Test whether the quantity equals zero.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
static CharUnits One()
One - Construct a CharUnits quantity of one.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
CharUnits alignTo(const CharUnits &Align) const
alignTo - Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is ...
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
Complex values, per C99 6.2.5p11.
Represents the canonical version of C arrays with a specified constant size.
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
Decl - This represents one declaration (or definition), e.g.
Decl * getMostRecentDecl()
Retrieve the most recent declaration that declares the same entity as this declaration (which may be ...
unsigned getMaxAlignment() const
getMaxAlignment - return the maximum alignment specified by attributes on this decl,...
bool isInvalidDecl() const
SourceLocation getLocation() const
A little helper class used to produce diagnostics.
A little helper class (which is basically a smart pointer that forwards info from DiagnosticsEngine a...
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Abstract interface for external sources of AST nodes.
virtual void CompleteType(TagDecl *Tag)
Gives the external AST source an opportunity to complete an incomplete type.
Represents a member of a struct/union/class.
bool isBitField() const
Determines whether this field is a bitfield.
unsigned getBitWidthValue() const
Computes the bit width of this field, if this is a bit field.
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
bool isPotentiallyOverlapping() const
Determine if this field is of potentially-overlapping class type, that is, subobject with the [[no_un...
Represents a function declaration or definition.
bool isInlineSpecified() const
Determine whether the "inline" keyword was specified for this function.
Represents a field injected from an anonymous union/struct into the parent scope.
ArrayRef< NamedDecl * > chain() const
This represents a decl that may have a name.
bool isExternallyVisible() const
Represents an ObjC class declaration.
ObjCIvarDecl - Represents an ObjC instance variable.
ObjCInterfaceDecl * getContainingInterface()
Return the class interface that this ivar is logically contained in; this is either the interface whe...
ObjCIvarDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this field.
A (possibly-)qualified type.
Represents a struct/union/class.
bool isMsStruct(const ASTContext &C) const
Get whether or not this is an ms_struct which can be turned on with an attribute, pragma,...
field_range fields() const
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Encodes a location in the source.
The basic abstraction for the target C++ ABI.
TailPaddingUseRules getTailPaddingUseRules() const
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
unsigned getLargestOverSizedBitfieldContainer() const
virtual bool defaultsToAIXPowerAlignment() const
Whether target defaults to the power alignment rules of AIX.
unsigned getCharAlign() const
unsigned getZeroLengthBitfieldBoundary() const
Get the fixed alignment value in bits for a member that follows a zero length bitfield.
bool useExplicitBitFieldAlignment() const
Check whether explicit bitfield alignment attributes should be.
uint64_t getPointerAlign(LangAS AddrSpace) const
TargetCXXABI getCXXABI() const
Get the C++ ABI currently in use.
unsigned getCharWidth() const
bool useZeroLengthBitfieldAlignment() const
Check whether zero length bitfields should force alignment of the next member.
bool useBitFieldTypeAlignment() const
Check whether the alignment of bit-field types is respected when laying out structures.
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 * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
const T * getAs() const
Member-template getAs<specific type>'.
const Type * getUnqualifiedDesugaredType() const
Return the specified type with any "sugar" removed from the type, removing any typedefs,...
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Defines the clang::TargetInfo interface.
The JSON file list parser is used to communicate input to InstallAPI.
@ 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
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.