20 #include "llvm/ADT/SmallSet.h" 21 #include "llvm/Support/Format.h" 22 #include "llvm/Support/MathExtras.h" 24 using namespace clang;
39 struct BaseSubobjectInfo {
51 BaseSubobjectInfo *PrimaryVirtualBaseInfo;
54 const BaseSubobjectInfo *Derived;
60 struct 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;
80 uint64_t getExternalFieldOffset(
const FieldDecl *FD) {
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;
105 class 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,
138 return Offset <= MaxEmptyClassOffset;
144 assert(FieldOffset % CharWidth == 0 &&
145 "Field offset not at char boundary!");
154 bool CanPlaceBaseSubobjectAtOffset(
const BaseSubobjectInfo *Info,
160 bool CanPlaceFieldSubobjectAtOffset(
const FieldDecl *FD,
170 : Context(Context), CharWidth(Context.
getCharWidth()), Class(Class) {
171 ComputeEmptySubobjectSizes();
178 bool CanPlaceBaseAtOffset(
const BaseSubobjectInfo *Info,
186 void EmptySubobjectMap::ComputeEmptySubobjectSizes() {
201 if (EmptySize > SizeOfLargestEmptySubobject)
202 SizeOfLargestEmptySubobject = EmptySize;
225 if (EmptySize > SizeOfLargestEmptySubobject)
226 SizeOfLargestEmptySubobject = EmptySize;
231 EmptySubobjectMap::CanPlaceSubobjectAtOffset(
const CXXRecordDecl *RD,
237 EmptyClassOffsetsMapTy::const_iterator I = EmptyClassOffsets.find(Offset);
238 if (I == EmptyClassOffsets.end())
241 const ClassVectorTy &Classes = I->second;
242 if (std::find(Classes.begin(), Classes.end(), RD) == Classes.end())
249 void EmptySubobjectMap::AddSubobjectAtOffset(
const CXXRecordDecl *RD,
257 ClassVectorTy &Classes = EmptyClassOffsets[
Offset];
258 if (std::find(Classes.begin(), Classes.end(), RD) != Classes.end())
261 Classes.push_back(RD);
264 if (Offset > MaxEmptyClassOffset)
265 MaxEmptyClassOffset =
Offset;
269 EmptySubobjectMap::CanPlaceBaseSubobjectAtOffset(
const BaseSubobjectInfo *Info,
273 if (!AnyEmptySubobjectsBeyondOffset(Offset))
276 if (!CanPlaceSubobjectAtOffset(Info->Class, Offset))
281 for (
const BaseSubobjectInfo *
Base : Info->Bases) {
287 if (!CanPlaceBaseSubobjectAtOffset(Base, BaseOffset))
291 if (Info->PrimaryVirtualBaseInfo) {
292 BaseSubobjectInfo *PrimaryVirtualBaseInfo = Info->PrimaryVirtualBaseInfo;
294 if (Info == PrimaryVirtualBaseInfo->Derived) {
295 if (!CanPlaceBaseSubobjectAtOffset(PrimaryVirtualBaseInfo, Offset))
301 unsigned FieldNo = 0;
303 E = Info->Class->field_end(); I != E; ++I, ++FieldNo) {
308 if (!CanPlaceFieldSubobjectAtOffset(*I, FieldOffset))
315 void EmptySubobjectMap::UpdateEmptyBaseSubobjects(
const BaseSubobjectInfo *Info,
317 bool PlacingEmptyBase) {
318 if (!PlacingEmptyBase && Offset >= SizeOfLargestEmptySubobject) {
327 AddSubobjectAtOffset(Info->Class, Offset);
331 for (
const BaseSubobjectInfo *Base : Info->Bases) {
336 UpdateEmptyBaseSubobjects(Base, BaseOffset, PlacingEmptyBase);
339 if (Info->PrimaryVirtualBaseInfo) {
340 BaseSubobjectInfo *PrimaryVirtualBaseInfo = Info->PrimaryVirtualBaseInfo;
342 if (Info == PrimaryVirtualBaseInfo->Derived)
343 UpdateEmptyBaseSubobjects(PrimaryVirtualBaseInfo, Offset,
348 unsigned FieldNo = 0;
350 E = Info->Class->field_end(); I != E; ++I, ++FieldNo) {
355 UpdateEmptyFieldSubobjects(*I, FieldOffset);
359 bool EmptySubobjectMap::CanPlaceBaseAtOffset(
const BaseSubobjectInfo *Info,
363 if (SizeOfLargestEmptySubobject.isZero())
366 if (!CanPlaceBaseSubobjectAtOffset(Info, Offset))
371 UpdateEmptyBaseSubobjects(Info, Offset, Info->Class->isEmpty());
376 EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(
const CXXRecordDecl *RD,
381 if (!AnyEmptySubobjectsBeyondOffset(Offset))
384 if (!CanPlaceSubobjectAtOffset(RD, Offset))
391 if (Base.isVirtual())
394 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
397 if (!CanPlaceFieldSubobjectAtOffset(BaseDecl, Class, BaseOffset))
404 const CXXRecordDecl *VBaseDecl = Base.getType()->getAsCXXRecordDecl();
407 if (!CanPlaceFieldSubobjectAtOffset(VBaseDecl, Class, VBaseOffset))
413 unsigned FieldNo = 0;
415 I != E; ++I, ++FieldNo) {
421 if (!CanPlaceFieldSubobjectAtOffset(*I, FieldOffset))
429 EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(
const FieldDecl *FD,
433 if (!AnyEmptySubobjectsBeyondOffset(Offset))
438 return CanPlaceFieldSubobjectAtOffset(RD, RD, Offset);
452 for (uint64_t I = 0; I != NumElements; ++I) {
455 if (!AnyEmptySubobjectsBeyondOffset(ElementOffset))
458 if (!CanPlaceFieldSubobjectAtOffset(RD, RD, ElementOffset))
461 ElementOffset += Layout.
getSize();
469 EmptySubobjectMap::CanPlaceFieldAtOffset(
const FieldDecl *FD,
471 if (!CanPlaceFieldSubobjectAtOffset(FD, Offset))
476 UpdateEmptyFieldSubobjects(FD, Offset);
480 void EmptySubobjectMap::UpdateEmptyFieldSubobjects(
const CXXRecordDecl *RD,
488 if (Offset >= SizeOfLargestEmptySubobject)
491 AddSubobjectAtOffset(RD, Offset);
497 if (Base.isVirtual())
500 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
503 UpdateEmptyFieldSubobjects(BaseDecl, Class, BaseOffset);
509 const CXXRecordDecl *VBaseDecl = Base.getType()->getAsCXXRecordDecl();
512 UpdateEmptyFieldSubobjects(VBaseDecl, Class, VBaseOffset);
517 unsigned FieldNo = 0;
519 I != E; ++I, ++FieldNo) {
525 UpdateEmptyFieldSubobjects(*I, FieldOffset);
529 void EmptySubobjectMap::UpdateEmptyFieldSubobjects(
const FieldDecl *FD,
533 UpdateEmptyFieldSubobjects(RD, RD, Offset);
550 for (uint64_t I = 0; I != NumElements; ++I) {
556 if (ElementOffset >= SizeOfLargestEmptySubobject)
559 UpdateEmptyFieldSubobjects(RD, RD, ElementOffset);
560 ElementOffset += Layout.
getSize();
565 typedef llvm::SmallPtrSet<const CXXRecordDecl*, 4> ClassSetTy;
567 class ItaniumRecordLayoutBuilder {
574 EmptySubobjectMap *EmptySubobjects;
589 unsigned UseExternalLayout : 1;
593 unsigned InferAlignment : 1;
598 unsigned IsUnion : 1;
600 unsigned IsMac68kAlign : 1;
602 unsigned IsMsStruct : 1;
608 unsigned char UnfilledBitsInLastUnit;
611 unsigned char LastBitfieldTypeSize;
629 bool PrimaryBaseIsVirtual;
638 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
641 BaseOffsetsMapTy Bases;
656 llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBases;
659 ExternalLayout External;
661 ItaniumRecordLayoutBuilder(
const ASTContext &Context,
662 EmptySubobjectMap *EmptySubobjects)
663 : Context(Context), EmptySubobjects(EmptySubobjects), Size(0),
667 UnfilledBitsInLastUnit(0), LastBitfieldTypeSize(0),
668 MaxFieldAlignment(
CharUnits::Zero()), DataSize(0),
670 NonVirtualAlignment(
CharUnits::One()), PrimaryBase(nullptr),
671 PrimaryBaseIsVirtual(
false), HasOwnVFPtr(
false),
672 HasPackedField(
false), FirstNearlyEmptyVBase(nullptr) {}
679 void LayoutField(
const FieldDecl *D,
bool InsertExtraPadding);
680 void LayoutWideBitField(uint64_t FieldSize, uint64_t TypeSize,
689 llvm::SpecificBumpPtrAllocator<BaseSubobjectInfo> BaseSubobjectInfoAllocator;
691 typedef llvm::DenseMap<const CXXRecordDecl *, BaseSubobjectInfo *>
692 BaseSubobjectInfoMapTy;
700 BaseSubobjectInfoMapTy NonVirtualBaseInfo;
708 BaseSubobjectInfo *ComputeBaseSubobjectInfo(
const CXXRecordDecl *RD,
710 BaseSubobjectInfo *Derived);
717 void EnsureVTablePointerAlignment(
CharUnits UnpackedBaseAlign);
724 void LayoutNonVirtualBase(
const BaseSubobjectInfo *Base);
726 void AddPrimaryVirtualBaseOffsets(
const BaseSubobjectInfo *Info,
734 void LayoutVirtualBase(
const BaseSubobjectInfo *Base);
738 CharUnits LayoutBase(
const BaseSubobjectInfo *Base);
741 void InitializeLayout(
const Decl *D);
748 void UpdateAlignment(
CharUnits NewAlignment) {
749 UpdateAlignment(NewAlignment, NewAlignment);
757 uint64_t updateExternalFieldOffset(
const FieldDecl *Field,
758 uint64_t ComputedOffset);
760 void CheckFieldPadding(uint64_t Offset, uint64_t UnpaddedOffset,
761 uint64_t UnpackedOffset,
unsigned UnpackedAlign,
770 uint64_t getSizeInBits()
const {
return Size; }
773 void setSize(uint64_t NewSize) { Size = NewSize; }
775 CharUnits getAligment()
const {
return Alignment; }
781 uint64_t getDataSizeInBits()
const {
return DataSize; }
783 void setDataSize(
CharUnits NewSize) { DataSize = Context.
toBits(NewSize); }
784 void setDataSize(uint64_t NewSize) { DataSize = NewSize; }
786 ItaniumRecordLayoutBuilder(
const ItaniumRecordLayoutBuilder &) =
delete;
787 void operator=(
const ItaniumRecordLayoutBuilder &) =
delete;
791 void ItaniumRecordLayoutBuilder::SelectPrimaryVBase(
const CXXRecordDecl *RD) {
792 for (
const auto &I : RD->
bases()) {
793 assert(!I.getType()->isDependentType() &&
794 "Cannot layout class with dependent bases.");
796 const CXXRecordDecl *Base = I.getType()->getAsCXXRecordDecl();
802 if (!IndirectPrimaryBases.count(Base)) {
804 PrimaryBaseIsVirtual =
true;
809 if (!FirstNearlyEmptyVBase)
810 FirstNearlyEmptyVBase = Base;
813 SelectPrimaryVBase(Base);
820 void ItaniumRecordLayoutBuilder::DeterminePrimaryBase(
const CXXRecordDecl *RD) {
832 for (
const auto &I : RD->
bases()) {
837 const CXXRecordDecl *Base = I.getType()->getAsCXXRecordDecl();
842 PrimaryBaseIsVirtual =
false;
852 SelectPrimaryVBase(RD);
858 if (FirstNearlyEmptyVBase) {
859 PrimaryBase = FirstNearlyEmptyVBase;
860 PrimaryBaseIsVirtual =
true;
864 assert(!PrimaryBase &&
"Should not get here with a primary base!");
867 BaseSubobjectInfo *ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo(
868 const CXXRecordDecl *RD,
bool IsVirtual, BaseSubobjectInfo *Derived) {
869 BaseSubobjectInfo *Info;
873 BaseSubobjectInfo *&InfoSlot = VirtualBaseInfo[RD];
875 assert(InfoSlot->Class == RD &&
"Wrong class for virtual base info!");
880 InfoSlot =
new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo;
883 Info =
new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo;
887 Info->IsVirtual = IsVirtual;
888 Info->Derived =
nullptr;
889 Info->PrimaryVirtualBaseInfo =
nullptr;
892 BaseSubobjectInfo *PrimaryVirtualBaseInfo =
nullptr;
900 assert(PrimaryVirtualBase &&
"Didn't have a primary virtual base!");
903 PrimaryVirtualBaseInfo = VirtualBaseInfo.lookup(PrimaryVirtualBase);
905 if (PrimaryVirtualBaseInfo) {
906 if (PrimaryVirtualBaseInfo->Derived) {
910 PrimaryVirtualBase =
nullptr;
913 Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;
914 PrimaryVirtualBaseInfo->Derived = Info;
921 for (
const auto &I : RD->
bases()) {
922 bool IsVirtual = I.isVirtual();
924 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
926 Info->Bases.push_back(ComputeBaseSubobjectInfo(BaseDecl, IsVirtual, Info));
929 if (PrimaryVirtualBase && !PrimaryVirtualBaseInfo) {
932 PrimaryVirtualBaseInfo = VirtualBaseInfo.lookup(PrimaryVirtualBase);
933 assert(PrimaryVirtualBaseInfo &&
934 "Did not create a primary virtual base!");
937 Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;
938 PrimaryVirtualBaseInfo->Derived = Info;
944 void ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo(
946 for (
const auto &I : RD->
bases()) {
947 bool IsVirtual = I.isVirtual();
949 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
952 BaseSubobjectInfo *Info = ComputeBaseSubobjectInfo(BaseDecl, IsVirtual,
957 assert(VirtualBaseInfo.count(BaseDecl) &&
958 "Did not add virtual base!");
961 assert(!NonVirtualBaseInfo.count(BaseDecl) &&
962 "Non-virtual base already exists!");
963 NonVirtualBaseInfo.insert(std::make_pair(BaseDecl, Info));
968 void ItaniumRecordLayoutBuilder::EnsureVTablePointerAlignment(
973 if (!MaxFieldAlignment.
isZero()) {
974 BaseAlign =
std::min(BaseAlign, MaxFieldAlignment);
975 UnpackedBaseAlign =
std::min(UnpackedBaseAlign, MaxFieldAlignment);
979 setSize(getSize().alignTo(BaseAlign));
980 setDataSize(getSize());
983 UpdateAlignment(BaseAlign, UnpackedBaseAlign);
986 void ItaniumRecordLayoutBuilder::LayoutNonVirtualBases(
989 DeterminePrimaryBase(RD);
992 ComputeBaseSubobjectInfo(RD);
996 if (PrimaryBaseIsVirtual) {
999 BaseSubobjectInfo *PrimaryBaseInfo = VirtualBaseInfo.lookup(PrimaryBase);
1000 PrimaryBaseInfo->Derived =
nullptr;
1003 IndirectPrimaryBases.insert(PrimaryBase);
1005 assert(!VisitedVirtualBases.count(PrimaryBase) &&
1006 "vbase already visited!");
1007 VisitedVirtualBases.insert(PrimaryBase);
1009 LayoutVirtualBase(PrimaryBaseInfo);
1011 BaseSubobjectInfo *PrimaryBaseInfo =
1012 NonVirtualBaseInfo.lookup(PrimaryBase);
1013 assert(PrimaryBaseInfo &&
1014 "Did not find base info for non-virtual primary base!");
1016 LayoutNonVirtualBase(PrimaryBaseInfo);
1022 assert(DataSize == 0 &&
"Vtable pointer must be at offset zero!");
1027 EnsureVTablePointerAlignment(PtrAlign);
1029 setSize(getSize() + PtrWidth);
1030 setDataSize(getSize());
1034 for (
const auto &I : RD->
bases()) {
1040 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
1045 if (BaseDecl == PrimaryBase && !PrimaryBaseIsVirtual)
1049 BaseSubobjectInfo *BaseInfo = NonVirtualBaseInfo.
lookup(BaseDecl);
1050 assert(BaseInfo &&
"Did not find base info for non-virtual base!");
1052 LayoutNonVirtualBase(BaseInfo);
1056 void ItaniumRecordLayoutBuilder::LayoutNonVirtualBase(
1057 const BaseSubobjectInfo *Base) {
1062 assert(!Bases.count(Base->Class) &&
"base offset already exists!");
1063 Bases.insert(std::make_pair(Base->Class, Offset));
1065 AddPrimaryVirtualBaseOffsets(Base, Offset);
1068 void ItaniumRecordLayoutBuilder::AddPrimaryVirtualBaseOffsets(
1069 const BaseSubobjectInfo *Info,
CharUnits Offset) {
1071 if (!Info->Class->getNumVBases())
1075 if (Info->PrimaryVirtualBaseInfo) {
1076 assert(Info->PrimaryVirtualBaseInfo->IsVirtual &&
1077 "Primary virtual base is not virtual!");
1078 if (Info->PrimaryVirtualBaseInfo->Derived == Info) {
1080 assert(!VBases.count(Info->PrimaryVirtualBaseInfo->Class) &&
1081 "primary vbase offset already exists!");
1082 VBases.insert(std::make_pair(Info->PrimaryVirtualBaseInfo->Class,
1086 AddPrimaryVirtualBaseOffsets(Info->PrimaryVirtualBaseInfo, Offset);
1092 for (
const BaseSubobjectInfo *Base : Info->Bases) {
1093 if (Base->IsVirtual)
1097 AddPrimaryVirtualBaseOffsets(Base, BaseOffset);
1101 void ItaniumRecordLayoutBuilder::LayoutVirtualBases(
1104 bool PrimaryBaseIsVirtual;
1106 if (MostDerivedClass == RD) {
1107 PrimaryBase = this->PrimaryBase;
1108 PrimaryBaseIsVirtual = this->PrimaryBaseIsVirtual;
1116 assert(!Base.getType()->isDependentType() &&
1117 "Cannot layout class with dependent bases.");
1119 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
1121 if (Base.isVirtual()) {
1122 if (PrimaryBase != BaseDecl || !PrimaryBaseIsVirtual) {
1123 bool IndirectPrimaryBase = IndirectPrimaryBases.count(BaseDecl);
1126 if (!IndirectPrimaryBase) {
1128 if (!VisitedVirtualBases.insert(BaseDecl).second)
1131 const BaseSubobjectInfo *BaseInfo = VirtualBaseInfo.lookup(BaseDecl);
1132 assert(BaseInfo &&
"Did not find virtual base info!");
1133 LayoutVirtualBase(BaseInfo);
1138 if (!BaseDecl->getNumVBases()) {
1143 LayoutVirtualBases(BaseDecl, MostDerivedClass);
1147 void ItaniumRecordLayoutBuilder::LayoutVirtualBase(
1148 const BaseSubobjectInfo *Base) {
1149 assert(!Base->Derived &&
"Trying to lay out a primary virtual base!");
1155 assert(!VBases.count(Base->Class) &&
"vbase offset already exists!");
1156 VBases.insert(std::make_pair(Base->Class,
1159 AddPrimaryVirtualBaseOffsets(Base, Offset);
1163 ItaniumRecordLayoutBuilder::LayoutBase(
const BaseSubobjectInfo *Base) {
1170 bool HasExternalLayout =
false;
1171 if (UseExternalLayout) {
1172 if (Base->IsVirtual)
1173 HasExternalLayout = External.getExternalNVBaseOffset(Base->Class, Offset);
1175 HasExternalLayout = External.getExternalVBaseOffset(Base->Class, Offset);
1182 if (Base->Class->isEmpty() &&
1186 UpdateAlignment(BaseAlign, UnpackedBaseAlign);
1192 if (!MaxFieldAlignment.
isZero()) {
1193 BaseAlign =
std::min(BaseAlign, MaxFieldAlignment);
1194 UnpackedBaseAlign =
std::min(UnpackedBaseAlign, MaxFieldAlignment);
1197 if (!HasExternalLayout) {
1199 Offset = getDataSize().
alignTo(BaseAlign);
1202 while (!EmptySubobjects->CanPlaceBaseAtOffset(Base, Offset))
1203 Offset += BaseAlign;
1205 bool Allowed = EmptySubobjects->CanPlaceBaseAtOffset(Base, Offset);
1207 assert(Allowed &&
"Base subobject externally placed at overlapping offset");
1209 if (InferAlignment && Offset < getDataSize().alignTo(BaseAlign)) {
1213 InferAlignment =
false;
1217 if (!Base->Class->isEmpty()) {
1221 setSize(
std::max(getSize(), getDataSize()));
1226 UpdateAlignment(BaseAlign, UnpackedBaseAlign);
1231 void ItaniumRecordLayoutBuilder::InitializeLayout(
const Decl *D) {
1232 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
1237 Packed = D->
hasAttr<PackedAttr>();
1240 if (
unsigned DefaultMaxFieldAlignment = Context.
getLangOpts().PackStruct) {
1248 if (D->
hasAttr<AlignMac68kAttr>()) {
1249 IsMac68kAlign =
true;
1253 if (
const MaxFieldAlignmentAttr *MFAA = D->
getAttr<MaxFieldAlignmentAttr>())
1261 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(D))
1263 UseExternalLayout = Source->layoutRecordType(
1264 RD, External.Size, External.Align, External.FieldOffsets,
1265 External.BaseOffsets, External.VirtualBaseOffsets);
1268 if (UseExternalLayout) {
1269 if (External.Align > 0) {
1273 InferAlignment =
true;
1279 void ItaniumRecordLayoutBuilder::Layout(
const RecordDecl *D) {
1280 InitializeLayout(D);
1288 void ItaniumRecordLayoutBuilder::Layout(
const CXXRecordDecl *RD) {
1289 InitializeLayout(RD);
1292 LayoutNonVirtualBases(RD);
1298 NonVirtualAlignment = Alignment;
1301 LayoutVirtualBases(RD, RD);
1310 if (Base.isVirtual())
1313 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
1315 assert(Bases.count(BaseDecl) &&
"Did not find base offset!");
1320 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
1322 assert(VBases.count(BaseDecl) &&
"Did not find base offset!");
1336 setDataSize(getSize());
1339 InitializeLayout(D);
1343 LayoutField(IVD,
false);
1350 void ItaniumRecordLayoutBuilder::LayoutFields(
const RecordDecl *D) {
1359 InsertExtraPadding && (Next !=
End || !HasFlexibleArrayMember));
1368 return llvm::alignTo(Size, CharAlignment);
1371 void ItaniumRecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize,
1376 "Can only have wide bit-fields in C++!");
1388 for (
const QualType &QT : IntegralPODTypes) {
1391 if (Size > FieldSize)
1396 assert(!Type.
isNull() &&
"Did not find a type!");
1401 UnfilledBitsInLastUnit = 0;
1402 LastBitfieldTypeSize = 0;
1404 uint64_t FieldOffset;
1405 uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;
1410 setDataSize(
std::max(getDataSizeInBits(), RoundedFieldSize));
1415 FieldOffset = llvm::alignTo(getDataSizeInBits(), Context.
toBits(TypeAlign));
1417 uint64_t NewSizeInBits = FieldOffset + FieldSize;
1421 UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits;
1425 FieldOffsets.push_back(FieldOffset);
1427 CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, FieldOffset,
1428 Context.
toBits(TypeAlign), FieldPacked, D);
1431 setSize(
std::max(getSizeInBits(), getDataSizeInBits()));
1434 UpdateAlignment(TypeAlign);
1437 void ItaniumRecordLayoutBuilder::LayoutBitField(
const FieldDecl *D) {
1438 bool FieldPacked = Packed || D->
hasAttr<PackedAttr>();
1441 uint64_t TypeSize = FieldInfo.
Width;
1442 unsigned FieldAlign = FieldInfo.
Align;
1504 FieldAlign = TypeSize;
1509 if (LastBitfieldTypeSize != TypeSize) {
1511 if (!LastBitfieldTypeSize && !FieldSize)
1514 UnfilledBitsInLastUnit = 0;
1515 LastBitfieldTypeSize = 0;
1521 if (FieldSize > TypeSize) {
1522 LayoutWideBitField(FieldSize, TypeSize, FieldPacked, D);
1527 uint64_t FieldOffset =
1528 IsUnion ? 0 : (getDataSizeInBits() - UnfilledBitsInLastUnit);
1533 if (FieldSize == 0 &&
1537 unsigned ZeroLengthBitfieldBoundary =
1539 FieldAlign =
std::max(FieldAlign, ZeroLengthBitfieldBoundary);
1548 unsigned UnpackedFieldAlign = FieldAlign;
1551 if (!IsMsStruct && FieldPacked && FieldSize != 0)
1556 if (ExplicitFieldAlign) {
1557 FieldAlign =
std::max(FieldAlign, ExplicitFieldAlign);
1558 UnpackedFieldAlign =
std::max(UnpackedFieldAlign, ExplicitFieldAlign);
1563 unsigned MaxFieldAlignmentInBits = Context.
toBits(MaxFieldAlignment);
1564 if (!MaxFieldAlignment.
isZero() && FieldSize) {
1565 UnpackedFieldAlign =
std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits);
1567 FieldAlign = UnpackedFieldAlign;
1569 FieldAlign =
std::min(FieldAlign, MaxFieldAlignmentInBits);
1574 if (IsMsStruct && IsUnion) {
1575 FieldAlign = UnpackedFieldAlign = 1;
1581 uint64_t UnpaddedFieldOffset = FieldOffset;
1582 uint64_t UnpackedFieldOffset = FieldOffset;
1592 if (FieldSize == 0 || FieldSize > UnfilledBitsInLastUnit) {
1593 FieldOffset = llvm::alignTo(FieldOffset, FieldAlign);
1594 UnpackedFieldOffset =
1595 llvm::alignTo(UnpackedFieldOffset, UnpackedFieldAlign);
1596 UnfilledBitsInLastUnit = 0;
1601 bool AllowPadding = MaxFieldAlignment.
isZero();
1604 if (FieldSize == 0 ||
1606 (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize)) {
1607 FieldOffset = llvm::alignTo(FieldOffset, FieldAlign);
1608 }
else if (ExplicitFieldAlign &&
1609 (MaxFieldAlignmentInBits == 0 ||
1610 ExplicitFieldAlign <= MaxFieldAlignmentInBits) &&
1614 FieldOffset = llvm::alignTo(FieldOffset, ExplicitFieldAlign);
1618 if (FieldSize == 0 ||
1620 (UnpackedFieldOffset & (UnpackedFieldAlign-1)) + FieldSize > TypeSize))
1621 UnpackedFieldOffset =
1622 llvm::alignTo(UnpackedFieldOffset, UnpackedFieldAlign);
1623 else if (ExplicitFieldAlign &&
1624 (MaxFieldAlignmentInBits == 0 ||
1625 ExplicitFieldAlign <= MaxFieldAlignmentInBits) &&
1627 UnpackedFieldOffset =
1628 llvm::alignTo(UnpackedFieldOffset, ExplicitFieldAlign);
1633 if (UseExternalLayout)
1634 FieldOffset = updateExternalFieldOffset(D, FieldOffset);
1637 FieldOffsets.push_back(FieldOffset);
1646 FieldAlign = UnpackedFieldAlign = 1;
1649 if (!UseExternalLayout)
1650 CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, UnpackedFieldOffset,
1651 UnpackedFieldAlign, FieldPacked, D);
1659 uint64_t RoundedFieldSize;
1669 setDataSize(
std::max(getDataSizeInBits(), RoundedFieldSize));
1673 }
else if (IsMsStruct && FieldSize) {
1676 if (!UnfilledBitsInLastUnit) {
1677 setDataSize(FieldOffset + TypeSize);
1678 UnfilledBitsInLastUnit = TypeSize;
1680 UnfilledBitsInLastUnit -= FieldSize;
1681 LastBitfieldTypeSize = TypeSize;
1687 uint64_t NewSizeInBits = FieldOffset + FieldSize;
1689 setDataSize(llvm::alignTo(NewSizeInBits, CharAlignment));
1690 UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits;
1695 LastBitfieldTypeSize = 0;
1699 setSize(
std::max(getSizeInBits(), getDataSizeInBits()));
1706 void ItaniumRecordLayoutBuilder::LayoutField(
const FieldDecl *D,
1707 bool InsertExtraPadding) {
1713 uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;
1716 UnfilledBitsInLastUnit = 0;
1717 LastBitfieldTypeSize = 0;
1719 bool FieldPacked = Packed || D->
hasAttr<PackedAttr>();
1740 std::pair<CharUnits, CharUnits> FieldInfo =
1742 FieldSize = FieldInfo.first;
1743 FieldAlign = FieldInfo.second;
1754 if (TypeSize > FieldAlign)
1755 FieldAlign = TypeSize;
1762 CharUnits UnpackedFieldAlign = FieldAlign;
1763 CharUnits UnpackedFieldOffset = FieldOffset;
1769 FieldAlign =
std::max(FieldAlign, MaxAlignmentInChars);
1770 UnpackedFieldAlign =
std::max(UnpackedFieldAlign, MaxAlignmentInChars);
1773 if (!MaxFieldAlignment.
isZero()) {
1774 FieldAlign =
std::min(FieldAlign, MaxFieldAlignment);
1775 UnpackedFieldAlign =
std::min(UnpackedFieldAlign, MaxFieldAlignment);
1779 FieldOffset = FieldOffset.alignTo(FieldAlign);
1780 UnpackedFieldOffset = UnpackedFieldOffset.
alignTo(UnpackedFieldAlign);
1782 if (UseExternalLayout) {
1784 updateExternalFieldOffset(D, Context.
toBits(FieldOffset)));
1786 if (!IsUnion && EmptySubobjects) {
1788 bool Allowed = EmptySubobjects->CanPlaceFieldAtOffset(D, FieldOffset);
1790 assert(Allowed &&
"Externally-placed field cannot be placed here");
1793 if (!IsUnion && EmptySubobjects) {
1795 while (!EmptySubobjects->CanPlaceFieldAtOffset(D, FieldOffset)) {
1797 FieldOffset += FieldAlign;
1803 FieldOffsets.push_back(Context.
toBits(FieldOffset));
1805 if (!UseExternalLayout)
1806 CheckFieldPadding(Context.
toBits(FieldOffset), UnpaddedFieldOffset,
1807 Context.
toBits(UnpackedFieldOffset),
1808 Context.
toBits(UnpackedFieldAlign), FieldPacked, D);
1810 if (InsertExtraPadding) {
1812 CharUnits ExtraSizeForAsan = ASanAlignment;
1813 if (FieldSize % ASanAlignment)
1816 FieldSize += ExtraSizeForAsan;
1820 uint64_t FieldSizeInBits = Context.
toBits(FieldSize);
1822 setDataSize(
std::max(getDataSizeInBits(), FieldSizeInBits));
1824 setDataSize(FieldOffset + FieldSize);
1827 setSize(
std::max(getSizeInBits(), getDataSizeInBits()));
1830 UpdateAlignment(FieldAlign, UnpackedFieldAlign);
1833 void ItaniumRecordLayoutBuilder::FinishLayout(
const NamedDecl *D) {
1835 if (Context.
getLangOpts().CPlusPlus && getSizeInBits() == 0) {
1849 uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastUnit;
1850 uint64_t UnpackedSizeInBits =
1851 llvm::alignTo(getSizeInBits(), Context.
toBits(UnpackedAlignment));
1852 uint64_t RoundedSize =
1853 llvm::alignTo(getSizeInBits(), Context.
toBits(Alignment));
1855 if (UseExternalLayout) {
1859 if (InferAlignment && External.Size < RoundedSize) {
1861 InferAlignment =
false;
1863 setSize(External.Size);
1868 setSize(RoundedSize);
1871 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
1873 if (getSizeInBits() > UnpaddedSize) {
1874 unsigned PadSize = getSizeInBits() - UnpaddedSize;
1876 if (PadSize % CharBitNum == 0) {
1877 PadSize = PadSize / CharBitNum;
1883 << (InBits ? 1 : 0);
1889 if (Packed && UnpackedAlignment <= Alignment &&
1890 UnpackedSizeInBits == getSizeInBits() && !HasPackedField)
1896 void ItaniumRecordLayoutBuilder::UpdateAlignment(
1900 if (IsMac68kAlign || (UseExternalLayout && !InferAlignment))
1903 if (NewAlignment > Alignment) {
1904 assert(llvm::isPowerOf2_64(NewAlignment.
getQuantity()) &&
1905 "Alignment not a power of 2");
1906 Alignment = NewAlignment;
1909 if (UnpackedNewAlignment > UnpackedAlignment) {
1910 assert(llvm::isPowerOf2_64(UnpackedNewAlignment.
getQuantity()) &&
1911 "Alignment not a power of 2");
1912 UnpackedAlignment = UnpackedNewAlignment;
1917 ItaniumRecordLayoutBuilder::updateExternalFieldOffset(
const FieldDecl *Field,
1918 uint64_t ComputedOffset) {
1919 uint64_t ExternalFieldOffset = External.getExternalFieldOffset(Field);
1921 if (InferAlignment && ExternalFieldOffset < ComputedOffset) {
1925 InferAlignment =
false;
1929 return ExternalFieldOffset;
1942 default: llvm_unreachable(
"Invalid tag kind for field padding diagnostic!");
1946 void ItaniumRecordLayoutBuilder::CheckFieldPadding(
1947 uint64_t Offset, uint64_t UnpaddedOffset, uint64_t UnpackedOffset,
1948 unsigned UnpackedAlign,
bool isPacked,
const FieldDecl *D) {
1951 if (isa<ObjCIvarDecl>(D))
1962 if (!IsUnion && Offset > UnpaddedOffset) {
1963 unsigned PadSize = Offset - UnpaddedOffset;
1965 if (PadSize % CharBitNum == 0) {
1966 PadSize = PadSize / CharBitNum;
1981 << (InBits ? 1 : 0);
1983 if (isPacked && Offset != UnpackedOffset) {
1984 HasPackedField =
true;
2008 bool allowInlineFunctions =
2012 if (!MD->isVirtual())
2020 if (MD->isImplicit())
2023 if (MD->isInlineSpecified())
2026 if (MD->hasInlineBody())
2030 if (!MD->isUserProvided())
2034 if (!allowInlineFunctions) {
2046 if (!MD->hasAttr<CUDADeviceAttr>())
2050 if (!MD->hasAttr<CUDAHostAttr>() && MD->hasAttr<CUDADeviceAttr>())
2058 if (MD->hasAttr<DLLImportAttr>() && !RD->
hasAttr<DLLImportAttr>())
2112 llvm_unreachable(
"bad tail-padding use kind");
2210 struct MicrosoftRecordLayoutBuilder {
2211 struct ElementInfo {
2215 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
2216 MicrosoftRecordLayoutBuilder(
const ASTContext &Context) : Context(Context) {}
2218 MicrosoftRecordLayoutBuilder(
const MicrosoftRecordLayoutBuilder &) =
delete;
2219 void operator=(
const MicrosoftRecordLayoutBuilder &) =
delete;
2240 void layoutBitField(
const FieldDecl *FD);
2243 void layoutZeroWidthBitField(
const FieldDecl *FD);
2252 ElementInfo getAdjustedElementInfo(
const FieldDecl *FD);
2254 void placeFieldAtOffset(
CharUnits FieldOffset) {
2255 FieldOffsets.push_back(Context.
toBits(FieldOffset));
2258 void placeFieldAtBitOffset(uint64_t FieldOffset) {
2259 FieldOffsets.push_back(FieldOffset);
2262 void computeVtorDispSet(
2263 llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtorDispSet,
2288 ElementInfo PointerInfo;
2296 BaseOffsetsMapTy Bases;
2302 unsigned RemainingBitsInField;
2306 bool LastFieldIsNonZeroWidthBitfield : 1;
2308 bool HasOwnVFPtr : 1;
2314 bool EndsWithZeroSizedObject : 1;
2317 bool LeadsWithZeroSizedBase : 1;
2320 bool UseExternalLayout : 1;
2324 ExternalLayout External;
2328 MicrosoftRecordLayoutBuilder::ElementInfo
2329 MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
2334 if (!MaxFieldAlignment.
isZero())
2335 Info.Alignment =
std::min(Info.Alignment, MaxFieldAlignment);
2341 Alignment =
std::max(Alignment, Info.Alignment);
2348 MicrosoftRecordLayoutBuilder::ElementInfo
2349 MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
2354 std::tie(Info.Size, Info.Alignment) =
2367 Info.Alignment =
std::max(Info.Alignment, FieldRequiredAlignment);
2373 FieldRequiredAlignment =
std::max(FieldRequiredAlignment,
2377 RequiredAlignment =
std::max(RequiredAlignment, FieldRequiredAlignment);
2380 if (!MaxFieldAlignment.
isZero())
2381 Info.Alignment =
std::min(Info.Alignment, MaxFieldAlignment);
2382 if (FD->
hasAttr<PackedAttr>())
2384 Info.Alignment =
std::max(Info.Alignment, FieldRequiredAlignment);
2388 void MicrosoftRecordLayoutBuilder::layout(
const RecordDecl *RD) {
2391 initializeLayout(RD);
2393 DataSize = Size = Size.alignTo(Alignment);
2399 void MicrosoftRecordLayoutBuilder::cxxLayout(
const CXXRecordDecl *RD) {
2402 initializeLayout(RD);
2403 initializeCXXLayout(RD);
2404 layoutNonVirtualBases(RD);
2408 if (HasOwnVFPtr || (HasVBPtr && !SharedVBPtrBase))
2409 Alignment =
std::max(Alignment, PointerInfo.Alignment);
2410 auto RoundingAlignment = Alignment;
2411 if (!MaxFieldAlignment.
isZero())
2412 RoundingAlignment =
std::min(RoundingAlignment, MaxFieldAlignment);
2413 NonVirtualSize = Size = Size.
alignTo(RoundingAlignment);
2416 layoutVirtualBases(RD);
2420 void MicrosoftRecordLayoutBuilder::initializeLayout(
const RecordDecl *RD) {
2433 if (
unsigned DefaultMaxFieldAlignment = Context.
getLangOpts().PackStruct)
2437 if (
const MaxFieldAlignmentAttr *MFAA = RD->
getAttr<MaxFieldAlignmentAttr>()){
2438 unsigned PackedAlignment = MFAA->getAlignment();
2443 if (RD->
hasAttr<PackedAttr>())
2447 UseExternalLayout =
false;
2449 UseExternalLayout = Source->layoutRecordType(
2450 RD, External.Size, External.Align, External.FieldOffsets,
2451 External.BaseOffsets, External.VirtualBaseOffsets);
2455 MicrosoftRecordLayoutBuilder::initializeCXXLayout(
const CXXRecordDecl *RD) {
2456 EndsWithZeroSizedObject =
false;
2457 LeadsWithZeroSizedBase =
false;
2458 HasOwnVFPtr =
false;
2460 PrimaryBase =
nullptr;
2461 SharedVBPtrBase =
nullptr;
2466 PointerInfo.Alignment =
2469 if (!MaxFieldAlignment.
isZero())
2470 PointerInfo.Alignment =
std::min(PointerInfo.Alignment, MaxFieldAlignment);
2474 MicrosoftRecordLayoutBuilder::layoutNonVirtualBases(
const CXXRecordDecl *RD) {
2484 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
2487 if (Base.isVirtual()) {
2492 if (!SharedVBPtrBase && BaseLayout.
hasVBPtr()) {
2493 SharedVBPtrBase = BaseDecl;
2501 PrimaryBase = BaseDecl;
2505 layoutNonVirtualBase(RD, BaseDecl, BaseLayout, PreviousBaseLayout);
2511 !HasOwnVFPtr && i != e; ++i)
2512 HasOwnVFPtr = i->isVirtual() && i->size_overridden_methods() == 0;
2515 bool CheckLeadingLayout = !PrimaryBase;
2518 if (Base.isVirtual())
2520 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
2529 if (CheckLeadingLayout) {
2530 CheckLeadingLayout =
false;
2534 layoutNonVirtualBase(RD, BaseDecl, BaseLayout, PreviousBaseLayout);
2540 else if (SharedVBPtrBase) {
2547 if (!isa<CXXRecordDecl>(RD))
2549 if (RD->
hasAttr<EmptyBasesAttr>())
2551 if (
auto *LVA = RD->
getAttr<LayoutVersionAttr>())
2561 void MicrosoftRecordLayoutBuilder::layoutNonVirtualBase(
2573 ElementInfo Info = getAdjustedElementInfo(BaseLayout);
2577 bool FoundBase =
false;
2578 if (UseExternalLayout) {
2579 FoundBase = External.getExternalNVBaseOffset(BaseDecl, BaseOffset);
2581 assert(BaseOffset >= Size &&
"base offset already allocated");
2587 if (MDCUsesEBO && BaseDecl->
isEmpty() &&
2592 BaseOffset = Size = Size.
alignTo(Info.Alignment);
2595 Bases.insert(std::make_pair(BaseDecl, BaseOffset));
2597 PreviousBaseLayout = &BaseLayout;
2600 void MicrosoftRecordLayoutBuilder::layoutFields(
const RecordDecl *RD) {
2601 LastFieldIsNonZeroWidthBitfield =
false;
2606 void MicrosoftRecordLayoutBuilder::layoutField(
const FieldDecl *FD) {
2611 LastFieldIsNonZeroWidthBitfield =
false;
2612 ElementInfo Info = getAdjustedElementInfo(FD);
2613 Alignment =
std::max(Alignment, Info.Alignment);
2619 if (UseExternalLayout) {
2622 assert(FieldOffset >= Size &&
"field offset already allocated");
2624 FieldOffset = Size.
alignTo(Info.Alignment);
2626 placeFieldAtOffset(FieldOffset);
2627 Size = FieldOffset + Info.Size;
2631 void MicrosoftRecordLayoutBuilder::layoutBitField(
const FieldDecl *FD) {
2634 layoutZeroWidthBitField(FD);
2637 ElementInfo Info = getAdjustedElementInfo(FD);
2640 if (Width > Context.
toBits(Info.Size))
2641 Width = Context.
toBits(Info.Size);
2645 if (!IsUnion && LastFieldIsNonZeroWidthBitfield &&
2646 CurrentBitfieldSize == Info.Size && Width <= RemainingBitsInField) {
2647 placeFieldAtBitOffset(Context.
toBits(Size) - RemainingBitsInField);
2648 RemainingBitsInField -= Width;
2651 LastFieldIsNonZeroWidthBitfield =
true;
2652 CurrentBitfieldSize = Info.Size;
2660 placeFieldAtOffset(FieldOffset);
2661 Size = FieldOffset + Info.Size;
2662 Alignment =
std::max(Alignment, Info.Alignment);
2663 RemainingBitsInField = Context.
toBits(Info.Size) - Width;
2668 MicrosoftRecordLayoutBuilder::layoutZeroWidthBitField(
const FieldDecl *FD) {
2671 if (!LastFieldIsNonZeroWidthBitfield) {
2677 LastFieldIsNonZeroWidthBitfield =
false;
2678 ElementInfo Info = getAdjustedElementInfo(FD);
2686 placeFieldAtOffset(FieldOffset);
2688 Alignment =
std::max(Alignment, Info.Alignment);
2692 void MicrosoftRecordLayoutBuilder::injectVBPtr(
const CXXRecordDecl *RD) {
2693 if (!HasVBPtr || SharedVBPtrBase)
2698 VBPtrOffset = VBPtrOffset.
alignTo(PointerInfo.Alignment);
2701 if (UseExternalLayout)
2704 CharUnits FieldStart = VBPtrOffset + PointerInfo.Size;
2707 CharUnits Offset = (FieldStart - InjectionSite)
2708 .alignTo(
std::max(RequiredAlignment, Alignment));
2710 for (uint64_t &FieldOffset : FieldOffsets)
2711 FieldOffset += Context.
toBits(Offset);
2712 for (BaseOffsetsMapTy::value_type &Base : Bases)
2713 if (Base.second >= InjectionSite)
2717 void MicrosoftRecordLayoutBuilder::injectVFPtr(
const CXXRecordDecl *RD) {
2729 if (UseExternalLayout)
2736 for (uint64_t &FieldOffset : FieldOffsets)
2737 FieldOffset += Context.
toBits(Offset);
2738 for (BaseOffsetsMapTy::value_type &Base : Bases)
2742 void MicrosoftRecordLayoutBuilder::layoutVirtualBases(
const CXXRecordDecl *RD) {
2747 CharUnits VtorDispAlignment = VtorDispSize;
2749 if (!MaxFieldAlignment.
isZero())
2750 VtorDispAlignment =
std::min(VtorDispAlignment, MaxFieldAlignment);
2755 const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl();
2760 VtorDispAlignment =
std::max(VtorDispAlignment, RequiredAlignment);
2762 llvm::SmallPtrSet<const CXXRecordDecl *, 2> HasVtorDispSet;
2763 computeVtorDispSet(HasVtorDispSet, RD);
2767 const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl();
2769 bool HasVtordisp = HasVtorDispSet.count(BaseDecl) > 0;
2778 Size = Size.alignTo(VtorDispAlignment) + VtorDispSize;
2779 Alignment =
std::max(VtorDispAlignment, Alignment);
2782 ElementInfo Info = getAdjustedElementInfo(BaseLayout);
2786 bool FoundBase =
false;
2787 if (UseExternalLayout) {
2788 FoundBase = External.getExternalVBaseOffset(BaseDecl, BaseOffset);
2790 assert(BaseOffset >= Size &&
"base offset already allocated");
2793 BaseOffset = Size.
alignTo(Info.Alignment);
2795 VBases.insert(std::make_pair(BaseDecl,
2798 PreviousBaseLayout = &BaseLayout;
2802 void MicrosoftRecordLayoutBuilder::finalizeLayout(
const RecordDecl *RD) {
2806 if (!RequiredAlignment.isZero()) {
2807 Alignment =
std::max(Alignment, RequiredAlignment);
2808 auto RoundingAlignment = Alignment;
2809 if (!MaxFieldAlignment.
isZero())
2810 RoundingAlignment =
std::min(RoundingAlignment, MaxFieldAlignment);
2811 RoundingAlignment =
std::max(RoundingAlignment, RequiredAlignment);
2812 Size = Size.alignTo(RoundingAlignment);
2814 if (Size.isZero()) {
2815 if (!
recordUsesEBO(RD) || !cast<CXXRecordDecl>(RD)->isEmpty()) {
2816 EndsWithZeroSizedObject =
true;
2817 LeadsWithZeroSizedBase =
true;
2821 if (RequiredAlignment >= MinEmptyStructSize)
2824 Size = MinEmptyStructSize;
2827 if (UseExternalLayout) {
2838 BasesWithOverriddenMethods,
2840 if (BasesWithOverriddenMethods.count(RD))
2845 if (!Base.isVirtual() &&
2847 Base.getType()->getAsCXXRecordDecl()))
2852 void MicrosoftRecordLayoutBuilder::computeVtorDispSet(
2853 llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtordispSet,
2859 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
2862 HasVtordispSet.insert(BaseDecl);
2870 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
2873 if (bi.second.hasVtorDisp())
2874 HasVtordispSet.insert(bi.first);
2890 llvm::SmallPtrSet<const CXXMethodDecl *, 8> Work;
2891 llvm::SmallPtrSet<const CXXRecordDecl *, 2> BasesWithOverriddenMethods;
2894 if (MD->isVirtual() && !isa<CXXDestructorDecl>(MD) && !MD->isPure())
2896 while (!Work.empty()) {
2900 if (MethodRange.begin() == MethodRange.end())
2901 BasesWithOverriddenMethods.insert(MD->
getParent());
2903 Work.insert(MethodRange.begin(), MethodRange.end());
2910 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
2911 if (!HasVtordispSet.count(BaseDecl) &&
2913 HasVtordispSet.insert(BaseDecl);
2928 getExternalSource()->CompleteType(const_cast<RecordDecl*>(D));
2931 assert(D &&
"Cannot get layout of forward declarations!");
2932 assert(!D->
isInvalidDecl() &&
"Cannot get layout of invalid decl!");
2939 if (Entry)
return *Entry;
2944 MicrosoftRecordLayoutBuilder Builder(*
this);
2945 if (
const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
2946 Builder.cxxLayout(RD);
2948 *
this, Builder.Size, Builder.Alignment, Builder.RequiredAlignment,
2949 Builder.HasOwnVFPtr, Builder.HasOwnVFPtr || Builder.PrimaryBase,
2950 Builder.VBPtrOffset, Builder.DataSize, Builder.FieldOffsets,
2952 Builder.PrimaryBase,
false, Builder.SharedVBPtrBase,
2953 Builder.EndsWithZeroSizedObject, Builder.LeadsWithZeroSizedBase,
2954 Builder.Bases, Builder.VBases);
2958 *
this, Builder.Size, Builder.Alignment, Builder.RequiredAlignment,
2959 Builder.Size, Builder.FieldOffsets);
2962 if (
const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
2963 EmptySubobjectMap EmptySubobjects(*
this, RD);
2964 ItaniumRecordLayoutBuilder Builder(*
this, &EmptySubobjects);
2970 bool skipTailPadding =
2975 skipTailPadding ? Builder.getSize() : Builder.getDataSize();
2977 skipTailPadding ? DataSize : Builder.NonVirtualSize;
2979 *
this, Builder.getSize(), Builder.Alignment,
2983 NonVirtualSize, Builder.NonVirtualAlignment,
2984 EmptySubobjects.SizeOfLargestEmptySubobject, Builder.PrimaryBase,
2985 Builder.PrimaryBaseIsVirtual,
nullptr,
false,
false, Builder.Bases,
2988 ItaniumRecordLayoutBuilder Builder(*
this,
nullptr);
2992 *
this, Builder.getSize(), Builder.Alignment,
2994 Builder.Alignment, Builder.getSize(), Builder.FieldOffsets);
2998 ASTRecordLayouts[D] = NewEntry;
3000 if (getLangOpts().DumpRecordLayouts) {
3001 llvm::outs() <<
"\n*** Dumping AST Record Layout\n";
3009 if (!getTargetInfo().getCXXABI().hasKeyFunctions())
3012 assert(RD->
getDefinition() &&
"Cannot get key function for forward decl!");
3013 RD = cast<CXXRecordDecl>(RD->getDefinition());
3025 if (Entry.isOffset() || Entry.isValid() !=
bool(Result))
3026 KeyFunctions[RD] = const_cast<Decl*>(Result);
3028 return cast_or_null<CXXMethodDecl>(
Result);
3033 "not working with method declaration from class definition");
3038 const auto &Map = KeyFunctions;
3042 if (I == Map.end())
return;
3048 if (Ptr.
get(getExternalSource()) == Method) {
3050 KeyFunctions.erase(Method->
getParent());
3060 uint64_t OffsetInBits;
3061 if (
const FieldDecl *FD = dyn_cast<FieldDecl>(VD)) {
3071 return OffsetInBits;
3087 RL = &getASTObjCImplementationLayout(ID);
3089 RL = &getASTObjCInterfaceLayout(Container);
3104 assert(Index < RL->getFieldCount() &&
"Ivar is not inside record layout!");
3119 getExternalSource()->CompleteType(const_cast<ObjCInterfaceDecl*>(D));
3131 unsigned SynthCount = CountNonClassIvars(D);
3136 if (SynthCount == 0)
3137 return getObjCLayout(D,
nullptr);
3140 ItaniumRecordLayoutBuilder Builder(*
this,
nullptr);
3148 Builder.getDataSize(),
3149 Builder.FieldOffsets);
3151 ObjCLayouts[Key] = NewEntry;
3157 CharUnits Offset,
unsigned IndentLevel) {
3158 OS << llvm::format(
"%10" PRId64
" | ", (int64_t)Offset.
getQuantity());
3159 OS.indent(IndentLevel * 2);
3163 unsigned Begin,
unsigned Width,
3164 unsigned IndentLevel) {
3167 llvm::raw_svector_ostream BufferOS(Buffer);
3172 BufferOS << Begin <<
'-' << (Begin + Width - 1);
3176 OS << llvm::right_justify(Buffer, 10) <<
" | ";
3177 OS.indent(IndentLevel * 2);
3182 OS.indent(IndentLevel * 2);
3188 unsigned IndentLevel,
3189 const char* Description,
3191 bool IncludeVirtualBases) {
3198 OS <<
' ' << Description;
3199 if (CXXRD && CXXRD->isEmpty())
3212 if (CXXRD->isDynamicClass() && !PrimaryBase && !
isMsLayout(C)) {
3214 OS <<
'(' << *RD <<
" vtable pointer)\n";
3215 }
else if (HasOwnVFPtr) {
3218 OS <<
'(' << *RD <<
" vftable pointer)\n";
3224 assert(!Base.getType()->isDependentType() &&
3225 "Cannot layout class with dependent bases.");
3226 if (!Base.isVirtual())
3227 Bases.push_back(Base.getType()->getAsCXXRecordDecl());
3231 std::stable_sort(Bases.begin(), Bases.end(),
3240 Base == PrimaryBase ?
"(primary base)" :
"(base)",
3248 OS <<
'(' << *RD <<
" vbtable pointer)\n";
3253 uint64_t FieldNo = 0;
3255 E = RD->
field_end(); I != E; ++I, ++FieldNo) {
3257 uint64_t LocalFieldOffsetInBits = Layout.
getFieldOffset(FieldNo);
3271 uint64_t LocalFieldByteOffsetInBits = C.
toBits(FieldOffset - Offset);
3272 unsigned Begin = LocalFieldOffsetInBits - LocalFieldByteOffsetInBits;
3282 if (CXXRD && IncludeVirtualBases) {
3287 assert(Base.isVirtual() &&
"Found non-virtual class!");
3288 const CXXRecordDecl *VBase = Base.getType()->getAsCXXRecordDecl();
3292 if (VtorDisps.find(VBase)->second.hasVtorDisp()) {
3294 OS <<
"(vtordisp for vbase " << *VBase <<
")\n";
3299 "(primary virtual base)" :
"(virtual base)",
3305 if (!PrintSizeInfo)
return;
3324 bool Simple)
const {
3340 OS <<
"Type: " << getTypeDeclType(RD).getAsString() <<
"\n";
3342 OS <<
"<ASTRecordLayout\n";
3343 OS <<
" Size:" << toBits(Info.
getSize()) <<
"\n";
3345 OS <<
" DataSize:" << toBits(Info.
getDataSize()) <<
"\n";
3346 OS <<
" Alignment:" << toBits(Info.
getAlignment()) <<
"\n";
3347 OS <<
" FieldOffsets: [";
3348 for (
unsigned i = 0, e = Info.
getFieldCount(); i != e; ++i) {
static uint64_t getFieldOffset(const ASTContext &C, const FieldDecl *FD)
Defines the clang::ASTContext interface.
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 ...
An instance of this class is created to represent a function declaration or definition.
Only allocate objects in the tail padding of a base class if the base class is not POD according to t...
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.
bool isPrimaryBaseVirtual() const
isPrimaryBaseVirtual - Get whether the primary base for this record is virtual or not...
A (possibly-)qualified type.
bool isStandardLayout() const
Determine whether this class has standard layout per (C++ [class]p7)
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 void DumpRecordLayout(raw_ostream &OS, const RecordDecl *RD, const ASTContext &C, CharUnits Offset, unsigned IndentLevel, const char *Description, bool PrintSizeInfo, bool IncludeVirtualBases)
The basic abstraction for the target C++ ABI.
bool isThisDeclarationADefinition() const
Determine whether this particular declaration of this class is actually also a definition.
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D...
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
Decl - This represents one declaration (or definition), e.g.
bool isPOD() const
Whether this class is a POD-type (C++ [class]p4)
unsigned getFieldIndex() const
getFieldIndex - Returns the index of this field within its record, as appropriate for passing to ASTR...
const RecordDecl * getParent() const
getParent - Returns the parent of this field declaration, which is the struct in which this field is ...
The base class of the type hierarchy.
DiagnosticsEngine & getDiagnostics() const
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
bool isZero() const
isZero - Test whether the quantity equals zero.
const TargetInfo & getTargetInfo() const
CharUnits getAlignment() const
getAlignment - Get the record alignment in characters.
unsigned getCharWidth() const
QualType getElementType() const
bool isCompleteDefinition() const
isCompleteDefinition - Return true if this decl has its body fully specified.
bool hasVBPtr() const
hasVBPtr - Does this class have a virtual function table pointer.
const T * getAs() const
Member-template getAs<specific type>'.
unsigned getCharAlign() const
The "__interface" keyword.
bool hasOwnVFPtr() const
hasOwnVFPtr - Does this class provide its own virtual-function table pointer, rather than inheriting ...
bool isInvalidDecl() const
unsigned getZeroLengthBitfieldBoundary() const
Get the fixed alignment value in bits for a member that follows a zero length bitfield.
bool mayInsertExtraPadding(bool EmitRemark=false) const
Whether we are allowed to insert extra padding between fields.
IdentifierInfo * getIdentifier() const
getIdentifier - Get the identifier that names this declaration, if there is one.
RecordDecl - Represents a struct/union/class.
uint64_t getPointerWidth(unsigned AddrSpace) const
Return the width of pointers on this target, for the specified address space.
bool isEmpty() const
Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).
TargetCXXABI getCXXABI() const
Get the C++ ABI currently in use.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
RecordDecl * getDefinition() const
getDefinition - Returns the RecordDecl that actually defines this struct/union/class.
field_range fields() const
FieldDecl - An instance of this class is created by Sema::ActOnField to represent a member of a struc...
bool hasUserDeclaredDestructor() const
Determine whether this class has a user-declared destructor.
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const
getVBaseClassOffset - Get the offset, in chars, for the given base class.
method_iterator method_begin() const
Method begin iterator.
uint64_t lookupFieldBitOffset(const ObjCInterfaceDecl *OID, const ObjCImplementationDecl *ID, const ObjCIvarDecl *Ivar) const
Get the offset of an ObjCIvarDecl in bits.
const ASTRecordLayout & getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D) const
Get or compute information about the layout of the specified Objective-C interface.
specific_decl_iterator< FieldDecl > field_iterator
bool canKeyFunctionBeInline() const
Can an out-of-line inline function serve as a key function?
uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const
Return number of constant array elements.
bool isBitField() const
Determines whether this field is a bitfield.
ObjCContainerDecl - Represents a container for method declarations.
TagKind getTagKind() const
CharUnits - This is an opaque type for sizes expressed in character units.
bool endsWithZeroSizedObject() const
ArrayRef< NamedDecl * > chain() const
field_iterator field_begin() const
unsigned getBitWidthValue(const ASTContext &Ctx) const
bool declaresSameEntity(const Decl *D1, const Decl *D2)
Determine whether two declarations declare the same entity.
const VBaseOffsetsMapTy & getVBaseOffsetsMap() const
bool isAlignmentRequired(const Type *T) const
Determine if the alignment the type has was required using an alignment attribute.
bool useZeroLengthBitfieldAlignment() const
Check whether zero length bitfields should force alignment of the next member.
Represents an ObjC class declaration.
const Type * getUnqualifiedDesugaredType() const
Return the specified type with any "sugar" removed from the type, removing any typedefs, typeofs, etc., as well as any qualifiers.
CanQualType UnsignedCharTy
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
static CharUnits One()
One - Construct a CharUnits quantity of one.
A little helper class used to produce diagnostics.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isDynamicClass() const
bool useExplicitBitFieldAlignment() const
Check whether explicit bitfield alignment attributes should be.
static void PrintOffset(raw_ostream &OS, CharUnits Offset, unsigned IndentLevel)
TemplateSpecializationKind getTemplateSpecializationKind() const
Determine whether this particular class is a specialization or instantiation of a class template or m...
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
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 isInlineSpecified() const
Determine whether the "inline" keyword was specified for this function.
ValueDecl - Represent the declaration of a variable (in which case it is an lvalue) a function (in wh...
const FunctionProtoType * T
bool isNearlyEmpty(const CXXRecordDecl *RD) const
field_iterator field_end() const
CharUnits getSizeOfLargestEmptySubobject() const
overridden_method_range overridden_methods() const
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
CXXRecordDecl * getDefinition() const
ObjCInterfaceDecl * getSuperClass() const
const CXXRecordDecl * getPrimaryBase() const
getPrimaryBase - Get the primary base for this record.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
unsigned getFieldCount() const
getFieldCount - Get the number of fields in the layout.
char __ovld __cnfn min(char x, char y)
Returns y if y < x, otherwise it returns x.
bool isTrivial() const
Determine whether this class is considered trivial.
bool isPolymorphic() const
Whether this class is polymorphic (C++ [class.virtual]), which means that the class contains or inher...
bool hasExtendableVFPtr() const
hasVFPtr - Does this class have a virtual function table pointer that can be extended by a derived cl...
unsigned getMaxAlignment() const
getMaxAlignment - return the maximum alignment specified by attributes on this decl, 0 if there are none.
method_iterator method_end() const
Method past-the-end iterator.
CharUnits getVBPtrOffset() const
getVBPtrOffset - Get the offset for virtual base table pointer.
const Type * getBaseElementTypeUnsafe() const
Get the base element type of this type, potentially discarding type qualifiers.
CharUnits getRequiredAlignment() const
QualType getTypeDeclType(const TypeDecl *Decl, const TypeDecl *PrevDecl=nullptr) const
Return the unique reference to the type for the specified type declaration.
The result type of a method or function.
This template specialization was implicitly instantiated from a template.
void getIndirectPrimaryBases(CXXIndirectPrimaryBaseSet &Bases) const
Get the indirect primary bases for this class.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
decl_type * getFirstDecl()
Return the first declaration of this declaration or itself if this is the only declaration.
static bool recordUsesEBO(const RecordDecl *RD)
RecordDecl * getDecl() const
Abstract interface for external sources of AST nodes.
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
static uint64_t roundUpSizeToCharAlignment(uint64_t Size, const ASTContext &Context)
Only allocate objects in the tail padding of a base class if the base class is not POD according to t...
Encodes a location in the source.
A set of all the primary bases for a class.
static void PrintIndentNoOffset(raw_ostream &OS, unsigned IndentLevel)
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
Represents a static or instance method of a struct/union/class.
const ConstantArrayType * getAsConstantArrayType(QualType T) const
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
bool hasExternalLexicalStorage() const
Whether this DeclContext has external storage containing additional declarations that are lexically i...
This template specialization was instantiated from a template due to an explicit instantiation defini...
CharUnits getDataSize() const
getDataSize() - Get the record data size, which is the record size without tail padding, in characters.
bool useBitFieldTypeAlignment() const
Check whether the alignment of bit-field types is respected when laying out structures.
MSVtorDispAttr::Mode getMSVtorDispMode() const
Controls when vtordisps will be emitted if this record is used as a virtual base. ...
static unsigned getPaddingDiagFromTagKind(TagTypeKind Tag)
Get diagnostic select index for tag kind for field padding diagnostic message.
bool hasFlexibleArrayMember() const
ASTContext & operator=(const ASTContext &)=delete
std::pair< CharUnits, CharUnits > getTypeInfoInChars(const Type *T) const
CanQualType UnsignedShortTy
ObjCIvarDecl * getNextIvar()
CharUnits getNonVirtualAlignment() const
getNonVirtualSize - Get the non-virtual alignment (in chars) of an object, which is the alignment of ...
TagTypeKind
The kind of a tag type.
const ObjCInterfaceDecl * getClassInterface() const
Dataflow Directional Tag Classes.
CharUnits getSize() const
getSize - Get the record size in characters.
IndirectFieldDecl - An instance of this class is created to represent a field injected from an anonym...
CanQualType UnsignedLongLongTy
ObjCInterfaceDecl * getDefinition()
Retrieve the definition of this class, or NULL if this class has been forward-declared (with @class) ...
This template specialization was instantiated from a template due to an explicit instantiation declar...
bool hasUserDeclaredConstructor() const
Determine whether this class has any user-declared constructors.
TailPaddingUseRules getTailPaddingUseRules() const
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
const CXXRecordDecl * getParent() const
Returns the parent of this method declaration, which is the class in which this method is defined...
void DumpRecordLayout(const RecordDecl *RD, raw_ostream &OS, bool Simple=false) const
const ObjCInterfaceDecl * getContainingInterface() const
Return the class interface that this ivar is logically contained in; this is either the interface whe...
TemplateSpecializationKind
Describes the kind of template specialization that a particular template specialization declaration r...
ExternalASTSource * getExternalSource() const
Retrieve a pointer to the external AST source associated with this AST context, if any...
T * get(ExternalASTSource *Source) const
Retrieve the pointer to the AST node that this lazy pointer.
specific_decl_iterator - Iterates over a subrange of declarations stored in a DeclContext, providing only those that are of type SpecificDecl (or a class derived from it).
All virtual base related information about a given record decl.
ObjCImplementationDecl - Represents a class definition - this is where method definitions are specifi...
bool isIncompleteArrayType() const
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
CanQualType UnsignedLongTy
static bool RequiresVtordisp(const llvm::SmallPtrSetImpl< const CXXRecordDecl *> &BasesWithOverriddenMethods, const CXXRecordDecl *RD)
uint64_t getCharWidth() const
Return the size of the character type, in bits.
void setNonKeyFunction(const CXXMethodDecl *method)
Observe that the given method cannot be a key function.
Base for LValueReferenceType and RValueReferenceType.
Represents a base class of a C++ class.
char __ovld __cnfn max(char x, char y)
Returns y if x < y, otherwise it returns x.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
uint64_t getFieldOffset(const ValueDecl *FD) const
Get the offset of a FieldDecl or IndirectFieldDecl, in bits.
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate.h) and friends (in DeclFriend.h).
int64_t toBits(CharUnits CharSize) const
Convert a size in characters to a size in bits.
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...
Represents a C++ struct/union/class.
TypeInfo getTypeInfo(const Type *T) const
Get the size and alignment of the specified complete type in bits.
ObjCIvarDecl - Represents an ObjC instance variable.
CharUnits getNonVirtualSize() const
getNonVirtualSize - Get the non-virtual size (in chars) of an object, which is the size of the object...
static bool isMsLayout(const ASTContext &Context)
static unsigned getCharWidth(tok::TokenKind kind, const TargetInfo &Target)
This class is used for builtin types like 'int'.
static const CXXMethodDecl * computeKeyFunction(ASTContext &Context, const CXXRecordDecl *RD)
The tail-padding of a base class is always theoretically available, even if it's POD.
llvm::DenseMap< const CXXRecordDecl *, VBaseInfo > VBaseOffsetsMapTy
uint64_t getPointerAlign(unsigned AddrSpace) const
Defines the clang::TargetInfo interface.
bool isMicrosoft() const
Is this ABI an MSVC-compatible ABI?
StringRef getName() const
getName - Get the name of identifier for this declaration as a StringRef.
static void PrintBitFieldOffset(raw_ostream &OS, CharUnits Offset, unsigned Begin, unsigned Width, unsigned IndentLevel)
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
NamedDecl - This represents a decl with a name.
ObjCIvarDecl * all_declared_ivar_begin()
all_declared_ivar_begin - return first ivar declared in this class, its extensions and its implementa...
bool hasOwnVBPtr() const
hasOwnVBPtr - Does this class provide its own virtual-base table pointer, rather than inheriting one ...
unsigned getTargetAddressSpace(QualType T) const
const LangOptions & getLangOpts() const
Represents the canonical version of C arrays with a specified constant size.
base_class_range vbases()
SourceLocation getLocation() const
bool isExternallyVisible() const
CanQualType UnsignedIntTy
bool leadsWithZeroSizedBase() const
method_range methods() const