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;
592 unsigned UseExternalLayout : 1;
596 unsigned InferAlignment : 1;
601 unsigned IsUnion : 1;
603 unsigned IsMac68kAlign : 1;
605 unsigned IsMsStruct : 1;
611 unsigned char UnfilledBitsInLastUnit;
614 unsigned char LastBitfieldTypeSize;
632 bool PrimaryBaseIsVirtual;
641 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
644 BaseOffsetsMapTy Bases;
659 llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBases;
662 ExternalLayout External;
664 ItaniumRecordLayoutBuilder(
const ASTContext &Context,
665 EmptySubobjectMap *EmptySubobjects)
666 : Context(Context), EmptySubobjects(EmptySubobjects), Size(0),
671 UnfilledBitsInLastUnit(0), LastBitfieldTypeSize(0),
672 MaxFieldAlignment(
CharUnits::Zero()), DataSize(0),
674 NonVirtualAlignment(
CharUnits::One()), PrimaryBase(nullptr),
675 PrimaryBaseIsVirtual(
false), HasOwnVFPtr(
false),
676 HasPackedField(
false), FirstNearlyEmptyVBase(nullptr) {}
683 void LayoutField(
const FieldDecl *D,
bool InsertExtraPadding);
684 void LayoutWideBitField(uint64_t FieldSize, uint64_t TypeSize,
693 llvm::SpecificBumpPtrAllocator<BaseSubobjectInfo> BaseSubobjectInfoAllocator;
695 typedef llvm::DenseMap<const CXXRecordDecl *, BaseSubobjectInfo *>
696 BaseSubobjectInfoMapTy;
704 BaseSubobjectInfoMapTy NonVirtualBaseInfo;
712 BaseSubobjectInfo *ComputeBaseSubobjectInfo(
const CXXRecordDecl *RD,
714 BaseSubobjectInfo *Derived);
721 void EnsureVTablePointerAlignment(
CharUnits UnpackedBaseAlign);
728 void LayoutNonVirtualBase(
const BaseSubobjectInfo *Base);
730 void AddPrimaryVirtualBaseOffsets(
const BaseSubobjectInfo *Info,
738 void LayoutVirtualBase(
const BaseSubobjectInfo *Base);
742 CharUnits LayoutBase(
const BaseSubobjectInfo *Base);
745 void InitializeLayout(
const Decl *D);
752 void UpdateAlignment(
CharUnits NewAlignment) {
753 UpdateAlignment(NewAlignment, NewAlignment);
761 uint64_t updateExternalFieldOffset(
const FieldDecl *Field,
762 uint64_t ComputedOffset);
764 void CheckFieldPadding(uint64_t Offset, uint64_t UnpaddedOffset,
765 uint64_t UnpackedOffset,
unsigned UnpackedAlign,
774 uint64_t getSizeInBits()
const {
return Size; }
777 void setSize(uint64_t NewSize) { Size = NewSize; }
779 CharUnits getAligment()
const {
return Alignment; }
785 uint64_t getDataSizeInBits()
const {
return DataSize; }
787 void setDataSize(
CharUnits NewSize) { DataSize = Context.
toBits(NewSize); }
788 void setDataSize(uint64_t NewSize) { DataSize = NewSize; }
790 ItaniumRecordLayoutBuilder(
const ItaniumRecordLayoutBuilder &) =
delete;
791 void operator=(
const ItaniumRecordLayoutBuilder &) =
delete;
795 void ItaniumRecordLayoutBuilder::SelectPrimaryVBase(
const CXXRecordDecl *RD) {
796 for (
const auto &I : RD->
bases()) {
797 assert(!I.getType()->isDependentType() &&
798 "Cannot layout class with dependent bases.");
800 const CXXRecordDecl *Base = I.getType()->getAsCXXRecordDecl();
806 if (!IndirectPrimaryBases.count(Base)) {
808 PrimaryBaseIsVirtual =
true;
813 if (!FirstNearlyEmptyVBase)
814 FirstNearlyEmptyVBase = Base;
817 SelectPrimaryVBase(Base);
824 void ItaniumRecordLayoutBuilder::DeterminePrimaryBase(
const CXXRecordDecl *RD) {
836 for (
const auto &I : RD->
bases()) {
841 const CXXRecordDecl *Base = I.getType()->getAsCXXRecordDecl();
846 PrimaryBaseIsVirtual =
false;
856 SelectPrimaryVBase(RD);
862 if (FirstNearlyEmptyVBase) {
863 PrimaryBase = FirstNearlyEmptyVBase;
864 PrimaryBaseIsVirtual =
true;
868 assert(!PrimaryBase &&
"Should not get here with a primary base!");
871 BaseSubobjectInfo *ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo(
872 const CXXRecordDecl *RD,
bool IsVirtual, BaseSubobjectInfo *Derived) {
873 BaseSubobjectInfo *Info;
877 BaseSubobjectInfo *&InfoSlot = VirtualBaseInfo[RD];
879 assert(InfoSlot->Class == RD &&
"Wrong class for virtual base info!");
884 InfoSlot =
new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo;
887 Info =
new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo;
891 Info->IsVirtual = IsVirtual;
892 Info->Derived =
nullptr;
893 Info->PrimaryVirtualBaseInfo =
nullptr;
896 BaseSubobjectInfo *PrimaryVirtualBaseInfo =
nullptr;
904 assert(PrimaryVirtualBase &&
"Didn't have a primary virtual base!");
907 PrimaryVirtualBaseInfo = VirtualBaseInfo.lookup(PrimaryVirtualBase);
909 if (PrimaryVirtualBaseInfo) {
910 if (PrimaryVirtualBaseInfo->Derived) {
914 PrimaryVirtualBase =
nullptr;
917 Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;
918 PrimaryVirtualBaseInfo->Derived = Info;
925 for (
const auto &I : RD->
bases()) {
926 bool IsVirtual = I.isVirtual();
928 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
930 Info->Bases.push_back(ComputeBaseSubobjectInfo(BaseDecl, IsVirtual, Info));
933 if (PrimaryVirtualBase && !PrimaryVirtualBaseInfo) {
936 PrimaryVirtualBaseInfo = VirtualBaseInfo.lookup(PrimaryVirtualBase);
937 assert(PrimaryVirtualBaseInfo &&
938 "Did not create a primary virtual base!");
941 Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;
942 PrimaryVirtualBaseInfo->Derived = Info;
948 void ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo(
950 for (
const auto &I : RD->
bases()) {
951 bool IsVirtual = I.isVirtual();
953 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
956 BaseSubobjectInfo *Info = ComputeBaseSubobjectInfo(BaseDecl, IsVirtual,
961 assert(VirtualBaseInfo.count(BaseDecl) &&
962 "Did not add virtual base!");
965 assert(!NonVirtualBaseInfo.count(BaseDecl) &&
966 "Non-virtual base already exists!");
967 NonVirtualBaseInfo.insert(std::make_pair(BaseDecl, Info));
972 void ItaniumRecordLayoutBuilder::EnsureVTablePointerAlignment(
977 if (!MaxFieldAlignment.
isZero()) {
978 BaseAlign =
std::min(BaseAlign, MaxFieldAlignment);
979 UnpackedBaseAlign =
std::min(UnpackedBaseAlign, MaxFieldAlignment);
983 setSize(getSize().alignTo(BaseAlign));
984 setDataSize(getSize());
987 UpdateAlignment(BaseAlign, UnpackedBaseAlign);
990 void ItaniumRecordLayoutBuilder::LayoutNonVirtualBases(
993 DeterminePrimaryBase(RD);
996 ComputeBaseSubobjectInfo(RD);
1000 if (PrimaryBaseIsVirtual) {
1003 BaseSubobjectInfo *PrimaryBaseInfo = VirtualBaseInfo.lookup(PrimaryBase);
1004 PrimaryBaseInfo->Derived =
nullptr;
1007 IndirectPrimaryBases.insert(PrimaryBase);
1009 assert(!VisitedVirtualBases.count(PrimaryBase) &&
1010 "vbase already visited!");
1011 VisitedVirtualBases.insert(PrimaryBase);
1013 LayoutVirtualBase(PrimaryBaseInfo);
1015 BaseSubobjectInfo *PrimaryBaseInfo =
1016 NonVirtualBaseInfo.lookup(PrimaryBase);
1017 assert(PrimaryBaseInfo &&
1018 "Did not find base info for non-virtual primary base!");
1020 LayoutNonVirtualBase(PrimaryBaseInfo);
1026 assert(DataSize == 0 &&
"Vtable pointer must be at offset zero!");
1031 EnsureVTablePointerAlignment(PtrAlign);
1033 setSize(getSize() + PtrWidth);
1034 setDataSize(getSize());
1038 for (
const auto &I : RD->
bases()) {
1044 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
1049 if (BaseDecl == PrimaryBase && !PrimaryBaseIsVirtual)
1053 BaseSubobjectInfo *BaseInfo = NonVirtualBaseInfo.
lookup(BaseDecl);
1054 assert(BaseInfo &&
"Did not find base info for non-virtual base!");
1056 LayoutNonVirtualBase(BaseInfo);
1060 void ItaniumRecordLayoutBuilder::LayoutNonVirtualBase(
1061 const BaseSubobjectInfo *Base) {
1066 assert(!Bases.count(Base->Class) &&
"base offset already exists!");
1067 Bases.insert(std::make_pair(Base->Class, Offset));
1069 AddPrimaryVirtualBaseOffsets(Base, Offset);
1072 void ItaniumRecordLayoutBuilder::AddPrimaryVirtualBaseOffsets(
1073 const BaseSubobjectInfo *Info,
CharUnits Offset) {
1075 if (!Info->Class->getNumVBases())
1079 if (Info->PrimaryVirtualBaseInfo) {
1080 assert(Info->PrimaryVirtualBaseInfo->IsVirtual &&
1081 "Primary virtual base is not virtual!");
1082 if (Info->PrimaryVirtualBaseInfo->Derived == Info) {
1084 assert(!VBases.count(Info->PrimaryVirtualBaseInfo->Class) &&
1085 "primary vbase offset already exists!");
1086 VBases.insert(std::make_pair(Info->PrimaryVirtualBaseInfo->Class,
1090 AddPrimaryVirtualBaseOffsets(Info->PrimaryVirtualBaseInfo, Offset);
1096 for (
const BaseSubobjectInfo *Base : Info->Bases) {
1097 if (Base->IsVirtual)
1101 AddPrimaryVirtualBaseOffsets(Base, BaseOffset);
1105 void ItaniumRecordLayoutBuilder::LayoutVirtualBases(
1108 bool PrimaryBaseIsVirtual;
1110 if (MostDerivedClass == RD) {
1111 PrimaryBase = this->PrimaryBase;
1112 PrimaryBaseIsVirtual = this->PrimaryBaseIsVirtual;
1120 assert(!Base.getType()->isDependentType() &&
1121 "Cannot layout class with dependent bases.");
1123 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
1125 if (Base.isVirtual()) {
1126 if (PrimaryBase != BaseDecl || !PrimaryBaseIsVirtual) {
1127 bool IndirectPrimaryBase = IndirectPrimaryBases.count(BaseDecl);
1130 if (!IndirectPrimaryBase) {
1132 if (!VisitedVirtualBases.insert(BaseDecl).second)
1135 const BaseSubobjectInfo *BaseInfo = VirtualBaseInfo.lookup(BaseDecl);
1136 assert(BaseInfo &&
"Did not find virtual base info!");
1137 LayoutVirtualBase(BaseInfo);
1142 if (!BaseDecl->getNumVBases()) {
1147 LayoutVirtualBases(BaseDecl, MostDerivedClass);
1151 void ItaniumRecordLayoutBuilder::LayoutVirtualBase(
1152 const BaseSubobjectInfo *Base) {
1153 assert(!Base->Derived &&
"Trying to lay out a primary virtual base!");
1159 assert(!VBases.count(Base->Class) &&
"vbase offset already exists!");
1160 VBases.insert(std::make_pair(Base->Class,
1163 AddPrimaryVirtualBaseOffsets(Base, Offset);
1167 ItaniumRecordLayoutBuilder::LayoutBase(
const BaseSubobjectInfo *Base) {
1174 bool HasExternalLayout =
false;
1175 if (UseExternalLayout) {
1176 if (Base->IsVirtual)
1177 HasExternalLayout = External.getExternalNVBaseOffset(Base->Class, Offset);
1179 HasExternalLayout = External.getExternalVBaseOffset(Base->Class, Offset);
1186 (Packed && ((Context.
getLangOpts().getClangABICompat() <=
1190 : UnpackedBaseAlign;
1193 if (Base->Class->isEmpty() &&
1197 UpdateAlignment(BaseAlign, UnpackedBaseAlign);
1203 if (!MaxFieldAlignment.
isZero()) {
1204 BaseAlign =
std::min(BaseAlign, MaxFieldAlignment);
1205 UnpackedBaseAlign =
std::min(UnpackedBaseAlign, MaxFieldAlignment);
1208 if (!HasExternalLayout) {
1210 Offset = getDataSize().
alignTo(BaseAlign);
1213 while (!EmptySubobjects->CanPlaceBaseAtOffset(Base, Offset))
1214 Offset += BaseAlign;
1216 bool Allowed = EmptySubobjects->CanPlaceBaseAtOffset(Base, Offset);
1218 assert(Allowed &&
"Base subobject externally placed at overlapping offset");
1220 if (InferAlignment && Offset < getDataSize().alignTo(BaseAlign)) {
1224 InferAlignment =
false;
1228 if (!Base->Class->isEmpty()) {
1232 setSize(
std::max(getSize(), getDataSize()));
1237 UpdateAlignment(BaseAlign, UnpackedBaseAlign);
1242 void ItaniumRecordLayoutBuilder::InitializeLayout(
const Decl *D) {
1243 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
1248 Packed = D->
hasAttr<PackedAttr>();
1251 if (
unsigned DefaultMaxFieldAlignment = Context.
getLangOpts().PackStruct) {
1259 if (D->
hasAttr<AlignMac68kAttr>()) {
1260 IsMac68kAlign =
true;
1264 if (
const MaxFieldAlignmentAttr *MFAA = D->
getAttr<MaxFieldAlignmentAttr>())
1272 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(D))
1274 UseExternalLayout = Source->layoutRecordType(
1275 RD, External.Size, External.Align, External.FieldOffsets,
1276 External.BaseOffsets, External.VirtualBaseOffsets);
1279 if (UseExternalLayout) {
1280 if (External.Align > 0) {
1284 InferAlignment =
true;
1290 void ItaniumRecordLayoutBuilder::Layout(
const RecordDecl *D) {
1291 InitializeLayout(D);
1299 void ItaniumRecordLayoutBuilder::Layout(
const CXXRecordDecl *RD) {
1300 InitializeLayout(RD);
1303 LayoutNonVirtualBases(RD);
1309 NonVirtualAlignment = Alignment;
1312 LayoutVirtualBases(RD, RD);
1321 if (Base.isVirtual())
1324 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
1326 assert(Bases.count(BaseDecl) &&
"Did not find base offset!");
1331 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
1333 assert(VBases.count(BaseDecl) &&
"Did not find base offset!");
1347 setDataSize(getSize());
1350 InitializeLayout(D);
1354 LayoutField(IVD,
false);
1361 void ItaniumRecordLayoutBuilder::LayoutFields(
const RecordDecl *D) {
1370 InsertExtraPadding && (Next !=
End || !HasFlexibleArrayMember));
1379 return llvm::alignTo(Size, CharAlignment);
1382 void ItaniumRecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize,
1387 "Can only have wide bit-fields in C++!");
1399 for (
const QualType &QT : IntegralPODTypes) {
1402 if (Size > FieldSize)
1407 assert(!Type.
isNull() &&
"Did not find a type!");
1412 UnfilledBitsInLastUnit = 0;
1413 LastBitfieldTypeSize = 0;
1415 uint64_t FieldOffset;
1416 uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;
1421 setDataSize(
std::max(getDataSizeInBits(), RoundedFieldSize));
1426 FieldOffset = llvm::alignTo(getDataSizeInBits(), Context.
toBits(TypeAlign));
1428 uint64_t NewSizeInBits = FieldOffset + FieldSize;
1432 UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits;
1436 FieldOffsets.push_back(FieldOffset);
1438 CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, FieldOffset,
1439 Context.
toBits(TypeAlign), FieldPacked, D);
1442 setSize(
std::max(getSizeInBits(), getDataSizeInBits()));
1445 UpdateAlignment(TypeAlign);
1448 void ItaniumRecordLayoutBuilder::LayoutBitField(
const FieldDecl *D) {
1449 bool FieldPacked = Packed || D->
hasAttr<PackedAttr>();
1452 uint64_t TypeSize = FieldInfo.
Width;
1453 unsigned FieldAlign = FieldInfo.
Align;
1515 FieldAlign = TypeSize;
1520 if (LastBitfieldTypeSize != TypeSize ||
1521 UnfilledBitsInLastUnit < FieldSize) {
1523 if (!LastBitfieldTypeSize && !FieldSize)
1526 UnfilledBitsInLastUnit = 0;
1527 LastBitfieldTypeSize = 0;
1533 if (FieldSize > TypeSize) {
1534 LayoutWideBitField(FieldSize, TypeSize, FieldPacked, D);
1539 uint64_t FieldOffset =
1540 IsUnion ? 0 : (getDataSizeInBits() - UnfilledBitsInLastUnit);
1545 if (FieldSize == 0 &&
1549 unsigned ZeroLengthBitfieldBoundary =
1551 FieldAlign =
std::max(FieldAlign, ZeroLengthBitfieldBoundary);
1560 unsigned UnpackedFieldAlign = FieldAlign;
1563 if (!IsMsStruct && FieldPacked && FieldSize != 0)
1568 if (ExplicitFieldAlign) {
1569 FieldAlign =
std::max(FieldAlign, ExplicitFieldAlign);
1570 UnpackedFieldAlign =
std::max(UnpackedFieldAlign, ExplicitFieldAlign);
1575 unsigned MaxFieldAlignmentInBits = Context.
toBits(MaxFieldAlignment);
1576 if (!MaxFieldAlignment.
isZero() && FieldSize) {
1577 UnpackedFieldAlign =
std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits);
1579 FieldAlign = UnpackedFieldAlign;
1581 FieldAlign =
std::min(FieldAlign, MaxFieldAlignmentInBits);
1586 if (IsMsStruct && IsUnion) {
1587 FieldAlign = UnpackedFieldAlign = 1;
1593 uint64_t UnpaddedFieldOffset = FieldOffset;
1594 uint64_t UnpackedFieldOffset = FieldOffset;
1604 if (FieldSize == 0 || FieldSize > UnfilledBitsInLastUnit) {
1605 FieldOffset = llvm::alignTo(FieldOffset, FieldAlign);
1606 UnpackedFieldOffset =
1607 llvm::alignTo(UnpackedFieldOffset, UnpackedFieldAlign);
1608 UnfilledBitsInLastUnit = 0;
1613 bool AllowPadding = MaxFieldAlignment.
isZero();
1616 if (FieldSize == 0 ||
1618 (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize)) {
1619 FieldOffset = llvm::alignTo(FieldOffset, FieldAlign);
1620 }
else if (ExplicitFieldAlign &&
1621 (MaxFieldAlignmentInBits == 0 ||
1622 ExplicitFieldAlign <= MaxFieldAlignmentInBits) &&
1626 FieldOffset = llvm::alignTo(FieldOffset, ExplicitFieldAlign);
1630 if (FieldSize == 0 ||
1632 (UnpackedFieldOffset & (UnpackedFieldAlign-1)) + FieldSize > TypeSize))
1633 UnpackedFieldOffset =
1634 llvm::alignTo(UnpackedFieldOffset, UnpackedFieldAlign);
1635 else if (ExplicitFieldAlign &&
1636 (MaxFieldAlignmentInBits == 0 ||
1637 ExplicitFieldAlign <= MaxFieldAlignmentInBits) &&
1639 UnpackedFieldOffset =
1640 llvm::alignTo(UnpackedFieldOffset, ExplicitFieldAlign);
1645 if (UseExternalLayout)
1646 FieldOffset = updateExternalFieldOffset(D, FieldOffset);
1649 FieldOffsets.push_back(FieldOffset);
1658 FieldAlign = UnpackedFieldAlign = 1;
1661 if (!UseExternalLayout)
1662 CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, UnpackedFieldOffset,
1663 UnpackedFieldAlign, FieldPacked, D);
1671 uint64_t RoundedFieldSize;
1681 setDataSize(
std::max(getDataSizeInBits(), RoundedFieldSize));
1685 }
else if (IsMsStruct && FieldSize) {
1688 if (!UnfilledBitsInLastUnit) {
1689 setDataSize(FieldOffset + TypeSize);
1690 UnfilledBitsInLastUnit = TypeSize;
1692 UnfilledBitsInLastUnit -= FieldSize;
1693 LastBitfieldTypeSize = TypeSize;
1699 uint64_t NewSizeInBits = FieldOffset + FieldSize;
1701 setDataSize(llvm::alignTo(NewSizeInBits, CharAlignment));
1702 UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits;
1707 LastBitfieldTypeSize = 0;
1711 setSize(
std::max(getSizeInBits(), getDataSizeInBits()));
1714 UnadjustedAlignment =
1720 void ItaniumRecordLayoutBuilder::LayoutField(
const FieldDecl *D,
1721 bool InsertExtraPadding) {
1727 uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;
1730 UnfilledBitsInLastUnit = 0;
1731 LastBitfieldTypeSize = 0;
1733 bool FieldPacked = Packed || D->
hasAttr<PackedAttr>();
1754 std::pair<CharUnits, CharUnits> FieldInfo =
1756 FieldSize = FieldInfo.first;
1757 FieldAlign = FieldInfo.second;
1769 if (!llvm::isPowerOf2_64(TypeSize.
getQuantity())) {
1772 "Non PowerOf2 size in MSVC mode");
1794 if (TypeSize > FieldAlign &&
1796 FieldAlign = TypeSize;
1803 CharUnits UnpackedFieldAlign = FieldAlign;
1804 CharUnits UnpackedFieldOffset = FieldOffset;
1810 FieldAlign =
std::max(FieldAlign, MaxAlignmentInChars);
1811 UnpackedFieldAlign =
std::max(UnpackedFieldAlign, MaxAlignmentInChars);
1814 if (!MaxFieldAlignment.
isZero()) {
1815 FieldAlign =
std::min(FieldAlign, MaxFieldAlignment);
1816 UnpackedFieldAlign =
std::min(UnpackedFieldAlign, MaxFieldAlignment);
1820 FieldOffset = FieldOffset.alignTo(FieldAlign);
1821 UnpackedFieldOffset = UnpackedFieldOffset.
alignTo(UnpackedFieldAlign);
1823 if (UseExternalLayout) {
1825 updateExternalFieldOffset(D, Context.
toBits(FieldOffset)));
1827 if (!IsUnion && EmptySubobjects) {
1829 bool Allowed = EmptySubobjects->CanPlaceFieldAtOffset(D, FieldOffset);
1831 assert(Allowed &&
"Externally-placed field cannot be placed here");
1834 if (!IsUnion && EmptySubobjects) {
1836 while (!EmptySubobjects->CanPlaceFieldAtOffset(D, FieldOffset)) {
1838 FieldOffset += FieldAlign;
1844 FieldOffsets.push_back(Context.
toBits(FieldOffset));
1846 if (!UseExternalLayout)
1847 CheckFieldPadding(Context.
toBits(FieldOffset), UnpaddedFieldOffset,
1848 Context.
toBits(UnpackedFieldOffset),
1849 Context.
toBits(UnpackedFieldAlign), FieldPacked, D);
1851 if (InsertExtraPadding) {
1853 CharUnits ExtraSizeForAsan = ASanAlignment;
1854 if (FieldSize % ASanAlignment)
1857 FieldSize += ExtraSizeForAsan;
1861 uint64_t FieldSizeInBits = Context.
toBits(FieldSize);
1863 setDataSize(
std::max(getDataSizeInBits(), FieldSizeInBits));
1865 setDataSize(FieldOffset + FieldSize);
1868 setSize(
std::max(getSizeInBits(), getDataSizeInBits()));
1871 UnadjustedAlignment =
std::max(UnadjustedAlignment, FieldAlign);
1872 UpdateAlignment(FieldAlign, UnpackedFieldAlign);
1875 void ItaniumRecordLayoutBuilder::FinishLayout(
const NamedDecl *D) {
1877 if (Context.
getLangOpts().CPlusPlus && getSizeInBits() == 0) {
1883 setSize(CharUnits::One());
1886 setSize(CharUnits::One());
1891 uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastUnit;
1892 uint64_t UnpackedSizeInBits =
1893 llvm::alignTo(getSizeInBits(), Context.
toBits(UnpackedAlignment));
1894 uint64_t RoundedSize =
1895 llvm::alignTo(getSizeInBits(), Context.
toBits(Alignment));
1897 if (UseExternalLayout) {
1901 if (InferAlignment && External.Size < RoundedSize) {
1903 InferAlignment =
false;
1905 setSize(External.Size);
1910 setSize(RoundedSize);
1913 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
1915 if (getSizeInBits() > UnpaddedSize) {
1916 unsigned PadSize = getSizeInBits() - UnpaddedSize;
1918 if (PadSize % CharBitNum == 0) {
1919 PadSize = PadSize / CharBitNum;
1925 << (InBits ? 1 : 0);
1931 if (Packed && UnpackedAlignment <= Alignment &&
1932 UnpackedSizeInBits == getSizeInBits() && !HasPackedField)
1938 void ItaniumRecordLayoutBuilder::UpdateAlignment(
1942 if (IsMac68kAlign || (UseExternalLayout && !InferAlignment))
1945 if (NewAlignment > Alignment) {
1946 assert(llvm::isPowerOf2_64(NewAlignment.
getQuantity()) &&
1947 "Alignment not a power of 2");
1948 Alignment = NewAlignment;
1951 if (UnpackedNewAlignment > UnpackedAlignment) {
1952 assert(llvm::isPowerOf2_64(UnpackedNewAlignment.
getQuantity()) &&
1953 "Alignment not a power of 2");
1954 UnpackedAlignment = UnpackedNewAlignment;
1959 ItaniumRecordLayoutBuilder::updateExternalFieldOffset(
const FieldDecl *Field,
1960 uint64_t ComputedOffset) {
1961 uint64_t ExternalFieldOffset = External.getExternalFieldOffset(Field);
1963 if (InferAlignment && ExternalFieldOffset < ComputedOffset) {
1967 InferAlignment =
false;
1971 return ExternalFieldOffset;
1984 default: llvm_unreachable(
"Invalid tag kind for field padding diagnostic!");
1988 void ItaniumRecordLayoutBuilder::CheckFieldPadding(
1989 uint64_t Offset, uint64_t UnpaddedOffset, uint64_t UnpackedOffset,
1990 unsigned UnpackedAlign,
bool isPacked,
const FieldDecl *D) {
1993 if (isa<ObjCIvarDecl>(D))
2004 if (!IsUnion && Offset > UnpaddedOffset) {
2005 unsigned PadSize = Offset - UnpaddedOffset;
2007 if (PadSize % CharBitNum == 0) {
2008 PadSize = PadSize / CharBitNum;
2023 << (InBits ? 1 : 0);
2025 if (isPacked && Offset != UnpackedOffset) {
2026 HasPackedField =
true;
2050 bool allowInlineFunctions =
2054 if (!MD->isVirtual())
2062 if (MD->isImplicit())
2065 if (MD->isInlineSpecified())
2068 if (MD->hasInlineBody())
2072 if (!MD->isUserProvided())
2076 if (!allowInlineFunctions) {
2088 if (!MD->hasAttr<CUDADeviceAttr>())
2092 if (!MD->hasAttr<CUDAHostAttr>() && MD->hasAttr<CUDADeviceAttr>())
2100 if (MD->hasAttr<DLLImportAttr>() && !RD->
hasAttr<DLLImportAttr>())
2154 llvm_unreachable(
"bad tail-padding use kind");
2252 struct MicrosoftRecordLayoutBuilder {
2253 struct ElementInfo {
2257 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
2258 MicrosoftRecordLayoutBuilder(
const ASTContext &Context) : Context(Context) {}
2260 MicrosoftRecordLayoutBuilder(
const MicrosoftRecordLayoutBuilder &) =
delete;
2261 void operator=(
const MicrosoftRecordLayoutBuilder &) =
delete;
2282 void layoutBitField(
const FieldDecl *FD);
2285 void layoutZeroWidthBitField(
const FieldDecl *FD);
2294 ElementInfo getAdjustedElementInfo(
const FieldDecl *FD);
2296 void placeFieldAtOffset(
CharUnits FieldOffset) {
2297 FieldOffsets.push_back(Context.
toBits(FieldOffset));
2300 void placeFieldAtBitOffset(uint64_t FieldOffset) {
2301 FieldOffsets.push_back(FieldOffset);
2304 void computeVtorDispSet(
2305 llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtorDispSet,
2330 ElementInfo PointerInfo;
2338 BaseOffsetsMapTy Bases;
2344 unsigned RemainingBitsInField;
2348 bool LastFieldIsNonZeroWidthBitfield : 1;
2350 bool HasOwnVFPtr : 1;
2356 bool EndsWithZeroSizedObject : 1;
2359 bool LeadsWithZeroSizedBase : 1;
2362 bool UseExternalLayout : 1;
2366 ExternalLayout External;
2370 MicrosoftRecordLayoutBuilder::ElementInfo
2371 MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
2376 if (!MaxFieldAlignment.
isZero())
2377 Info.Alignment =
std::min(Info.Alignment, MaxFieldAlignment);
2383 Alignment =
std::max(Alignment, Info.Alignment);
2390 MicrosoftRecordLayoutBuilder::ElementInfo
2391 MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
2396 std::tie(Info.Size, Info.Alignment) =
2409 Info.Alignment =
std::max(Info.Alignment, FieldRequiredAlignment);
2415 FieldRequiredAlignment =
std::max(FieldRequiredAlignment,
2419 RequiredAlignment =
std::max(RequiredAlignment, FieldRequiredAlignment);
2422 if (!MaxFieldAlignment.
isZero())
2423 Info.Alignment =
std::min(Info.Alignment, MaxFieldAlignment);
2424 if (FD->
hasAttr<PackedAttr>())
2425 Info.Alignment = CharUnits::One();
2426 Info.Alignment =
std::max(Info.Alignment, FieldRequiredAlignment);
2430 void MicrosoftRecordLayoutBuilder::layout(
const RecordDecl *RD) {
2433 initializeLayout(RD);
2435 DataSize = Size = Size.alignTo(Alignment);
2441 void MicrosoftRecordLayoutBuilder::cxxLayout(
const CXXRecordDecl *RD) {
2444 initializeLayout(RD);
2445 initializeCXXLayout(RD);
2446 layoutNonVirtualBases(RD);
2450 if (HasOwnVFPtr || (HasVBPtr && !SharedVBPtrBase))
2451 Alignment =
std::max(Alignment, PointerInfo.Alignment);
2452 auto RoundingAlignment = Alignment;
2453 if (!MaxFieldAlignment.
isZero())
2454 RoundingAlignment =
std::min(RoundingAlignment, MaxFieldAlignment);
2455 if (!UseExternalLayout)
2456 Size = Size.alignTo(RoundingAlignment);
2457 NonVirtualSize = Size;
2460 layoutVirtualBases(RD);
2464 void MicrosoftRecordLayoutBuilder::initializeLayout(
const RecordDecl *RD) {
2477 if (
unsigned DefaultMaxFieldAlignment = Context.
getLangOpts().PackStruct)
2481 if (
const MaxFieldAlignmentAttr *MFAA = RD->
getAttr<MaxFieldAlignmentAttr>()){
2482 unsigned PackedAlignment = MFAA->getAlignment();
2487 if (RD->
hasAttr<PackedAttr>())
2491 UseExternalLayout =
false;
2493 UseExternalLayout = Source->layoutRecordType(
2494 RD, External.Size, External.Align, External.FieldOffsets,
2495 External.BaseOffsets, External.VirtualBaseOffsets);
2499 MicrosoftRecordLayoutBuilder::initializeCXXLayout(
const CXXRecordDecl *RD) {
2500 EndsWithZeroSizedObject =
false;
2501 LeadsWithZeroSizedBase =
false;
2502 HasOwnVFPtr =
false;
2504 PrimaryBase =
nullptr;
2505 SharedVBPtrBase =
nullptr;
2510 PointerInfo.Alignment =
2513 if (!MaxFieldAlignment.
isZero())
2514 PointerInfo.Alignment =
std::min(PointerInfo.Alignment, MaxFieldAlignment);
2518 MicrosoftRecordLayoutBuilder::layoutNonVirtualBases(
const CXXRecordDecl *RD) {
2528 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
2531 if (Base.isVirtual()) {
2536 if (!SharedVBPtrBase && BaseLayout.
hasVBPtr()) {
2537 SharedVBPtrBase = BaseDecl;
2545 PrimaryBase = BaseDecl;
2549 layoutNonVirtualBase(RD, BaseDecl, BaseLayout, PreviousBaseLayout);
2555 !HasOwnVFPtr && i != e; ++i)
2556 HasOwnVFPtr = i->isVirtual() && i->size_overridden_methods() == 0;
2559 bool CheckLeadingLayout = !PrimaryBase;
2562 if (Base.isVirtual())
2564 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
2573 if (CheckLeadingLayout) {
2574 CheckLeadingLayout =
false;
2578 layoutNonVirtualBase(RD, BaseDecl, BaseLayout, PreviousBaseLayout);
2584 else if (SharedVBPtrBase) {
2591 if (!isa<CXXRecordDecl>(RD))
2593 if (RD->
hasAttr<EmptyBasesAttr>())
2595 if (
auto *LVA = RD->
getAttr<LayoutVersionAttr>())
2605 void MicrosoftRecordLayoutBuilder::layoutNonVirtualBase(
2617 ElementInfo Info = getAdjustedElementInfo(BaseLayout);
2621 bool FoundBase =
false;
2622 if (UseExternalLayout) {
2623 FoundBase = External.getExternalNVBaseOffset(BaseDecl, BaseOffset);
2625 assert(BaseOffset >= Size &&
"base offset already allocated");
2631 if (MDCUsesEBO && BaseDecl->
isEmpty()) {
2636 BaseOffset = Size = Size.
alignTo(Info.Alignment);
2639 Bases.insert(std::make_pair(BaseDecl, BaseOffset));
2641 PreviousBaseLayout = &BaseLayout;
2644 void MicrosoftRecordLayoutBuilder::layoutFields(
const RecordDecl *RD) {
2645 LastFieldIsNonZeroWidthBitfield =
false;
2650 void MicrosoftRecordLayoutBuilder::layoutField(
const FieldDecl *FD) {
2655 LastFieldIsNonZeroWidthBitfield =
false;
2656 ElementInfo Info = getAdjustedElementInfo(FD);
2657 Alignment =
std::max(Alignment, Info.Alignment);
2659 if (UseExternalLayout)
2665 FieldOffset = Size.
alignTo(Info.Alignment);
2666 placeFieldAtOffset(FieldOffset);
2667 Size =
std::max(Size, FieldOffset + Info.Size);
2670 void MicrosoftRecordLayoutBuilder::layoutBitField(
const FieldDecl *FD) {
2673 layoutZeroWidthBitField(FD);
2676 ElementInfo Info = getAdjustedElementInfo(FD);
2679 if (Width > Context.
toBits(Info.Size))
2680 Width = Context.
toBits(Info.Size);
2684 if (!UseExternalLayout && !IsUnion && LastFieldIsNonZeroWidthBitfield &&
2685 CurrentBitfieldSize == Info.Size && Width <= RemainingBitsInField) {
2686 placeFieldAtBitOffset(Context.
toBits(Size) - RemainingBitsInField);
2687 RemainingBitsInField -= Width;
2690 LastFieldIsNonZeroWidthBitfield =
true;
2691 CurrentBitfieldSize = Info.Size;
2692 if (UseExternalLayout) {
2693 auto FieldBitOffset = External.getExternalFieldOffset(FD);
2694 placeFieldAtBitOffset(FieldBitOffset);
2696 llvm::alignTo(FieldBitOffset + Width, Context.
getCharWidth()));
2698 Alignment =
std::max(Alignment, Info.Alignment);
2699 }
else if (IsUnion) {
2706 placeFieldAtOffset(FieldOffset);
2707 Size = FieldOffset + Info.Size;
2708 Alignment =
std::max(Alignment, Info.Alignment);
2709 RemainingBitsInField = Context.
toBits(Info.Size) - Width;
2714 MicrosoftRecordLayoutBuilder::layoutZeroWidthBitField(
const FieldDecl *FD) {
2717 if (!LastFieldIsNonZeroWidthBitfield) {
2723 LastFieldIsNonZeroWidthBitfield =
false;
2724 ElementInfo Info = getAdjustedElementInfo(FD);
2732 placeFieldAtOffset(FieldOffset);
2734 Alignment =
std::max(Alignment, Info.Alignment);
2738 void MicrosoftRecordLayoutBuilder::injectVBPtr(
const CXXRecordDecl *RD) {
2739 if (!HasVBPtr || SharedVBPtrBase)
2744 VBPtrOffset = VBPtrOffset.
alignTo(PointerInfo.Alignment);
2747 if (UseExternalLayout)
2750 CharUnits FieldStart = VBPtrOffset + PointerInfo.Size;
2753 CharUnits Offset = (FieldStart - InjectionSite)
2754 .alignTo(
std::max(RequiredAlignment, Alignment));
2756 for (uint64_t &FieldOffset : FieldOffsets)
2757 FieldOffset += Context.
toBits(Offset);
2758 for (BaseOffsetsMapTy::value_type &Base : Bases)
2759 if (Base.second >= InjectionSite)
2763 void MicrosoftRecordLayoutBuilder::injectVFPtr(
const CXXRecordDecl *RD) {
2775 if (UseExternalLayout)
2782 for (uint64_t &FieldOffset : FieldOffsets)
2783 FieldOffset += Context.
toBits(Offset);
2784 for (BaseOffsetsMapTy::value_type &Base : Bases)
2788 void MicrosoftRecordLayoutBuilder::layoutVirtualBases(
const CXXRecordDecl *RD) {
2793 CharUnits VtorDispAlignment = VtorDispSize;
2795 if (!MaxFieldAlignment.
isZero())
2796 VtorDispAlignment =
std::min(VtorDispAlignment, MaxFieldAlignment);
2801 const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl();
2806 VtorDispAlignment =
std::max(VtorDispAlignment, RequiredAlignment);
2808 llvm::SmallPtrSet<const CXXRecordDecl *, 2> HasVtorDispSet;
2809 computeVtorDispSet(HasVtorDispSet, RD);
2813 const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl();
2815 bool HasVtordisp = HasVtorDispSet.count(BaseDecl) > 0;
2824 Size = Size.alignTo(VtorDispAlignment) + VtorDispSize;
2825 Alignment =
std::max(VtorDispAlignment, Alignment);
2828 ElementInfo Info = getAdjustedElementInfo(BaseLayout);
2832 if (UseExternalLayout) {
2833 if (!External.getExternalVBaseOffset(BaseDecl, BaseOffset))
2836 BaseOffset = Size.
alignTo(Info.Alignment);
2838 assert(BaseOffset >= Size &&
"base offset already allocated");
2840 VBases.insert(std::make_pair(BaseDecl,
2843 PreviousBaseLayout = &BaseLayout;
2847 void MicrosoftRecordLayoutBuilder::finalizeLayout(
const RecordDecl *RD) {
2851 if (!RequiredAlignment.isZero()) {
2852 Alignment =
std::max(Alignment, RequiredAlignment);
2853 auto RoundingAlignment = Alignment;
2854 if (!MaxFieldAlignment.
isZero())
2855 RoundingAlignment =
std::min(RoundingAlignment, MaxFieldAlignment);
2856 RoundingAlignment =
std::max(RoundingAlignment, RequiredAlignment);
2857 Size = Size.alignTo(RoundingAlignment);
2859 if (Size.isZero()) {
2860 if (!
recordUsesEBO(RD) || !cast<CXXRecordDecl>(RD)->isEmpty()) {
2861 EndsWithZeroSizedObject =
true;
2862 LeadsWithZeroSizedBase =
true;
2866 if (RequiredAlignment >= MinEmptyStructSize)
2869 Size = MinEmptyStructSize;
2872 if (UseExternalLayout) {
2883 BasesWithOverriddenMethods,
2885 if (BasesWithOverriddenMethods.count(RD))
2890 if (!Base.isVirtual() &&
2892 Base.getType()->getAsCXXRecordDecl()))
2897 void MicrosoftRecordLayoutBuilder::computeVtorDispSet(
2898 llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtordispSet,
2904 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
2907 HasVtordispSet.insert(BaseDecl);
2915 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
2918 if (bi.second.hasVtorDisp())
2919 HasVtordispSet.insert(bi.first);
2935 llvm::SmallPtrSet<const CXXMethodDecl *, 8> Work;
2936 llvm::SmallPtrSet<const CXXRecordDecl *, 2> BasesWithOverriddenMethods;
2939 if (MD->isVirtual() && !isa<CXXDestructorDecl>(MD) && !MD->isPure())
2941 while (!Work.empty()) {
2945 if (MethodRange.begin() == MethodRange.end())
2946 BasesWithOverriddenMethods.insert(MD->
getParent());
2948 Work.insert(MethodRange.begin(), MethodRange.end());
2955 const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
2956 if (!HasVtordispSet.count(BaseDecl) &&
2958 HasVtordispSet.insert(BaseDecl);
2973 getExternalSource()->CompleteType(const_cast<RecordDecl*>(D));
2976 assert(D &&
"Cannot get layout of forward declarations!");
2977 assert(!D->
isInvalidDecl() &&
"Cannot get layout of invalid decl!");
2984 if (Entry)
return *Entry;
2989 MicrosoftRecordLayoutBuilder Builder(*
this);
2990 if (
const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
2991 Builder.cxxLayout(RD);
2993 *
this, Builder.Size, Builder.Alignment, Builder.Alignment,
2994 Builder.RequiredAlignment,
2995 Builder.HasOwnVFPtr, Builder.HasOwnVFPtr || Builder.PrimaryBase,
2996 Builder.VBPtrOffset, Builder.DataSize, Builder.FieldOffsets,
2998 Builder.PrimaryBase,
false, Builder.SharedVBPtrBase,
2999 Builder.EndsWithZeroSizedObject, Builder.LeadsWithZeroSizedBase,
3000 Builder.Bases, Builder.VBases);
3004 *
this, Builder.Size, Builder.Alignment, Builder.Alignment,
3005 Builder.RequiredAlignment,
3006 Builder.Size, Builder.FieldOffsets);
3009 if (
const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
3010 EmptySubobjectMap EmptySubobjects(*
this, RD);
3011 ItaniumRecordLayoutBuilder Builder(*
this, &EmptySubobjects);
3017 bool skipTailPadding =
3022 skipTailPadding ? Builder.getSize() : Builder.getDataSize();
3024 skipTailPadding ? DataSize : Builder.NonVirtualSize;
3026 *
this, Builder.getSize(), Builder.Alignment, Builder.UnadjustedAlignment,
3030 NonVirtualSize, Builder.NonVirtualAlignment,
3031 EmptySubobjects.SizeOfLargestEmptySubobject, Builder.PrimaryBase,
3032 Builder.PrimaryBaseIsVirtual,
nullptr,
false,
false, Builder.Bases,
3035 ItaniumRecordLayoutBuilder Builder(*
this,
nullptr);
3039 *
this, Builder.getSize(), Builder.Alignment, Builder.UnadjustedAlignment,
3041 Builder.Alignment, Builder.getSize(), Builder.FieldOffsets);
3045 ASTRecordLayouts[D] = NewEntry;
3047 if (getLangOpts().DumpRecordLayouts) {
3048 llvm::outs() <<
"\n*** Dumping AST Record Layout\n";
3056 if (!getTargetInfo().getCXXABI().hasKeyFunctions())
3059 assert(RD->
getDefinition() &&
"Cannot get key function for forward decl!");
3073 KeyFunctions[RD] = const_cast<Decl*>(Result);
3075 return cast_or_null<CXXMethodDecl>(
Result);
3080 "not working with method declaration from class definition");
3085 const auto &Map = KeyFunctions;
3089 if (I == Map.end())
return;
3095 if (Ptr.
get(getExternalSource()) == Method) {
3097 KeyFunctions.erase(Method->
getParent());
3107 uint64_t OffsetInBits;
3108 if (
const FieldDecl *FD = dyn_cast<FieldDecl>(VD)) {
3118 return OffsetInBits;
3134 RL = &getASTObjCImplementationLayout(ID);
3136 RL = &getASTObjCInterfaceLayout(Container);
3151 assert(Index < RL->getFieldCount() &&
"Ivar is not inside record layout!");
3166 getExternalSource()->CompleteType(const_cast<ObjCInterfaceDecl*>(D));
3178 unsigned SynthCount = CountNonClassIvars(D);
3183 if (SynthCount == 0)
3184 return getObjCLayout(D,
nullptr);
3187 ItaniumRecordLayoutBuilder Builder(*
this,
nullptr);
3193 Builder.UnadjustedAlignment,
3196 Builder.getDataSize(),
3197 Builder.FieldOffsets);
3199 ObjCLayouts[Key] = NewEntry;
3205 CharUnits Offset,
unsigned IndentLevel) {
3206 OS << llvm::format(
"%10" PRId64
" | ", (int64_t)Offset.
getQuantity());
3207 OS.indent(IndentLevel * 2);
3211 unsigned Begin,
unsigned Width,
3212 unsigned IndentLevel) {
3215 llvm::raw_svector_ostream BufferOS(Buffer);
3220 BufferOS << Begin <<
'-' << (Begin + Width - 1);
3224 OS << llvm::right_justify(Buffer, 10) <<
" | ";
3225 OS.indent(IndentLevel * 2);
3230 OS.indent(IndentLevel * 2);
3236 unsigned IndentLevel,
3237 const char* Description,
3239 bool IncludeVirtualBases) {
3246 OS <<
' ' << Description;
3247 if (CXXRD && CXXRD->isEmpty())
3260 if (CXXRD->isDynamicClass() && !PrimaryBase && !
isMsLayout(C)) {
3262 OS <<
'(' << *RD <<
" vtable pointer)\n";
3263 }
else if (HasOwnVFPtr) {
3266 OS <<
'(' << *RD <<
" vftable pointer)\n";
3272 assert(!Base.getType()->isDependentType() &&
3273 "Cannot layout class with dependent bases.");
3274 if (!Base.isVirtual())
3275 Bases.push_back(Base.getType()->getAsCXXRecordDecl());
3279 std::stable_sort(Bases.begin(), Bases.end(),
3288 Base == PrimaryBase ?
"(primary base)" :
"(base)",
3296 OS <<
'(' << *RD <<
" vbtable pointer)\n";
3301 uint64_t FieldNo = 0;
3303 E = RD->
field_end(); I != E; ++I, ++FieldNo) {
3305 uint64_t LocalFieldOffsetInBits = Layout.
getFieldOffset(FieldNo);
3319 uint64_t LocalFieldByteOffsetInBits = C.
toBits(FieldOffset - Offset);
3320 unsigned Begin = LocalFieldOffsetInBits - LocalFieldByteOffsetInBits;
3330 if (CXXRD && IncludeVirtualBases) {
3335 assert(Base.isVirtual() &&
"Found non-virtual class!");
3336 const CXXRecordDecl *VBase = Base.getType()->getAsCXXRecordDecl();
3340 if (VtorDisps.find(VBase)->second.hasVtorDisp()) {
3342 OS <<
"(vtordisp for vbase " << *VBase <<
")\n";
3347 "(primary virtual base)" :
"(virtual base)",
3353 if (!PrintSizeInfo)
return;
3372 bool Simple)
const {
3388 OS <<
"Type: " << getTypeDeclType(RD).getAsString() <<
"\n";
3390 OS <<
"<ASTRecordLayout\n";
3391 OS <<
" Size:" << toBits(Info.
getSize()) <<
"\n";
3393 OS <<
" DataSize:" << toBits(Info.
getDataSize()) <<
"\n";
3394 OS <<
" Alignment:" << toBits(Info.
getAlignment()) <<
"\n";
3395 OS <<
" FieldOffsets: [";
3396 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 ...
Represents 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.
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)
Attempt to be ABI-compatible with code generated by Clang 6.0.x (SVN r321711).
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
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined...
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
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
Get the identifier that names this declaration, if there is one.
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
Returns the RecordDecl that actually defines this struct/union/class.
field_range fields() const
Represents a member of a struct/union/class.
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.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
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.
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
bool isValid() const
Whether this pointer is non-NULL.
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.
Represents a field injected from an anonymous union/struct into the parent scope. ...
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
bool isCXX11StandardLayout() const
Determine whether this class was standard-layout per C++11 [class]p7, specifically using the C++11 ru...
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 points to.
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.
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
bool isOffset() const
Whether this pointer is currently stored as an offset.
uint64_t getPointerAlign(unsigned AddrSpace) const
Defines the clang::TargetInfo interface.
bool isMicrosoft() const
Is this ABI an MSVC-compatible ABI?
StringRef getName() const
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)
__DEVICE__ int max(int __a, int __b)
__DEVICE__ int min(int __a, int __b)
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
This represents a decl that may have 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