20#include "llvm/Support/Format.h"
21#include "llvm/Support/MathExtras.h"
38struct BaseSubobjectInfo {
40 const CXXRecordDecl *Class;
46 SmallVector<BaseSubobjectInfo*, 4> Bases;
50 BaseSubobjectInfo *PrimaryVirtualBaseInfo;
53 const BaseSubobjectInfo *Derived;
59struct ExternalLayout {
60 ExternalLayout() =
default;
69 llvm::DenseMap<const FieldDecl *, uint64_t> FieldOffsets;
72 llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsets;
75 llvm::DenseMap<const CXXRecordDecl *, CharUnits> VirtualBaseOffsets;
79 uint64_t getExternalFieldOffset(
const FieldDecl *FD) {
80 assert(FieldOffsets.count(FD) &&
81 "Field does not have an external offset");
82 return FieldOffsets[FD];
85 bool getExternalNVBaseOffset(
const CXXRecordDecl *RD, CharUnits &BaseOffset) {
86 auto Known = BaseOffsets.find(RD);
87 if (Known == BaseOffsets.end())
89 BaseOffset = Known->second;
93 bool getExternalVBaseOffset(
const CXXRecordDecl *RD, CharUnits &BaseOffset) {
94 auto Known = VirtualBaseOffsets.find(RD);
95 if (Known == VirtualBaseOffsets.end())
97 BaseOffset = Known->second;
104class EmptySubobjectMap {
105 const ASTContext &Context;
109 const CXXRecordDecl *Class;
112 typedef llvm::TinyPtrVector<const CXXRecordDecl *> ClassVectorTy;
113 typedef llvm::DenseMap<CharUnits, ClassVectorTy> EmptyClassOffsetsMapTy;
114 EmptyClassOffsetsMapTy EmptyClassOffsets;
118 CharUnits MaxEmptyClassOffset;
122 void ComputeEmptySubobjectSizes();
124 void AddSubobjectAtOffset(
const CXXRecordDecl *RD, CharUnits Offset);
126 void UpdateEmptyBaseSubobjects(
const BaseSubobjectInfo *Info,
127 CharUnits Offset,
bool PlacingEmptyBase);
129 void UpdateEmptyFieldSubobjects(
const CXXRecordDecl *RD,
130 const CXXRecordDecl *Class, CharUnits Offset,
131 bool PlacingOverlappingField);
132 void UpdateEmptyFieldSubobjects(
const FieldDecl *FD, CharUnits Offset,
133 bool PlacingOverlappingField);
137 bool AnyEmptySubobjectsBeyondOffset(CharUnits Offset)
const {
138 return Offset <= MaxEmptyClassOffset;
142 const FieldDecl *Field)
const {
144 assert(FieldOffset % CharWidth == 0 &&
145 "Field offset not at char boundary!");
147 return Context.toCharUnitsFromBits(FieldOffset);
151 bool CanPlaceSubobjectAtOffset(
const CXXRecordDecl *RD,
152 CharUnits Offset)
const;
154 bool CanPlaceBaseSubobjectAtOffset(
const BaseSubobjectInfo *Info,
157 bool CanPlaceFieldSubobjectAtOffset(
const CXXRecordDecl *RD,
158 const CXXRecordDecl *Class,
159 CharUnits Offset)
const;
160 bool CanPlaceFieldSubobjectAtOffset(
const FieldDecl *FD,
161 CharUnits Offset)
const;
167 CharUnits SizeOfLargestEmptySubobject;
169 EmptySubobjectMap(
const ASTContext &Context,
const CXXRecordDecl *Class)
170 : Context(Context), CharWidth(Context.
getCharWidth()), Class(Class) {
171 ComputeEmptySubobjectSizes();
178 bool CanPlaceBaseAtOffset(
const BaseSubobjectInfo *Info,
183 bool CanPlaceFieldAtOffset(
const FieldDecl *FD, CharUnits Offset);
186void EmptySubobjectMap::ComputeEmptySubobjectSizes() {
188 for (
const CXXBaseSpecifier &Base :
Class->bases()) {
189 const CXXRecordDecl *BaseDecl =
Base.getType()->getAsCXXRecordDecl();
190 assert(BaseDecl !=
Class &&
"Class cannot inherit from itself.");
202 if (EmptySize > SizeOfLargestEmptySubobject)
203 SizeOfLargestEmptySubobject = EmptySize;
207 for (
const FieldDecl *FD :
Class->fields()) {
209 const auto *MemberDecl =
216 if (MemberDecl->isEmpty()) {
224 if (EmptySize > SizeOfLargestEmptySubobject)
225 SizeOfLargestEmptySubobject = EmptySize;
230EmptySubobjectMap::CanPlaceSubobjectAtOffset(
const CXXRecordDecl *RD,
231 CharUnits Offset)
const {
236 EmptyClassOffsetsMapTy::const_iterator I = EmptyClassOffsets.find(Offset);
237 if (I == EmptyClassOffsets.end())
240 const ClassVectorTy &Classes = I->second;
241 if (!llvm::is_contained(Classes, RD))
248void EmptySubobjectMap::AddSubobjectAtOffset(
const CXXRecordDecl *RD,
256 ClassVectorTy &Classes = EmptyClassOffsets[Offset];
257 if (llvm::is_contained(Classes, RD))
260 Classes.push_back(RD);
263 if (Offset > MaxEmptyClassOffset)
264 MaxEmptyClassOffset = Offset;
268EmptySubobjectMap::CanPlaceBaseSubobjectAtOffset(
const BaseSubobjectInfo *Info,
272 if (!AnyEmptySubobjectsBeyondOffset(Offset))
275 if (!CanPlaceSubobjectAtOffset(Info->Class, Offset))
280 for (
const BaseSubobjectInfo *Base : Info->Bases) {
286 if (!CanPlaceBaseSubobjectAtOffset(Base, BaseOffset))
290 if (Info->PrimaryVirtualBaseInfo) {
291 BaseSubobjectInfo *PrimaryVirtualBaseInfo = Info->PrimaryVirtualBaseInfo;
293 if (Info == PrimaryVirtualBaseInfo->Derived) {
294 if (!CanPlaceBaseSubobjectAtOffset(PrimaryVirtualBaseInfo, Offset))
300 for (
const FieldDecl *Field : Info->Class->
fields()) {
301 if (
Field->isBitField())
305 if (!CanPlaceFieldSubobjectAtOffset(Field, FieldOffset))
312void EmptySubobjectMap::UpdateEmptyBaseSubobjects(
const BaseSubobjectInfo *Info,
314 bool PlacingEmptyBase) {
315 if (!PlacingEmptyBase && Offset >= SizeOfLargestEmptySubobject) {
324 AddSubobjectAtOffset(Info->Class, Offset);
328 for (
const BaseSubobjectInfo *Base : Info->Bases) {
333 UpdateEmptyBaseSubobjects(Base, BaseOffset, PlacingEmptyBase);
336 if (Info->PrimaryVirtualBaseInfo) {
337 BaseSubobjectInfo *PrimaryVirtualBaseInfo = Info->PrimaryVirtualBaseInfo;
339 if (Info == PrimaryVirtualBaseInfo->Derived)
340 UpdateEmptyBaseSubobjects(PrimaryVirtualBaseInfo, Offset,
345 for (
const FieldDecl *Field : Info->Class->
fields()) {
346 if (
Field->isBitField())
350 UpdateEmptyFieldSubobjects(Field, FieldOffset, PlacingEmptyBase);
354bool EmptySubobjectMap::CanPlaceBaseAtOffset(
const BaseSubobjectInfo *Info,
358 if (SizeOfLargestEmptySubobject.
isZero())
361 if (!CanPlaceBaseSubobjectAtOffset(Info, Offset))
366 UpdateEmptyBaseSubobjects(Info, Offset, Info->Class->
isEmpty());
371EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(
const CXXRecordDecl *RD,
372 const CXXRecordDecl *
Class,
373 CharUnits Offset)
const {
376 if (!AnyEmptySubobjectsBeyondOffset(Offset))
379 if (!CanPlaceSubobjectAtOffset(RD, Offset))
385 for (
const CXXBaseSpecifier &Base : RD->
bases()) {
386 if (
Base.isVirtual())
389 const CXXRecordDecl *BaseDecl =
Base.getType()->getAsCXXRecordDecl();
392 if (!CanPlaceFieldSubobjectAtOffset(BaseDecl,
Class, BaseOffset))
398 for (
const CXXBaseSpecifier &Base : RD->
vbases()) {
399 const CXXRecordDecl *VBaseDecl =
Base.getType()->getAsCXXRecordDecl();
402 if (!CanPlaceFieldSubobjectAtOffset(VBaseDecl,
Class, VBaseOffset))
408 for (
const FieldDecl *Field : RD->
fields()) {
409 if (
Field->isBitField())
413 if (!CanPlaceFieldSubobjectAtOffset(Field, FieldOffset))
421EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(
const FieldDecl *FD,
422 CharUnits Offset)
const {
425 if (!AnyEmptySubobjectsBeyondOffset(Offset))
430 return CanPlaceFieldSubobjectAtOffset(RD, RD, Offset);
442 CharUnits ElementOffset = Offset;
443 for (uint64_t I = 0; I != NumElements; ++I) {
446 if (!AnyEmptySubobjectsBeyondOffset(ElementOffset))
449 if (!CanPlaceFieldSubobjectAtOffset(RD, RD, ElementOffset))
452 ElementOffset += Layout.
getSize();
459bool EmptySubobjectMap::CanPlaceFieldAtOffset(
const FieldDecl *FD,
461 if (!CanPlaceFieldSubobjectAtOffset(FD, Offset))
466 UpdateEmptyFieldSubobjects(FD, Offset, FD->
hasAttr<NoUniqueAddressAttr>());
470void EmptySubobjectMap::UpdateEmptyFieldSubobjects(
471 const CXXRecordDecl *RD,
const CXXRecordDecl *
Class, CharUnits Offset,
472 bool PlacingOverlappingField) {
483 if (!PlacingOverlappingField && Offset >= SizeOfLargestEmptySubobject)
486 AddSubobjectAtOffset(RD, Offset);
491 for (
const CXXBaseSpecifier &Base : RD->
bases()) {
492 if (
Base.isVirtual())
495 const CXXRecordDecl *BaseDecl =
Base.getType()->getAsCXXRecordDecl();
498 UpdateEmptyFieldSubobjects(BaseDecl,
Class, BaseOffset,
499 PlacingOverlappingField);
504 for (
const CXXBaseSpecifier &Base : RD->
vbases()) {
505 const CXXRecordDecl *VBaseDecl =
Base.getType()->getAsCXXRecordDecl();
508 UpdateEmptyFieldSubobjects(VBaseDecl,
Class, VBaseOffset,
509 PlacingOverlappingField);
514 for (
const FieldDecl *Field : RD->
fields()) {
515 if (
Field->isBitField())
519 UpdateEmptyFieldSubobjects(Field, FieldOffset, PlacingOverlappingField);
523void EmptySubobjectMap::UpdateEmptyFieldSubobjects(
524 const FieldDecl *FD, CharUnits Offset,
bool PlacingOverlappingField) {
527 UpdateEmptyFieldSubobjects(RD, RD, Offset, PlacingOverlappingField);
541 CharUnits ElementOffset = Offset;
543 for (uint64_t I = 0; I != NumElements; ++I) {
549 if (!PlacingOverlappingField &&
550 ElementOffset >= SizeOfLargestEmptySubobject)
553 UpdateEmptyFieldSubobjects(RD, RD, ElementOffset,
554 PlacingOverlappingField);
555 ElementOffset += Layout.
getSize();
560typedef llvm::SmallPtrSet<const CXXRecordDecl*, 4> ClassSetTy;
562class ItaniumRecordLayoutBuilder {
565 friend class clang::ASTContext;
567 const ASTContext &Context;
569 EmptySubobjectMap *EmptySubobjects;
578 CharUnits PreferredAlignment;
581 CharUnits UnpackedAlignment;
584 CharUnits UnadjustedAlignment;
586 SmallVector<uint64_t, 16> FieldOffsets;
590 LLVM_PREFERRED_TYPE(
bool)
591 unsigned UseExternalLayout : 1;
595 LLVM_PREFERRED_TYPE(
bool)
596 unsigned InferAlignment : 1;
599 LLVM_PREFERRED_TYPE(
bool)
602 LLVM_PREFERRED_TYPE(
bool)
603 unsigned IsUnion : 1;
605 LLVM_PREFERRED_TYPE(
bool)
606 unsigned IsMac68kAlign : 1;
608 LLVM_PREFERRED_TYPE(
bool)
609 unsigned IsNaturalAlign : 1;
611 LLVM_PREFERRED_TYPE(
bool)
612 unsigned IsMsStruct : 1;
622 uint64_t LastBitfieldStorageUnitSize;
626 CharUnits MaxFieldAlignment;
631 CharUnits NonVirtualSize;
632 CharUnits NonVirtualAlignment;
633 CharUnits PreferredNVAlignment;
637 CharUnits PaddedFieldSize;
641 const CXXRecordDecl *PrimaryBase;
645 bool PrimaryBaseIsVirtual;
658 bool HandledFirstNonOverlappingEmptyField;
660 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
663 BaseOffsetsMapTy Bases;
670 CXXIndirectPrimaryBaseSet IndirectPrimaryBases;
674 const CXXRecordDecl *FirstNearlyEmptyVBase;
678 llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBases;
683 ItaniumRecordLayoutBuilder(
const ASTContext &Context,
684 EmptySubobjectMap *EmptySubobjects)
685 : Context(Context), EmptySubobjects(EmptySubobjects),
Size(0),
686 Alignment(CharUnits::One()), PreferredAlignment(CharUnits::One()),
687 UnpackedAlignment(CharUnits::One()),
688 UnadjustedAlignment(CharUnits::One()), UseExternalLayout(
false),
690 IsMac68kAlign(
false),
691 IsNaturalAlign(!Context.getTargetInfo().
getTriple().isOSAIX()),
692 IsMsStruct(
false), UnfilledBitsInLastUnit(0),
693 LastBitfieldStorageUnitSize(0), MaxFieldAlignment(CharUnits::
Zero()),
694 DataSize(0), NonVirtualSize(CharUnits::
Zero()),
695 NonVirtualAlignment(CharUnits::One()),
696 PreferredNVAlignment(CharUnits::One()),
697 PaddedFieldSize(CharUnits::
Zero()), PrimaryBase(
nullptr),
698 PrimaryBaseIsVirtual(
false), HasOwnVFPtr(
false), HasPackedField(
false),
699 HandledFirstNonOverlappingEmptyField(
false),
700 FirstNearlyEmptyVBase(
nullptr) {}
702 void Layout(
const RecordDecl *D);
703 void Layout(
const CXXRecordDecl *D);
704 void Layout(
const ObjCInterfaceDecl *D);
706 void LayoutFields(
const RecordDecl *D);
707 void LayoutField(
const FieldDecl *D,
bool InsertExtraPadding);
708 void LayoutWideBitField(uint64_t FieldSize, uint64_t StorageUnitSize,
709 bool FieldPacked,
const FieldDecl *D);
710 void LayoutBitField(
const FieldDecl *D);
712 TargetCXXABI getCXXABI()
const {
717 llvm::SpecificBumpPtrAllocator<BaseSubobjectInfo> BaseSubobjectInfoAllocator;
719 typedef llvm::DenseMap<const CXXRecordDecl *, BaseSubobjectInfo *>
720 BaseSubobjectInfoMapTy;
724 BaseSubobjectInfoMapTy VirtualBaseInfo;
728 BaseSubobjectInfoMapTy NonVirtualBaseInfo;
732 void ComputeBaseSubobjectInfo(
const CXXRecordDecl *RD);
736 BaseSubobjectInfo *ComputeBaseSubobjectInfo(
const CXXRecordDecl *RD,
738 BaseSubobjectInfo *Derived);
741 void DeterminePrimaryBase(
const CXXRecordDecl *RD);
743 void SelectPrimaryVBase(
const CXXRecordDecl *RD);
745 void EnsureVTablePointerAlignment(CharUnits UnpackedBaseAlign);
749 void LayoutNonVirtualBases(
const CXXRecordDecl *RD);
752 void LayoutNonVirtualBase(
const BaseSubobjectInfo *Base);
754 void AddPrimaryVirtualBaseOffsets(
const BaseSubobjectInfo *Info,
758 void LayoutVirtualBases(
const CXXRecordDecl *RD,
759 const CXXRecordDecl *MostDerivedClass);
762 void LayoutVirtualBase(
const BaseSubobjectInfo *Base);
766 CharUnits LayoutBase(
const BaseSubobjectInfo *Base);
769 void InitializeLayout(
const Decl *D);
773 void FinishLayout(
const NamedDecl *D);
775 void UpdateAlignment(CharUnits NewAlignment, CharUnits UnpackedNewAlignment,
776 CharUnits PreferredAlignment);
777 void UpdateAlignment(CharUnits NewAlignment, CharUnits UnpackedNewAlignment) {
778 UpdateAlignment(NewAlignment, UnpackedNewAlignment, NewAlignment);
780 void UpdateAlignment(CharUnits NewAlignment) {
781 UpdateAlignment(NewAlignment, NewAlignment, NewAlignment);
789 uint64_t updateExternalFieldOffset(
const FieldDecl *Field,
790 uint64_t ComputedOffset);
793 uint64_t UnpackedOffset,
unsigned UnpackedAlign,
794 bool isPacked,
const FieldDecl *D);
796 DiagnosticBuilder
Diag(SourceLocation Loc,
unsigned DiagID);
798 CharUnits getSize()
const {
804 void setSize(CharUnits NewSize) {
Size = Context.
toBits(NewSize); }
805 void setSize(uint64_t NewSize) {
Size = NewSize; }
807 CharUnits getAlignment()
const {
return Alignment; }
809 CharUnits getDataSize()
const {
813 uint64_t getDataSizeInBits()
const {
return DataSize; }
815 void setDataSize(CharUnits NewSize) { DataSize = Context.
toBits(NewSize); }
816 void setDataSize(uint64_t NewSize) { DataSize = NewSize; }
818 ItaniumRecordLayoutBuilder(
const ItaniumRecordLayoutBuilder &) =
delete;
819 void operator=(
const ItaniumRecordLayoutBuilder &) =
delete;
823void ItaniumRecordLayoutBuilder::SelectPrimaryVBase(
const CXXRecordDecl *RD) {
824 for (
const auto &I : RD->
bases()) {
825 assert(!I.getType()->isDependentType() &&
826 "Cannot layout class with dependent bases.");
828 const CXXRecordDecl *
Base = I.getType()->getAsCXXRecordDecl();
834 if (!IndirectPrimaryBases.count(Base)) {
836 PrimaryBaseIsVirtual =
true;
841 if (!FirstNearlyEmptyVBase)
842 FirstNearlyEmptyVBase =
Base;
845 SelectPrimaryVBase(Base);
852void ItaniumRecordLayoutBuilder::DeterminePrimaryBase(
const CXXRecordDecl *RD) {
864 for (
const auto &I : RD->
bases()) {
869 const CXXRecordDecl *
Base = I.getType()->getAsCXXRecordDecl();
871 if (
Base->isDynamicClass()) {
874 PrimaryBaseIsVirtual =
false;
884 SelectPrimaryVBase(RD);
890 if (FirstNearlyEmptyVBase) {
891 PrimaryBase = FirstNearlyEmptyVBase;
892 PrimaryBaseIsVirtual =
true;
896 assert(!PrimaryBase &&
"Should not get here with a primary base!");
899BaseSubobjectInfo *ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo(
900 const CXXRecordDecl *RD,
bool IsVirtual, BaseSubobjectInfo *Derived) {
901 BaseSubobjectInfo *Info;
905 BaseSubobjectInfo *&InfoSlot = VirtualBaseInfo[RD];
907 assert(InfoSlot->Class == RD &&
"Wrong class for virtual base info!");
912 InfoSlot =
new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo;
915 Info =
new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo;
919 Info->IsVirtual = IsVirtual;
920 Info->Derived =
nullptr;
921 Info->PrimaryVirtualBaseInfo =
nullptr;
923 const CXXRecordDecl *PrimaryVirtualBase =
nullptr;
924 BaseSubobjectInfo *PrimaryVirtualBaseInfo =
nullptr;
932 assert(PrimaryVirtualBase &&
"Didn't have a primary virtual base!");
935 PrimaryVirtualBaseInfo = VirtualBaseInfo.lookup(PrimaryVirtualBase);
937 if (PrimaryVirtualBaseInfo) {
938 if (PrimaryVirtualBaseInfo->Derived) {
942 PrimaryVirtualBase =
nullptr;
945 Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;
946 PrimaryVirtualBaseInfo->Derived = Info;
953 for (
const auto &I : RD->
bases()) {
954 bool IsVirtual = I.isVirtual();
956 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
958 Info->Bases.push_back(ComputeBaseSubobjectInfo(BaseDecl, IsVirtual, Info));
961 if (PrimaryVirtualBase && !PrimaryVirtualBaseInfo) {
964 PrimaryVirtualBaseInfo = VirtualBaseInfo.lookup(PrimaryVirtualBase);
965 assert(PrimaryVirtualBaseInfo &&
966 "Did not create a primary virtual base!");
969 Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;
970 PrimaryVirtualBaseInfo->Derived = Info;
976void ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo(
977 const CXXRecordDecl *RD) {
978 for (
const auto &I : RD->
bases()) {
979 bool IsVirtual = I.isVirtual();
981 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
984 BaseSubobjectInfo *Info = ComputeBaseSubobjectInfo(BaseDecl, IsVirtual,
989 assert(VirtualBaseInfo.count(BaseDecl) &&
990 "Did not add virtual base!");
993 assert(!NonVirtualBaseInfo.count(BaseDecl) &&
994 "Non-virtual base already exists!");
995 NonVirtualBaseInfo.insert(std::make_pair(BaseDecl, Info));
1000void ItaniumRecordLayoutBuilder::EnsureVTablePointerAlignment(
1001 CharUnits UnpackedBaseAlign) {
1005 if (!MaxFieldAlignment.
isZero()) {
1006 BaseAlign = std::min(BaseAlign, MaxFieldAlignment);
1007 UnpackedBaseAlign = std::min(UnpackedBaseAlign, MaxFieldAlignment);
1011 setSize(getSize().alignTo(BaseAlign));
1014 UpdateAlignment(BaseAlign, UnpackedBaseAlign, BaseAlign);
1017void ItaniumRecordLayoutBuilder::LayoutNonVirtualBases(
1018 const CXXRecordDecl *RD) {
1020 DeterminePrimaryBase(RD);
1023 ComputeBaseSubobjectInfo(RD);
1027 if (PrimaryBaseIsVirtual) {
1030 BaseSubobjectInfo *PrimaryBaseInfo = VirtualBaseInfo.lookup(PrimaryBase);
1031 PrimaryBaseInfo->Derived =
nullptr;
1034 IndirectPrimaryBases.insert(PrimaryBase);
1036 assert(!VisitedVirtualBases.count(PrimaryBase) &&
1037 "vbase already visited!");
1038 VisitedVirtualBases.insert(PrimaryBase);
1040 LayoutVirtualBase(PrimaryBaseInfo);
1042 BaseSubobjectInfo *PrimaryBaseInfo =
1043 NonVirtualBaseInfo.lookup(PrimaryBase);
1044 assert(PrimaryBaseInfo &&
1045 "Did not find base info for non-virtual primary base!");
1047 LayoutNonVirtualBase(PrimaryBaseInfo);
1053 assert(DataSize == 0 &&
"Vtable pointer must be at offset zero!");
1058 EnsureVTablePointerAlignment(PtrAlign);
1061 assert(!IsUnion &&
"Unions cannot be dynamic classes.");
1062 HandledFirstNonOverlappingEmptyField =
true;
1064 setSize(getSize() + PtrWidth);
1065 setDataSize(getSize());
1069 for (
const auto &I : RD->
bases()) {
1075 const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
1080 if (BaseDecl == PrimaryBase && !PrimaryBaseIsVirtual)
1084 BaseSubobjectInfo *BaseInfo = NonVirtualBaseInfo.
lookup(BaseDecl);
1085 assert(BaseInfo &&
"Did not find base info for non-virtual base!");
1087 LayoutNonVirtualBase(BaseInfo);
1091void ItaniumRecordLayoutBuilder::LayoutNonVirtualBase(
1092 const BaseSubobjectInfo *Base) {
1094 CharUnits Offset = LayoutBase(Base);
1097 assert(!Bases.count(
Base->Class) &&
"base offset already exists!");
1098 Bases.insert(std::make_pair(
Base->Class, Offset));
1100 AddPrimaryVirtualBaseOffsets(Base, Offset);
1103void ItaniumRecordLayoutBuilder::AddPrimaryVirtualBaseOffsets(
1104 const BaseSubobjectInfo *Info, CharUnits Offset) {
1110 if (Info->PrimaryVirtualBaseInfo) {
1111 assert(Info->PrimaryVirtualBaseInfo->IsVirtual &&
1112 "Primary virtual base is not virtual!");
1113 if (Info->PrimaryVirtualBaseInfo->Derived == Info) {
1115 assert(!VBases.count(Info->PrimaryVirtualBaseInfo->Class) &&
1116 "primary vbase offset already exists!");
1117 VBases.insert(std::make_pair(Info->PrimaryVirtualBaseInfo->Class,
1118 ASTRecordLayout::VBaseInfo(Offset,
false)));
1121 AddPrimaryVirtualBaseOffsets(Info->PrimaryVirtualBaseInfo, Offset);
1127 for (
const BaseSubobjectInfo *Base : Info->Bases) {
1128 if (
Base->IsVirtual)
1132 AddPrimaryVirtualBaseOffsets(Base, BaseOffset);
1136void ItaniumRecordLayoutBuilder::LayoutVirtualBases(
1137 const CXXRecordDecl *RD,
const CXXRecordDecl *MostDerivedClass) {
1138 const CXXRecordDecl *PrimaryBase;
1139 bool PrimaryBaseIsVirtual;
1141 if (MostDerivedClass == RD) {
1142 PrimaryBase = this->PrimaryBase;
1143 PrimaryBaseIsVirtual = this->PrimaryBaseIsVirtual;
1150 for (
const CXXBaseSpecifier &Base : RD->
bases()) {
1151 assert(!
Base.getType()->isDependentType() &&
1152 "Cannot layout class with dependent bases.");
1154 const CXXRecordDecl *BaseDecl =
Base.getType()->getAsCXXRecordDecl();
1156 if (
Base.isVirtual()) {
1157 if (PrimaryBase != BaseDecl || !PrimaryBaseIsVirtual) {
1158 bool IndirectPrimaryBase = IndirectPrimaryBases.count(BaseDecl);
1161 if (!IndirectPrimaryBase) {
1163 if (!VisitedVirtualBases.insert(BaseDecl).second)
1166 const BaseSubobjectInfo *BaseInfo = VirtualBaseInfo.lookup(BaseDecl);
1167 assert(BaseInfo &&
"Did not find virtual base info!");
1168 LayoutVirtualBase(BaseInfo);
1178 LayoutVirtualBases(BaseDecl, MostDerivedClass);
1182void ItaniumRecordLayoutBuilder::LayoutVirtualBase(
1183 const BaseSubobjectInfo *Base) {
1184 assert(!
Base->Derived &&
"Trying to lay out a primary virtual base!");
1187 CharUnits Offset = LayoutBase(Base);
1190 assert(!VBases.count(
Base->Class) &&
"vbase offset already exists!");
1191 VBases.insert(std::make_pair(
Base->Class,
1192 ASTRecordLayout::VBaseInfo(Offset,
false)));
1194 AddPrimaryVirtualBaseOffsets(Base, Offset);
1198ItaniumRecordLayoutBuilder::LayoutBase(
const BaseSubobjectInfo *Base) {
1199 assert(!IsUnion &&
"Unions cannot have base classes.");
1205 bool HasExternalLayout =
false;
1206 if (UseExternalLayout) {
1207 if (
Base->IsVirtual)
1208 HasExternalLayout =
External.getExternalVBaseOffset(
Base->Class, Offset);
1210 HasExternalLayout =
External.getExternalNVBaseOffset(
Base->Class, Offset);
1213 auto getBaseOrPreferredBaseAlignFromUnpacked = [&](CharUnits UnpackedAlign) {
1217 LangOptions::ClangABI::Ver6) ||
1226 CharUnits BaseAlign =
1227 getBaseOrPreferredBaseAlignFromUnpacked(UnpackedBaseAlign);
1228 CharUnits PreferredBaseAlign =
1229 getBaseOrPreferredBaseAlignFromUnpacked(UnpackedPreferredBaseAlign);
1231 const bool DefaultsToAIXPowerAlignment =
1233 if (DefaultsToAIXPowerAlignment) {
1238 if (!
Base->Class->isEmpty() && !HandledFirstNonOverlappingEmptyField) {
1241 HandledFirstNonOverlappingEmptyField =
true;
1242 }
else if (!IsNaturalAlign) {
1243 UnpackedPreferredBaseAlign = UnpackedBaseAlign;
1244 PreferredBaseAlign = BaseAlign;
1248 CharUnits UnpackedAlignTo = !DefaultsToAIXPowerAlignment
1250 : UnpackedPreferredBaseAlign;
1252 if (
Base->Class->isEmpty() &&
1255 setSize(std::max(getSize(), Layout.
getSize()));
1258 UpdateAlignment(BaseAlign, UnpackedAlignTo, PreferredBaseAlign);
1265 if (!MaxFieldAlignment.
isZero()) {
1266 BaseAlign = std::min(BaseAlign, MaxFieldAlignment);
1267 PreferredBaseAlign = std::min(PreferredBaseAlign, MaxFieldAlignment);
1268 UnpackedAlignTo = std::min(UnpackedAlignTo, MaxFieldAlignment);
1272 !DefaultsToAIXPowerAlignment ? BaseAlign : PreferredBaseAlign;
1273 if (!HasExternalLayout) {
1275 Offset = getDataSize().
alignTo(AlignTo);
1278 while (!EmptySubobjects->CanPlaceBaseAtOffset(Base, Offset))
1281 bool Allowed = EmptySubobjects->CanPlaceBaseAtOffset(Base, Offset);
1283 assert(Allowed &&
"Base subobject externally placed at overlapping offset");
1285 if (InferAlignment && Offset < getDataSize().alignTo(AlignTo)) {
1289 InferAlignment =
false;
1293 if (!
Base->Class->isEmpty()) {
1297 setSize(std::max(getSize(), getDataSize()));
1299 setSize(std::max(getSize(), Offset + Layout.
getSize()));
1302 UnadjustedAlignment = std::max(UnadjustedAlignment, BaseAlign);
1303 UpdateAlignment(BaseAlign, UnpackedAlignTo, PreferredBaseAlign);
1308void ItaniumRecordLayoutBuilder::InitializeLayout(
const Decl *D) {
1309 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
1317 if (
unsigned DefaultMaxFieldAlignment = Context.
getLangOpts().PackStruct) {
1325 if (D->
hasAttr<AlignMac68kAttr>()) {
1327 !D->
hasAttr<AlignNaturalAttr>() &&
1328 "Having both mac68k and natural alignment on a decl is not allowed.");
1329 IsMac68kAlign =
true;
1334 if (D->
hasAttr<AlignNaturalAttr>())
1335 IsNaturalAlign =
true;
1337 if (
const MaxFieldAlignmentAttr *MFAA = D->
getAttr<MaxFieldAlignmentAttr>())
1344 HandledFirstNonOverlappingEmptyField =
1348 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(D))
1350 UseExternalLayout = Source->layoutRecordType(
1355 if (UseExternalLayout) {
1361 InferAlignment =
true;
1367void ItaniumRecordLayoutBuilder::Layout(
const RecordDecl *D) {
1368 InitializeLayout(D);
1376void ItaniumRecordLayoutBuilder::Layout(
const CXXRecordDecl *RD) {
1377 InitializeLayout(RD);
1380 LayoutNonVirtualBases(RD);
1386 NonVirtualAlignment = Alignment;
1387 PreferredNVAlignment = PreferredAlignment;
1390 LayoutVirtualBases(RD, RD);
1398 for (
const CXXBaseSpecifier &Base : RD->
bases()) {
1399 if (
Base.isVirtual())
1402 const CXXRecordDecl *BaseDecl =
Base.getType()->getAsCXXRecordDecl();
1404 assert(Bases.count(BaseDecl) &&
"Did not find base offset!");
1408 for (
const CXXBaseSpecifier &Base : RD->
vbases()) {
1409 const CXXRecordDecl *BaseDecl =
Base.getType()->getAsCXXRecordDecl();
1411 assert(VBases.count(BaseDecl) &&
"Did not find base offset!");
1416void ItaniumRecordLayoutBuilder::Layout(
const ObjCInterfaceDecl *D) {
1425 setSize(getDataSize());
1428 InitializeLayout(D);
1432 LayoutField(IVD,
false);
1439void ItaniumRecordLayoutBuilder::LayoutFields(
const RecordDecl *D) {
1445 LayoutField(*I, InsertExtraPadding &&
1446 (std::next(I) != End || !HasFlexibleArrayMember));
1454 uint64_t CharAlignment = Context.getTargetInfo().getCharAlign();
1455 return llvm::alignTo(Size, CharAlignment);
1458void ItaniumRecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize,
1459 uint64_t StorageUnitSize,
1461 const FieldDecl *D) {
1463 "Can only have wide bit-fields in C++!");
1469 QualType IntegralPODTypes[] = {
1478 for (
const QualType &QT : IntegralPODTypes) {
1481 if (Size > FieldSize || Size > MaxSize)
1486 assert(!
Type.isNull() &&
"Did not find a type!");
1491 UnfilledBitsInLastUnit = 0;
1492 LastBitfieldStorageUnitSize = 0;
1495 uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;
1500 setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize));
1505 FieldOffset = llvm::alignTo(getDataSizeInBits(), Context.
toBits(TypeAlign));
1507 uint64_t NewSizeInBits = FieldOffset + FieldSize;
1511 UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits;
1515 FieldOffsets.push_back(FieldOffset);
1518 Context.
toBits(TypeAlign), FieldPacked, D);
1521 setSize(std::max(getSizeInBits(), getDataSizeInBits()));
1524 UnadjustedAlignment = std::max(UnadjustedAlignment, TypeAlign);
1525 UpdateAlignment(TypeAlign);
1529 return Context.getTargetInfo().getTriple().getOS() == llvm::Triple::AIX;
1532void ItaniumRecordLayoutBuilder::LayoutBitField(
const FieldDecl *D) {
1537 unsigned FieldAlign = FieldInfo.
Align;
1539 unsigned char PaddingInLastUnit = 0;
1601 FieldAlign = StorageUnitSize;
1606 if (LastBitfieldStorageUnitSize != StorageUnitSize ||
1607 UnfilledBitsInLastUnit < FieldSize) {
1609 if (!LastBitfieldStorageUnitSize && !FieldSize)
1612 PaddingInLastUnit = UnfilledBitsInLastUnit;
1613 UnfilledBitsInLastUnit = 0;
1614 LastBitfieldStorageUnitSize = 0;
1628 StorageUnitSize = 32;
1630 if (!AlignIsRequired)
1634 if (FieldAlign < StorageUnitSize) {
1637 FieldAlign = StorageUnitSize;
1644 if (FieldSize > StorageUnitSize && !
isAIXLayout(Context)) {
1645 LayoutWideBitField(FieldSize, StorageUnitSize, FieldPacked, D);
1651 IsUnion ? 0 : (getDataSizeInBits() - UnfilledBitsInLastUnit);
1656 if (FieldSize == 0 &&
1659 if (!IsUnion && FieldOffset == 0 &&
1665 unsigned ZeroLengthBitfieldBoundary =
1667 FieldAlign = std::max(FieldAlign, ZeroLengthBitfieldBoundary);
1676 unsigned UnpackedFieldAlign = FieldAlign;
1679 if (FieldPacked && FieldSize != 0)
1684 if (ExplicitFieldAlign) {
1685 FieldAlign = std::max(FieldAlign, ExplicitFieldAlign);
1686 UnpackedFieldAlign = std::max(UnpackedFieldAlign, ExplicitFieldAlign);
1691 unsigned MaxFieldAlignmentInBits = Context.
toBits(MaxFieldAlignment);
1692 if (!MaxFieldAlignment.
isZero() && FieldSize) {
1693 UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits);
1695 FieldAlign = UnpackedFieldAlign;
1697 FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits);
1702 if (IsMsStruct && IsUnion) {
1703 FieldAlign = UnpackedFieldAlign = 1;
1709 uint64_t UnpaddedFieldOffset = FieldOffset - PaddingInLastUnit;
1710 uint64_t UnpackedFieldOffset = FieldOffset;
1720 if (FieldSize == 0 || FieldSize > UnfilledBitsInLastUnit) {
1721 FieldOffset = llvm::alignTo(FieldOffset, FieldAlign);
1722 UnpackedFieldOffset =
1723 llvm::alignTo(UnpackedFieldOffset, UnpackedFieldAlign);
1724 UnfilledBitsInLastUnit = 0;
1729 bool AllowPadding = MaxFieldAlignment.
isZero();
1732 if (FieldSize == 0 ||
1734 (FieldOffset & (FieldAlign - 1)) + FieldSize > StorageUnitSize)) {
1735 FieldOffset = llvm::alignTo(FieldOffset, FieldAlign);
1736 }
else if (ExplicitFieldAlign &&
1737 (MaxFieldAlignmentInBits == 0 ||
1738 ExplicitFieldAlign <= MaxFieldAlignmentInBits) &&
1742 FieldOffset = llvm::alignTo(FieldOffset, ExplicitFieldAlign);
1746 if (FieldSize == 0 ||
1748 (UnpackedFieldOffset & (UnpackedFieldAlign - 1)) + FieldSize >
1750 UnpackedFieldOffset =
1751 llvm::alignTo(UnpackedFieldOffset, UnpackedFieldAlign);
1752 else if (ExplicitFieldAlign &&
1753 (MaxFieldAlignmentInBits == 0 ||
1754 ExplicitFieldAlign <= MaxFieldAlignmentInBits) &&
1756 UnpackedFieldOffset =
1757 llvm::alignTo(UnpackedFieldOffset, ExplicitFieldAlign);
1762 if (UseExternalLayout)
1763 FieldOffset = updateExternalFieldOffset(D, FieldOffset);
1766 FieldOffsets.push_back(FieldOffset);
1775 FieldAlign = UnpackedFieldAlign = 1;
1783 if (!MaxFieldAlignment.
isZero()) {
1784 UnpackedFieldAlign =
1785 std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits);
1786 FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits);
1791 if (!UseExternalLayout)
1793 UnpackedFieldAlign, FieldPacked, D);
1803 RoundedFieldSize = (FieldSize ? StorageUnitSize
1811 setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize));
1815 }
else if (IsMsStruct && FieldSize) {
1818 if (!UnfilledBitsInLastUnit) {
1819 setDataSize(FieldOffset + StorageUnitSize);
1820 UnfilledBitsInLastUnit = StorageUnitSize;
1822 UnfilledBitsInLastUnit -= FieldSize;
1823 LastBitfieldStorageUnitSize = StorageUnitSize;
1829 uint64_t NewSizeInBits = FieldOffset + FieldSize;
1831 setDataSize(llvm::alignTo(NewSizeInBits, CharAlignment));
1832 UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits;
1837 LastBitfieldStorageUnitSize = 0;
1841 setSize(std::max(getSizeInBits(), getDataSizeInBits()));
1844 UnadjustedAlignment =
1850void ItaniumRecordLayoutBuilder::LayoutField(
const FieldDecl *D,
1851 bool InsertExtraPadding) {
1853 bool IsOverlappingEmptyField =
1856 CharUnits FieldOffset =
1857 (IsUnion || IsOverlappingEmptyField) ?
CharUnits::Zero() : getDataSize();
1859 const bool DefaultsToAIXPowerAlignment =
1861 bool FoundFirstNonOverlappingEmptyFieldForAIX =
false;
1862 if (DefaultsToAIXPowerAlignment && !HandledFirstNonOverlappingEmptyField) {
1864 "The first non-overlapping empty field should have been handled.");
1866 if (!IsOverlappingEmptyField) {
1867 FoundFirstNonOverlappingEmptyFieldForAIX =
true;
1874 HandledFirstNonOverlappingEmptyField = !IsUnion;
1883 uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;
1885 UnfilledBitsInLastUnit = 0;
1886 LastBitfieldStorageUnitSize = 0;
1891 CharUnits FieldSize;
1892 CharUnits FieldAlign;
1896 CharUnits EffectiveFieldSize;
1898 auto setDeclInfo = [&](
bool IsIncompleteArrayType) {
1900 FieldAlign = TI.Align;
1903 EffectiveFieldSize = FieldSize =
1905 AlignRequirement = TI.AlignRequirement;
1911 setDeclInfo(
false );
1917 EffectiveFieldSize =
1928 if (
const BuiltinType *BTy =
T->
getAs<BuiltinType>()) {
1931 if (!llvm::isPowerOf2_64(TypeSize.
getQuantity())) {
1934 "Non PowerOf2 size in MSVC mode");
1956 if (TypeSize > FieldAlign &&
1958 FieldAlign = TypeSize;
1965 (!FieldClass || FieldClass->isPOD() ||
1966 FieldClass->hasAttr<PackedAttr>() ||
1975 auto alignedAttrCanDecreaseAIXAlignment = [AlignRequirement, FieldPacked] {
1979 return AlignRequirement == AlignRequirementKind::RequiredByTypedef ||
1980 (AlignRequirement == AlignRequirementKind::RequiredByRecord &&
1993 CharUnits PreferredAlign = FieldAlign;
1994 if (DefaultsToAIXPowerAlignment && !alignedAttrCanDecreaseAIXAlignment() &&
1995 (FoundFirstNonOverlappingEmptyFieldForAIX || IsNaturalAlign)) {
1996 auto performBuiltinTypeAlignmentUpgrade = [&](
const BuiltinType *BTy) {
1997 if (BTy->getKind() == BuiltinType::Double ||
1998 BTy->getKind() == BuiltinType::LongDouble) {
2000 "No need to upgrade the alignment value.");
2006 if (
const ComplexType *CTy = BaseTy->
getAs<ComplexType>()) {
2007 performBuiltinTypeAlignmentUpgrade(
2008 CTy->getElementType()->castAs<BuiltinType>());
2009 }
else if (
const BuiltinType *BTy = BaseTy->
getAs<BuiltinType>()) {
2010 performBuiltinTypeAlignmentUpgrade(BTy);
2011 }
else if (
const RecordType *RT = BaseTy->
getAsCanonical<RecordType>()) {
2012 const RecordDecl *RD = RT->getDecl();
2020 CharUnits UnpackedFieldAlign = FieldAlign;
2022 CharUnits UnpackedFieldOffset = FieldOffset;
2023 CharUnits OriginalFieldAlign = UnpackedFieldAlign;
2025 CharUnits MaxAlignmentInChars =
2027 PackedFieldAlign = std::max(PackedFieldAlign, MaxAlignmentInChars);
2028 PreferredAlign = std::max(PreferredAlign, MaxAlignmentInChars);
2029 UnpackedFieldAlign = std::max(UnpackedFieldAlign, MaxAlignmentInChars);
2032 if (!MaxFieldAlignment.
isZero()) {
2033 PackedFieldAlign = std::min(PackedFieldAlign, MaxFieldAlignment);
2034 PreferredAlign = std::min(PreferredAlign, MaxFieldAlignment);
2035 UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignment);
2040 FieldAlign = UnpackedFieldAlign;
2041 if (DefaultsToAIXPowerAlignment)
2042 UnpackedFieldAlign = PreferredAlign;
2044 PreferredAlign = PackedFieldAlign;
2045 FieldAlign = PackedFieldAlign;
2049 !DefaultsToAIXPowerAlignment ? FieldAlign : PreferredAlign;
2051 FieldOffset = FieldOffset.
alignTo(AlignTo);
2052 UnpackedFieldOffset = UnpackedFieldOffset.
alignTo(UnpackedFieldAlign);
2054 if (UseExternalLayout) {
2056 updateExternalFieldOffset(D, Context.
toBits(FieldOffset)));
2058 if (!IsUnion && EmptySubobjects) {
2060 bool Allowed = EmptySubobjects->CanPlaceFieldAtOffset(D, FieldOffset);
2062 assert(Allowed &&
"Externally-placed field cannot be placed here");
2065 if (!IsUnion && EmptySubobjects) {
2067 while (!EmptySubobjects->CanPlaceFieldAtOffset(D, FieldOffset)) {
2072 FieldOffset = getDataSize().
alignTo(AlignTo);
2074 FieldOffset += AlignTo;
2080 FieldOffsets.push_back(Context.
toBits(FieldOffset));
2082 if (!UseExternalLayout)
2084 Context.
toBits(UnpackedFieldOffset),
2085 Context.
toBits(UnpackedFieldAlign), FieldPacked, D);
2087 if (InsertExtraPadding) {
2089 CharUnits ExtraSizeForAsan = ASanAlignment;
2091 ExtraSizeForAsan += ASanAlignment - (FieldSize % ASanAlignment);
2092 EffectiveFieldSize = FieldSize = FieldSize + ExtraSizeForAsan;
2096 if (!IsOverlappingEmptyField) {
2097 uint64_t EffectiveFieldSizeInBits = Context.
toBits(EffectiveFieldSize);
2099 setDataSize(std::max(getDataSizeInBits(), EffectiveFieldSizeInBits));
2101 setDataSize(FieldOffset + EffectiveFieldSize);
2103 PaddedFieldSize = std::max(PaddedFieldSize, FieldOffset + FieldSize);
2104 setSize(std::max(getSizeInBits(), getDataSizeInBits()));
2106 setSize(std::max(getSizeInBits(),
2107 (uint64_t)Context.
toBits(FieldOffset + FieldSize)));
2111 UnadjustedAlignment = std::max(UnadjustedAlignment, FieldAlign);
2112 UpdateAlignment(FieldAlign, UnpackedFieldAlign, PreferredAlign);
2116 if (
const RecordDecl *RD = D->
getParent()) {
2118 if (RD->
hasAttr<PackedAttr>() || !MaxFieldAlignment.
isZero())
2119 if (FieldAlign < OriginalFieldAlign)
2131 if (
Packed && !FieldPacked && PackedFieldAlign < FieldAlign)
2135void ItaniumRecordLayoutBuilder::FinishLayout(
const NamedDecl *D) {
2137 if (Context.
getLangOpts().CPlusPlus && getSizeInBits() == 0) {
2138 if (
const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
2151 setSize(std::max(getSizeInBits(), (uint64_t)Context.
toBits(PaddedFieldSize)));
2155 uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastUnit;
2157 llvm::alignTo(getSizeInBits(), Context.
toBits(UnpackedAlignment));
2159 uint64_t RoundedSize = llvm::alignTo(
2163 : PreferredAlignment));
2165 if (UseExternalLayout) {
2169 if (InferAlignment &&
External.Size < RoundedSize) {
2172 InferAlignment =
false;
2179 setSize(RoundedSize);
2182 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
2184 if (getSizeInBits() > UnpaddedSize) {
2185 unsigned PadSize = getSizeInBits() - UnpaddedSize;
2187 if (PadSize % CharBitNum == 0) {
2188 PadSize = PadSize / CharBitNum;
2193 << (InBits ? 1 : 0);
2196 const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD);
2204 if (
Packed && UnpackedAlignment <= Alignment &&
2205 UnpackedSizeInBits == getSizeInBits() && !HasPackedField &&
2206 (!CXXRD || CXXRD->isPOD() ||
2213void ItaniumRecordLayoutBuilder::UpdateAlignment(
2214 CharUnits NewAlignment, CharUnits UnpackedNewAlignment,
2215 CharUnits PreferredNewAlignment) {
2218 if (IsMac68kAlign || (UseExternalLayout && !InferAlignment))
2221 if (NewAlignment > Alignment) {
2222 assert(llvm::isPowerOf2_64(NewAlignment.
getQuantity()) &&
2223 "Alignment not a power of 2");
2224 Alignment = NewAlignment;
2227 if (UnpackedNewAlignment > UnpackedAlignment) {
2228 assert(llvm::isPowerOf2_64(UnpackedNewAlignment.
getQuantity()) &&
2229 "Alignment not a power of 2");
2230 UnpackedAlignment = UnpackedNewAlignment;
2233 if (PreferredNewAlignment > PreferredAlignment) {
2234 assert(llvm::isPowerOf2_64(PreferredNewAlignment.
getQuantity()) &&
2235 "Alignment not a power of 2");
2236 PreferredAlignment = PreferredNewAlignment;
2241ItaniumRecordLayoutBuilder::updateExternalFieldOffset(
const FieldDecl *Field,
2242 uint64_t ComputedOffset) {
2245 if (InferAlignment && ExternalFieldOffset < ComputedOffset) {
2250 InferAlignment =
false;
2254 return ExternalFieldOffset;
2270 default: llvm_unreachable(
"Invalid tag kind for field padding diagnostic!");
2275 uint64_t Offset, uint64_t UnpaddedOffset,
2287 unsigned CharBitNum = Context.getTargetInfo().getCharWidth();
2290 if (!IsUnion && Offset > UnpaddedOffset) {
2291 unsigned PadSize = Offset - UnpaddedOffset;
2293 if (PadSize % CharBitNum == 0) {
2294 PadSize = PadSize / CharBitNum;
2299 : diag::warn_padded_struct_field;
2303 << Context.getCanonicalTagType(D->
getParent()) << PadSize
2308 : diag::warn_padded_struct_anon_field;
2312 << Context.getCanonicalTagType(D->
getParent()) << PadSize
2313 << (InBits ? 1 : 0);
2318void ItaniumRecordLayoutBuilder::CheckFieldPadding(
2319 uint64_t Offset, uint64_t UnpaddedOffset, uint64_t UnpackedOffset,
2320 unsigned UnpackedAlign,
bool isPacked,
const FieldDecl *D) {
2322 if (isPacked && Offset != UnpackedOffset) {
2323 HasPackedField =
true;
2347 bool allowInlineFunctions =
2348 Context.getTargetInfo().getCXXABI().canKeyFunctionBeInline();
2351 if (!MD->isVirtual())
2354 if (MD->isPureVirtual())
2359 if (MD->isImplicit())
2362 if (MD->isInlineSpecified() || MD->isConstexpr())
2365 if (MD->hasInlineBody())
2369 if (!MD->isUserProvided())
2373 if (!allowInlineFunctions) {
2379 if (Context.getLangOpts().CUDA) {
2383 if (Context.getLangOpts().CUDAIsDevice) {
2385 if (!MD->hasAttr<CUDADeviceAttr>())
2389 if (!MD->hasAttr<CUDAHostAttr>() && MD->hasAttr<CUDADeviceAttr>())
2397 if (MD->hasAttr<DLLImportAttr>() && !RD->
hasAttr<DLLImportAttr>() &&
2398 !Context.getTargetInfo().hasPS4DLLImportExport())
2408DiagnosticBuilder ItaniumRecordLayoutBuilder::Diag(SourceLocation Loc,
2452 llvm_unreachable(
"bad tail-padding use kind");
2546struct MicrosoftRecordLayoutBuilder {
2547 struct ElementInfo {
2549 CharUnits Alignment;
2554 CharUnits NonRequiredAlignment;
2556 typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
2557 MicrosoftRecordLayoutBuilder(
const ASTContext &Context,
2558 EmptySubobjectMap *EmptySubobjects)
2559 : Context(Context), EmptySubobjects(EmptySubobjects),
2560 RemainingBitsInField(0) {}
2563 MicrosoftRecordLayoutBuilder(
const MicrosoftRecordLayoutBuilder &) =
delete;
2564 void operator=(
const MicrosoftRecordLayoutBuilder &) =
delete;
2566 void layout(
const RecordDecl *RD);
2567 void cxxLayout(
const CXXRecordDecl *RD);
2569 void initializeLayout(
const RecordDecl *RD);
2573 void initializeCXXLayout(
const CXXRecordDecl *RD);
2574 void layoutNonVirtualBases(
const CXXRecordDecl *RD);
2575 void layoutNonVirtualBase(
const CXXRecordDecl *RD,
2576 const CXXRecordDecl *BaseDecl,
2577 const ASTRecordLayout &BaseLayout,
2578 const ASTRecordLayout *&PreviousBaseLayout);
2579 void injectVFPtr(
const CXXRecordDecl *RD);
2580 void injectVBPtr(
const CXXRecordDecl *RD);
2583 void layoutFields(
const RecordDecl *RD);
2584 void layoutField(
const FieldDecl *FD);
2585 void layoutBitField(
const FieldDecl *FD);
2588 void layoutZeroWidthBitField(
const FieldDecl *FD);
2589 void layoutVirtualBases(
const CXXRecordDecl *RD);
2590 void finalizeLayout(
const RecordDecl *RD);
2593 ElementInfo getAdjustedElementInfo(
const ASTRecordLayout &Layout);
2597 ElementInfo getAdjustedElementInfo(
const FieldDecl *FD);
2601 bool reuseOveralignedBaseTailPadding()
const {
2603 return Triple.isAArch64() && !Triple.isWindowsArm64EC();
2606 void placeFieldAtOffset(CharUnits FieldOffset) {
2607 FieldOffsets.push_back(Context.
toBits(FieldOffset));
2610 void placeFieldAtBitOffset(uint64_t FieldOffset) {
2611 FieldOffsets.push_back(FieldOffset);
2614 void computeVtorDispSet(
2615 llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtorDispSet,
2616 const CXXRecordDecl *RD)
const;
2617 const ASTContext &Context;
2618 EmptySubobjectMap *EmptySubobjects;
2623 CharUnits NonVirtualSize;
2627 CharUnits Alignment;
2629 CharUnits MaxFieldAlignment;
2632 CharUnits RequiredAlignment;
2635 CharUnits NonRequiredAlignment;
2639 CharUnits CurrentBitfieldSize;
2641 CharUnits VBPtrOffset;
2643 CharUnits MinEmptyStructSize;
2645 ElementInfo PointerInfo;
2647 const CXXRecordDecl *PrimaryBase;
2649 const CXXRecordDecl *SharedVBPtrBase;
2651 SmallVector<uint64_t, 16> FieldOffsets;
2653 BaseOffsetsMapTy Bases;
2657 unsigned RemainingBitsInField;
2661 bool LastFieldIsNonZeroWidthBitfield : 1;
2663 bool HasOwnVFPtr : 1;
2669 bool EndsWithZeroSizedObject : 1;
2672 bool LeadsWithZeroSizedBase : 1;
2675 bool UseExternalLayout : 1;
2683MicrosoftRecordLayoutBuilder::ElementInfo
2684MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
2685 const ASTRecordLayout &Layout) {
2689 if (!MaxFieldAlignment.
isZero())
2690 Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment);
2699 CharUnits BaseAlignment = Info.Alignment;
2700 if (reuseOveralignedBaseTailPadding()) {
2702 if (!MaxFieldAlignment.
isZero())
2703 BaseAlignment = std::min(BaseAlignment, MaxFieldAlignment);
2705 Alignment = std::max(Alignment, BaseAlignment);
2708 Info.NonRequiredAlignment = Info.Alignment;
2713MicrosoftRecordLayoutBuilder::ElementInfo
2714MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
2715 const FieldDecl *FD) {
2722 CharUnits DirectFieldAlignment =
2735 std::max(Info.Alignment,
2736 std::max(DirectFieldAlignment, FieldTypeRequiredAlignment));
2738 if (
const auto *RT = FD->
getType()
2743 FieldTypeRequiredAlignment =
2748 std::max(RequiredAlignment,
2749 std::max(DirectFieldAlignment, FieldTypeRequiredAlignment));
2752 if (!MaxFieldAlignment.
isZero())
2753 Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment);
2754 if (FD->
hasAttr<PackedAttr>())
2760 Info.NonRequiredAlignment =
2761 std::max(Info.Alignment, FieldTypeRequiredAlignment);
2762 Info.Alignment = std::max(Info.NonRequiredAlignment, DirectFieldAlignment);
2768 if (!reuseOveralignedBaseTailPadding() || FD->
isBitField())
2769 Info.NonRequiredAlignment = Info.Alignment;
2773void MicrosoftRecordLayoutBuilder::layout(
const RecordDecl *RD) {
2776 initializeLayout(RD);
2778 DataSize =
Size =
Size.alignTo(Alignment);
2779 RequiredAlignment = std::max(
2784void MicrosoftRecordLayoutBuilder::cxxLayout(
const CXXRecordDecl *RD) {
2787 initializeLayout(RD);
2788 initializeCXXLayout(RD);
2789 layoutNonVirtualBases(RD);
2793 if (HasOwnVFPtr || (HasVBPtr && !SharedVBPtrBase))
2794 Alignment = std::max(Alignment, PointerInfo.Alignment);
2795 auto RoundingAlignment = Alignment;
2796 if (!MaxFieldAlignment.
isZero())
2797 RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment);
2798 if (!UseExternalLayout)
2799 Size =
Size.alignTo(RoundingAlignment);
2800 NonVirtualSize =
Size;
2801 RequiredAlignment = std::max(
2803 layoutVirtualBases(RD);
2807void MicrosoftRecordLayoutBuilder::initializeLayout(
const RecordDecl *RD) {
2817 : CharUnits::
Zero();
2821 if (
unsigned DefaultMaxFieldAlignment = Context.
getLangOpts().PackStruct)
2825 if (
const MaxFieldAlignmentAttr *MFAA = RD->
getAttr<MaxFieldAlignmentAttr>()){
2826 unsigned PackedAlignment = MFAA->getAlignment();
2827 if (PackedAlignment <=
2832 if (RD->
hasAttr<PackedAttr>())
2836 UseExternalLayout =
false;
2838 UseExternalLayout = Source->layoutRecordType(
2844 if (Location.isValid())
2846 diag::err_itanium_layout_unimplemented);
2851MicrosoftRecordLayoutBuilder::initializeCXXLayout(
const CXXRecordDecl *RD) {
2852 EndsWithZeroSizedObject =
false;
2853 LeadsWithZeroSizedBase =
false;
2854 HasOwnVFPtr =
false;
2856 PrimaryBase =
nullptr;
2857 SharedVBPtrBase =
nullptr;
2865 if (!MaxFieldAlignment.
isZero())
2866 PointerInfo.Alignment = std::min(PointerInfo.Alignment, MaxFieldAlignment);
2870MicrosoftRecordLayoutBuilder::layoutNonVirtualBases(
const CXXRecordDecl *RD) {
2877 const ASTRecordLayout *PreviousBaseLayout =
nullptr;
2878 bool HasPolymorphicBaseClass =
false;
2880 for (
const CXXBaseSpecifier &Base : RD->
bases()) {
2881 const CXXRecordDecl *BaseDecl =
Base.getType()->getAsCXXRecordDecl();
2885 if (
Base.isVirtual()) {
2890 if (!SharedVBPtrBase && BaseLayout.
hasVBPtr()) {
2891 SharedVBPtrBase = BaseDecl;
2899 PrimaryBase = BaseDecl;
2903 layoutNonVirtualBase(RD, BaseDecl, BaseLayout, PreviousBaseLayout);
2907 if (!HasPolymorphicBaseClass)
2911 else if (!PrimaryBase) {
2914 for (CXXMethodDecl *M : RD->
methods()) {
2915 if (MicrosoftVTableContext::hasVtableSlot(M) &&
2916 M->size_overridden_methods() == 0) {
2925 bool CheckLeadingLayout = !PrimaryBase;
2927 for (
const CXXBaseSpecifier &Base : RD->
bases()) {
2928 if (
Base.isVirtual())
2930 const CXXRecordDecl *BaseDecl =
Base.getType()->getAsCXXRecordDecl();
2939 if (CheckLeadingLayout) {
2940 CheckLeadingLayout =
false;
2944 layoutNonVirtualBase(RD, BaseDecl, BaseLayout, PreviousBaseLayout);
2950 else if (SharedVBPtrBase) {
2959 if (RD->
hasAttr<EmptyBasesAttr>())
2961 if (
auto *LVA = RD->
getAttr<LayoutVersionAttr>())
2971void MicrosoftRecordLayoutBuilder::layoutNonVirtualBase(
2972 const CXXRecordDecl *RD,
const CXXRecordDecl *BaseDecl,
2973 const ASTRecordLayout &BaseLayout,
2974 const ASTRecordLayout *&PreviousBaseLayout) {
2982 ElementInfo Info = getAdjustedElementInfo(BaseLayout);
2983 CharUnits BaseOffset;
2986 bool FoundBase =
false;
2987 if (UseExternalLayout) {
2988 FoundBase =
External.getExternalNVBaseOffset(BaseDecl, BaseOffset);
2989 if (BaseOffset > Size) {
2995 if (MDCUsesEBO && BaseDecl->
isEmpty() &&
3000 BaseOffset =
Size =
Size.alignTo(Info.Alignment);
3003 Bases.insert(std::make_pair(BaseDecl, BaseOffset));
3006 PreviousBaseLayout = &BaseLayout;
3009void MicrosoftRecordLayoutBuilder::layoutFields(
const RecordDecl *RD) {
3010 LastFieldIsNonZeroWidthBitfield =
false;
3011 for (
const FieldDecl *Field : RD->
fields())
3015void MicrosoftRecordLayoutBuilder::layoutField(
const FieldDecl *FD) {
3020 LastFieldIsNonZeroWidthBitfield =
false;
3021 ElementInfo Info = getAdjustedElementInfo(FD);
3022 Alignment = std::max(Alignment, Info.NonRequiredAlignment);
3027 FieldClass->
fields().empty();
3030 if (UseExternalLayout) {
3033 }
else if (IsUnion) {
3035 }
else if (EmptySubobjects) {
3036 if (!IsOverlappingEmptyField)
3037 FieldOffset = DataSize.alignTo(Info.Alignment);
3039 while (!EmptySubobjects->CanPlaceFieldAtOffset(FD, FieldOffset)) {
3041 bool HasBases = ParentClass && (!ParentClass->
bases().empty() ||
3042 !ParentClass->
vbases().empty());
3047 FieldOffset = DataSize.alignTo(Info.Alignment);
3049 FieldOffset += Info.Alignment;
3053 FieldOffset =
Size.alignTo(Info.Alignment);
3056 uint64_t UnpaddedFielddOffsetInBits =
3057 Context.
toBits(DataSize) - RemainingBitsInField;
3060 UnpaddedFielddOffsetInBits, FD);
3062 RemainingBitsInField = 0;
3064 placeFieldAtOffset(FieldOffset);
3066 if (!IsOverlappingEmptyField)
3067 DataSize = std::max(DataSize, FieldOffset + Info.Size);
3069 Size = std::max(Size, FieldOffset + Info.Size);
3072void MicrosoftRecordLayoutBuilder::layoutBitField(
const FieldDecl *FD) {
3075 layoutZeroWidthBitField(FD);
3078 ElementInfo Info = getAdjustedElementInfo(FD);
3081 if (Width > Context.
toBits(Info.Size))
3082 Width = Context.
toBits(Info.Size);
3086 if (!UseExternalLayout && !IsUnion && LastFieldIsNonZeroWidthBitfield &&
3087 CurrentBitfieldSize == Info.Size && Width <= RemainingBitsInField) {
3088 placeFieldAtBitOffset(Context.
toBits(Size) - RemainingBitsInField);
3089 RemainingBitsInField -= Width;
3092 LastFieldIsNonZeroWidthBitfield =
true;
3093 CurrentBitfieldSize = Info.Size;
3094 if (UseExternalLayout) {
3095 auto FieldBitOffset =
External.getExternalFieldOffset(FD);
3096 placeFieldAtBitOffset(FieldBitOffset);
3098 llvm::alignDown(FieldBitOffset, Context.
toBits(Info.Alignment)) +
3099 Context.
toBits(Info.Size));
3100 Size = std::max(Size, NewSize);
3101 Alignment = std::max(Alignment, Info.NonRequiredAlignment);
3102 }
else if (IsUnion) {
3104 Size = std::max(Size, Info.Size);
3108 CharUnits FieldOffset =
Size.alignTo(Info.Alignment);
3109 uint64_t UnpaddedFieldOffsetInBits =
3110 Context.
toBits(DataSize) - RemainingBitsInField;
3111 placeFieldAtOffset(FieldOffset);
3112 Size = FieldOffset + Info.Size;
3113 Alignment = std::max(Alignment, Info.NonRequiredAlignment);
3114 RemainingBitsInField = Context.
toBits(Info.Size) - Width;
3116 UnpaddedFieldOffsetInBits, FD);
3122MicrosoftRecordLayoutBuilder::layoutZeroWidthBitField(
const FieldDecl *FD) {
3125 if (!LastFieldIsNonZeroWidthBitfield) {
3131 LastFieldIsNonZeroWidthBitfield =
false;
3132 ElementInfo Info = getAdjustedElementInfo(FD);
3135 Size = std::max(Size, Info.Size);
3139 CharUnits FieldOffset =
Size.alignTo(Info.Alignment);
3140 uint64_t UnpaddedFieldOffsetInBits =
3141 Context.
toBits(DataSize) - RemainingBitsInField;
3142 placeFieldAtOffset(FieldOffset);
3143 RemainingBitsInField = 0;
3145 Alignment = std::max(Alignment, Info.NonRequiredAlignment);
3147 UnpaddedFieldOffsetInBits, FD);
3152void MicrosoftRecordLayoutBuilder::injectVBPtr(
const CXXRecordDecl *RD) {
3153 if (!HasVBPtr || SharedVBPtrBase)
3156 CharUnits InjectionSite = VBPtrOffset;
3158 VBPtrOffset = VBPtrOffset.
alignTo(PointerInfo.Alignment);
3160 CharUnits FieldStart = VBPtrOffset + PointerInfo.Size;
3163 if (UseExternalLayout) {
3166 if (Size < FieldStart)
3172 CharUnits Offset = (FieldStart - InjectionSite)
3173 .alignTo(std::max(RequiredAlignment, Alignment));
3175 for (uint64_t &FieldOffset : FieldOffsets)
3176 FieldOffset += Context.
toBits(Offset);
3177 for (BaseOffsetsMapTy::value_type &Base : Bases)
3178 if (
Base.second >= InjectionSite)
3179 Base.second += Offset;
3182void MicrosoftRecordLayoutBuilder::injectVFPtr(
const CXXRecordDecl *RD) {
3188 PointerInfo.Size.
alignTo(std::max(RequiredAlignment, Alignment));
3192 VBPtrOffset += Offset;
3194 if (UseExternalLayout) {
3206 for (uint64_t &FieldOffset : FieldOffsets)
3207 FieldOffset += Context.
toBits(Offset);
3208 for (BaseOffsetsMapTy::value_type &Base : Bases)
3209 Base.second += Offset;
3212void MicrosoftRecordLayoutBuilder::layoutVirtualBases(
const CXXRecordDecl *RD) {
3217 CharUnits VtorDispAlignment = VtorDispSize;
3219 if (!MaxFieldAlignment.
isZero())
3220 VtorDispAlignment = std::min(VtorDispAlignment, MaxFieldAlignment);
3224 for (
const CXXBaseSpecifier &VBase : RD->
vbases()) {
3225 const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl();
3230 VtorDispAlignment = std::max(VtorDispAlignment, RequiredAlignment);
3232 llvm::SmallPtrSet<const CXXRecordDecl *, 2> HasVtorDispSet;
3233 computeVtorDispSet(HasVtorDispSet, RD);
3235 const ASTRecordLayout *PreviousBaseLayout =
nullptr;
3236 for (
const CXXBaseSpecifier &VBase : RD->
vbases()) {
3237 const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl();
3239 bool HasVtordisp = HasVtorDispSet.contains(BaseDecl);
3248 Size =
Size.alignTo(VtorDispAlignment) + VtorDispSize;
3249 Alignment = std::max(VtorDispAlignment, Alignment);
3252 ElementInfo Info = getAdjustedElementInfo(BaseLayout);
3253 CharUnits BaseOffset;
3256 if (UseExternalLayout) {
3257 if (!
External.getExternalVBaseOffset(BaseDecl, BaseOffset))
3260 BaseOffset =
Size.alignTo(Info.Alignment);
3262 assert(BaseOffset >= Size &&
"base offset already allocated");
3264 VBases.insert(std::make_pair(BaseDecl,
3265 ASTRecordLayout::VBaseInfo(BaseOffset, HasVtordisp)));
3267 PreviousBaseLayout = &BaseLayout;
3271void MicrosoftRecordLayoutBuilder::finalizeLayout(
const RecordDecl *RD) {
3273 UnpaddedSizeInBits -= RemainingBitsInField;
3278 UnpaddedSizeInBits += 8;
3286 NonRequiredAlignment = Alignment;
3287 if (!RequiredAlignment.
isZero()) {
3288 Alignment = std::max(Alignment, RequiredAlignment);
3289 auto RoundingAlignment = Alignment;
3290 if (!MaxFieldAlignment.
isZero())
3291 RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment);
3292 RoundingAlignment = std::max(RoundingAlignment, RequiredAlignment);
3293 Size =
Size.alignTo(RoundingAlignment);
3295 if (
Size.isZero()) {
3297 EndsWithZeroSizedObject =
true;
3298 LeadsWithZeroSizedBase =
true;
3302 if (RequiredAlignment >= MinEmptyStructSize)
3305 Size = MinEmptyStructSize;
3308 if (UseExternalLayout) {
3315 NonRequiredAlignment = Alignment;
3322 if (SizeInBits > UnpaddedSizeInBits) {
3323 unsigned int PadSize = SizeInBits - UnpaddedSizeInBits;
3325 if (PadSize % CharBitNum == 0) {
3326 PadSize = PadSize / CharBitNum;
3331 diag::warn_padded_struct_size)
3333 << (InBits ? 1 : 0);
3341 BasesWithOverriddenMethods,
3343 if (BasesWithOverriddenMethods.count(RD))
3348 if (!
Base.isVirtual() &&
3350 Base.getType()->getAsCXXRecordDecl()))
3355void MicrosoftRecordLayoutBuilder::computeVtorDispSet(
3356 llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtordispSet,
3357 const CXXRecordDecl *RD)
const {
3361 for (
const CXXBaseSpecifier &Base : RD->
vbases()) {
3362 const CXXRecordDecl *BaseDecl =
Base.getType()->getAsCXXRecordDecl();
3365 HasVtordispSet.insert(BaseDecl);
3372 for (
const CXXBaseSpecifier &Base : RD->
bases()) {
3373 const CXXRecordDecl *BaseDecl =
Base.getType()->getAsCXXRecordDecl();
3376 if (bi.second.hasVtorDisp())
3377 HasVtordispSet.insert(bi.first);
3393 llvm::SmallPtrSet<const CXXMethodDecl *, 8> Work;
3394 llvm::SmallPtrSet<const CXXRecordDecl *, 2> BasesWithOverriddenMethods;
3396 for (
const CXXMethodDecl *MD : RD->
methods())
3397 if (MicrosoftVTableContext::hasVtableSlot(MD) &&
3400 while (!Work.empty()) {
3401 const CXXMethodDecl *MD = *Work.begin();
3404 if (MethodRange.begin() == MethodRange.end())
3405 BasesWithOverriddenMethods.insert(MD->
getParent());
3407 Work.insert_range(MethodRange);
3413 for (
const CXXBaseSpecifier &Base : RD->
vbases()) {
3414 const CXXRecordDecl *BaseDecl =
Base.getType()->getAsCXXRecordDecl();
3415 if (!HasVtordispSet.count(BaseDecl) &&
3417 HasVtordispSet.insert(BaseDecl);
3441 assert(D &&
"Cannot get layout of forward declarations!");
3442 assert(!D->
isInvalidDecl() &&
"Cannot get layout of invalid decl!");
3449 if (Entry)
return *Entry;
3454 if (
const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
3455 EmptySubobjectMap EmptySubobjects(*
this, RD);
3456 MicrosoftRecordLayoutBuilder Builder(*
this, &EmptySubobjects);
3457 Builder.cxxLayout(RD);
3459 *
this, Builder.Size, Builder.Alignment, Builder.Alignment,
3460 Builder.Alignment, Builder.RequiredAlignment, Builder.HasOwnVFPtr,
3461 Builder.HasOwnVFPtr || Builder.PrimaryBase, Builder.VBPtrOffset,
3462 Builder.DataSize, Builder.FieldOffsets, Builder.NonVirtualSize,
3463 Builder.Alignment, Builder.Alignment, Builder.NonRequiredAlignment,
3465 Builder.SharedVBPtrBase, Builder.EndsWithZeroSizedObject,
3466 Builder.LeadsWithZeroSizedBase, Builder.Bases, Builder.VBases);
3468 MicrosoftRecordLayoutBuilder Builder(*
this,
nullptr);
3471 *
this, Builder.Size, Builder.Alignment, Builder.Alignment,
3472 Builder.Alignment, Builder.RequiredAlignment, Builder.Size,
3473 Builder.FieldOffsets);
3476 if (
const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
3477 EmptySubobjectMap EmptySubobjects(*
this, RD);
3478 ItaniumRecordLayoutBuilder Builder(*
this, &EmptySubobjects);
3484 bool skipTailPadding =
3489 skipTailPadding ? Builder.getSize() : Builder.getDataSize();
3491 skipTailPadding ? DataSize : Builder.NonVirtualSize;
3493 *
this, Builder.getSize(), Builder.Alignment,
3494 Builder.PreferredAlignment, Builder.UnadjustedAlignment,
3498 NonVirtualSize, Builder.NonVirtualAlignment,
3499 Builder.PreferredNVAlignment, Builder.NonVirtualAlignment,
3500 EmptySubobjects.SizeOfLargestEmptySubobject, Builder.PrimaryBase,
3501 Builder.PrimaryBaseIsVirtual,
nullptr,
false,
false, Builder.Bases,
3504 ItaniumRecordLayoutBuilder Builder(*
this,
nullptr);
3508 *
this, Builder.getSize(), Builder.Alignment,
3509 Builder.PreferredAlignment, Builder.UnadjustedAlignment,
3511 Builder.Alignment, Builder.getSize(), Builder.FieldOffsets);
3515 ASTRecordLayouts[D] = NewEntry;
3517 constexpr uint64_t MaxStructSizeInBytes = 1ULL << 60;
3519 if (
static_cast<uint64_t
>(StructSize.
getQuantity()) >= MaxStructSizeInBytes) {
3521 << D->
getName() << MaxStructSizeInBytes;
3525 llvm::outs() <<
"\n*** Dumping AST Record Layout\n";
3536 assert(RD->
getDefinition() &&
"Cannot get key function for forward decl!");
3550 KeyFunctions[RD] =
const_cast<Decl*
>(
Result);
3552 return cast_or_null<CXXMethodDecl>(
Result);
3557 "not working with method declaration from class definition");
3562 const auto &Map = KeyFunctions;
3563 auto I = Map.find(
Method->getParent());
3566 if (I == Map.end())
return;
3574 KeyFunctions.erase(
Method->getParent());
3584 uint64_t OffsetInBits;
3585 if (
const FieldDecl *FD = dyn_cast<FieldDecl>(VD)) {
3595 return OffsetInBits;
3617 assert(Index < RL->getFieldCount() &&
"Ivar is not inside record layout!");
3634 "Invalid interface decl!");
3640 ItaniumRecordLayoutBuilder Builder(*
this,
nullptr);
3644 *
this, Builder.getSize(), Builder.Alignment, Builder.PreferredAlignment,
3645 Builder.UnadjustedAlignment,
3647 Builder.Alignment, Builder.getDataSize(), Builder.FieldOffsets);
3649 ObjCLayouts[D] = NewEntry;
3656 OS << llvm::format(
"%10" PRId64
" | ", (int64_t)Offset.getQuantity());
3661 unsigned Begin,
unsigned Width,
3665 llvm::raw_svector_ostream BufferOS(Buffer);
3666 BufferOS << Offset.getQuantity() <<
':';
3670 BufferOS << Begin <<
'-' << (Begin + Width - 1);
3674 OS << llvm::right_justify(Buffer, 10) <<
" | ";
3687 const char* Description,
3689 bool IncludeVirtualBases) {
3691 auto CXXRD = dyn_cast<CXXRecordDecl>(RD);
3694 OS <<
C.getCanonicalTagType(
const_cast<RecordDecl *
>(RD));
3696 OS <<
' ' << Description;
3697 if (CXXRD && CXXRD->isEmpty())
3710 if (CXXRD->isDynamicClass() && !PrimaryBase &&
3711 !
C.getTargetInfo().hasMicrosoftRecordLayout()) {
3713 OS <<
'(' << *RD <<
" vtable pointer)\n";
3714 }
else if (HasOwnVFPtr) {
3717 OS <<
'(' << *RD <<
" vftable pointer)\n";
3723 assert(!
Base.getType()->isDependentType() &&
3724 "Cannot layout class with dependent bases.");
3725 if (!
Base.isVirtual())
3726 Bases.push_back(
Base.getType()->getAsCXXRecordDecl());
3739 Base == PrimaryBase ?
"(primary base)" :
"(base)",
3747 OS <<
'(' << *RD <<
" vbtable pointer)\n";
3753 uint64_t LocalFieldOffsetInBits =
3756 Offset +
C.toCharUnitsFromBits(LocalFieldOffsetInBits);
3759 if (
const auto *RD = Field->getType()->getAsRecordDecl()) {
3761 Field->getName().data(),
3767 if (Field->isBitField()) {
3768 uint64_t LocalFieldByteOffsetInBits =
C.toBits(FieldOffset - Offset);
3769 unsigned Begin = LocalFieldOffsetInBits - LocalFieldByteOffsetInBits;
3770 unsigned Width = Field->getBitWidthValue();
3775 const QualType &FieldType =
C.getLangOpts().DumpRecordLayoutsCanonical
3776 ? Field->getType().getCanonicalType()
3778 OS << FieldType <<
' ' << *Field <<
'\n';
3782 if (CXXRD && IncludeVirtualBases) {
3787 assert(
Base.isVirtual() &&
"Found non-virtual class!");
3792 if (VtorDisps.find(VBase)->second.hasVtorDisp()) {
3794 OS <<
"(vtordisp for vbase " << *VBase <<
")\n";
3799 "(primary virtual base)" :
"(virtual base)",
3805 if (!PrintSizeInfo)
return;
3809 if (CXXRD && !
C.getTargetInfo().hasMicrosoftRecordLayout())
3812 if (
C.getTargetInfo().defaultsToAIXPowerAlignment())
3820 if (
C.getTargetInfo().defaultsToAIXPowerAlignment())
3821 OS <<
", preferrednvalign="
3828 bool Simple)
const {
3846 OS <<
"<ASTRecordLayout\n";
3851 if (Target->defaultsToAIXPowerAlignment())
3854 if (
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
3855 OS <<
" BaseOffsets: [";
3857 for (
auto I : CXXRD->bases()) {
3862 Base = I.getType()->getAsCXXRecordDecl();
3863 OS << Info.CXXInfo->BaseOffsets[
Base].getQuantity();
3866 OS <<
" VBaseOffsets: [";
3868 for (
auto I : CXXRD->vbases()) {
3871 VBase = I.getType()->getAsCXXRecordDecl();
3872 OS << Info.CXXInfo->VBaseOffsets[VBase].VBaseOffset.getQuantity();
3876 OS <<
" FieldOffsets: [";
3877 for (
unsigned i = 0, e = Info.
getFieldCount(); i != e; ++i) {
Defines the clang::ASTContext interface.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
static unsigned getCharWidth(tok::TokenKind kind, const TargetInfo &Target)
llvm::MachO::Target Target
static StringRef getTriple(const Command &Job)
static const CXXMethodDecl * computeKeyFunction(ASTContext &Context, const CXXRecordDecl *RD)
static bool mustSkipTailPadding(TargetCXXABI ABI, const CXXRecordDecl *RD)
Does the target C++ ABI require us to skip over the tail-padding of the given class (considering it a...
static bool isAIXLayout(const ASTContext &Context)
static void PrintIndentNoOffset(raw_ostream &OS, unsigned IndentLevel)
static uint64_t roundUpSizeToCharAlignment(uint64_t Size, const ASTContext &Context)
static void PrintOffset(raw_ostream &OS, CharUnits Offset, unsigned IndentLevel)
static unsigned getPaddingDiagFromTagKind(TagTypeKind Tag)
Get diagnostic select index for tag kind for field padding diagnostic message.
static void DumpRecordLayout(raw_ostream &OS, const RecordDecl *RD, const ASTContext &C, CharUnits Offset, unsigned IndentLevel, const char *Description, bool PrintSizeInfo, bool IncludeVirtualBases)
static void CheckFieldPadding(const ASTContext &Context, bool IsUnion, uint64_t Offset, uint64_t UnpaddedOffset, const FieldDecl *D)
static uint64_t getFieldOffset(const ASTContext &C, const FieldDecl *FD)
static bool RequiresVtordisp(const llvm::SmallPtrSetImpl< const CXXRecordDecl * > &BasesWithOverriddenMethods, const CXXRecordDecl *RD)
static void PrintBitFieldOffset(raw_ostream &OS, CharUnits Offset, unsigned Begin, unsigned Width, unsigned IndentLevel)
static bool recordUsesEBO(const RecordDecl *RD)
uint64_t getFieldOffset(const ValueDecl *FD) const
Get the offset of a FieldDecl or IndirectFieldDecl, in bits.
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
void DumpRecordLayout(const RecordDecl *RD, raw_ostream &OS, bool Simple=false) const
bool defaultsToMsStruct() const
Return whether unannotated records are treated as if they have [[gnu::ms_struct]].
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...
uint64_t lookupFieldBitOffset(const ObjCInterfaceDecl *OID, const ObjCIvarDecl *Ivar) const
Get the offset of an ObjCIvarDecl in bits.
void setNonKeyFunction(const CXXMethodDecl *method)
Observe that the given method cannot be a key function.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const ConstantArrayType * getAsConstantArrayType(QualType T) const
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
const LangOptions & getLangOpts() const
const ASTRecordLayout & getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D) const
Get or compute information about the layout of the specified Objective-C interface.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
bool isNearlyEmpty(const CXXRecordDecl *RD) const
friend class CXXRecordDecl
CanQualType UnsignedLongTy
TypeInfo getTypeInfo(const Type *T) const
Get the size and alignment of the specified complete type in bits.
bool isAlignmentRequired(const Type *T) const
Determine if the alignment the type has was required using an alignment attribute.
TypeInfoChars getTypeInfoInChars(const Type *T) const
int64_t toBits(CharUnits CharSize) const
Convert a size in characters to a size in bits.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CanQualType UnsignedInt128Ty
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CanQualType UnsignedCharTy
CanQualType UnsignedIntTy
CanQualType UnsignedLongLongTy
CanQualType UnsignedShortTy
DiagnosticsEngine & getDiagnostics() const
const TargetInfo & getTargetInfo() const
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
ExternalASTSource * getExternalSource() const
Retrieve a pointer to the external AST source associated with this AST context, if any.
uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const
Return number of constant array elements.
CanQualType getCanonicalTagType(const TagDecl *TD) const
uint64_t getCharWidth() const
Return the size of the character type, in bits.
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
bool endsWithZeroSizedObject() const
bool hasOwnVFPtr() const
hasOwnVFPtr - Does this class provide its own virtual-function table pointer, rather than inheriting ...
CharUnits getAlignment() const
getAlignment - Get the record alignment in characters.
CharUnits getPreferredAlignment() const
getPreferredFieldAlignment - Get the record preferred alignment in characters.
bool hasOwnVBPtr() const
hasOwnVBPtr - Does this class provide its own virtual-base table pointer, rather than inheriting one ...
llvm::DenseMap< const CXXRecordDecl *, VBaseInfo > VBaseOffsetsMapTy
CharUnits getNonRequiredNVAlignment() const
getNonRequiredNVAlignment - Get the non-virtual alignment (in chars) of an object ignoring over-align...
CharUnits getSize() const
getSize - Get the record size in characters.
unsigned getFieldCount() const
getFieldCount - Get the number of fields in the layout.
bool hasVBPtr() const
hasVBPtr - Does this class have a virtual function table pointer.
bool leadsWithZeroSizedBase() const
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
CharUnits getNonVirtualAlignment() const
getNonVirtualAlignment - Get the non-virtual alignment (in chars) of an object, which is the alignmen...
CharUnits getVBPtrOffset() const
getVBPtrOffset - Get the offset for virtual base table pointer.
CharUnits getDataSize() const
getDataSize() - Get the record data size, which is the record size without tail padding,...
CharUnits getRequiredAlignment() const
CharUnits getSizeOfLargestEmptySubobject() const
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
CharUnits getPreferredNVAlignment() const
getPreferredNVAlignment - Get the preferred non-virtual alignment (in chars) of an object,...
CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const
getVBaseClassOffset - Get the offset, in chars, for the given base class.
const VBaseOffsetsMapTy & getVBaseOffsetsMap() const
const CXXRecordDecl * getPrimaryBase() const
getPrimaryBase - Get the primary base for this record.
bool hasExtendableVFPtr() const
hasVFPtr - Does this class have a virtual function table pointer that can be extended by a derived cl...
bool isPrimaryBaseVirtual() const
isPrimaryBaseVirtual - Get whether the primary base for this record is virtual or not.
CharUnits getNonVirtualSize() const
getNonVirtualSize - Get the non-virtual size (in chars) of an object, which is the size of the object...
Represents a base class of a C++ class.
Represents a static or instance method of a struct/union/class.
overridden_method_range overridden_methods() const
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Represents a C++ struct/union/class.
void getIndirectPrimaryBases(CXXIndirectPrimaryBaseSet &Bases) const
Get the indirect primary bases for this class.
bool hasUserDeclaredDestructor() const
Determine whether this class has a user-declared destructor.
method_range methods() const
CXXRecordDecl * getDefinition() const
bool isPolymorphic() const
Whether this class is polymorphic (C++ [class.virtual]), which means that the class contains or inher...
TemplateSpecializationKind getTemplateSpecializationKind() const
Determine whether this particular class is a specialization or instantiation of a class template or m...
base_class_range vbases()
bool isDynamicClass() const
bool isCXX11StandardLayout() const
Determine whether this class was standard-layout per C++11 [class]p7, specifically using the C++11 ru...
bool hasUserDeclaredConstructor() const
Determine whether this class has any user-declared constructors.
bool isPOD() const
Whether this class is a POD-type (C++ [class]p4)
MSVtorDispMode getMSVtorDispMode() const
Controls when vtordisps will be emitted if this record is used as a virtual base.
bool isEmpty() const
Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).
bool isTrivial() const
Determine whether this class is considered trivial.
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
CharUnits - This is an opaque type for sizes expressed in character units.
bool isZero() const
isZero - Test whether the quantity equals zero.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
static CharUnits One()
One - Construct a CharUnits quantity of one.
bool isMultipleOf(CharUnits N) const
Test whether this is a multiple of the other value.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
CharUnits alignTo(const CharUnits &Align) const
alignTo - Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is ...
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
bool hasExternalLexicalStorage() const
Whether this DeclContext has external storage containing additional declarations that are lexically i...
Decl - This represents one declaration (or definition), e.g.
unsigned getMaxAlignment() const
getMaxAlignment - return the maximum alignment specified by attributes on this decl,...
bool isInvalidDecl() const
SourceLocation getLocation() const
A little helper class (which is basically a smart pointer that forwards info from DiagnosticsEngine a...
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Represents a member of a struct/union/class.
bool isBitField() const
Determines whether this field is a bitfield.
unsigned getBitWidthValue() const
Computes the bit width of this field, if this is a bit field.
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
bool isPotentiallyOverlapping() const
Determine if this field is of potentially-overlapping class type, that is, subobject with the [[no_un...
Represents a function declaration or definition.
bool isInlineSpecified() const
Determine whether the "inline" keyword was specified for this function.
Represents a field injected from an anonymous union/struct into the parent scope.
ArrayRef< NamedDecl * > chain() const
bool isCompatibleWith(ClangABI Version) const
This represents a decl that may have a name.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
bool isExternallyVisible() const
Represents an ObjC class declaration.
ObjCIvarDecl * all_declared_ivar_begin()
all_declared_ivar_begin - return first ivar declared in this class, its extensions and its implementa...
bool isThisDeclarationADefinition() const
Determine whether this particular declaration of this class is actually also a definition.
ObjCInterfaceDecl * getSuperClass() const
ObjCInterfaceDecl * getDefinition()
Retrieve the definition of this class, or NULL if this class has been forward-declared (with @class) ...
ObjCIvarDecl - Represents an ObjC instance variable.
ObjCInterfaceDecl * getContainingInterface()
Return the class interface that this ivar is logically contained in; this is either the interface whe...
ObjCIvarDecl * getNextIvar()
ObjCIvarDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this field.
A (possibly-)qualified type.
Represents a struct/union/class.
bool isMsStruct(const ASTContext &C) const
Get whether or not this is an ms_struct which can be turned on with an attribute, pragma,...
bool hasFlexibleArrayMember() const
field_iterator field_end() const
field_range fields() const
bool mayInsertExtraPadding(bool EmitRemark=false) const
Whether we are allowed to insert extra padding between fields.
RecordDecl * getMostRecentDecl()
RecordDecl * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
field_iterator field_begin() const
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
TagKind getTagKind() const
The basic abstraction for the target C++ ABI.
TailPaddingUseRules getTailPaddingUseRules() const
@ AlwaysUseTailPadding
The tail-padding of a base class is always theoretically available, even if it's POD.
@ UseTailPaddingUnlessPOD11
Only allocate objects in the tail padding of a base class if the base class is not POD according to t...
@ UseTailPaddingUnlessPOD03
Only allocate objects in the tail padding of a base class if the base class is not POD according to t...
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
bool useLeadingZeroLengthBitfield() const
Check whether zero length bitfield alignment is respected if they are leading members.
uint64_t getPointerWidth(LangAS AddrSpace) const
Return the width of pointers on this target, for the specified address space.
unsigned getLargestOverSizedBitfieldContainer() const
virtual bool defaultsToAIXPowerAlignment() const
Whether target defaults to the power alignment rules of AIX.
unsigned getCharAlign() const
unsigned getZeroLengthBitfieldBoundary() const
Get the fixed alignment value in bits for a member that follows a zero length bitfield.
bool useExplicitBitFieldAlignment() const
Check whether explicit bitfield alignment attributes should be.
uint64_t getPointerAlign(LangAS AddrSpace) const
TargetCXXABI getCXXABI() const
Get the C++ ABI currently in use.
unsigned getCharWidth() const
bool useZeroLengthBitfieldAlignment() const
Check whether zero length bitfields should force alignment of the next member.
bool useBitFieldTypeAlignment() const
Check whether the alignment of bit-field types is respected when laying out structures.
bool isIncompleteArrayType() const
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
const Type * getBaseElementTypeUnsafe() const
Get the base element type of this type, potentially discarding type qualifiers.
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
const T * getAs() const
Member-template getAs<specific type>'.
const Type * getUnqualifiedDesugaredType() const
Return the specified type with any "sugar" removed from the type, removing any typedefs,...
bool isRecordType() const
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Defines the clang::TargetInfo interface.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
LazyOffsetPtr< Decl, GlobalDeclID, &ExternalASTSource::GetExternalDecl > LazyDeclPtr
A lazy pointer to a declaration.
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
@ External
External linkage, which indicates that the entity can be referred to from other translation units.
@ Result
The result type of a method or function.
const FunctionProtoType * T
TagTypeKind
The kind of a tag type.
@ Interface
The "__interface" keyword.
@ Struct
The "struct" keyword.
@ Class
The "class" keyword.
@ Type
The name was classified as a type.
TemplateSpecializationKind
Describes the kind of template specialization that a particular template specialization declaration r...
@ TSK_ExplicitInstantiationDefinition
This template specialization was instantiated from a template due to an explicit instantiation defini...
@ TSK_ExplicitInstantiationDeclaration
This template specialization was instantiated from a template due to an explicit instantiation declar...
@ TSK_ImplicitInstantiation
This template specialization was implicitly instantiated from a template.
U cast(CodeGen::Address addr)
@ Class
The "class" keyword introduces the elaborated-type-specifier.
bool isValid() const
Whether this pointer is non-NULL.
bool isOffset() const
Whether this pointer is currently stored as an offset.
T * get(ExternalASTSource *Source) const
Retrieve the pointer to the AST node that this lazy pointer points to.