20#include "llvm/ADT/SmallSet.h"
21#include "llvm/Support/Format.h"
22#include "llvm/Support/MathExtras.h"
39struct BaseSubobjectInfo {
51 BaseSubobjectInfo *PrimaryVirtualBaseInfo;
54 const BaseSubobjectInfo *Derived;
60struct ExternalLayout {
61 ExternalLayout() :
Size(0), Align(0) {}
70 llvm::DenseMap<const FieldDecl *, uint64_t> FieldOffsets;
73 llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsets;
76 llvm::DenseMap<const CXXRecordDecl *, CharUnits> VirtualBaseOffsets;
81 assert(FieldOffsets.count(FD) &&
82 "Field does not have an external offset");
83 return FieldOffsets[FD];
87 auto Known = BaseOffsets.find(RD);
88 if (Known == BaseOffsets.end())
90 BaseOffset = Known->second;
95 auto Known = VirtualBaseOffsets.find(RD);
96 if (Known == VirtualBaseOffsets.end())
98 BaseOffset = Known->second;
105class EmptySubobjectMap {
113 typedef llvm::TinyPtrVector<const CXXRecordDecl *> ClassVectorTy;
114 typedef llvm::DenseMap<CharUnits, ClassVectorTy> EmptyClassOffsetsMapTy;
115 EmptyClassOffsetsMapTy EmptyClassOffsets;
123 void ComputeEmptySubobjectSizes();
127 void UpdateEmptyBaseSubobjects(
const BaseSubobjectInfo *Info,
132 bool PlacingOverlappingField);
134 bool PlacingOverlappingField);
139 return Offset <= MaxEmptyClassOffset;
145 assert(FieldOffset % CharWidth == 0 &&
146 "Field offset not at char boundary!");
155 bool CanPlaceBaseSubobjectAtOffset(
const BaseSubobjectInfo *Info,
161 bool CanPlaceFieldSubobjectAtOffset(
const FieldDecl *FD,
172 ComputeEmptySubobjectSizes();
179 bool CanPlaceBaseAtOffset(
const BaseSubobjectInfo *Info,
187void EmptySubobjectMap::ComputeEmptySubobjectSizes() {
202 if (EmptySize > SizeOfLargestEmptySubobject)
203 SizeOfLargestEmptySubobject = EmptySize;
226 if (EmptySize > SizeOfLargestEmptySubobject)
227 SizeOfLargestEmptySubobject = EmptySize;
232EmptySubobjectMap::CanPlaceSubobjectAtOffset(
const CXXRecordDecl *RD,
238 EmptyClassOffsetsMapTy::const_iterator I = EmptyClassOffsets.find(
Offset);
239 if (I == EmptyClassOffsets.end())
242 const ClassVectorTy &Classes = I->second;
243 if (!llvm::is_contained(Classes, RD))
250void EmptySubobjectMap::AddSubobjectAtOffset(
const CXXRecordDecl *RD,
258 ClassVectorTy &Classes = EmptyClassOffsets[
Offset];
259 if (llvm::is_contained(Classes, RD))
262 Classes.push_back(RD);
265 if (
Offset > MaxEmptyClassOffset)
266 MaxEmptyClassOffset =
Offset;
270EmptySubobjectMap::CanPlaceBaseSubobjectAtOffset(
const BaseSubobjectInfo *Info,
274 if (!AnyEmptySubobjectsBeyondOffset(
Offset))
277 if (!CanPlaceSubobjectAtOffset(Info->Class,
Offset))
282 for (
const BaseSubobjectInfo *
Base : Info->Bases) {
288 if (!CanPlaceBaseSubobjectAtOffset(
Base, BaseOffset))
292 if (Info->PrimaryVirtualBaseInfo) {
293 BaseSubobjectInfo *PrimaryVirtualBaseInfo = Info->PrimaryVirtualBaseInfo;
295 if (Info == PrimaryVirtualBaseInfo->Derived) {
296 if (!CanPlaceBaseSubobjectAtOffset(PrimaryVirtualBaseInfo,
Offset))
302 unsigned FieldNo = 0;
304 E = Info->Class->field_end(); I != E; ++I, ++FieldNo) {
309 if (!CanPlaceFieldSubobjectAtOffset(*I, FieldOffset))
316void EmptySubobjectMap::UpdateEmptyBaseSubobjects(
const BaseSubobjectInfo *Info,
318 bool PlacingEmptyBase) {
319 if (!PlacingEmptyBase &&
Offset >= SizeOfLargestEmptySubobject) {
328 AddSubobjectAtOffset(Info->Class,
Offset);
332 for (
const BaseSubobjectInfo *
Base : Info->Bases) {
337 UpdateEmptyBaseSubobjects(
Base, BaseOffset, PlacingEmptyBase);
340 if (Info->PrimaryVirtualBaseInfo) {
341 BaseSubobjectInfo *PrimaryVirtualBaseInfo = Info->PrimaryVirtualBaseInfo;
343 if (Info == PrimaryVirtualBaseInfo->Derived)
344 UpdateEmptyBaseSubobjects(PrimaryVirtualBaseInfo,
Offset,
349 unsigned FieldNo = 0;
351 E = Info->Class->field_end(); I != E; ++I, ++FieldNo) {
356 UpdateEmptyFieldSubobjects(*I, FieldOffset, PlacingEmptyBase);
360bool EmptySubobjectMap::CanPlaceBaseAtOffset(
const BaseSubobjectInfo *Info,
364 if (SizeOfLargestEmptySubobject.isZero())
367 if (!CanPlaceBaseSubobjectAtOffset(Info,
Offset))
372 UpdateEmptyBaseSubobjects(Info,
Offset, Info->Class->isEmpty());
377EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(
const CXXRecordDecl *RD,
382 if (!AnyEmptySubobjectsBeyondOffset(
Offset))
385 if (!CanPlaceSubobjectAtOffset(RD,
Offset))
392 if (
Base.isVirtual())
398 if (!CanPlaceFieldSubobjectAtOffset(BaseDecl, Class, BaseOffset))
408 if (!CanPlaceFieldSubobjectAtOffset(VBaseDecl, Class, VBaseOffset))
414 unsigned FieldNo = 0;
416 I != E; ++I, ++FieldNo) {
422 if (!CanPlaceFieldSubobjectAtOffset(*I, FieldOffset))
430EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(
const FieldDecl *FD,
434 if (!AnyEmptySubobjectsBeyondOffset(
Offset))
439 return CanPlaceFieldSubobjectAtOffset(RD, RD,
Offset);
453 for (uint64_t I = 0; I != NumElements; ++I) {
456 if (!AnyEmptySubobjectsBeyondOffset(ElementOffset))
459 if (!CanPlaceFieldSubobjectAtOffset(RD, RD, ElementOffset))
462 ElementOffset += Layout.
getSize();
470EmptySubobjectMap::CanPlaceFieldAtOffset(
const FieldDecl *FD,
472 if (!CanPlaceFieldSubobjectAtOffset(FD,
Offset))
477 UpdateEmptyFieldSubobjects(FD,
Offset, FD->
hasAttr<NoUniqueAddressAttr>());
481void EmptySubobjectMap::UpdateEmptyFieldSubobjects(
483 bool PlacingOverlappingField) {
494 if (!PlacingOverlappingField &&
Offset >= SizeOfLargestEmptySubobject)
497 AddSubobjectAtOffset(RD,
Offset);
503 if (
Base.isVirtual())
509 UpdateEmptyFieldSubobjects(BaseDecl, Class, BaseOffset,
510 PlacingOverlappingField);
519 UpdateEmptyFieldSubobjects(VBaseDecl, Class, VBaseOffset,
520 PlacingOverlappingField);
525 unsigned FieldNo = 0;
527 I != E; ++I, ++FieldNo) {
533 UpdateEmptyFieldSubobjects(*I, FieldOffset, PlacingOverlappingField);
537void EmptySubobjectMap::UpdateEmptyFieldSubobjects(
541 UpdateEmptyFieldSubobjects(RD, RD,
Offset, PlacingOverlappingField);
558 for (uint64_t I = 0; I != NumElements; ++I) {
564 if (!PlacingOverlappingField &&
565 ElementOffset >= SizeOfLargestEmptySubobject)
568 UpdateEmptyFieldSubobjects(RD, RD, ElementOffset,
569 PlacingOverlappingField);
570 ElementOffset += Layout.
getSize();
577class ItaniumRecordLayoutBuilder {
584 EmptySubobjectMap *EmptySubobjects;
605 unsigned UseExternalLayout : 1;
609 unsigned InferAlignment : 1;
614 unsigned IsUnion : 1;
616 unsigned IsMac68kAlign : 1;
618 unsigned IsNaturalAlign : 1;
620 unsigned IsMsStruct : 1;
626 unsigned char UnfilledBitsInLastUnit;
630 unsigned char LastBitfieldStorageUnitSize;
653 bool PrimaryBaseIsVirtual;
666 bool HandledFirstNonOverlappingEmptyField;
668 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
671 BaseOffsetsMapTy Bases;
689 ExternalLayout External;
691 ItaniumRecordLayoutBuilder(
const ASTContext &Context,
692 EmptySubobjectMap *EmptySubobjects)
693 : Context(Context), EmptySubobjects(EmptySubobjects),
Size(0),
698 IsMac68kAlign(
false),
699 IsNaturalAlign(!Context.getTargetInfo().getTriple().isOSAIX()),
700 IsMsStruct(
false), UnfilledBitsInLastUnit(0),
701 LastBitfieldStorageUnitSize(0), MaxFieldAlignment(
CharUnits::
Zero()),
706 PrimaryBaseIsVirtual(
false), HasOwnVFPtr(
false), HasPackedField(
false),
707 HandledFirstNonOverlappingEmptyField(
false),
708 FirstNearlyEmptyVBase(nullptr) {}
715 void LayoutField(
const FieldDecl *D,
bool InsertExtraPadding);
716 void LayoutWideBitField(uint64_t FieldSize, uint64_t StorageUnitSize,
725 llvm::SpecificBumpPtrAllocator<BaseSubobjectInfo> BaseSubobjectInfoAllocator;
727 typedef llvm::DenseMap<const CXXRecordDecl *, BaseSubobjectInfo *>
728 BaseSubobjectInfoMapTy;
736 BaseSubobjectInfoMapTy NonVirtualBaseInfo;
744 BaseSubobjectInfo *ComputeBaseSubobjectInfo(
const CXXRecordDecl *RD,
746 BaseSubobjectInfo *Derived);
753 void EnsureVTablePointerAlignment(
CharUnits UnpackedBaseAlign);
760 void LayoutNonVirtualBase(
const BaseSubobjectInfo *
Base);
762 void AddPrimaryVirtualBaseOffsets(
const BaseSubobjectInfo *Info,
770 void LayoutVirtualBase(
const BaseSubobjectInfo *
Base);
777 void InitializeLayout(
const Decl *D);
786 UpdateAlignment(NewAlignment, UnpackedNewAlignment, NewAlignment);
788 void UpdateAlignment(
CharUnits NewAlignment) {
789 UpdateAlignment(NewAlignment, NewAlignment, NewAlignment);
798 uint64_t ComputedOffset);
800 void CheckFieldPadding(uint64_t
Offset, uint64_t UnpaddedOffset,
801 uint64_t UnpackedOffset,
unsigned UnpackedAlign,
813 void setSize(uint64_t NewSize) {
Size = NewSize; }
815 CharUnits getAligment()
const {
return Alignment; }
821 uint64_t getDataSizeInBits()
const {
return DataSize; }
823 void setDataSize(
CharUnits NewSize) { DataSize = Context.
toBits(NewSize); }
824 void setDataSize(uint64_t NewSize) { DataSize = NewSize; }
826 ItaniumRecordLayoutBuilder(
const ItaniumRecordLayoutBuilder &) =
delete;
827 void operator=(
const ItaniumRecordLayoutBuilder &) =
delete;
831void ItaniumRecordLayoutBuilder::SelectPrimaryVBase(
const CXXRecordDecl *RD) {
832 for (
const auto &I : RD->
bases()) {
833 assert(!I.getType()->isDependentType() &&
834 "Cannot layout class with dependent bases.");
842 if (!IndirectPrimaryBases.count(
Base)) {
844 PrimaryBaseIsVirtual =
true;
849 if (!FirstNearlyEmptyVBase)
850 FirstNearlyEmptyVBase =
Base;
853 SelectPrimaryVBase(
Base);
860void ItaniumRecordLayoutBuilder::DeterminePrimaryBase(
const CXXRecordDecl *RD) {
872 for (
const auto &I : RD->
bases()) {
879 if (
Base->isDynamicClass()) {
882 PrimaryBaseIsVirtual =
false;
892 SelectPrimaryVBase(RD);
898 if (FirstNearlyEmptyVBase) {
899 PrimaryBase = FirstNearlyEmptyVBase;
900 PrimaryBaseIsVirtual =
true;
904 assert(!PrimaryBase &&
"Should not get here with a primary base!");
907BaseSubobjectInfo *ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo(
908 const CXXRecordDecl *RD,
bool IsVirtual, BaseSubobjectInfo *Derived) {
909 BaseSubobjectInfo *Info;
915 assert(InfoSlot->Class == RD &&
"Wrong class for virtual base info!");
920 InfoSlot =
new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo;
923 Info =
new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo;
927 Info->IsVirtual = IsVirtual;
928 Info->Derived =
nullptr;
929 Info->PrimaryVirtualBaseInfo =
nullptr;
932 BaseSubobjectInfo *PrimaryVirtualBaseInfo =
nullptr;
940 assert(PrimaryVirtualBase &&
"Didn't have a primary virtual base!");
945 if (PrimaryVirtualBaseInfo) {
946 if (PrimaryVirtualBaseInfo->Derived) {
950 PrimaryVirtualBase =
nullptr;
953 Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;
954 PrimaryVirtualBaseInfo->Derived = Info;
961 for (
const auto &I : RD->
bases()) {
962 bool IsVirtual = I.isVirtual();
964 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
966 Info->Bases.push_back(ComputeBaseSubobjectInfo(BaseDecl, IsVirtual, Info));
969 if (PrimaryVirtualBase && !PrimaryVirtualBaseInfo) {
973 assert(PrimaryVirtualBaseInfo &&
974 "Did not create a primary virtual base!");
977 Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;
978 PrimaryVirtualBaseInfo->Derived = Info;
984void ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo(
986 for (
const auto &I : RD->
bases()) {
987 bool IsVirtual = I.isVirtual();
989 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
992 BaseSubobjectInfo *Info = ComputeBaseSubobjectInfo(BaseDecl, IsVirtual,
998 "Did not add virtual base!");
1001 assert(!NonVirtualBaseInfo.count(BaseDecl) &&
1002 "Non-virtual base already exists!");
1003 NonVirtualBaseInfo.insert(std::make_pair(BaseDecl, Info));
1008void ItaniumRecordLayoutBuilder::EnsureVTablePointerAlignment(
1013 if (!MaxFieldAlignment.
isZero()) {
1014 BaseAlign = std::min(BaseAlign, MaxFieldAlignment);
1015 UnpackedBaseAlign = std::min(UnpackedBaseAlign, MaxFieldAlignment);
1019 setSize(getSize().alignTo(BaseAlign));
1022 UpdateAlignment(BaseAlign, UnpackedBaseAlign, BaseAlign);
1025void ItaniumRecordLayoutBuilder::LayoutNonVirtualBases(
1028 DeterminePrimaryBase(RD);
1031 ComputeBaseSubobjectInfo(RD);
1035 if (PrimaryBaseIsVirtual) {
1038 BaseSubobjectInfo *PrimaryBaseInfo =
VirtualBaseInfo.lookup(PrimaryBase);
1039 PrimaryBaseInfo->Derived =
nullptr;
1042 IndirectPrimaryBases.insert(PrimaryBase);
1044 assert(!VisitedVirtualBases.count(PrimaryBase) &&
1045 "vbase already visited!");
1046 VisitedVirtualBases.insert(PrimaryBase);
1048 LayoutVirtualBase(PrimaryBaseInfo);
1050 BaseSubobjectInfo *PrimaryBaseInfo =
1051 NonVirtualBaseInfo.lookup(PrimaryBase);
1052 assert(PrimaryBaseInfo &&
1053 "Did not find base info for non-virtual primary base!");
1055 LayoutNonVirtualBase(PrimaryBaseInfo);
1061 assert(DataSize == 0 &&
"Vtable pointer must be at offset zero!");
1066 EnsureVTablePointerAlignment(PtrAlign);
1069 assert(!IsUnion &&
"Unions cannot be dynamic classes.");
1070 HandledFirstNonOverlappingEmptyField =
true;
1072 setSize(getSize() + PtrWidth);
1073 setDataSize(getSize());
1077 for (
const auto &I : RD->
bases()) {
1083 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
1088 if (BaseDecl == PrimaryBase && !PrimaryBaseIsVirtual)
1092 BaseSubobjectInfo *BaseInfo = NonVirtualBaseInfo.
lookup(BaseDecl);
1093 assert(BaseInfo &&
"Did not find base info for non-virtual base!");
1095 LayoutNonVirtualBase(BaseInfo);
1099void ItaniumRecordLayoutBuilder::LayoutNonVirtualBase(
1100 const BaseSubobjectInfo *
Base) {
1105 assert(!Bases.count(
Base->Class) &&
"base offset already exists!");
1106 Bases.insert(std::make_pair(
Base->Class,
Offset));
1111void ItaniumRecordLayoutBuilder::AddPrimaryVirtualBaseOffsets(
1114 if (!Info->Class->getNumVBases())
1118 if (Info->PrimaryVirtualBaseInfo) {
1119 assert(Info->PrimaryVirtualBaseInfo->IsVirtual &&
1120 "Primary virtual base is not virtual!");
1121 if (Info->PrimaryVirtualBaseInfo->Derived == Info) {
1123 assert(!VBases.count(Info->PrimaryVirtualBaseInfo->Class) &&
1124 "primary vbase offset already exists!");
1125 VBases.insert(std::make_pair(Info->PrimaryVirtualBaseInfo->Class,
1129 AddPrimaryVirtualBaseOffsets(Info->PrimaryVirtualBaseInfo,
Offset);
1135 for (
const BaseSubobjectInfo *
Base : Info->Bases) {
1136 if (
Base->IsVirtual)
1140 AddPrimaryVirtualBaseOffsets(
Base, BaseOffset);
1144void ItaniumRecordLayoutBuilder::LayoutVirtualBases(
1147 bool PrimaryBaseIsVirtual;
1149 if (MostDerivedClass == RD) {
1150 PrimaryBase = this->PrimaryBase;
1151 PrimaryBaseIsVirtual = this->PrimaryBaseIsVirtual;
1159 assert(!
Base.getType()->isDependentType() &&
1160 "Cannot layout class with dependent bases.");
1164 if (
Base.isVirtual()) {
1165 if (PrimaryBase != BaseDecl || !PrimaryBaseIsVirtual) {
1166 bool IndirectPrimaryBase = IndirectPrimaryBases.count(BaseDecl);
1169 if (!IndirectPrimaryBase) {
1171 if (!VisitedVirtualBases.insert(BaseDecl).second)
1175 assert(BaseInfo &&
"Did not find virtual base info!");
1176 LayoutVirtualBase(BaseInfo);
1186 LayoutVirtualBases(BaseDecl, MostDerivedClass);
1190void ItaniumRecordLayoutBuilder::LayoutVirtualBase(
1191 const BaseSubobjectInfo *
Base) {
1192 assert(!
Base->Derived &&
"Trying to lay out a primary virtual base!");
1198 assert(!VBases.count(
Base->Class) &&
"vbase offset already exists!");
1199 VBases.insert(std::make_pair(
Base->Class,
1206ItaniumRecordLayoutBuilder::LayoutBase(
const BaseSubobjectInfo *
Base) {
1207 assert(!IsUnion &&
"Unions cannot have base classes.");
1213 bool HasExternalLayout =
false;
1214 if (UseExternalLayout) {
1215 if (
Base->IsVirtual)
1216 HasExternalLayout = External.getExternalVBaseOffset(
Base->Class,
Offset);
1218 HasExternalLayout = External.getExternalNVBaseOffset(
Base->Class,
Offset);
1221 auto getBaseOrPreferredBaseAlignFromUnpacked = [&](
CharUnits UnpackedAlign) {
1224 return (Packed && ((Context.
getLangOpts().getClangABICompat() <=
1235 getBaseOrPreferredBaseAlignFromUnpacked(UnpackedBaseAlign);
1237 getBaseOrPreferredBaseAlignFromUnpacked(UnpackedPreferredBaseAlign);
1239 const bool DefaultsToAIXPowerAlignment =
1241 if (DefaultsToAIXPowerAlignment) {
1246 if (!
Base->Class->isEmpty() && !HandledFirstNonOverlappingEmptyField) {
1249 HandledFirstNonOverlappingEmptyField =
true;
1250 }
else if (!IsNaturalAlign) {
1251 UnpackedPreferredBaseAlign = UnpackedBaseAlign;
1252 PreferredBaseAlign = BaseAlign;
1256 CharUnits UnpackedAlignTo = !DefaultsToAIXPowerAlignment
1258 : UnpackedPreferredBaseAlign;
1260 if (
Base->Class->isEmpty() &&
1263 setSize(std::max(getSize(), Layout.
getSize()));
1266 UpdateAlignment(BaseAlign, UnpackedAlignTo, PreferredBaseAlign);
1273 if (!MaxFieldAlignment.
isZero()) {
1274 BaseAlign = std::min(BaseAlign, MaxFieldAlignment);
1275 PreferredBaseAlign = std::min(PreferredBaseAlign, MaxFieldAlignment);
1276 UnpackedAlignTo = std::min(UnpackedAlignTo, MaxFieldAlignment);
1280 !DefaultsToAIXPowerAlignment ? BaseAlign : PreferredBaseAlign;
1281 if (!HasExternalLayout) {
1283 Offset = getDataSize().alignTo(AlignTo);
1286 while (!EmptySubobjects->CanPlaceBaseAtOffset(
Base,
Offset))
1289 bool Allowed = EmptySubobjects->CanPlaceBaseAtOffset(
Base,
Offset);
1291 assert(Allowed &&
"Base subobject externally placed at overlapping offset");
1293 if (InferAlignment &&
Offset < getDataSize().alignTo(AlignTo)) {
1297 InferAlignment =
false;
1301 if (!
Base->Class->isEmpty()) {
1305 setSize(std::max(getSize(), getDataSize()));
1310 UpdateAlignment(BaseAlign, UnpackedAlignTo, PreferredBaseAlign);
1315void ItaniumRecordLayoutBuilder::InitializeLayout(
const Decl *D) {
1316 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
1321 Packed = D->
hasAttr<PackedAttr>();
1324 if (
unsigned DefaultMaxFieldAlignment = Context.
getLangOpts().PackStruct) {
1332 if (D->
hasAttr<AlignMac68kAttr>()) {
1334 !D->
hasAttr<AlignNaturalAttr>() &&
1335 "Having both mac68k and natural alignment on a decl is not allowed.");
1336 IsMac68kAlign =
true;
1341 if (D->
hasAttr<AlignNaturalAttr>())
1342 IsNaturalAlign =
true;
1344 if (
const MaxFieldAlignmentAttr *MFAA = D->
getAttr<MaxFieldAlignmentAttr>())
1351 HandledFirstNonOverlappingEmptyField =
1355 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(D))
1357 UseExternalLayout = Source->layoutRecordType(
1358 RD, External.Size, External.Align, External.FieldOffsets,
1359 External.BaseOffsets, External.VirtualBaseOffsets);
1362 if (UseExternalLayout) {
1363 if (External.Align > 0) {
1368 InferAlignment =
true;
1374void ItaniumRecordLayoutBuilder::Layout(
const RecordDecl *D) {
1375 InitializeLayout(D);
1383void ItaniumRecordLayoutBuilder::Layout(
const CXXRecordDecl *RD) {
1384 InitializeLayout(RD);
1387 LayoutNonVirtualBases(RD);
1393 NonVirtualAlignment = Alignment;
1394 PreferredNVAlignment = PreferredAlignment;
1397 LayoutVirtualBases(RD, RD);
1406 if (
Base.isVirtual())
1411 assert(Bases.count(BaseDecl) &&
"Did not find base offset!");
1418 assert(VBases.count(BaseDecl) &&
"Did not find base offset!");
1432 setSize(getDataSize());
1435 InitializeLayout(D);
1439 LayoutField(IVD,
false);
1446void ItaniumRecordLayoutBuilder::LayoutFields(
const RecordDecl *D) {
1455 InsertExtraPadding && (Next != End || !HasFlexibleArrayMember));
1464 return llvm::alignTo(Size, CharAlignment);
1467void ItaniumRecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize,
1468 uint64_t StorageUnitSize,
1472 "Can only have wide bit-fields in C++!");
1484 for (
const QualType &QT : IntegralPODTypes) {
1487 if (Size > FieldSize)
1492 assert(!
Type.isNull() &&
"Did not find a type!");
1497 UnfilledBitsInLastUnit = 0;
1498 LastBitfieldStorageUnitSize = 0;
1501 uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;
1506 setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize));
1511 FieldOffset = llvm::alignTo(getDataSizeInBits(), Context.
toBits(TypeAlign));
1513 uint64_t NewSizeInBits = FieldOffset + FieldSize;
1517 UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits;
1521 FieldOffsets.push_back(FieldOffset);
1523 CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, FieldOffset,
1524 Context.
toBits(TypeAlign), FieldPacked, D);
1527 setSize(std::max(getSizeInBits(), getDataSizeInBits()));
1530 UpdateAlignment(TypeAlign);
1537void ItaniumRecordLayoutBuilder::LayoutBitField(
const FieldDecl *D) {
1538 bool FieldPacked = Packed || D->
hasAttr<PackedAttr>();
1542 unsigned FieldAlign = FieldInfo.
Align;
1605 FieldAlign = StorageUnitSize;
1610 if (LastBitfieldStorageUnitSize != StorageUnitSize ||
1611 UnfilledBitsInLastUnit < FieldSize) {
1613 if (!LastBitfieldStorageUnitSize && !FieldSize)
1616 UnfilledBitsInLastUnit = 0;
1617 LastBitfieldStorageUnitSize = 0;
1631 StorageUnitSize = 32;
1633 if (!AlignIsRequired)
1637 if (FieldAlign < StorageUnitSize) {
1640 FieldAlign = StorageUnitSize;
1647 if (FieldSize > StorageUnitSize && !
isAIXLayout(Context)) {
1648 LayoutWideBitField(FieldSize, StorageUnitSize, FieldPacked, D);
1654 IsUnion ? 0 : (getDataSizeInBits() - UnfilledBitsInLastUnit);
1659 if (FieldSize == 0 &&
1662 if (!IsUnion && FieldOffset == 0 &&
1668 unsigned ZeroLengthBitfieldBoundary =
1670 FieldAlign = std::max(FieldAlign, ZeroLengthBitfieldBoundary);
1679 unsigned UnpackedFieldAlign = FieldAlign;
1682 if (!IsMsStruct && FieldPacked && FieldSize != 0)
1687 if (ExplicitFieldAlign) {
1688 FieldAlign = std::max(FieldAlign, ExplicitFieldAlign);
1689 UnpackedFieldAlign = std::max(UnpackedFieldAlign, ExplicitFieldAlign);
1694 unsigned MaxFieldAlignmentInBits = Context.
toBits(MaxFieldAlignment);
1695 if (!MaxFieldAlignment.
isZero() && FieldSize) {
1696 UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits);
1698 FieldAlign = UnpackedFieldAlign;
1700 FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits);
1705 if (IsMsStruct && IsUnion) {
1706 FieldAlign = UnpackedFieldAlign = 1;
1712 uint64_t UnpaddedFieldOffset = FieldOffset;
1713 uint64_t UnpackedFieldOffset = FieldOffset;
1723 if (FieldSize == 0 || FieldSize > UnfilledBitsInLastUnit) {
1724 FieldOffset = llvm::alignTo(FieldOffset, FieldAlign);
1725 UnpackedFieldOffset =
1726 llvm::alignTo(UnpackedFieldOffset, UnpackedFieldAlign);
1727 UnfilledBitsInLastUnit = 0;
1732 bool AllowPadding = MaxFieldAlignment.
isZero();
1735 if (FieldSize == 0 ||
1737 (FieldOffset & (FieldAlign - 1)) + FieldSize > StorageUnitSize)) {
1738 FieldOffset = llvm::alignTo(FieldOffset, FieldAlign);
1739 }
else if (ExplicitFieldAlign &&
1740 (MaxFieldAlignmentInBits == 0 ||
1741 ExplicitFieldAlign <= MaxFieldAlignmentInBits) &&
1745 FieldOffset = llvm::alignTo(FieldOffset, ExplicitFieldAlign);
1749 if (FieldSize == 0 ||
1751 (UnpackedFieldOffset & (UnpackedFieldAlign - 1)) + FieldSize >
1753 UnpackedFieldOffset =
1754 llvm::alignTo(UnpackedFieldOffset, UnpackedFieldAlign);
1755 else if (ExplicitFieldAlign &&
1756 (MaxFieldAlignmentInBits == 0 ||
1757 ExplicitFieldAlign <= MaxFieldAlignmentInBits) &&
1759 UnpackedFieldOffset =
1760 llvm::alignTo(UnpackedFieldOffset, ExplicitFieldAlign);
1765 if (UseExternalLayout)
1766 FieldOffset = updateExternalFieldOffset(D, FieldOffset);
1769 FieldOffsets.push_back(FieldOffset);
1778 FieldAlign = UnpackedFieldAlign = 1;
1786 if (!MaxFieldAlignment.
isZero()) {
1787 UnpackedFieldAlign =
1788 std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits);
1789 FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits);
1794 if (!UseExternalLayout)
1795 CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, UnpackedFieldOffset,
1796 UnpackedFieldAlign, FieldPacked, D);
1806 RoundedFieldSize = (FieldSize ? StorageUnitSize
1814 setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize));
1818 }
else if (IsMsStruct && FieldSize) {
1821 if (!UnfilledBitsInLastUnit) {
1822 setDataSize(FieldOffset + StorageUnitSize);
1823 UnfilledBitsInLastUnit = StorageUnitSize;
1825 UnfilledBitsInLastUnit -= FieldSize;
1826 LastBitfieldStorageUnitSize = StorageUnitSize;
1832 uint64_t NewSizeInBits = FieldOffset + FieldSize;
1834 setDataSize(llvm::alignTo(NewSizeInBits, CharAlignment));
1835 UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits;
1840 LastBitfieldStorageUnitSize = 0;
1844 setSize(std::max(getSizeInBits(), getDataSizeInBits()));
1847 UnadjustedAlignment =
1853void ItaniumRecordLayoutBuilder::LayoutField(
const FieldDecl *D,
1854 bool InsertExtraPadding) {
1856 bool IsOverlappingEmptyField =
1860 (IsUnion || IsOverlappingEmptyField) ?
CharUnits::Zero() : getDataSize();
1862 const bool DefaultsToAIXPowerAlignment =
1864 bool FoundFirstNonOverlappingEmptyFieldForAIX =
false;
1865 if (DefaultsToAIXPowerAlignment && !HandledFirstNonOverlappingEmptyField) {
1867 "The first non-overlapping empty field should have been handled.");
1869 if (!IsOverlappingEmptyField) {
1870 FoundFirstNonOverlappingEmptyFieldForAIX =
true;
1877 HandledFirstNonOverlappingEmptyField = !IsUnion;
1886 uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;
1888 UnfilledBitsInLastUnit = 0;
1889 LastBitfieldStorageUnitSize = 0;
1901 auto setDeclInfo = [&](
bool IsIncompleteArrayType) {
1903 FieldAlign = TI.Align;
1906 EffectiveFieldSize = FieldSize =
1908 AlignRequirement = TI.AlignRequirement;
1914 setDeclInfo(
false );
1920 EffectiveFieldSize =
1934 if (!llvm::isPowerOf2_64(TypeSize.
getQuantity())) {
1937 "Non PowerOf2 size in MSVC mode");
1959 if (TypeSize > FieldAlign &&
1961 FieldAlign = TypeSize;
1966 bool FieldPacked = (Packed && (!FieldClass || FieldClass->isPOD() ||
1967 FieldClass->hasAttr<PackedAttr>() ||
1978 auto alignedAttrCanDecreaseAIXAlignment = [AlignRequirement, FieldPacked] {
1997 if (DefaultsToAIXPowerAlignment && !alignedAttrCanDecreaseAIXAlignment() &&
1998 (FoundFirstNonOverlappingEmptyFieldForAIX || IsNaturalAlign)) {
1999 auto performBuiltinTypeAlignmentUpgrade = [&](
const BuiltinType *BTy) {
2000 if (BTy->getKind() == BuiltinType::Double ||
2001 BTy->getKind() == BuiltinType::LongDouble) {
2003 "No need to upgrade the alignment value.");
2010 performBuiltinTypeAlignmentUpgrade(
2013 performBuiltinTypeAlignmentUpgrade(BTy);
2016 assert(RD &&
"Expected non-null RecordDecl.");
2024 CharUnits UnpackedFieldAlign = FieldAlign;
2026 CharUnits UnpackedFieldOffset = FieldOffset;
2027 CharUnits OriginalFieldAlign = UnpackedFieldAlign;
2031 PackedFieldAlign = std::max(PackedFieldAlign, MaxAlignmentInChars);
2032 PreferredAlign = std::max(PreferredAlign, MaxAlignmentInChars);
2033 UnpackedFieldAlign = std::max(UnpackedFieldAlign, MaxAlignmentInChars);
2036 if (!MaxFieldAlignment.
isZero()) {
2037 PackedFieldAlign = std::min(PackedFieldAlign, MaxFieldAlignment);
2038 PreferredAlign = std::min(PreferredAlign, MaxFieldAlignment);
2039 UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignment);
2044 FieldAlign = UnpackedFieldAlign;
2045 if (DefaultsToAIXPowerAlignment)
2046 UnpackedFieldAlign = PreferredAlign;
2048 PreferredAlign = PackedFieldAlign;
2049 FieldAlign = PackedFieldAlign;
2053 !DefaultsToAIXPowerAlignment ? FieldAlign : PreferredAlign;
2055 FieldOffset = FieldOffset.
alignTo(AlignTo);
2056 UnpackedFieldOffset = UnpackedFieldOffset.
alignTo(UnpackedFieldAlign);
2058 if (UseExternalLayout) {
2060 updateExternalFieldOffset(D, Context.
toBits(FieldOffset)));
2062 if (!IsUnion && EmptySubobjects) {
2064 bool Allowed = EmptySubobjects->CanPlaceFieldAtOffset(D, FieldOffset);
2066 assert(Allowed &&
"Externally-placed field cannot be placed here");
2069 if (!IsUnion && EmptySubobjects) {
2071 while (!EmptySubobjects->CanPlaceFieldAtOffset(D, FieldOffset)) {
2076 FieldOffset = getDataSize().
alignTo(AlignTo);
2078 FieldOffset += AlignTo;
2084 FieldOffsets.push_back(Context.
toBits(FieldOffset));
2086 if (!UseExternalLayout)
2087 CheckFieldPadding(Context.
toBits(FieldOffset), UnpaddedFieldOffset,
2088 Context.
toBits(UnpackedFieldOffset),
2089 Context.
toBits(UnpackedFieldAlign), FieldPacked, D);
2091 if (InsertExtraPadding) {
2093 CharUnits ExtraSizeForAsan = ASanAlignment;
2094 if (FieldSize % ASanAlignment)
2097 EffectiveFieldSize = FieldSize = FieldSize + ExtraSizeForAsan;
2101 if (!IsOverlappingEmptyField) {
2102 uint64_t EffectiveFieldSizeInBits = Context.
toBits(EffectiveFieldSize);
2104 setDataSize(std::max(getDataSizeInBits(), EffectiveFieldSizeInBits));
2106 setDataSize(FieldOffset + EffectiveFieldSize);
2108 PaddedFieldSize = std::max(PaddedFieldSize, FieldOffset + FieldSize);
2109 setSize(std::max(getSizeInBits(), getDataSizeInBits()));
2111 setSize(std::max(getSizeInBits(),
2112 (uint64_t)Context.
toBits(FieldOffset + FieldSize)));
2116 UnadjustedAlignment = std::max(UnadjustedAlignment, FieldAlign);
2117 UpdateAlignment(FieldAlign, UnpackedFieldAlign, PreferredAlign);
2123 if (RD->
hasAttr<PackedAttr>() || !MaxFieldAlignment.
isZero())
2124 if (FieldAlign < OriginalFieldAlign)
2129 if (FieldOffset % OriginalFieldAlign != 0)
2135 if (Packed && !FieldPacked && PackedFieldAlign < FieldAlign)
2139void ItaniumRecordLayoutBuilder::FinishLayout(
const NamedDecl *D) {
2141 if (Context.
getLangOpts().CPlusPlus && getSizeInBits() == 0) {
2155 setSize(std::max(getSizeInBits(), (uint64_t)Context.
toBits(PaddedFieldSize)));
2159 uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastUnit;
2161 llvm::alignTo(getSizeInBits(), Context.
toBits(UnpackedAlignment));
2163 uint64_t RoundedSize = llvm::alignTo(
2167 : PreferredAlignment));
2169 if (UseExternalLayout) {
2173 if (InferAlignment && External.Size < RoundedSize) {
2176 InferAlignment =
false;
2178 setSize(External.Size);
2183 setSize(RoundedSize);
2186 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
2188 if (getSizeInBits() > UnpaddedSize) {
2189 unsigned PadSize = getSizeInBits() - UnpaddedSize;
2191 if (PadSize % CharBitNum == 0) {
2192 PadSize = PadSize / CharBitNum;
2198 << (InBits ? 1 : 0);
2201 const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD);
2209 if (Packed && UnpackedAlignment <= Alignment &&
2210 UnpackedSizeInBits == getSizeInBits() && !HasPackedField &&
2211 (!CXXRD || CXXRD->isPOD() ||
2219void ItaniumRecordLayoutBuilder::UpdateAlignment(
2224 if (IsMac68kAlign || (UseExternalLayout && !InferAlignment))
2227 if (NewAlignment > Alignment) {
2228 assert(llvm::isPowerOf2_64(NewAlignment.
getQuantity()) &&
2229 "Alignment not a power of 2");
2230 Alignment = NewAlignment;
2233 if (UnpackedNewAlignment > UnpackedAlignment) {
2234 assert(llvm::isPowerOf2_64(UnpackedNewAlignment.
getQuantity()) &&
2235 "Alignment not a power of 2");
2236 UnpackedAlignment = UnpackedNewAlignment;
2239 if (PreferredNewAlignment > PreferredAlignment) {
2240 assert(llvm::isPowerOf2_64(PreferredNewAlignment.
getQuantity()) &&
2241 "Alignment not a power of 2");
2242 PreferredAlignment = PreferredNewAlignment;
2247ItaniumRecordLayoutBuilder::updateExternalFieldOffset(
const FieldDecl *Field,
2248 uint64_t ComputedOffset) {
2249 uint64_t ExternalFieldOffset = External.getExternalFieldOffset(Field);
2251 if (InferAlignment && ExternalFieldOffset < ComputedOffset) {
2256 InferAlignment =
false;
2260 return ExternalFieldOffset;
2273 default: llvm_unreachable(
"Invalid tag kind for field padding diagnostic!");
2277void ItaniumRecordLayoutBuilder::CheckFieldPadding(
2278 uint64_t
Offset, uint64_t UnpaddedOffset, uint64_t UnpackedOffset,
2279 unsigned UnpackedAlign,
bool isPacked,
const FieldDecl *D) {
2282 if (isa<ObjCIvarDecl>(D))
2293 if (!IsUnion &&
Offset > UnpaddedOffset) {
2294 unsigned PadSize =
Offset - UnpaddedOffset;
2296 if (PadSize % CharBitNum == 0) {
2297 PadSize = PadSize / CharBitNum;
2312 << (InBits ? 1 : 0);
2314 if (isPacked &&
Offset != UnpackedOffset) {
2315 HasPackedField =
true;
2339 bool allowInlineFunctions =
2343 if (!MD->isVirtual())
2351 if (MD->isImplicit())
2354 if (MD->isInlineSpecified() || MD->isConstexpr())
2357 if (MD->hasInlineBody())
2361 if (!MD->isUserProvided())
2365 if (!allowInlineFunctions) {
2377 if (!MD->hasAttr<CUDADeviceAttr>())
2381 if (!MD->hasAttr<CUDAHostAttr>() && MD->hasAttr<CUDADeviceAttr>())
2389 if (MD->hasAttr<DLLImportAttr>() && !RD->
hasAttr<DLLImportAttr>() &&
2444 llvm_unreachable(
"bad tail-padding use kind");
2542struct MicrosoftRecordLayoutBuilder {
2543 struct ElementInfo {
2547 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
2548 MicrosoftRecordLayoutBuilder(
const ASTContext &Context) : Context(Context) {}
2550 MicrosoftRecordLayoutBuilder(
const MicrosoftRecordLayoutBuilder &) =
delete;
2551 void operator=(
const MicrosoftRecordLayoutBuilder &) =
delete;
2572 void layoutBitField(
const FieldDecl *FD);
2575 void layoutZeroWidthBitField(
const FieldDecl *FD);
2584 ElementInfo getAdjustedElementInfo(
const FieldDecl *FD);
2586 void placeFieldAtOffset(
CharUnits FieldOffset) {
2587 FieldOffsets.push_back(Context.
toBits(FieldOffset));
2590 void placeFieldAtBitOffset(uint64_t FieldOffset) {
2591 FieldOffsets.push_back(FieldOffset);
2594 void computeVtorDispSet(
2595 llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtorDispSet,
2620 ElementInfo PointerInfo;
2628 BaseOffsetsMapTy Bases;
2634 unsigned RemainingBitsInField;
2638 bool LastFieldIsNonZeroWidthBitfield : 1;
2640 bool HasOwnVFPtr : 1;
2646 bool EndsWithZeroSizedObject : 1;
2649 bool LeadsWithZeroSizedBase : 1;
2652 bool UseExternalLayout : 1;
2656 ExternalLayout External;
2660MicrosoftRecordLayoutBuilder::ElementInfo
2661MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
2666 if (!MaxFieldAlignment.
isZero())
2667 Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment);
2673 Alignment = std::max(Alignment, Info.Alignment);
2680MicrosoftRecordLayoutBuilder::ElementInfo
2681MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
2687 ElementInfo Info{TInfo.
Width, TInfo.Align};
2693 FieldRequiredAlignment = std::max(
2699 Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment);
2705 FieldRequiredAlignment = std::max(FieldRequiredAlignment,
2709 RequiredAlignment = std::max(RequiredAlignment, FieldRequiredAlignment);
2712 if (!MaxFieldAlignment.
isZero())
2713 Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment);
2714 if (FD->
hasAttr<PackedAttr>())
2716 Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment);
2720void MicrosoftRecordLayoutBuilder::layout(
const RecordDecl *RD) {
2723 initializeLayout(RD);
2725 DataSize =
Size =
Size.alignTo(Alignment);
2726 RequiredAlignment = std::max(
2731void MicrosoftRecordLayoutBuilder::cxxLayout(
const CXXRecordDecl *RD) {
2734 initializeLayout(RD);
2735 initializeCXXLayout(RD);
2736 layoutNonVirtualBases(RD);
2740 if (HasOwnVFPtr || (HasVBPtr && !SharedVBPtrBase))
2741 Alignment = std::max(Alignment, PointerInfo.Alignment);
2742 auto RoundingAlignment = Alignment;
2743 if (!MaxFieldAlignment.
isZero())
2744 RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment);
2745 if (!UseExternalLayout)
2746 Size =
Size.alignTo(RoundingAlignment);
2747 NonVirtualSize =
Size;
2748 RequiredAlignment = std::max(
2750 layoutVirtualBases(RD);
2754void MicrosoftRecordLayoutBuilder::initializeLayout(
const RecordDecl *RD) {
2767 if (
unsigned DefaultMaxFieldAlignment = Context.
getLangOpts().PackStruct)
2771 if (
const MaxFieldAlignmentAttr *MFAA = RD->
getAttr<MaxFieldAlignmentAttr>()){
2772 unsigned PackedAlignment = MFAA->getAlignment();
2773 if (PackedAlignment <=
2778 if (RD->
hasAttr<PackedAttr>())
2782 UseExternalLayout =
false;
2784 UseExternalLayout = Source->layoutRecordType(
2785 RD, External.Size, External.Align, External.FieldOffsets,
2786 External.BaseOffsets, External.VirtualBaseOffsets);
2790MicrosoftRecordLayoutBuilder::initializeCXXLayout(
const CXXRecordDecl *RD) {
2791 EndsWithZeroSizedObject =
false;
2792 LeadsWithZeroSizedBase =
false;
2793 HasOwnVFPtr =
false;
2795 PrimaryBase =
nullptr;
2796 SharedVBPtrBase =
nullptr;
2804 if (!MaxFieldAlignment.
isZero())
2805 PointerInfo.Alignment = std::min(PointerInfo.Alignment, MaxFieldAlignment);
2809MicrosoftRecordLayoutBuilder::layoutNonVirtualBases(
const CXXRecordDecl *RD) {
2817 bool HasPolymorphicBaseClass =
false;
2824 if (
Base.isVirtual()) {
2829 if (!SharedVBPtrBase && BaseLayout.
hasVBPtr()) {
2830 SharedVBPtrBase = BaseDecl;
2838 PrimaryBase = BaseDecl;
2842 layoutNonVirtualBase(RD, BaseDecl, BaseLayout, PreviousBaseLayout);
2846 if (!HasPolymorphicBaseClass)
2850 else if (!PrimaryBase) {
2854 if (MicrosoftVTableContext::hasVtableSlot(M) &&
2855 M->size_overridden_methods() == 0) {
2864 bool CheckLeadingLayout = !PrimaryBase;
2867 if (
Base.isVirtual())
2878 if (CheckLeadingLayout) {
2879 CheckLeadingLayout =
false;
2883 layoutNonVirtualBase(RD, BaseDecl, BaseLayout, PreviousBaseLayout);
2889 else if (SharedVBPtrBase) {
2896 if (!isa<CXXRecordDecl>(RD))
2898 if (RD->
hasAttr<EmptyBasesAttr>())
2900 if (
auto *LVA = RD->
getAttr<LayoutVersionAttr>())
2910void MicrosoftRecordLayoutBuilder::layoutNonVirtualBase(
2922 ElementInfo Info = getAdjustedElementInfo(BaseLayout);
2926 bool FoundBase =
false;
2927 if (UseExternalLayout) {
2928 FoundBase = External.getExternalNVBaseOffset(BaseDecl, BaseOffset);
2930 assert(BaseOffset >= Size &&
"base offset already allocated");
2936 if (MDCUsesEBO && BaseDecl->
isEmpty()) {
2941 BaseOffset =
Size =
Size.alignTo(Info.Alignment);
2944 Bases.insert(std::make_pair(BaseDecl, BaseOffset));
2946 PreviousBaseLayout = &BaseLayout;
2949void MicrosoftRecordLayoutBuilder::layoutFields(
const RecordDecl *RD) {
2950 LastFieldIsNonZeroWidthBitfield =
false;
2955void MicrosoftRecordLayoutBuilder::layoutField(
const FieldDecl *FD) {
2960 LastFieldIsNonZeroWidthBitfield =
false;
2961 ElementInfo Info = getAdjustedElementInfo(FD);
2962 Alignment = std::max(Alignment, Info.Alignment);
2964 if (UseExternalLayout)
2970 FieldOffset =
Size.alignTo(Info.Alignment);
2971 placeFieldAtOffset(FieldOffset);
2972 Size = std::max(Size, FieldOffset + Info.Size);
2975void MicrosoftRecordLayoutBuilder::layoutBitField(
const FieldDecl *FD) {
2978 layoutZeroWidthBitField(FD);
2981 ElementInfo Info = getAdjustedElementInfo(FD);
2984 if (Width > Context.
toBits(Info.Size))
2985 Width = Context.
toBits(Info.Size);
2989 if (!UseExternalLayout && !IsUnion && LastFieldIsNonZeroWidthBitfield &&
2990 CurrentBitfieldSize == Info.Size && Width <= RemainingBitsInField) {
2991 placeFieldAtBitOffset(Context.
toBits(Size) - RemainingBitsInField);
2992 RemainingBitsInField -= Width;
2995 LastFieldIsNonZeroWidthBitfield =
true;
2996 CurrentBitfieldSize = Info.Size;
2997 if (UseExternalLayout) {
2998 auto FieldBitOffset = External.getExternalFieldOffset(FD);
2999 placeFieldAtBitOffset(FieldBitOffset);
3001 llvm::alignDown(FieldBitOffset, Context.
toBits(Info.Alignment)) +
3002 Context.
toBits(Info.Size));
3003 Size = std::max(Size, NewSize);
3004 Alignment = std::max(Alignment, Info.Alignment);
3005 }
else if (IsUnion) {
3007 Size = std::max(Size, Info.Size);
3012 placeFieldAtOffset(FieldOffset);
3013 Size = FieldOffset + Info.Size;
3014 Alignment = std::max(Alignment, Info.Alignment);
3015 RemainingBitsInField = Context.
toBits(Info.Size) - Width;
3020MicrosoftRecordLayoutBuilder::layoutZeroWidthBitField(
const FieldDecl *FD) {
3023 if (!LastFieldIsNonZeroWidthBitfield) {
3029 LastFieldIsNonZeroWidthBitfield =
false;
3030 ElementInfo Info = getAdjustedElementInfo(FD);
3033 Size = std::max(Size, Info.Size);
3038 placeFieldAtOffset(FieldOffset);
3040 Alignment = std::max(Alignment, Info.Alignment);
3044void MicrosoftRecordLayoutBuilder::injectVBPtr(
const CXXRecordDecl *RD) {
3045 if (!HasVBPtr || SharedVBPtrBase)
3050 VBPtrOffset = VBPtrOffset.
alignTo(PointerInfo.Alignment);
3052 CharUnits FieldStart = VBPtrOffset + PointerInfo.Size;
3055 if (UseExternalLayout) {
3058 if (Size < FieldStart)
3065 .alignTo(std::max(RequiredAlignment, Alignment));
3067 for (uint64_t &FieldOffset : FieldOffsets)
3069 for (BaseOffsetsMapTy::value_type &
Base : Bases)
3070 if (
Base.second >= InjectionSite)
3074void MicrosoftRecordLayoutBuilder::injectVFPtr(
const CXXRecordDecl *RD) {
3080 PointerInfo.Size.alignTo(std::max(RequiredAlignment, Alignment));
3086 if (UseExternalLayout) {
3098 for (uint64_t &FieldOffset : FieldOffsets)
3100 for (BaseOffsetsMapTy::value_type &
Base : Bases)
3104void MicrosoftRecordLayoutBuilder::layoutVirtualBases(
const CXXRecordDecl *RD) {
3109 CharUnits VtorDispAlignment = VtorDispSize;
3111 if (!MaxFieldAlignment.
isZero())
3112 VtorDispAlignment = std::min(VtorDispAlignment, MaxFieldAlignment);
3117 const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl();
3122 VtorDispAlignment = std::max(VtorDispAlignment, RequiredAlignment);
3125 computeVtorDispSet(HasVtorDispSet, RD);
3129 const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl();
3131 bool HasVtordisp = HasVtorDispSet.contains(BaseDecl);
3140 Size =
Size.alignTo(VtorDispAlignment) + VtorDispSize;
3141 Alignment = std::max(VtorDispAlignment, Alignment);
3144 ElementInfo Info = getAdjustedElementInfo(BaseLayout);
3148 if (UseExternalLayout) {
3149 if (!External.getExternalVBaseOffset(BaseDecl, BaseOffset))
3152 BaseOffset =
Size.alignTo(Info.Alignment);
3154 assert(BaseOffset >= Size &&
"base offset already allocated");
3156 VBases.insert(std::make_pair(BaseDecl,
3159 PreviousBaseLayout = &BaseLayout;
3163void MicrosoftRecordLayoutBuilder::finalizeLayout(
const RecordDecl *RD) {
3167 if (!RequiredAlignment.isZero()) {
3168 Alignment = std::max(Alignment, RequiredAlignment);
3169 auto RoundingAlignment = Alignment;
3170 if (!MaxFieldAlignment.
isZero())
3171 RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment);
3172 RoundingAlignment = std::max(RoundingAlignment, RequiredAlignment);
3173 Size =
Size.alignTo(RoundingAlignment);
3175 if (
Size.isZero()) {
3176 if (!
recordUsesEBO(RD) || !cast<CXXRecordDecl>(RD)->isEmpty()) {
3177 EndsWithZeroSizedObject =
true;
3178 LeadsWithZeroSizedBase =
true;
3182 if (RequiredAlignment >= MinEmptyStructSize)
3185 Size = MinEmptyStructSize;
3188 if (UseExternalLayout) {
3199 BasesWithOverriddenMethods,
3201 if (BasesWithOverriddenMethods.count(RD))
3206 if (!
Base.isVirtual() &&
3208 Base.getType()->getAsCXXRecordDecl()))
3213void MicrosoftRecordLayoutBuilder::computeVtorDispSet(
3214 llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtordispSet,
3223 HasVtordispSet.insert(BaseDecl);
3234 if (bi.second.hasVtorDisp())
3235 HasVtordispSet.insert(bi.first);
3255 if (MicrosoftVTableContext::hasVtableSlot(MD) &&
3256 !isa<CXXDestructorDecl>(MD) && !MD->isPure())
3258 while (!Work.empty()) {
3262 if (MethodRange.begin() == MethodRange.end())
3263 BasesWithOverriddenMethods.insert(MD->
getParent());
3265 Work.insert(MethodRange.begin(), MethodRange.end());
3273 if (!HasVtordispSet.count(BaseDecl) &&
3275 HasVtordispSet.insert(BaseDecl);
3295 assert(D &&
"Cannot get layout of forward declarations!");
3296 assert(!D->
isInvalidDecl() &&
"Cannot get layout of invalid decl!");
3303 if (Entry)
return *Entry;
3308 MicrosoftRecordLayoutBuilder Builder(*
this);
3309 if (
const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
3310 Builder.cxxLayout(RD);
3312 *
this, Builder.Size, Builder.Alignment, Builder.Alignment,
3313 Builder.Alignment, Builder.RequiredAlignment, Builder.HasOwnVFPtr,
3314 Builder.HasOwnVFPtr || Builder.PrimaryBase, Builder.VBPtrOffset,
3315 Builder.DataSize, Builder.FieldOffsets, Builder.NonVirtualSize,
3317 Builder.PrimaryBase,
false, Builder.SharedVBPtrBase,
3318 Builder.EndsWithZeroSizedObject, Builder.LeadsWithZeroSizedBase,
3319 Builder.Bases, Builder.VBases);
3323 *
this, Builder.Size, Builder.Alignment, Builder.Alignment,
3324 Builder.Alignment, Builder.RequiredAlignment, Builder.Size,
3325 Builder.FieldOffsets);
3328 if (
const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
3329 EmptySubobjectMap EmptySubobjects(*
this, RD);
3330 ItaniumRecordLayoutBuilder Builder(*
this, &EmptySubobjects);
3336 bool skipTailPadding =
3341 skipTailPadding ? Builder.getSize() : Builder.getDataSize();
3343 skipTailPadding ? DataSize : Builder.NonVirtualSize;
3345 *
this, Builder.getSize(), Builder.Alignment,
3346 Builder.PreferredAlignment, Builder.UnadjustedAlignment,
3350 NonVirtualSize, Builder.NonVirtualAlignment,
3351 Builder.PreferredNVAlignment,
3352 EmptySubobjects.SizeOfLargestEmptySubobject, Builder.PrimaryBase,
3353 Builder.PrimaryBaseIsVirtual,
nullptr,
false,
false, Builder.Bases,
3356 ItaniumRecordLayoutBuilder Builder(*
this,
nullptr);
3360 *
this, Builder.getSize(), Builder.Alignment,
3361 Builder.PreferredAlignment, Builder.UnadjustedAlignment,
3363 Builder.Alignment, Builder.getSize(), Builder.FieldOffsets);
3367 ASTRecordLayouts[D] = NewEntry;
3370 llvm::outs() <<
"\n*** Dumping AST Record Layout\n";
3381 assert(RD->
getDefinition() &&
"Cannot get key function for forward decl!");
3395 KeyFunctions[RD] =
const_cast<Decl*
>(
Result);
3397 return cast_or_null<CXXMethodDecl>(
Result);
3402 "not working with method declaration from class definition");
3407 const auto &Map = KeyFunctions;
3411 if (I == Map.end())
return;
3419 KeyFunctions.erase(Method->
getParent());
3429 uint64_t OffsetInBits;
3430 if (
const FieldDecl *FD = dyn_cast<FieldDecl>(VD)) {
3440 return OffsetInBits;
3468 for (
const ObjCIvarDecl *IVD = Container->all_declared_ivar_begin();
3469 IVD; IVD = IVD->getNextIvar()) {
3474 assert(Index < RL->getFieldCount() &&
"Ivar is not inside record layout!");
3492 "Invalid interface decl!");
3507 if (SynthCount == 0)
3508 return getObjCLayout(D,
nullptr);
3511 ItaniumRecordLayoutBuilder Builder(*
this,
nullptr);
3515 *
this, Builder.getSize(), Builder.Alignment, Builder.PreferredAlignment,
3516 Builder.UnadjustedAlignment,
3518 Builder.Alignment, Builder.getDataSize(), Builder.FieldOffsets);
3520 ObjCLayouts[Key] = NewEntry;
3527 OS << llvm::format(
"%10" PRId64
" | ", (int64_t)
Offset.getQuantity());
3528 OS.indent(IndentLevel * 2);
3532 unsigned Begin,
unsigned Width,
3533 unsigned IndentLevel) {
3536 llvm::raw_svector_ostream BufferOS(Buffer);
3537 BufferOS <<
Offset.getQuantity() <<
':';
3541 BufferOS <<
Begin <<
'-' << (
Begin + Width - 1);
3545 OS << llvm::right_justify(Buffer, 10) <<
" | ";
3546 OS.indent(IndentLevel * 2);
3551 OS.indent(IndentLevel * 2);
3557 unsigned IndentLevel,
3558 const char* Description,
3560 bool IncludeVirtualBases) {
3562 auto CXXRD = dyn_cast<CXXRecordDecl>(RD);
3565 OS <<
C.getTypeDeclType(
const_cast<RecordDecl *
>(RD));
3567 OS <<
' ' << Description;
3568 if (CXXRD && CXXRD->isEmpty())
3581 if (CXXRD->isDynamicClass() && !PrimaryBase && !
isMsLayout(
C)) {
3583 OS <<
'(' << *RD <<
" vtable pointer)\n";
3584 }
else if (HasOwnVFPtr) {
3587 OS <<
'(' << *RD <<
" vftable pointer)\n";
3593 assert(!
Base.getType()->isDependentType() &&
3594 "Cannot layout class with dependent bases.");
3595 if (!
Base.isVirtual())
3596 Bases.push_back(
Base.getType()->getAsCXXRecordDecl());
3609 Base == PrimaryBase ?
"(primary base)" :
"(base)",
3617 OS <<
'(' << *RD <<
" vbtable pointer)\n";
3622 uint64_t FieldNo = 0;
3624 E = RD->
field_end(); I != E; ++I, ++FieldNo) {
3626 uint64_t LocalFieldOffsetInBits = Layout.
getFieldOffset(FieldNo);
3628 Offset +
C.toCharUnitsFromBits(LocalFieldOffsetInBits);
3631 if (
auto RT = Field.getType()->getAs<
RecordType>()) {
3633 Field.getName().data(),
3639 if (Field.isBitField()) {
3640 uint64_t LocalFieldByteOffsetInBits =
C.toBits(FieldOffset -
Offset);
3641 unsigned Begin = LocalFieldOffsetInBits - LocalFieldByteOffsetInBits;
3642 unsigned Width = Field.getBitWidthValue(
C);
3647 const QualType &FieldType =
C.getLangOpts().DumpRecordLayoutsCanonical
3648 ? Field.getType().getCanonicalType()
3650 OS << FieldType <<
' ' << Field <<
'\n';
3654 if (CXXRD && IncludeVirtualBases) {
3659 assert(
Base.isVirtual() &&
"Found non-virtual class!");
3664 if (VtorDisps.find(VBase)->second.hasVtorDisp()) {
3666 OS <<
"(vtordisp for vbase " << *VBase <<
")\n";
3671 "(primary virtual base)" :
"(virtual base)",
3677 if (!PrintSizeInfo)
return;
3684 if (
C.getTargetInfo().defaultsToAIXPowerAlignment())
3692 if (
C.getTargetInfo().defaultsToAIXPowerAlignment())
3693 OS <<
", preferrednvalign="
3700 bool Simple)
const {
3718 OS <<
"<ASTRecordLayout\n";
3723 if (
Target->defaultsToAIXPowerAlignment())
3726 OS <<
" FieldOffsets: [";
3727 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)
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
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.
bool hasExternalLexicalStorage() const
Whether this DeclContext has external storage containing additional declarations that are lexically i...
Decl - This represents one declaration (or definition), e.g.
unsigned getMaxAlignment() const
getMaxAlignment - return the maximum alignment specified by attributes on this decl,...
bool isInvalidDecl() const
SourceLocation getLocation() const
A little helper class used to produce diagnostics.
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
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.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
bool isExternallyVisible() const
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 * all_declared_ivar_begin()
all_declared_ivar_begin - return first ivar declared in this class, its extensions and its implementa...
bool isThisDeclarationADefinition() const
Determine whether this particular declaration of this class is actually also a definition.
ObjCInterfaceDecl * getSuperClass() const
ObjCInterfaceDecl * getDefinition()
Retrieve the definition of this class, or NULL if this class has been forward-declared (with @class) ...
ObjCIvarDecl - Represents an ObjC instance variable.
ObjCInterfaceDecl * getContainingInterface()
Return the class interface that this ivar is logically contained in; this is either the interface whe...
ObjCIvarDecl * getNextIvar()
ObjCIvarDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this field.
A (possibly-)qualified type.
Represents a struct/union/class.
bool isMsStruct(const ASTContext &C) const
Get whether or not this is an ms_struct which can be turned on with an attribute, pragma,...
bool hasFlexibleArrayMember() const
field_iterator field_end() const
field_range fields() const
bool mayInsertExtraPadding(bool EmitRemark=false) const
Whether we are allowed to insert extra padding between fields.
RecordDecl * getMostRecentDecl()
RecordDecl * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
field_iterator field_begin() const
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.
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
TagKind getTagKind() const
The basic abstraction for the target C++ ABI.
TailPaddingUseRules getTailPaddingUseRules() const
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...
bool isIncompleteArrayType() const
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,...
bool isRecordType() const
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Defines the clang::TargetInfo interface.
bool Zero(InterpState &S, CodePtr OpPC)
@ C
Languages that the frontend can parse and compile.
@ Result
The result type of a method or function.
TagTypeKind
The kind of a tag type.
@ TTK_Class
The "class" keyword.
@ TTK_Struct
The "struct" keyword.
@ TTK_Interface
The "__interface" keyword.
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.
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.