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 PotentiallyOverlapping = D->
hasAttr<NoUniqueAddressAttr>() && FieldClass;
1857 bool IsOverlappingEmptyField =
1858 PotentiallyOverlapping && FieldClass->isEmpty();
1861 (IsUnion || IsOverlappingEmptyField) ?
CharUnits::Zero() : getDataSize();
1863 const bool DefaultsToAIXPowerAlignment =
1865 bool FoundFirstNonOverlappingEmptyFieldForAIX =
false;
1866 if (DefaultsToAIXPowerAlignment && !HandledFirstNonOverlappingEmptyField) {
1868 "The first non-overlapping empty field should have been handled.");
1870 if (!IsOverlappingEmptyField) {
1871 FoundFirstNonOverlappingEmptyFieldForAIX =
true;
1878 HandledFirstNonOverlappingEmptyField = !IsUnion;
1887 uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;
1889 UnfilledBitsInLastUnit = 0;
1890 LastBitfieldStorageUnitSize = 0;
1902 auto setDeclInfo = [&](
bool IsIncompleteArrayType) {
1904 FieldAlign = TI.Align;
1907 EffectiveFieldSize = FieldSize =
1909 AlignRequirement = TI.AlignRequirement;
1915 setDeclInfo(
false );
1919 if (PotentiallyOverlapping) {
1921 EffectiveFieldSize =
1935 if (!llvm::isPowerOf2_64(TypeSize.
getQuantity())) {
1938 "Non PowerOf2 size in MSVC mode");
1960 if (TypeSize > FieldAlign &&
1962 FieldAlign = TypeSize;
1967 bool FieldPacked = (Packed && (!FieldClass || FieldClass->isPOD() ||
1968 FieldClass->hasAttr<PackedAttr>() ||
1979 auto alignedAttrCanDecreaseAIXAlignment = [AlignRequirement, FieldPacked] {
1998 if (DefaultsToAIXPowerAlignment && !alignedAttrCanDecreaseAIXAlignment() &&
1999 (FoundFirstNonOverlappingEmptyFieldForAIX || IsNaturalAlign)) {
2000 auto performBuiltinTypeAlignmentUpgrade = [&](
const BuiltinType *BTy) {
2001 if (BTy->getKind() == BuiltinType::Double ||
2002 BTy->getKind() == BuiltinType::LongDouble) {
2004 "No need to upgrade the alignment value.");
2011 performBuiltinTypeAlignmentUpgrade(
2014 performBuiltinTypeAlignmentUpgrade(BTy);
2017 assert(RD &&
"Expected non-null RecordDecl.");
2025 CharUnits UnpackedFieldAlign = FieldAlign;
2027 CharUnits UnpackedFieldOffset = FieldOffset;
2028 CharUnits OriginalFieldAlign = UnpackedFieldAlign;
2032 PackedFieldAlign = std::max(PackedFieldAlign, MaxAlignmentInChars);
2033 PreferredAlign = std::max(PreferredAlign, MaxAlignmentInChars);
2034 UnpackedFieldAlign = std::max(UnpackedFieldAlign, MaxAlignmentInChars);
2037 if (!MaxFieldAlignment.
isZero()) {
2038 PackedFieldAlign = std::min(PackedFieldAlign, MaxFieldAlignment);
2039 PreferredAlign = std::min(PreferredAlign, MaxFieldAlignment);
2040 UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignment);
2045 FieldAlign = UnpackedFieldAlign;
2046 if (DefaultsToAIXPowerAlignment)
2047 UnpackedFieldAlign = PreferredAlign;
2049 PreferredAlign = PackedFieldAlign;
2050 FieldAlign = PackedFieldAlign;
2054 !DefaultsToAIXPowerAlignment ? FieldAlign : PreferredAlign;
2056 FieldOffset = FieldOffset.
alignTo(AlignTo);
2057 UnpackedFieldOffset = UnpackedFieldOffset.
alignTo(UnpackedFieldAlign);
2059 if (UseExternalLayout) {
2061 updateExternalFieldOffset(D, Context.
toBits(FieldOffset)));
2063 if (!IsUnion && EmptySubobjects) {
2065 bool Allowed = EmptySubobjects->CanPlaceFieldAtOffset(D, FieldOffset);
2067 assert(Allowed &&
"Externally-placed field cannot be placed here");
2070 if (!IsUnion && EmptySubobjects) {
2072 while (!EmptySubobjects->CanPlaceFieldAtOffset(D, FieldOffset)) {
2077 FieldOffset = getDataSize().
alignTo(AlignTo);
2079 FieldOffset += AlignTo;
2085 FieldOffsets.push_back(Context.
toBits(FieldOffset));
2087 if (!UseExternalLayout)
2088 CheckFieldPadding(Context.
toBits(FieldOffset), UnpaddedFieldOffset,
2089 Context.
toBits(UnpackedFieldOffset),
2090 Context.
toBits(UnpackedFieldAlign), FieldPacked, D);
2092 if (InsertExtraPadding) {
2094 CharUnits ExtraSizeForAsan = ASanAlignment;
2095 if (FieldSize % ASanAlignment)
2098 EffectiveFieldSize = FieldSize = FieldSize + ExtraSizeForAsan;
2102 if (!IsOverlappingEmptyField) {
2103 uint64_t EffectiveFieldSizeInBits = Context.
toBits(EffectiveFieldSize);
2105 setDataSize(std::max(getDataSizeInBits(), EffectiveFieldSizeInBits));
2107 setDataSize(FieldOffset + EffectiveFieldSize);
2109 PaddedFieldSize = std::max(PaddedFieldSize, FieldOffset + FieldSize);
2110 setSize(std::max(getSizeInBits(), getDataSizeInBits()));
2112 setSize(std::max(getSizeInBits(),
2113 (uint64_t)Context.
toBits(FieldOffset + FieldSize)));
2117 UnadjustedAlignment = std::max(UnadjustedAlignment, FieldAlign);
2118 UpdateAlignment(FieldAlign, UnpackedFieldAlign, PreferredAlign);
2124 if (RD->
hasAttr<PackedAttr>() || !MaxFieldAlignment.
isZero())
2125 if (FieldAlign < OriginalFieldAlign)
2130 if (FieldOffset % OriginalFieldAlign != 0)
2136 if (Packed && !FieldPacked && PackedFieldAlign < FieldAlign)
2140void ItaniumRecordLayoutBuilder::FinishLayout(
const NamedDecl *D) {
2142 if (Context.
getLangOpts().CPlusPlus && getSizeInBits() == 0) {
2156 setSize(std::max(getSizeInBits(), (uint64_t)Context.
toBits(PaddedFieldSize)));
2160 uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastUnit;
2162 llvm::alignTo(getSizeInBits(), Context.
toBits(UnpackedAlignment));
2164 uint64_t RoundedSize = llvm::alignTo(
2168 : PreferredAlignment));
2170 if (UseExternalLayout) {
2174 if (InferAlignment && External.Size < RoundedSize) {
2177 InferAlignment =
false;
2179 setSize(External.Size);
2184 setSize(RoundedSize);
2187 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
2189 if (getSizeInBits() > UnpaddedSize) {
2190 unsigned PadSize = getSizeInBits() - UnpaddedSize;
2192 if (PadSize % CharBitNum == 0) {
2193 PadSize = PadSize / CharBitNum;
2199 << (InBits ? 1 : 0);
2205 if (Packed && UnpackedAlignment <= Alignment &&
2206 UnpackedSizeInBits == getSizeInBits() && !HasPackedField)
2212void ItaniumRecordLayoutBuilder::UpdateAlignment(
2217 if (IsMac68kAlign || (UseExternalLayout && !InferAlignment))
2220 if (NewAlignment > Alignment) {
2221 assert(llvm::isPowerOf2_64(NewAlignment.
getQuantity()) &&
2222 "Alignment not a power of 2");
2223 Alignment = NewAlignment;
2226 if (UnpackedNewAlignment > UnpackedAlignment) {
2227 assert(llvm::isPowerOf2_64(UnpackedNewAlignment.
getQuantity()) &&
2228 "Alignment not a power of 2");
2229 UnpackedAlignment = UnpackedNewAlignment;
2232 if (PreferredNewAlignment > PreferredAlignment) {
2233 assert(llvm::isPowerOf2_64(PreferredNewAlignment.
getQuantity()) &&
2234 "Alignment not a power of 2");
2235 PreferredAlignment = PreferredNewAlignment;
2240ItaniumRecordLayoutBuilder::updateExternalFieldOffset(
const FieldDecl *Field,
2241 uint64_t ComputedOffset) {
2242 uint64_t ExternalFieldOffset = External.getExternalFieldOffset(Field);
2244 if (InferAlignment && ExternalFieldOffset < ComputedOffset) {
2249 InferAlignment =
false;
2253 return ExternalFieldOffset;
2266 default: llvm_unreachable(
"Invalid tag kind for field padding diagnostic!");
2270void ItaniumRecordLayoutBuilder::CheckFieldPadding(
2271 uint64_t
Offset, uint64_t UnpaddedOffset, uint64_t UnpackedOffset,
2272 unsigned UnpackedAlign,
bool isPacked,
const FieldDecl *D) {
2275 if (isa<ObjCIvarDecl>(D))
2286 if (!IsUnion &&
Offset > UnpaddedOffset) {
2287 unsigned PadSize =
Offset - UnpaddedOffset;
2289 if (PadSize % CharBitNum == 0) {
2290 PadSize = PadSize / CharBitNum;
2305 << (InBits ? 1 : 0);
2307 if (isPacked &&
Offset != UnpackedOffset) {
2308 HasPackedField =
true;
2332 bool allowInlineFunctions =
2336 if (!MD->isVirtual())
2344 if (MD->isImplicit())
2347 if (MD->isInlineSpecified() || MD->isConstexpr())
2350 if (MD->hasInlineBody())
2354 if (!MD->isUserProvided())
2358 if (!allowInlineFunctions) {
2370 if (!MD->hasAttr<CUDADeviceAttr>())
2374 if (!MD->hasAttr<CUDAHostAttr>() && MD->hasAttr<CUDADeviceAttr>())
2382 if (MD->hasAttr<DLLImportAttr>() && !RD->
hasAttr<DLLImportAttr>() &&
2437 llvm_unreachable(
"bad tail-padding use kind");
2535struct MicrosoftRecordLayoutBuilder {
2536 struct ElementInfo {
2540 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
2541 MicrosoftRecordLayoutBuilder(
const ASTContext &Context) : Context(Context) {}
2543 MicrosoftRecordLayoutBuilder(
const MicrosoftRecordLayoutBuilder &) =
delete;
2544 void operator=(
const MicrosoftRecordLayoutBuilder &) =
delete;
2565 void layoutBitField(
const FieldDecl *FD);
2568 void layoutZeroWidthBitField(
const FieldDecl *FD);
2577 ElementInfo getAdjustedElementInfo(
const FieldDecl *FD);
2579 void placeFieldAtOffset(
CharUnits FieldOffset) {
2580 FieldOffsets.push_back(Context.
toBits(FieldOffset));
2583 void placeFieldAtBitOffset(uint64_t FieldOffset) {
2584 FieldOffsets.push_back(FieldOffset);
2587 void computeVtorDispSet(
2588 llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtorDispSet,
2613 ElementInfo PointerInfo;
2621 BaseOffsetsMapTy Bases;
2627 unsigned RemainingBitsInField;
2631 bool LastFieldIsNonZeroWidthBitfield : 1;
2633 bool HasOwnVFPtr : 1;
2639 bool EndsWithZeroSizedObject : 1;
2642 bool LeadsWithZeroSizedBase : 1;
2645 bool UseExternalLayout : 1;
2649 ExternalLayout External;
2653MicrosoftRecordLayoutBuilder::ElementInfo
2654MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
2659 if (!MaxFieldAlignment.
isZero())
2660 Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment);
2666 Alignment = std::max(Alignment, Info.Alignment);
2673MicrosoftRecordLayoutBuilder::ElementInfo
2674MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
2680 ElementInfo Info{TInfo.
Width, TInfo.Align};
2686 FieldRequiredAlignment = std::max(
2692 Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment);
2698 FieldRequiredAlignment = std::max(FieldRequiredAlignment,
2702 RequiredAlignment = std::max(RequiredAlignment, FieldRequiredAlignment);
2705 if (!MaxFieldAlignment.
isZero())
2706 Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment);
2707 if (FD->
hasAttr<PackedAttr>())
2709 Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment);
2713void MicrosoftRecordLayoutBuilder::layout(
const RecordDecl *RD) {
2716 initializeLayout(RD);
2718 DataSize =
Size =
Size.alignTo(Alignment);
2719 RequiredAlignment = std::max(
2724void MicrosoftRecordLayoutBuilder::cxxLayout(
const CXXRecordDecl *RD) {
2727 initializeLayout(RD);
2728 initializeCXXLayout(RD);
2729 layoutNonVirtualBases(RD);
2733 if (HasOwnVFPtr || (HasVBPtr && !SharedVBPtrBase))
2734 Alignment = std::max(Alignment, PointerInfo.Alignment);
2735 auto RoundingAlignment = Alignment;
2736 if (!MaxFieldAlignment.
isZero())
2737 RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment);
2738 if (!UseExternalLayout)
2739 Size =
Size.alignTo(RoundingAlignment);
2740 NonVirtualSize =
Size;
2741 RequiredAlignment = std::max(
2743 layoutVirtualBases(RD);
2747void MicrosoftRecordLayoutBuilder::initializeLayout(
const RecordDecl *RD) {
2760 if (
unsigned DefaultMaxFieldAlignment = Context.
getLangOpts().PackStruct)
2764 if (
const MaxFieldAlignmentAttr *MFAA = RD->
getAttr<MaxFieldAlignmentAttr>()){
2765 unsigned PackedAlignment = MFAA->getAlignment();
2766 if (PackedAlignment <=
2771 if (RD->
hasAttr<PackedAttr>())
2775 UseExternalLayout =
false;
2777 UseExternalLayout = Source->layoutRecordType(
2778 RD, External.Size, External.Align, External.FieldOffsets,
2779 External.BaseOffsets, External.VirtualBaseOffsets);
2783MicrosoftRecordLayoutBuilder::initializeCXXLayout(
const CXXRecordDecl *RD) {
2784 EndsWithZeroSizedObject =
false;
2785 LeadsWithZeroSizedBase =
false;
2786 HasOwnVFPtr =
false;
2788 PrimaryBase =
nullptr;
2789 SharedVBPtrBase =
nullptr;
2797 if (!MaxFieldAlignment.
isZero())
2798 PointerInfo.Alignment = std::min(PointerInfo.Alignment, MaxFieldAlignment);
2802MicrosoftRecordLayoutBuilder::layoutNonVirtualBases(
const CXXRecordDecl *RD) {
2810 bool HasPolymorphicBaseClass =
false;
2817 if (
Base.isVirtual()) {
2822 if (!SharedVBPtrBase && BaseLayout.
hasVBPtr()) {
2823 SharedVBPtrBase = BaseDecl;
2831 PrimaryBase = BaseDecl;
2835 layoutNonVirtualBase(RD, BaseDecl, BaseLayout, PreviousBaseLayout);
2839 if (!HasPolymorphicBaseClass)
2843 else if (!PrimaryBase) {
2847 if (MicrosoftVTableContext::hasVtableSlot(M) &&
2848 M->size_overridden_methods() == 0) {
2857 bool CheckLeadingLayout = !PrimaryBase;
2860 if (
Base.isVirtual())
2871 if (CheckLeadingLayout) {
2872 CheckLeadingLayout =
false;
2876 layoutNonVirtualBase(RD, BaseDecl, BaseLayout, PreviousBaseLayout);
2882 else if (SharedVBPtrBase) {
2889 if (!isa<CXXRecordDecl>(RD))
2891 if (RD->
hasAttr<EmptyBasesAttr>())
2893 if (
auto *LVA = RD->
getAttr<LayoutVersionAttr>())
2903void MicrosoftRecordLayoutBuilder::layoutNonVirtualBase(
2915 ElementInfo Info = getAdjustedElementInfo(BaseLayout);
2919 bool FoundBase =
false;
2920 if (UseExternalLayout) {
2921 FoundBase = External.getExternalNVBaseOffset(BaseDecl, BaseOffset);
2923 assert(BaseOffset >= Size &&
"base offset already allocated");
2929 if (MDCUsesEBO && BaseDecl->
isEmpty()) {
2934 BaseOffset =
Size =
Size.alignTo(Info.Alignment);
2937 Bases.insert(std::make_pair(BaseDecl, BaseOffset));
2939 PreviousBaseLayout = &BaseLayout;
2942void MicrosoftRecordLayoutBuilder::layoutFields(
const RecordDecl *RD) {
2943 LastFieldIsNonZeroWidthBitfield =
false;
2948void MicrosoftRecordLayoutBuilder::layoutField(
const FieldDecl *FD) {
2953 LastFieldIsNonZeroWidthBitfield =
false;
2954 ElementInfo Info = getAdjustedElementInfo(FD);
2955 Alignment = std::max(Alignment, Info.Alignment);
2957 if (UseExternalLayout)
2963 FieldOffset =
Size.alignTo(Info.Alignment);
2964 placeFieldAtOffset(FieldOffset);
2965 Size = std::max(Size, FieldOffset + Info.Size);
2968void MicrosoftRecordLayoutBuilder::layoutBitField(
const FieldDecl *FD) {
2971 layoutZeroWidthBitField(FD);
2974 ElementInfo Info = getAdjustedElementInfo(FD);
2977 if (Width > Context.
toBits(Info.Size))
2978 Width = Context.
toBits(Info.Size);
2982 if (!UseExternalLayout && !IsUnion && LastFieldIsNonZeroWidthBitfield &&
2983 CurrentBitfieldSize == Info.Size && Width <= RemainingBitsInField) {
2984 placeFieldAtBitOffset(Context.
toBits(Size) - RemainingBitsInField);
2985 RemainingBitsInField -= Width;
2988 LastFieldIsNonZeroWidthBitfield =
true;
2989 CurrentBitfieldSize = Info.Size;
2990 if (UseExternalLayout) {
2991 auto FieldBitOffset = External.getExternalFieldOffset(FD);
2992 placeFieldAtBitOffset(FieldBitOffset);
2994 llvm::alignDown(FieldBitOffset, Context.
toBits(Info.Alignment)) +
2995 Context.
toBits(Info.Size));
2996 Size = std::max(Size, NewSize);
2997 Alignment = std::max(Alignment, Info.Alignment);
2998 }
else if (IsUnion) {
3000 Size = std::max(Size, Info.Size);
3005 placeFieldAtOffset(FieldOffset);
3006 Size = FieldOffset + Info.Size;
3007 Alignment = std::max(Alignment, Info.Alignment);
3008 RemainingBitsInField = Context.
toBits(Info.Size) - Width;
3013MicrosoftRecordLayoutBuilder::layoutZeroWidthBitField(
const FieldDecl *FD) {
3016 if (!LastFieldIsNonZeroWidthBitfield) {
3022 LastFieldIsNonZeroWidthBitfield =
false;
3023 ElementInfo Info = getAdjustedElementInfo(FD);
3026 Size = std::max(Size, Info.Size);
3031 placeFieldAtOffset(FieldOffset);
3033 Alignment = std::max(Alignment, Info.Alignment);
3037void MicrosoftRecordLayoutBuilder::injectVBPtr(
const CXXRecordDecl *RD) {
3038 if (!HasVBPtr || SharedVBPtrBase)
3043 VBPtrOffset = VBPtrOffset.
alignTo(PointerInfo.Alignment);
3045 CharUnits FieldStart = VBPtrOffset + PointerInfo.Size;
3048 if (UseExternalLayout) {
3051 if (Size < FieldStart)
3058 .alignTo(std::max(RequiredAlignment, Alignment));
3060 for (uint64_t &FieldOffset : FieldOffsets)
3062 for (BaseOffsetsMapTy::value_type &
Base : Bases)
3063 if (
Base.second >= InjectionSite)
3067void MicrosoftRecordLayoutBuilder::injectVFPtr(
const CXXRecordDecl *RD) {
3073 PointerInfo.Size.alignTo(std::max(RequiredAlignment, Alignment));
3079 if (UseExternalLayout) {
3091 for (uint64_t &FieldOffset : FieldOffsets)
3093 for (BaseOffsetsMapTy::value_type &
Base : Bases)
3097void MicrosoftRecordLayoutBuilder::layoutVirtualBases(
const CXXRecordDecl *RD) {
3102 CharUnits VtorDispAlignment = VtorDispSize;
3104 if (!MaxFieldAlignment.
isZero())
3105 VtorDispAlignment = std::min(VtorDispAlignment, MaxFieldAlignment);
3110 const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl();
3115 VtorDispAlignment = std::max(VtorDispAlignment, RequiredAlignment);
3118 computeVtorDispSet(HasVtorDispSet, RD);
3122 const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl();
3124 bool HasVtordisp = HasVtorDispSet.contains(BaseDecl);
3133 Size =
Size.alignTo(VtorDispAlignment) + VtorDispSize;
3134 Alignment = std::max(VtorDispAlignment, Alignment);
3137 ElementInfo Info = getAdjustedElementInfo(BaseLayout);
3141 if (UseExternalLayout) {
3142 if (!External.getExternalVBaseOffset(BaseDecl, BaseOffset))
3145 BaseOffset =
Size.alignTo(Info.Alignment);
3147 assert(BaseOffset >= Size &&
"base offset already allocated");
3149 VBases.insert(std::make_pair(BaseDecl,
3152 PreviousBaseLayout = &BaseLayout;
3156void MicrosoftRecordLayoutBuilder::finalizeLayout(
const RecordDecl *RD) {
3160 if (!RequiredAlignment.isZero()) {
3161 Alignment = std::max(Alignment, RequiredAlignment);
3162 auto RoundingAlignment = Alignment;
3163 if (!MaxFieldAlignment.
isZero())
3164 RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment);
3165 RoundingAlignment = std::max(RoundingAlignment, RequiredAlignment);
3166 Size =
Size.alignTo(RoundingAlignment);
3168 if (
Size.isZero()) {
3169 if (!
recordUsesEBO(RD) || !cast<CXXRecordDecl>(RD)->isEmpty()) {
3170 EndsWithZeroSizedObject =
true;
3171 LeadsWithZeroSizedBase =
true;
3175 if (RequiredAlignment >= MinEmptyStructSize)
3178 Size = MinEmptyStructSize;
3181 if (UseExternalLayout) {
3192 BasesWithOverriddenMethods,
3194 if (BasesWithOverriddenMethods.count(RD))
3199 if (!
Base.isVirtual() &&
3201 Base.getType()->getAsCXXRecordDecl()))
3206void MicrosoftRecordLayoutBuilder::computeVtorDispSet(
3207 llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtordispSet,
3216 HasVtordispSet.insert(BaseDecl);
3227 if (bi.second.hasVtorDisp())
3228 HasVtordispSet.insert(bi.first);
3248 if (MicrosoftVTableContext::hasVtableSlot(MD) &&
3249 !isa<CXXDestructorDecl>(MD) && !MD->isPure())
3251 while (!Work.empty()) {
3255 if (MethodRange.begin() == MethodRange.end())
3256 BasesWithOverriddenMethods.insert(MD->
getParent());
3258 Work.insert(MethodRange.begin(), MethodRange.end());
3266 if (!HasVtordispSet.count(BaseDecl) &&
3268 HasVtordispSet.insert(BaseDecl);
3288 assert(D &&
"Cannot get layout of forward declarations!");
3289 assert(!D->
isInvalidDecl() &&
"Cannot get layout of invalid decl!");
3296 if (Entry)
return *Entry;
3301 MicrosoftRecordLayoutBuilder Builder(*
this);
3302 if (
const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
3303 Builder.cxxLayout(RD);
3305 *
this, Builder.Size, Builder.Alignment, Builder.Alignment,
3306 Builder.Alignment, Builder.RequiredAlignment, Builder.HasOwnVFPtr,
3307 Builder.HasOwnVFPtr || Builder.PrimaryBase, Builder.VBPtrOffset,
3308 Builder.DataSize, Builder.FieldOffsets, Builder.NonVirtualSize,
3310 Builder.PrimaryBase,
false, Builder.SharedVBPtrBase,
3311 Builder.EndsWithZeroSizedObject, Builder.LeadsWithZeroSizedBase,
3312 Builder.Bases, Builder.VBases);
3316 *
this, Builder.Size, Builder.Alignment, Builder.Alignment,
3317 Builder.Alignment, Builder.RequiredAlignment, Builder.Size,
3318 Builder.FieldOffsets);
3321 if (
const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
3322 EmptySubobjectMap EmptySubobjects(*
this, RD);
3323 ItaniumRecordLayoutBuilder Builder(*
this, &EmptySubobjects);
3329 bool skipTailPadding =
3334 skipTailPadding ? Builder.getSize() : Builder.getDataSize();
3336 skipTailPadding ? DataSize : Builder.NonVirtualSize;
3338 *
this, Builder.getSize(), Builder.Alignment,
3339 Builder.PreferredAlignment, Builder.UnadjustedAlignment,
3343 NonVirtualSize, Builder.NonVirtualAlignment,
3344 Builder.PreferredNVAlignment,
3345 EmptySubobjects.SizeOfLargestEmptySubobject, Builder.PrimaryBase,
3346 Builder.PrimaryBaseIsVirtual,
nullptr,
false,
false, Builder.Bases,
3349 ItaniumRecordLayoutBuilder Builder(*
this,
nullptr);
3353 *
this, Builder.getSize(), Builder.Alignment,
3354 Builder.PreferredAlignment, Builder.UnadjustedAlignment,
3356 Builder.Alignment, Builder.getSize(), Builder.FieldOffsets);
3360 ASTRecordLayouts[D] = NewEntry;
3363 llvm::outs() <<
"\n*** Dumping AST Record Layout\n";
3374 assert(RD->
getDefinition() &&
"Cannot get key function for forward decl!");
3388 KeyFunctions[RD] =
const_cast<Decl*
>(
Result);
3390 return cast_or_null<CXXMethodDecl>(
Result);
3395 "not working with method declaration from class definition");
3400 const auto &Map = KeyFunctions;
3404 if (I == Map.end())
return;
3412 KeyFunctions.erase(Method->
getParent());
3422 uint64_t OffsetInBits;
3423 if (
const FieldDecl *FD = dyn_cast<FieldDecl>(VD)) {
3433 return OffsetInBits;
3461 for (
const ObjCIvarDecl *IVD = Container->all_declared_ivar_begin();
3462 IVD; IVD = IVD->getNextIvar()) {
3467 assert(Index < RL->getFieldCount() &&
"Ivar is not inside record layout!");
3485 "Invalid interface decl!");
3500 if (SynthCount == 0)
3501 return getObjCLayout(D,
nullptr);
3504 ItaniumRecordLayoutBuilder Builder(*
this,
nullptr);
3508 *
this, Builder.getSize(), Builder.Alignment, Builder.PreferredAlignment,
3509 Builder.UnadjustedAlignment,
3511 Builder.Alignment, Builder.getDataSize(), Builder.FieldOffsets);
3513 ObjCLayouts[Key] = NewEntry;
3520 OS << llvm::format(
"%10" PRId64
" | ", (int64_t)
Offset.getQuantity());
3521 OS.indent(IndentLevel * 2);
3525 unsigned Begin,
unsigned Width,
3526 unsigned IndentLevel) {
3529 llvm::raw_svector_ostream BufferOS(Buffer);
3530 BufferOS <<
Offset.getQuantity() <<
':';
3534 BufferOS <<
Begin <<
'-' << (
Begin + Width - 1);
3538 OS << llvm::right_justify(Buffer, 10) <<
" | ";
3539 OS.indent(IndentLevel * 2);
3544 OS.indent(IndentLevel * 2);
3550 unsigned IndentLevel,
3551 const char* Description,
3553 bool IncludeVirtualBases) {
3555 auto CXXRD = dyn_cast<CXXRecordDecl>(RD);
3558 OS <<
C.getTypeDeclType(
const_cast<RecordDecl *
>(RD));
3560 OS <<
' ' << Description;
3561 if (CXXRD && CXXRD->isEmpty())
3574 if (CXXRD->isDynamicClass() && !PrimaryBase && !
isMsLayout(
C)) {
3576 OS <<
'(' << *RD <<
" vtable pointer)\n";
3577 }
else if (HasOwnVFPtr) {
3580 OS <<
'(' << *RD <<
" vftable pointer)\n";
3586 assert(!
Base.getType()->isDependentType() &&
3587 "Cannot layout class with dependent bases.");
3588 if (!
Base.isVirtual())
3589 Bases.push_back(
Base.getType()->getAsCXXRecordDecl());
3602 Base == PrimaryBase ?
"(primary base)" :
"(base)",
3610 OS <<
'(' << *RD <<
" vbtable pointer)\n";
3615 uint64_t FieldNo = 0;
3617 E = RD->
field_end(); I != E; ++I, ++FieldNo) {
3619 uint64_t LocalFieldOffsetInBits = Layout.
getFieldOffset(FieldNo);
3621 Offset +
C.toCharUnitsFromBits(LocalFieldOffsetInBits);
3624 if (
auto RT = Field.getType()->getAs<
RecordType>()) {
3626 Field.getName().data(),
3632 if (Field.isBitField()) {
3633 uint64_t LocalFieldByteOffsetInBits =
C.toBits(FieldOffset -
Offset);
3634 unsigned Begin = LocalFieldOffsetInBits - LocalFieldByteOffsetInBits;
3635 unsigned Width = Field.getBitWidthValue(
C);
3640 const QualType &FieldType =
C.getLangOpts().DumpRecordLayoutsCanonical
3641 ? Field.getType().getCanonicalType()
3643 OS << FieldType <<
' ' << Field <<
'\n';
3647 if (CXXRD && IncludeVirtualBases) {
3652 assert(
Base.isVirtual() &&
"Found non-virtual class!");
3657 if (VtorDisps.find(VBase)->second.hasVtorDisp()) {
3659 OS <<
"(vtordisp for vbase " << *VBase <<
")\n";
3664 "(primary virtual base)" :
"(virtual base)",
3670 if (!PrintSizeInfo)
return;
3677 if (
C.getTargetInfo().defaultsToAIXPowerAlignment())
3685 if (
C.getTargetInfo().defaultsToAIXPowerAlignment())
3686 OS <<
", preferrednvalign="
3693 bool Simple)
const {
3711 OS <<
"<ASTRecordLayout\n";
3716 if (
Target->defaultsToAIXPowerAlignment())
3719 OS <<
" FieldOffsets: [";
3720 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.
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.