10b57cec5SDimitry Andric //=== RecordLayoutBuilder.cpp - Helper class for building record layouts ---==//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #include "clang/AST/ASTContext.h"
100b57cec5SDimitry Andric #include "clang/AST/ASTDiagnostic.h"
110b57cec5SDimitry Andric #include "clang/AST/Attr.h"
120b57cec5SDimitry Andric #include "clang/AST/CXXInheritance.h"
130b57cec5SDimitry Andric #include "clang/AST/Decl.h"
140b57cec5SDimitry Andric #include "clang/AST/DeclCXX.h"
150b57cec5SDimitry Andric #include "clang/AST/DeclObjC.h"
160b57cec5SDimitry Andric #include "clang/AST/Expr.h"
175ffd83dbSDimitry Andric #include "clang/AST/VTableBuilder.h"
18e8d8bef9SDimitry Andric #include "clang/AST/RecordLayout.h"
190b57cec5SDimitry Andric #include "clang/Basic/TargetInfo.h"
200b57cec5SDimitry Andric #include "llvm/ADT/SmallSet.h"
210b57cec5SDimitry Andric #include "llvm/Support/Format.h"
220b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
230b57cec5SDimitry Andric
240b57cec5SDimitry Andric using namespace clang;
250b57cec5SDimitry Andric
260b57cec5SDimitry Andric namespace {
270b57cec5SDimitry Andric
280b57cec5SDimitry Andric /// BaseSubobjectInfo - Represents a single base subobject in a complete class.
290b57cec5SDimitry Andric /// For a class hierarchy like
300b57cec5SDimitry Andric ///
310b57cec5SDimitry Andric /// class A { };
320b57cec5SDimitry Andric /// class B : A { };
330b57cec5SDimitry Andric /// class C : A, B { };
340b57cec5SDimitry Andric ///
350b57cec5SDimitry Andric /// The BaseSubobjectInfo graph for C will have three BaseSubobjectInfo
360b57cec5SDimitry Andric /// instances, one for B and two for A.
370b57cec5SDimitry Andric ///
380b57cec5SDimitry Andric /// If a base is virtual, it will only have one BaseSubobjectInfo allocated.
390b57cec5SDimitry Andric struct BaseSubobjectInfo {
400b57cec5SDimitry Andric /// Class - The class for this base info.
410b57cec5SDimitry Andric const CXXRecordDecl *Class;
420b57cec5SDimitry Andric
430b57cec5SDimitry Andric /// IsVirtual - Whether the BaseInfo represents a virtual base or not.
440b57cec5SDimitry Andric bool IsVirtual;
450b57cec5SDimitry Andric
460b57cec5SDimitry Andric /// Bases - Information about the base subobjects.
470b57cec5SDimitry Andric SmallVector<BaseSubobjectInfo*, 4> Bases;
480b57cec5SDimitry Andric
490b57cec5SDimitry Andric /// PrimaryVirtualBaseInfo - Holds the base info for the primary virtual base
500b57cec5SDimitry Andric /// of this base info (if one exists).
510b57cec5SDimitry Andric BaseSubobjectInfo *PrimaryVirtualBaseInfo;
520b57cec5SDimitry Andric
530b57cec5SDimitry Andric // FIXME: Document.
540b57cec5SDimitry Andric const BaseSubobjectInfo *Derived;
550b57cec5SDimitry Andric };
560b57cec5SDimitry Andric
570b57cec5SDimitry Andric /// Externally provided layout. Typically used when the AST source, such
580b57cec5SDimitry Andric /// as DWARF, lacks all the information that was available at compile time, such
590b57cec5SDimitry Andric /// as alignment attributes on fields and pragmas in effect.
600b57cec5SDimitry Andric struct ExternalLayout {
615f757f3fSDimitry Andric ExternalLayout() = default;
620b57cec5SDimitry Andric
630b57cec5SDimitry Andric /// Overall record size in bits.
645f757f3fSDimitry Andric uint64_t Size = 0;
650b57cec5SDimitry Andric
660b57cec5SDimitry Andric /// Overall record alignment in bits.
675f757f3fSDimitry Andric uint64_t Align = 0;
680b57cec5SDimitry Andric
690b57cec5SDimitry Andric /// Record field offsets in bits.
700b57cec5SDimitry Andric llvm::DenseMap<const FieldDecl *, uint64_t> FieldOffsets;
710b57cec5SDimitry Andric
720b57cec5SDimitry Andric /// Direct, non-virtual base offsets.
730b57cec5SDimitry Andric llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsets;
740b57cec5SDimitry Andric
750b57cec5SDimitry Andric /// Virtual base offsets.
760b57cec5SDimitry Andric llvm::DenseMap<const CXXRecordDecl *, CharUnits> VirtualBaseOffsets;
770b57cec5SDimitry Andric
780b57cec5SDimitry Andric /// Get the offset of the given field. The external source must provide
790b57cec5SDimitry Andric /// entries for all fields in the record.
getExternalFieldOffset__anonbcc347f50111::ExternalLayout800b57cec5SDimitry Andric uint64_t getExternalFieldOffset(const FieldDecl *FD) {
810b57cec5SDimitry Andric assert(FieldOffsets.count(FD) &&
820b57cec5SDimitry Andric "Field does not have an external offset");
830b57cec5SDimitry Andric return FieldOffsets[FD];
840b57cec5SDimitry Andric }
850b57cec5SDimitry Andric
getExternalNVBaseOffset__anonbcc347f50111::ExternalLayout860b57cec5SDimitry Andric bool getExternalNVBaseOffset(const CXXRecordDecl *RD, CharUnits &BaseOffset) {
870b57cec5SDimitry Andric auto Known = BaseOffsets.find(RD);
880b57cec5SDimitry Andric if (Known == BaseOffsets.end())
890b57cec5SDimitry Andric return false;
900b57cec5SDimitry Andric BaseOffset = Known->second;
910b57cec5SDimitry Andric return true;
920b57cec5SDimitry Andric }
930b57cec5SDimitry Andric
getExternalVBaseOffset__anonbcc347f50111::ExternalLayout940b57cec5SDimitry Andric bool getExternalVBaseOffset(const CXXRecordDecl *RD, CharUnits &BaseOffset) {
950b57cec5SDimitry Andric auto Known = VirtualBaseOffsets.find(RD);
960b57cec5SDimitry Andric if (Known == VirtualBaseOffsets.end())
970b57cec5SDimitry Andric return false;
980b57cec5SDimitry Andric BaseOffset = Known->second;
990b57cec5SDimitry Andric return true;
1000b57cec5SDimitry Andric }
1010b57cec5SDimitry Andric };
1020b57cec5SDimitry Andric
1030b57cec5SDimitry Andric /// EmptySubobjectMap - Keeps track of which empty subobjects exist at different
1040b57cec5SDimitry Andric /// offsets while laying out a C++ class.
1050b57cec5SDimitry Andric class EmptySubobjectMap {
1060b57cec5SDimitry Andric const ASTContext &Context;
1070b57cec5SDimitry Andric uint64_t CharWidth;
1080b57cec5SDimitry Andric
1090b57cec5SDimitry Andric /// Class - The class whose empty entries we're keeping track of.
1100b57cec5SDimitry Andric const CXXRecordDecl *Class;
1110b57cec5SDimitry Andric
1120b57cec5SDimitry Andric /// EmptyClassOffsets - A map from offsets to empty record decls.
1130b57cec5SDimitry Andric typedef llvm::TinyPtrVector<const CXXRecordDecl *> ClassVectorTy;
1140b57cec5SDimitry Andric typedef llvm::DenseMap<CharUnits, ClassVectorTy> EmptyClassOffsetsMapTy;
1150b57cec5SDimitry Andric EmptyClassOffsetsMapTy EmptyClassOffsets;
1160b57cec5SDimitry Andric
1170b57cec5SDimitry Andric /// MaxEmptyClassOffset - The highest offset known to contain an empty
1180b57cec5SDimitry Andric /// base subobject.
1190b57cec5SDimitry Andric CharUnits MaxEmptyClassOffset;
1200b57cec5SDimitry Andric
1210b57cec5SDimitry Andric /// ComputeEmptySubobjectSizes - Compute the size of the largest base or
1220b57cec5SDimitry Andric /// member subobject that is empty.
1230b57cec5SDimitry Andric void ComputeEmptySubobjectSizes();
1240b57cec5SDimitry Andric
1250b57cec5SDimitry Andric void AddSubobjectAtOffset(const CXXRecordDecl *RD, CharUnits Offset);
1260b57cec5SDimitry Andric
1270b57cec5SDimitry Andric void UpdateEmptyBaseSubobjects(const BaseSubobjectInfo *Info,
1280b57cec5SDimitry Andric CharUnits Offset, bool PlacingEmptyBase);
1290b57cec5SDimitry Andric
1300b57cec5SDimitry Andric void UpdateEmptyFieldSubobjects(const CXXRecordDecl *RD,
1310b57cec5SDimitry Andric const CXXRecordDecl *Class, CharUnits Offset,
1320b57cec5SDimitry Andric bool PlacingOverlappingField);
1330b57cec5SDimitry Andric void UpdateEmptyFieldSubobjects(const FieldDecl *FD, CharUnits Offset,
1340b57cec5SDimitry Andric bool PlacingOverlappingField);
1350b57cec5SDimitry Andric
1360b57cec5SDimitry Andric /// AnyEmptySubobjectsBeyondOffset - Returns whether there are any empty
1370b57cec5SDimitry Andric /// subobjects beyond the given offset.
AnyEmptySubobjectsBeyondOffset(CharUnits Offset) const1380b57cec5SDimitry Andric bool AnyEmptySubobjectsBeyondOffset(CharUnits Offset) const {
1390b57cec5SDimitry Andric return Offset <= MaxEmptyClassOffset;
1400b57cec5SDimitry Andric }
1410b57cec5SDimitry Andric
1420b57cec5SDimitry Andric CharUnits
getFieldOffset(const ASTRecordLayout & Layout,unsigned FieldNo) const1430b57cec5SDimitry Andric getFieldOffset(const ASTRecordLayout &Layout, unsigned FieldNo) const {
1440b57cec5SDimitry Andric uint64_t FieldOffset = Layout.getFieldOffset(FieldNo);
1450b57cec5SDimitry Andric assert(FieldOffset % CharWidth == 0 &&
1460b57cec5SDimitry Andric "Field offset not at char boundary!");
1470b57cec5SDimitry Andric
1480b57cec5SDimitry Andric return Context.toCharUnitsFromBits(FieldOffset);
1490b57cec5SDimitry Andric }
1500b57cec5SDimitry Andric
1510b57cec5SDimitry Andric protected:
1520b57cec5SDimitry Andric bool CanPlaceSubobjectAtOffset(const CXXRecordDecl *RD,
1530b57cec5SDimitry Andric CharUnits Offset) const;
1540b57cec5SDimitry Andric
1550b57cec5SDimitry Andric bool CanPlaceBaseSubobjectAtOffset(const BaseSubobjectInfo *Info,
1560b57cec5SDimitry Andric CharUnits Offset);
1570b57cec5SDimitry Andric
1580b57cec5SDimitry Andric bool CanPlaceFieldSubobjectAtOffset(const CXXRecordDecl *RD,
1590b57cec5SDimitry Andric const CXXRecordDecl *Class,
1600b57cec5SDimitry Andric CharUnits Offset) const;
1610b57cec5SDimitry Andric bool CanPlaceFieldSubobjectAtOffset(const FieldDecl *FD,
1620b57cec5SDimitry Andric CharUnits Offset) const;
1630b57cec5SDimitry Andric
1640b57cec5SDimitry Andric public:
1650b57cec5SDimitry Andric /// This holds the size of the largest empty subobject (either a base
1660b57cec5SDimitry Andric /// or a member). Will be zero if the record being built doesn't contain
1670b57cec5SDimitry Andric /// any empty classes.
1680b57cec5SDimitry Andric CharUnits SizeOfLargestEmptySubobject;
1690b57cec5SDimitry Andric
EmptySubobjectMap(const ASTContext & Context,const CXXRecordDecl * Class)1700b57cec5SDimitry Andric EmptySubobjectMap(const ASTContext &Context, const CXXRecordDecl *Class)
1710b57cec5SDimitry Andric : Context(Context), CharWidth(Context.getCharWidth()), Class(Class) {
1720b57cec5SDimitry Andric ComputeEmptySubobjectSizes();
1730b57cec5SDimitry Andric }
1740b57cec5SDimitry Andric
1750b57cec5SDimitry Andric /// CanPlaceBaseAtOffset - Return whether the given base class can be placed
1760b57cec5SDimitry Andric /// at the given offset.
1770b57cec5SDimitry Andric /// Returns false if placing the record will result in two components
1780b57cec5SDimitry Andric /// (direct or indirect) of the same type having the same offset.
1790b57cec5SDimitry Andric bool CanPlaceBaseAtOffset(const BaseSubobjectInfo *Info,
1800b57cec5SDimitry Andric CharUnits Offset);
1810b57cec5SDimitry Andric
1820b57cec5SDimitry Andric /// CanPlaceFieldAtOffset - Return whether a field can be placed at the given
1830b57cec5SDimitry Andric /// offset.
1840b57cec5SDimitry Andric bool CanPlaceFieldAtOffset(const FieldDecl *FD, CharUnits Offset);
1850b57cec5SDimitry Andric };
1860b57cec5SDimitry Andric
ComputeEmptySubobjectSizes()1870b57cec5SDimitry Andric void EmptySubobjectMap::ComputeEmptySubobjectSizes() {
1880b57cec5SDimitry Andric // Check the bases.
1890b57cec5SDimitry Andric for (const CXXBaseSpecifier &Base : Class->bases()) {
1900b57cec5SDimitry Andric const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
1910b57cec5SDimitry Andric
1920b57cec5SDimitry Andric CharUnits EmptySize;
1930b57cec5SDimitry Andric const ASTRecordLayout &Layout = Context.getASTRecordLayout(BaseDecl);
1940b57cec5SDimitry Andric if (BaseDecl->isEmpty()) {
1950b57cec5SDimitry Andric // If the class decl is empty, get its size.
1960b57cec5SDimitry Andric EmptySize = Layout.getSize();
1970b57cec5SDimitry Andric } else {
1980b57cec5SDimitry Andric // Otherwise, we get the largest empty subobject for the decl.
1990b57cec5SDimitry Andric EmptySize = Layout.getSizeOfLargestEmptySubobject();
2000b57cec5SDimitry Andric }
2010b57cec5SDimitry Andric
2020b57cec5SDimitry Andric if (EmptySize > SizeOfLargestEmptySubobject)
2030b57cec5SDimitry Andric SizeOfLargestEmptySubobject = EmptySize;
2040b57cec5SDimitry Andric }
2050b57cec5SDimitry Andric
2060b57cec5SDimitry Andric // Check the fields.
2070b57cec5SDimitry Andric for (const FieldDecl *FD : Class->fields()) {
2080b57cec5SDimitry Andric const RecordType *RT =
2090b57cec5SDimitry Andric Context.getBaseElementType(FD->getType())->getAs<RecordType>();
2100b57cec5SDimitry Andric
2110b57cec5SDimitry Andric // We only care about record types.
2120b57cec5SDimitry Andric if (!RT)
2130b57cec5SDimitry Andric continue;
2140b57cec5SDimitry Andric
2150b57cec5SDimitry Andric CharUnits EmptySize;
2160b57cec5SDimitry Andric const CXXRecordDecl *MemberDecl = RT->getAsCXXRecordDecl();
2170b57cec5SDimitry Andric const ASTRecordLayout &Layout = Context.getASTRecordLayout(MemberDecl);
2180b57cec5SDimitry Andric if (MemberDecl->isEmpty()) {
2190b57cec5SDimitry Andric // If the class decl is empty, get its size.
2200b57cec5SDimitry Andric EmptySize = Layout.getSize();
2210b57cec5SDimitry Andric } else {
2220b57cec5SDimitry Andric // Otherwise, we get the largest empty subobject for the decl.
2230b57cec5SDimitry Andric EmptySize = Layout.getSizeOfLargestEmptySubobject();
2240b57cec5SDimitry Andric }
2250b57cec5SDimitry Andric
2260b57cec5SDimitry Andric if (EmptySize > SizeOfLargestEmptySubobject)
2270b57cec5SDimitry Andric SizeOfLargestEmptySubobject = EmptySize;
2280b57cec5SDimitry Andric }
2290b57cec5SDimitry Andric }
2300b57cec5SDimitry Andric
2310b57cec5SDimitry Andric bool
CanPlaceSubobjectAtOffset(const CXXRecordDecl * RD,CharUnits Offset) const2320b57cec5SDimitry Andric EmptySubobjectMap::CanPlaceSubobjectAtOffset(const CXXRecordDecl *RD,
2330b57cec5SDimitry Andric CharUnits Offset) const {
2340b57cec5SDimitry Andric // We only need to check empty bases.
2350b57cec5SDimitry Andric if (!RD->isEmpty())
2360b57cec5SDimitry Andric return true;
2370b57cec5SDimitry Andric
2380b57cec5SDimitry Andric EmptyClassOffsetsMapTy::const_iterator I = EmptyClassOffsets.find(Offset);
2390b57cec5SDimitry Andric if (I == EmptyClassOffsets.end())
2400b57cec5SDimitry Andric return true;
2410b57cec5SDimitry Andric
2420b57cec5SDimitry Andric const ClassVectorTy &Classes = I->second;
243349cc55cSDimitry Andric if (!llvm::is_contained(Classes, RD))
2440b57cec5SDimitry Andric return true;
2450b57cec5SDimitry Andric
2460b57cec5SDimitry Andric // There is already an empty class of the same type at this offset.
2470b57cec5SDimitry Andric return false;
2480b57cec5SDimitry Andric }
2490b57cec5SDimitry Andric
AddSubobjectAtOffset(const CXXRecordDecl * RD,CharUnits Offset)2500b57cec5SDimitry Andric void EmptySubobjectMap::AddSubobjectAtOffset(const CXXRecordDecl *RD,
2510b57cec5SDimitry Andric CharUnits Offset) {
2520b57cec5SDimitry Andric // We only care about empty bases.
2530b57cec5SDimitry Andric if (!RD->isEmpty())
2540b57cec5SDimitry Andric return;
2550b57cec5SDimitry Andric
2560b57cec5SDimitry Andric // If we have empty structures inside a union, we can assign both
2570b57cec5SDimitry Andric // the same offset. Just avoid pushing them twice in the list.
2580b57cec5SDimitry Andric ClassVectorTy &Classes = EmptyClassOffsets[Offset];
2590b57cec5SDimitry Andric if (llvm::is_contained(Classes, RD))
2600b57cec5SDimitry Andric return;
2610b57cec5SDimitry Andric
2620b57cec5SDimitry Andric Classes.push_back(RD);
2630b57cec5SDimitry Andric
2640b57cec5SDimitry Andric // Update the empty class offset.
2650b57cec5SDimitry Andric if (Offset > MaxEmptyClassOffset)
2660b57cec5SDimitry Andric MaxEmptyClassOffset = Offset;
2670b57cec5SDimitry Andric }
2680b57cec5SDimitry Andric
2690b57cec5SDimitry Andric bool
CanPlaceBaseSubobjectAtOffset(const BaseSubobjectInfo * Info,CharUnits Offset)2700b57cec5SDimitry Andric EmptySubobjectMap::CanPlaceBaseSubobjectAtOffset(const BaseSubobjectInfo *Info,
2710b57cec5SDimitry Andric CharUnits Offset) {
2720b57cec5SDimitry Andric // We don't have to keep looking past the maximum offset that's known to
2730b57cec5SDimitry Andric // contain an empty class.
2740b57cec5SDimitry Andric if (!AnyEmptySubobjectsBeyondOffset(Offset))
2750b57cec5SDimitry Andric return true;
2760b57cec5SDimitry Andric
2770b57cec5SDimitry Andric if (!CanPlaceSubobjectAtOffset(Info->Class, Offset))
2780b57cec5SDimitry Andric return false;
2790b57cec5SDimitry Andric
2800b57cec5SDimitry Andric // Traverse all non-virtual bases.
2810b57cec5SDimitry Andric const ASTRecordLayout &Layout = Context.getASTRecordLayout(Info->Class);
2820b57cec5SDimitry Andric for (const BaseSubobjectInfo *Base : Info->Bases) {
2830b57cec5SDimitry Andric if (Base->IsVirtual)
2840b57cec5SDimitry Andric continue;
2850b57cec5SDimitry Andric
2860b57cec5SDimitry Andric CharUnits BaseOffset = Offset + Layout.getBaseClassOffset(Base->Class);
2870b57cec5SDimitry Andric
2880b57cec5SDimitry Andric if (!CanPlaceBaseSubobjectAtOffset(Base, BaseOffset))
2890b57cec5SDimitry Andric return false;
2900b57cec5SDimitry Andric }
2910b57cec5SDimitry Andric
2920b57cec5SDimitry Andric if (Info->PrimaryVirtualBaseInfo) {
2930b57cec5SDimitry Andric BaseSubobjectInfo *PrimaryVirtualBaseInfo = Info->PrimaryVirtualBaseInfo;
2940b57cec5SDimitry Andric
2950b57cec5SDimitry Andric if (Info == PrimaryVirtualBaseInfo->Derived) {
2960b57cec5SDimitry Andric if (!CanPlaceBaseSubobjectAtOffset(PrimaryVirtualBaseInfo, Offset))
2970b57cec5SDimitry Andric return false;
2980b57cec5SDimitry Andric }
2990b57cec5SDimitry Andric }
3000b57cec5SDimitry Andric
3010b57cec5SDimitry Andric // Traverse all member variables.
3020b57cec5SDimitry Andric unsigned FieldNo = 0;
3030b57cec5SDimitry Andric for (CXXRecordDecl::field_iterator I = Info->Class->field_begin(),
3040b57cec5SDimitry Andric E = Info->Class->field_end(); I != E; ++I, ++FieldNo) {
3050b57cec5SDimitry Andric if (I->isBitField())
3060b57cec5SDimitry Andric continue;
3070b57cec5SDimitry Andric
3080b57cec5SDimitry Andric CharUnits FieldOffset = Offset + getFieldOffset(Layout, FieldNo);
3090b57cec5SDimitry Andric if (!CanPlaceFieldSubobjectAtOffset(*I, FieldOffset))
3100b57cec5SDimitry Andric return false;
3110b57cec5SDimitry Andric }
3120b57cec5SDimitry Andric
3130b57cec5SDimitry Andric return true;
3140b57cec5SDimitry Andric }
3150b57cec5SDimitry Andric
UpdateEmptyBaseSubobjects(const BaseSubobjectInfo * Info,CharUnits Offset,bool PlacingEmptyBase)3160b57cec5SDimitry Andric void EmptySubobjectMap::UpdateEmptyBaseSubobjects(const BaseSubobjectInfo *Info,
3170b57cec5SDimitry Andric CharUnits Offset,
3180b57cec5SDimitry Andric bool PlacingEmptyBase) {
3190b57cec5SDimitry Andric if (!PlacingEmptyBase && Offset >= SizeOfLargestEmptySubobject) {
3200b57cec5SDimitry Andric // We know that the only empty subobjects that can conflict with empty
3210b57cec5SDimitry Andric // subobject of non-empty bases, are empty bases that can be placed at
3220b57cec5SDimitry Andric // offset zero. Because of this, we only need to keep track of empty base
3230b57cec5SDimitry Andric // subobjects with offsets less than the size of the largest empty
3240b57cec5SDimitry Andric // subobject for our class.
3250b57cec5SDimitry Andric return;
3260b57cec5SDimitry Andric }
3270b57cec5SDimitry Andric
3280b57cec5SDimitry Andric AddSubobjectAtOffset(Info->Class, Offset);
3290b57cec5SDimitry Andric
3300b57cec5SDimitry Andric // Traverse all non-virtual bases.
3310b57cec5SDimitry Andric const ASTRecordLayout &Layout = Context.getASTRecordLayout(Info->Class);
3320b57cec5SDimitry Andric for (const BaseSubobjectInfo *Base : Info->Bases) {
3330b57cec5SDimitry Andric if (Base->IsVirtual)
3340b57cec5SDimitry Andric continue;
3350b57cec5SDimitry Andric
3360b57cec5SDimitry Andric CharUnits BaseOffset = Offset + Layout.getBaseClassOffset(Base->Class);
3370b57cec5SDimitry Andric UpdateEmptyBaseSubobjects(Base, BaseOffset, PlacingEmptyBase);
3380b57cec5SDimitry Andric }
3390b57cec5SDimitry Andric
3400b57cec5SDimitry Andric if (Info->PrimaryVirtualBaseInfo) {
3410b57cec5SDimitry Andric BaseSubobjectInfo *PrimaryVirtualBaseInfo = Info->PrimaryVirtualBaseInfo;
3420b57cec5SDimitry Andric
3430b57cec5SDimitry Andric if (Info == PrimaryVirtualBaseInfo->Derived)
3440b57cec5SDimitry Andric UpdateEmptyBaseSubobjects(PrimaryVirtualBaseInfo, Offset,
3450b57cec5SDimitry Andric PlacingEmptyBase);
3460b57cec5SDimitry Andric }
3470b57cec5SDimitry Andric
3480b57cec5SDimitry Andric // Traverse all member variables.
3490b57cec5SDimitry Andric unsigned FieldNo = 0;
3500b57cec5SDimitry Andric for (CXXRecordDecl::field_iterator I = Info->Class->field_begin(),
3510b57cec5SDimitry Andric E = Info->Class->field_end(); I != E; ++I, ++FieldNo) {
3520b57cec5SDimitry Andric if (I->isBitField())
3530b57cec5SDimitry Andric continue;
3540b57cec5SDimitry Andric
3550b57cec5SDimitry Andric CharUnits FieldOffset = Offset + getFieldOffset(Layout, FieldNo);
3560b57cec5SDimitry Andric UpdateEmptyFieldSubobjects(*I, FieldOffset, PlacingEmptyBase);
3570b57cec5SDimitry Andric }
3580b57cec5SDimitry Andric }
3590b57cec5SDimitry Andric
CanPlaceBaseAtOffset(const BaseSubobjectInfo * Info,CharUnits Offset)3600b57cec5SDimitry Andric bool EmptySubobjectMap::CanPlaceBaseAtOffset(const BaseSubobjectInfo *Info,
3610b57cec5SDimitry Andric CharUnits Offset) {
3620b57cec5SDimitry Andric // If we know this class doesn't have any empty subobjects we don't need to
3630b57cec5SDimitry Andric // bother checking.
3640b57cec5SDimitry Andric if (SizeOfLargestEmptySubobject.isZero())
3650b57cec5SDimitry Andric return true;
3660b57cec5SDimitry Andric
3670b57cec5SDimitry Andric if (!CanPlaceBaseSubobjectAtOffset(Info, Offset))
3680b57cec5SDimitry Andric return false;
3690b57cec5SDimitry Andric
3700b57cec5SDimitry Andric // We are able to place the base at this offset. Make sure to update the
3710b57cec5SDimitry Andric // empty base subobject map.
3720b57cec5SDimitry Andric UpdateEmptyBaseSubobjects(Info, Offset, Info->Class->isEmpty());
3730b57cec5SDimitry Andric return true;
3740b57cec5SDimitry Andric }
3750b57cec5SDimitry Andric
3760b57cec5SDimitry Andric bool
CanPlaceFieldSubobjectAtOffset(const CXXRecordDecl * RD,const CXXRecordDecl * Class,CharUnits Offset) const3770b57cec5SDimitry Andric EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(const CXXRecordDecl *RD,
3780b57cec5SDimitry Andric const CXXRecordDecl *Class,
3790b57cec5SDimitry Andric CharUnits Offset) const {
3800b57cec5SDimitry Andric // We don't have to keep looking past the maximum offset that's known to
3810b57cec5SDimitry Andric // contain an empty class.
3820b57cec5SDimitry Andric if (!AnyEmptySubobjectsBeyondOffset(Offset))
3830b57cec5SDimitry Andric return true;
3840b57cec5SDimitry Andric
3850b57cec5SDimitry Andric if (!CanPlaceSubobjectAtOffset(RD, Offset))
3860b57cec5SDimitry Andric return false;
3870b57cec5SDimitry Andric
3880b57cec5SDimitry Andric const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
3890b57cec5SDimitry Andric
3900b57cec5SDimitry Andric // Traverse all non-virtual bases.
3910b57cec5SDimitry Andric for (const CXXBaseSpecifier &Base : RD->bases()) {
3920b57cec5SDimitry Andric if (Base.isVirtual())
3930b57cec5SDimitry Andric continue;
3940b57cec5SDimitry Andric
3950b57cec5SDimitry Andric const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
3960b57cec5SDimitry Andric
3970b57cec5SDimitry Andric CharUnits BaseOffset = Offset + Layout.getBaseClassOffset(BaseDecl);
3980b57cec5SDimitry Andric if (!CanPlaceFieldSubobjectAtOffset(BaseDecl, Class, BaseOffset))
3990b57cec5SDimitry Andric return false;
4000b57cec5SDimitry Andric }
4010b57cec5SDimitry Andric
4020b57cec5SDimitry Andric if (RD == Class) {
4030b57cec5SDimitry Andric // This is the most derived class, traverse virtual bases as well.
4040b57cec5SDimitry Andric for (const CXXBaseSpecifier &Base : RD->vbases()) {
4050b57cec5SDimitry Andric const CXXRecordDecl *VBaseDecl = Base.getType()->getAsCXXRecordDecl();
4060b57cec5SDimitry Andric
4070b57cec5SDimitry Andric CharUnits VBaseOffset = Offset + Layout.getVBaseClassOffset(VBaseDecl);
4080b57cec5SDimitry Andric if (!CanPlaceFieldSubobjectAtOffset(VBaseDecl, Class, VBaseOffset))
4090b57cec5SDimitry Andric return false;
4100b57cec5SDimitry Andric }
4110b57cec5SDimitry Andric }
4120b57cec5SDimitry Andric
4130b57cec5SDimitry Andric // Traverse all member variables.
4140b57cec5SDimitry Andric unsigned FieldNo = 0;
4150b57cec5SDimitry Andric for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
4160b57cec5SDimitry Andric I != E; ++I, ++FieldNo) {
4170b57cec5SDimitry Andric if (I->isBitField())
4180b57cec5SDimitry Andric continue;
4190b57cec5SDimitry Andric
4200b57cec5SDimitry Andric CharUnits FieldOffset = Offset + getFieldOffset(Layout, FieldNo);
4210b57cec5SDimitry Andric
4220b57cec5SDimitry Andric if (!CanPlaceFieldSubobjectAtOffset(*I, FieldOffset))
4230b57cec5SDimitry Andric return false;
4240b57cec5SDimitry Andric }
4250b57cec5SDimitry Andric
4260b57cec5SDimitry Andric return true;
4270b57cec5SDimitry Andric }
4280b57cec5SDimitry Andric
4290b57cec5SDimitry Andric bool
CanPlaceFieldSubobjectAtOffset(const FieldDecl * FD,CharUnits Offset) const4300b57cec5SDimitry Andric EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(const FieldDecl *FD,
4310b57cec5SDimitry Andric CharUnits Offset) const {
4320b57cec5SDimitry Andric // We don't have to keep looking past the maximum offset that's known to
4330b57cec5SDimitry Andric // contain an empty class.
4340b57cec5SDimitry Andric if (!AnyEmptySubobjectsBeyondOffset(Offset))
4350b57cec5SDimitry Andric return true;
4360b57cec5SDimitry Andric
4370b57cec5SDimitry Andric QualType T = FD->getType();
4380b57cec5SDimitry Andric if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
4390b57cec5SDimitry Andric return CanPlaceFieldSubobjectAtOffset(RD, RD, Offset);
4400b57cec5SDimitry Andric
4410b57cec5SDimitry Andric // If we have an array type we need to look at every element.
4420b57cec5SDimitry Andric if (const ConstantArrayType *AT = Context.getAsConstantArrayType(T)) {
4430b57cec5SDimitry Andric QualType ElemTy = Context.getBaseElementType(AT);
4440b57cec5SDimitry Andric const RecordType *RT = ElemTy->getAs<RecordType>();
4450b57cec5SDimitry Andric if (!RT)
4460b57cec5SDimitry Andric return true;
4470b57cec5SDimitry Andric
4480b57cec5SDimitry Andric const CXXRecordDecl *RD = RT->getAsCXXRecordDecl();
4490b57cec5SDimitry Andric const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
4500b57cec5SDimitry Andric
4510b57cec5SDimitry Andric uint64_t NumElements = Context.getConstantArrayElementCount(AT);
4520b57cec5SDimitry Andric CharUnits ElementOffset = Offset;
4530b57cec5SDimitry Andric for (uint64_t I = 0; I != NumElements; ++I) {
4540b57cec5SDimitry Andric // We don't have to keep looking past the maximum offset that's known to
4550b57cec5SDimitry Andric // contain an empty class.
4560b57cec5SDimitry Andric if (!AnyEmptySubobjectsBeyondOffset(ElementOffset))
4570b57cec5SDimitry Andric return true;
4580b57cec5SDimitry Andric
4590b57cec5SDimitry Andric if (!CanPlaceFieldSubobjectAtOffset(RD, RD, ElementOffset))
4600b57cec5SDimitry Andric return false;
4610b57cec5SDimitry Andric
4620b57cec5SDimitry Andric ElementOffset += Layout.getSize();
4630b57cec5SDimitry Andric }
4640b57cec5SDimitry Andric }
4650b57cec5SDimitry Andric
4660b57cec5SDimitry Andric return true;
4670b57cec5SDimitry Andric }
4680b57cec5SDimitry Andric
4690b57cec5SDimitry Andric bool
CanPlaceFieldAtOffset(const FieldDecl * FD,CharUnits Offset)4700b57cec5SDimitry Andric EmptySubobjectMap::CanPlaceFieldAtOffset(const FieldDecl *FD,
4710b57cec5SDimitry Andric CharUnits Offset) {
4720b57cec5SDimitry Andric if (!CanPlaceFieldSubobjectAtOffset(FD, Offset))
4730b57cec5SDimitry Andric return false;
4740b57cec5SDimitry Andric
4750b57cec5SDimitry Andric // We are able to place the member variable at this offset.
4760b57cec5SDimitry Andric // Make sure to update the empty field subobject map.
4770b57cec5SDimitry Andric UpdateEmptyFieldSubobjects(FD, Offset, FD->hasAttr<NoUniqueAddressAttr>());
4780b57cec5SDimitry Andric return true;
4790b57cec5SDimitry Andric }
4800b57cec5SDimitry Andric
UpdateEmptyFieldSubobjects(const CXXRecordDecl * RD,const CXXRecordDecl * Class,CharUnits Offset,bool PlacingOverlappingField)4810b57cec5SDimitry Andric void EmptySubobjectMap::UpdateEmptyFieldSubobjects(
4820b57cec5SDimitry Andric const CXXRecordDecl *RD, const CXXRecordDecl *Class, CharUnits Offset,
4830b57cec5SDimitry Andric bool PlacingOverlappingField) {
4840b57cec5SDimitry Andric // We know that the only empty subobjects that can conflict with empty
4850b57cec5SDimitry Andric // field subobjects are subobjects of empty bases and potentially-overlapping
4860b57cec5SDimitry Andric // fields that can be placed at offset zero. Because of this, we only need to
4870b57cec5SDimitry Andric // keep track of empty field subobjects with offsets less than the size of
4880b57cec5SDimitry Andric // the largest empty subobject for our class.
4890b57cec5SDimitry Andric //
4900b57cec5SDimitry Andric // (Proof: we will only consider placing a subobject at offset zero or at
4910b57cec5SDimitry Andric // >= the current dsize. The only cases where the earlier subobject can be
4920b57cec5SDimitry Andric // placed beyond the end of dsize is if it's an empty base or a
4930b57cec5SDimitry Andric // potentially-overlapping field.)
4940b57cec5SDimitry Andric if (!PlacingOverlappingField && Offset >= SizeOfLargestEmptySubobject)
4950b57cec5SDimitry Andric return;
4960b57cec5SDimitry Andric
4970b57cec5SDimitry Andric AddSubobjectAtOffset(RD, Offset);
4980b57cec5SDimitry Andric
4990b57cec5SDimitry Andric const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
5000b57cec5SDimitry Andric
5010b57cec5SDimitry Andric // Traverse all non-virtual bases.
5020b57cec5SDimitry Andric for (const CXXBaseSpecifier &Base : RD->bases()) {
5030b57cec5SDimitry Andric if (Base.isVirtual())
5040b57cec5SDimitry Andric continue;
5050b57cec5SDimitry Andric
5060b57cec5SDimitry Andric const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
5070b57cec5SDimitry Andric
5080b57cec5SDimitry Andric CharUnits BaseOffset = Offset + Layout.getBaseClassOffset(BaseDecl);
5090b57cec5SDimitry Andric UpdateEmptyFieldSubobjects(BaseDecl, Class, BaseOffset,
5100b57cec5SDimitry Andric PlacingOverlappingField);
5110b57cec5SDimitry Andric }
5120b57cec5SDimitry Andric
5130b57cec5SDimitry Andric if (RD == Class) {
5140b57cec5SDimitry Andric // This is the most derived class, traverse virtual bases as well.
5150b57cec5SDimitry Andric for (const CXXBaseSpecifier &Base : RD->vbases()) {
5160b57cec5SDimitry Andric const CXXRecordDecl *VBaseDecl = Base.getType()->getAsCXXRecordDecl();
5170b57cec5SDimitry Andric
5180b57cec5SDimitry Andric CharUnits VBaseOffset = Offset + Layout.getVBaseClassOffset(VBaseDecl);
5190b57cec5SDimitry Andric UpdateEmptyFieldSubobjects(VBaseDecl, Class, VBaseOffset,
5200b57cec5SDimitry Andric PlacingOverlappingField);
5210b57cec5SDimitry Andric }
5220b57cec5SDimitry Andric }
5230b57cec5SDimitry Andric
5240b57cec5SDimitry Andric // Traverse all member variables.
5250b57cec5SDimitry Andric unsigned FieldNo = 0;
5260b57cec5SDimitry Andric for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
5270b57cec5SDimitry Andric I != E; ++I, ++FieldNo) {
5280b57cec5SDimitry Andric if (I->isBitField())
5290b57cec5SDimitry Andric continue;
5300b57cec5SDimitry Andric
5310b57cec5SDimitry Andric CharUnits FieldOffset = Offset + getFieldOffset(Layout, FieldNo);
5320b57cec5SDimitry Andric
5330b57cec5SDimitry Andric UpdateEmptyFieldSubobjects(*I, FieldOffset, PlacingOverlappingField);
5340b57cec5SDimitry Andric }
5350b57cec5SDimitry Andric }
5360b57cec5SDimitry Andric
UpdateEmptyFieldSubobjects(const FieldDecl * FD,CharUnits Offset,bool PlacingOverlappingField)5370b57cec5SDimitry Andric void EmptySubobjectMap::UpdateEmptyFieldSubobjects(
5380b57cec5SDimitry Andric const FieldDecl *FD, CharUnits Offset, bool PlacingOverlappingField) {
5390b57cec5SDimitry Andric QualType T = FD->getType();
5400b57cec5SDimitry Andric if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) {
5410b57cec5SDimitry Andric UpdateEmptyFieldSubobjects(RD, RD, Offset, PlacingOverlappingField);
5420b57cec5SDimitry Andric return;
5430b57cec5SDimitry Andric }
5440b57cec5SDimitry Andric
5450b57cec5SDimitry Andric // If we have an array type we need to update every element.
5460b57cec5SDimitry Andric if (const ConstantArrayType *AT = Context.getAsConstantArrayType(T)) {
5470b57cec5SDimitry Andric QualType ElemTy = Context.getBaseElementType(AT);
5480b57cec5SDimitry Andric const RecordType *RT = ElemTy->getAs<RecordType>();
5490b57cec5SDimitry Andric if (!RT)
5500b57cec5SDimitry Andric return;
5510b57cec5SDimitry Andric
5520b57cec5SDimitry Andric const CXXRecordDecl *RD = RT->getAsCXXRecordDecl();
5530b57cec5SDimitry Andric const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
5540b57cec5SDimitry Andric
5550b57cec5SDimitry Andric uint64_t NumElements = Context.getConstantArrayElementCount(AT);
5560b57cec5SDimitry Andric CharUnits ElementOffset = Offset;
5570b57cec5SDimitry Andric
5580b57cec5SDimitry Andric for (uint64_t I = 0; I != NumElements; ++I) {
5590b57cec5SDimitry Andric // We know that the only empty subobjects that can conflict with empty
5600b57cec5SDimitry Andric // field subobjects are subobjects of empty bases that can be placed at
5610b57cec5SDimitry Andric // offset zero. Because of this, we only need to keep track of empty field
5620b57cec5SDimitry Andric // subobjects with offsets less than the size of the largest empty
5630b57cec5SDimitry Andric // subobject for our class.
5640b57cec5SDimitry Andric if (!PlacingOverlappingField &&
5650b57cec5SDimitry Andric ElementOffset >= SizeOfLargestEmptySubobject)
5660b57cec5SDimitry Andric return;
5670b57cec5SDimitry Andric
5680b57cec5SDimitry Andric UpdateEmptyFieldSubobjects(RD, RD, ElementOffset,
5690b57cec5SDimitry Andric PlacingOverlappingField);
5700b57cec5SDimitry Andric ElementOffset += Layout.getSize();
5710b57cec5SDimitry Andric }
5720b57cec5SDimitry Andric }
5730b57cec5SDimitry Andric }
5740b57cec5SDimitry Andric
5750b57cec5SDimitry Andric typedef llvm::SmallPtrSet<const CXXRecordDecl*, 4> ClassSetTy;
5760b57cec5SDimitry Andric
5770b57cec5SDimitry Andric class ItaniumRecordLayoutBuilder {
5780b57cec5SDimitry Andric protected:
5790b57cec5SDimitry Andric // FIXME: Remove this and make the appropriate fields public.
5800b57cec5SDimitry Andric friend class clang::ASTContext;
5810b57cec5SDimitry Andric
5820b57cec5SDimitry Andric const ASTContext &Context;
5830b57cec5SDimitry Andric
5840b57cec5SDimitry Andric EmptySubobjectMap *EmptySubobjects;
5850b57cec5SDimitry Andric
5860b57cec5SDimitry Andric /// Size - The current size of the record layout.
5870b57cec5SDimitry Andric uint64_t Size;
5880b57cec5SDimitry Andric
5890b57cec5SDimitry Andric /// Alignment - The current alignment of the record layout.
5900b57cec5SDimitry Andric CharUnits Alignment;
5910b57cec5SDimitry Andric
592e8d8bef9SDimitry Andric /// PreferredAlignment - The preferred alignment of the record layout.
593e8d8bef9SDimitry Andric CharUnits PreferredAlignment;
594e8d8bef9SDimitry Andric
5950b57cec5SDimitry Andric /// The alignment if attribute packed is not used.
5960b57cec5SDimitry Andric CharUnits UnpackedAlignment;
5970b57cec5SDimitry Andric
5980b57cec5SDimitry Andric /// \brief The maximum of the alignments of top-level members.
5990b57cec5SDimitry Andric CharUnits UnadjustedAlignment;
6000b57cec5SDimitry Andric
6010b57cec5SDimitry Andric SmallVector<uint64_t, 16> FieldOffsets;
6020b57cec5SDimitry Andric
6030b57cec5SDimitry Andric /// Whether the external AST source has provided a layout for this
6040b57cec5SDimitry Andric /// record.
605*0fca6ea1SDimitry Andric LLVM_PREFERRED_TYPE(bool)
6060b57cec5SDimitry Andric unsigned UseExternalLayout : 1;
6070b57cec5SDimitry Andric
6080b57cec5SDimitry Andric /// Whether we need to infer alignment, even when we have an
6090b57cec5SDimitry Andric /// externally-provided layout.
610*0fca6ea1SDimitry Andric LLVM_PREFERRED_TYPE(bool)
6110b57cec5SDimitry Andric unsigned InferAlignment : 1;
6120b57cec5SDimitry Andric
6130b57cec5SDimitry Andric /// Packed - Whether the record is packed or not.
614*0fca6ea1SDimitry Andric LLVM_PREFERRED_TYPE(bool)
6150b57cec5SDimitry Andric unsigned Packed : 1;
6160b57cec5SDimitry Andric
617*0fca6ea1SDimitry Andric LLVM_PREFERRED_TYPE(bool)
6180b57cec5SDimitry Andric unsigned IsUnion : 1;
6190b57cec5SDimitry Andric
620*0fca6ea1SDimitry Andric LLVM_PREFERRED_TYPE(bool)
6210b57cec5SDimitry Andric unsigned IsMac68kAlign : 1;
6220b57cec5SDimitry Andric
623*0fca6ea1SDimitry Andric LLVM_PREFERRED_TYPE(bool)
624e8d8bef9SDimitry Andric unsigned IsNaturalAlign : 1;
625e8d8bef9SDimitry Andric
626*0fca6ea1SDimitry Andric LLVM_PREFERRED_TYPE(bool)
6270b57cec5SDimitry Andric unsigned IsMsStruct : 1;
6280b57cec5SDimitry Andric
6290b57cec5SDimitry Andric /// UnfilledBitsInLastUnit - If the last field laid out was a bitfield,
6300b57cec5SDimitry Andric /// this contains the number of bits in the last unit that can be used for
6310b57cec5SDimitry Andric /// an adjacent bitfield if necessary. The unit in question is usually
6320b57cec5SDimitry Andric /// a byte, but larger units are used if IsMsStruct.
6330b57cec5SDimitry Andric unsigned char UnfilledBitsInLastUnit;
634e8d8bef9SDimitry Andric
635e8d8bef9SDimitry Andric /// LastBitfieldStorageUnitSize - If IsMsStruct, represents the size of the
636e8d8bef9SDimitry Andric /// storage unit of the previous field if it was a bitfield.
637e8d8bef9SDimitry Andric unsigned char LastBitfieldStorageUnitSize;
6380b57cec5SDimitry Andric
6390b57cec5SDimitry Andric /// MaxFieldAlignment - The maximum allowed field alignment. This is set by
6400b57cec5SDimitry Andric /// #pragma pack.
6410b57cec5SDimitry Andric CharUnits MaxFieldAlignment;
6420b57cec5SDimitry Andric
6430b57cec5SDimitry Andric /// DataSize - The data size of the record being laid out.
6440b57cec5SDimitry Andric uint64_t DataSize;
6450b57cec5SDimitry Andric
6460b57cec5SDimitry Andric CharUnits NonVirtualSize;
6470b57cec5SDimitry Andric CharUnits NonVirtualAlignment;
648e8d8bef9SDimitry Andric CharUnits PreferredNVAlignment;
6490b57cec5SDimitry Andric
6500b57cec5SDimitry Andric /// If we've laid out a field but not included its tail padding in Size yet,
6510b57cec5SDimitry Andric /// this is the size up to the end of that field.
6520b57cec5SDimitry Andric CharUnits PaddedFieldSize;
6530b57cec5SDimitry Andric
6540b57cec5SDimitry Andric /// PrimaryBase - the primary base class (if one exists) of the class
6550b57cec5SDimitry Andric /// we're laying out.
6560b57cec5SDimitry Andric const CXXRecordDecl *PrimaryBase;
6570b57cec5SDimitry Andric
6580b57cec5SDimitry Andric /// PrimaryBaseIsVirtual - Whether the primary base of the class we're laying
6590b57cec5SDimitry Andric /// out is virtual.
6600b57cec5SDimitry Andric bool PrimaryBaseIsVirtual;
6610b57cec5SDimitry Andric
6620b57cec5SDimitry Andric /// HasOwnVFPtr - Whether the class provides its own vtable/vftbl
6630b57cec5SDimitry Andric /// pointer, as opposed to inheriting one from a primary base class.
6640b57cec5SDimitry Andric bool HasOwnVFPtr;
6650b57cec5SDimitry Andric
6660b57cec5SDimitry Andric /// the flag of field offset changing due to packed attribute.
6670b57cec5SDimitry Andric bool HasPackedField;
6680b57cec5SDimitry Andric
669e8d8bef9SDimitry Andric /// HandledFirstNonOverlappingEmptyField - An auxiliary field used for AIX.
670e8d8bef9SDimitry Andric /// When there are OverlappingEmptyFields existing in the aggregate, the
671e8d8bef9SDimitry Andric /// flag shows if the following first non-empty or empty-but-non-overlapping
672e8d8bef9SDimitry Andric /// field has been handled, if any.
673e8d8bef9SDimitry Andric bool HandledFirstNonOverlappingEmptyField;
674e8d8bef9SDimitry Andric
6750b57cec5SDimitry Andric typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
6760b57cec5SDimitry Andric
6770b57cec5SDimitry Andric /// Bases - base classes and their offsets in the record.
6780b57cec5SDimitry Andric BaseOffsetsMapTy Bases;
6790b57cec5SDimitry Andric
6800b57cec5SDimitry Andric // VBases - virtual base classes and their offsets in the record.
6810b57cec5SDimitry Andric ASTRecordLayout::VBaseOffsetsMapTy VBases;
6820b57cec5SDimitry Andric
6830b57cec5SDimitry Andric /// IndirectPrimaryBases - Virtual base classes, direct or indirect, that are
6840b57cec5SDimitry Andric /// primary base classes for some other direct or indirect base class.
6850b57cec5SDimitry Andric CXXIndirectPrimaryBaseSet IndirectPrimaryBases;
6860b57cec5SDimitry Andric
6870b57cec5SDimitry Andric /// FirstNearlyEmptyVBase - The first nearly empty virtual base class in
6880b57cec5SDimitry Andric /// inheritance graph order. Used for determining the primary base class.
6890b57cec5SDimitry Andric const CXXRecordDecl *FirstNearlyEmptyVBase;
6900b57cec5SDimitry Andric
6910b57cec5SDimitry Andric /// VisitedVirtualBases - A set of all the visited virtual bases, used to
6920b57cec5SDimitry Andric /// avoid visiting virtual bases more than once.
6930b57cec5SDimitry Andric llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBases;
6940b57cec5SDimitry Andric
6950b57cec5SDimitry Andric /// Valid if UseExternalLayout is true.
6960b57cec5SDimitry Andric ExternalLayout External;
6970b57cec5SDimitry Andric
ItaniumRecordLayoutBuilder(const ASTContext & Context,EmptySubobjectMap * EmptySubobjects)6980b57cec5SDimitry Andric ItaniumRecordLayoutBuilder(const ASTContext &Context,
6990b57cec5SDimitry Andric EmptySubobjectMap *EmptySubobjects)
7000b57cec5SDimitry Andric : Context(Context), EmptySubobjects(EmptySubobjects), Size(0),
701e8d8bef9SDimitry Andric Alignment(CharUnits::One()), PreferredAlignment(CharUnits::One()),
702e8d8bef9SDimitry Andric UnpackedAlignment(CharUnits::One()),
703e8d8bef9SDimitry Andric UnadjustedAlignment(CharUnits::One()), UseExternalLayout(false),
704e8d8bef9SDimitry Andric InferAlignment(false), Packed(false), IsUnion(false),
705e8d8bef9SDimitry Andric IsMac68kAlign(false),
706e8d8bef9SDimitry Andric IsNaturalAlign(!Context.getTargetInfo().getTriple().isOSAIX()),
707e8d8bef9SDimitry Andric IsMsStruct(false), UnfilledBitsInLastUnit(0),
708e8d8bef9SDimitry Andric LastBitfieldStorageUnitSize(0), MaxFieldAlignment(CharUnits::Zero()),
709e8d8bef9SDimitry Andric DataSize(0), NonVirtualSize(CharUnits::Zero()),
7100b57cec5SDimitry Andric NonVirtualAlignment(CharUnits::One()),
711e8d8bef9SDimitry Andric PreferredNVAlignment(CharUnits::One()),
7120b57cec5SDimitry Andric PaddedFieldSize(CharUnits::Zero()), PrimaryBase(nullptr),
713e8d8bef9SDimitry Andric PrimaryBaseIsVirtual(false), HasOwnVFPtr(false), HasPackedField(false),
714e8d8bef9SDimitry Andric HandledFirstNonOverlappingEmptyField(false),
715e8d8bef9SDimitry Andric FirstNearlyEmptyVBase(nullptr) {}
7160b57cec5SDimitry Andric
7170b57cec5SDimitry Andric void Layout(const RecordDecl *D);
7180b57cec5SDimitry Andric void Layout(const CXXRecordDecl *D);
7190b57cec5SDimitry Andric void Layout(const ObjCInterfaceDecl *D);
7200b57cec5SDimitry Andric
7210b57cec5SDimitry Andric void LayoutFields(const RecordDecl *D);
7220b57cec5SDimitry Andric void LayoutField(const FieldDecl *D, bool InsertExtraPadding);
723e8d8bef9SDimitry Andric void LayoutWideBitField(uint64_t FieldSize, uint64_t StorageUnitSize,
7240b57cec5SDimitry Andric bool FieldPacked, const FieldDecl *D);
7250b57cec5SDimitry Andric void LayoutBitField(const FieldDecl *D);
7260b57cec5SDimitry Andric
getCXXABI() const7270b57cec5SDimitry Andric TargetCXXABI getCXXABI() const {
7280b57cec5SDimitry Andric return Context.getTargetInfo().getCXXABI();
7290b57cec5SDimitry Andric }
7300b57cec5SDimitry Andric
7310b57cec5SDimitry Andric /// BaseSubobjectInfoAllocator - Allocator for BaseSubobjectInfo objects.
7320b57cec5SDimitry Andric llvm::SpecificBumpPtrAllocator<BaseSubobjectInfo> BaseSubobjectInfoAllocator;
7330b57cec5SDimitry Andric
7340b57cec5SDimitry Andric typedef llvm::DenseMap<const CXXRecordDecl *, BaseSubobjectInfo *>
7350b57cec5SDimitry Andric BaseSubobjectInfoMapTy;
7360b57cec5SDimitry Andric
7370b57cec5SDimitry Andric /// VirtualBaseInfo - Map from all the (direct or indirect) virtual bases
7380b57cec5SDimitry Andric /// of the class we're laying out to their base subobject info.
7390b57cec5SDimitry Andric BaseSubobjectInfoMapTy VirtualBaseInfo;
7400b57cec5SDimitry Andric
7410b57cec5SDimitry Andric /// NonVirtualBaseInfo - Map from all the direct non-virtual bases of the
7420b57cec5SDimitry Andric /// class we're laying out to their base subobject info.
7430b57cec5SDimitry Andric BaseSubobjectInfoMapTy NonVirtualBaseInfo;
7440b57cec5SDimitry Andric
7450b57cec5SDimitry Andric /// ComputeBaseSubobjectInfo - Compute the base subobject information for the
7460b57cec5SDimitry Andric /// bases of the given class.
7470b57cec5SDimitry Andric void ComputeBaseSubobjectInfo(const CXXRecordDecl *RD);
7480b57cec5SDimitry Andric
7490b57cec5SDimitry Andric /// ComputeBaseSubobjectInfo - Compute the base subobject information for a
7500b57cec5SDimitry Andric /// single class and all of its base classes.
7510b57cec5SDimitry Andric BaseSubobjectInfo *ComputeBaseSubobjectInfo(const CXXRecordDecl *RD,
7520b57cec5SDimitry Andric bool IsVirtual,
7530b57cec5SDimitry Andric BaseSubobjectInfo *Derived);
7540b57cec5SDimitry Andric
7550b57cec5SDimitry Andric /// DeterminePrimaryBase - Determine the primary base of the given class.
7560b57cec5SDimitry Andric void DeterminePrimaryBase(const CXXRecordDecl *RD);
7570b57cec5SDimitry Andric
7580b57cec5SDimitry Andric void SelectPrimaryVBase(const CXXRecordDecl *RD);
7590b57cec5SDimitry Andric
7600b57cec5SDimitry Andric void EnsureVTablePointerAlignment(CharUnits UnpackedBaseAlign);
7610b57cec5SDimitry Andric
7620b57cec5SDimitry Andric /// LayoutNonVirtualBases - Determines the primary base class (if any) and
7630b57cec5SDimitry Andric /// lays it out. Will then proceed to lay out all non-virtual base clasess.
7640b57cec5SDimitry Andric void LayoutNonVirtualBases(const CXXRecordDecl *RD);
7650b57cec5SDimitry Andric
7660b57cec5SDimitry Andric /// LayoutNonVirtualBase - Lays out a single non-virtual base.
7670b57cec5SDimitry Andric void LayoutNonVirtualBase(const BaseSubobjectInfo *Base);
7680b57cec5SDimitry Andric
7690b57cec5SDimitry Andric void AddPrimaryVirtualBaseOffsets(const BaseSubobjectInfo *Info,
7700b57cec5SDimitry Andric CharUnits Offset);
7710b57cec5SDimitry Andric
7720b57cec5SDimitry Andric /// LayoutVirtualBases - Lays out all the virtual bases.
7730b57cec5SDimitry Andric void LayoutVirtualBases(const CXXRecordDecl *RD,
7740b57cec5SDimitry Andric const CXXRecordDecl *MostDerivedClass);
7750b57cec5SDimitry Andric
7760b57cec5SDimitry Andric /// LayoutVirtualBase - Lays out a single virtual base.
7770b57cec5SDimitry Andric void LayoutVirtualBase(const BaseSubobjectInfo *Base);
7780b57cec5SDimitry Andric
7790b57cec5SDimitry Andric /// LayoutBase - Will lay out a base and return the offset where it was
7800b57cec5SDimitry Andric /// placed, in chars.
7810b57cec5SDimitry Andric CharUnits LayoutBase(const BaseSubobjectInfo *Base);
7820b57cec5SDimitry Andric
7830b57cec5SDimitry Andric /// InitializeLayout - Initialize record layout for the given record decl.
7840b57cec5SDimitry Andric void InitializeLayout(const Decl *D);
7850b57cec5SDimitry Andric
7860b57cec5SDimitry Andric /// FinishLayout - Finalize record layout. Adjust record size based on the
7870b57cec5SDimitry Andric /// alignment.
7880b57cec5SDimitry Andric void FinishLayout(const NamedDecl *D);
7890b57cec5SDimitry Andric
790e8d8bef9SDimitry Andric void UpdateAlignment(CharUnits NewAlignment, CharUnits UnpackedNewAlignment,
791e8d8bef9SDimitry Andric CharUnits PreferredAlignment);
UpdateAlignment(CharUnits NewAlignment,CharUnits UnpackedNewAlignment)792e8d8bef9SDimitry Andric void UpdateAlignment(CharUnits NewAlignment, CharUnits UnpackedNewAlignment) {
793e8d8bef9SDimitry Andric UpdateAlignment(NewAlignment, UnpackedNewAlignment, NewAlignment);
794e8d8bef9SDimitry Andric }
UpdateAlignment(CharUnits NewAlignment)7950b57cec5SDimitry Andric void UpdateAlignment(CharUnits NewAlignment) {
796e8d8bef9SDimitry Andric UpdateAlignment(NewAlignment, NewAlignment, NewAlignment);
7970b57cec5SDimitry Andric }
7980b57cec5SDimitry Andric
7990b57cec5SDimitry Andric /// Retrieve the externally-supplied field offset for the given
8000b57cec5SDimitry Andric /// field.
8010b57cec5SDimitry Andric ///
8020b57cec5SDimitry Andric /// \param Field The field whose offset is being queried.
8030b57cec5SDimitry Andric /// \param ComputedOffset The offset that we've computed for this field.
8040b57cec5SDimitry Andric uint64_t updateExternalFieldOffset(const FieldDecl *Field,
8050b57cec5SDimitry Andric uint64_t ComputedOffset);
8060b57cec5SDimitry Andric
8070b57cec5SDimitry Andric void CheckFieldPadding(uint64_t Offset, uint64_t UnpaddedOffset,
8080b57cec5SDimitry Andric uint64_t UnpackedOffset, unsigned UnpackedAlign,
8090b57cec5SDimitry Andric bool isPacked, const FieldDecl *D);
8100b57cec5SDimitry Andric
8110b57cec5SDimitry Andric DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID);
8120b57cec5SDimitry Andric
getSize() const8130b57cec5SDimitry Andric CharUnits getSize() const {
8140b57cec5SDimitry Andric assert(Size % Context.getCharWidth() == 0);
8150b57cec5SDimitry Andric return Context.toCharUnitsFromBits(Size);
8160b57cec5SDimitry Andric }
getSizeInBits() const8170b57cec5SDimitry Andric uint64_t getSizeInBits() const { return Size; }
8180b57cec5SDimitry Andric
setSize(CharUnits NewSize)8190b57cec5SDimitry Andric void setSize(CharUnits NewSize) { Size = Context.toBits(NewSize); }
setSize(uint64_t NewSize)8200b57cec5SDimitry Andric void setSize(uint64_t NewSize) { Size = NewSize; }
8210b57cec5SDimitry Andric
getAligment() const8220b57cec5SDimitry Andric CharUnits getAligment() const { return Alignment; }
8230b57cec5SDimitry Andric
getDataSize() const8240b57cec5SDimitry Andric CharUnits getDataSize() const {
8250b57cec5SDimitry Andric assert(DataSize % Context.getCharWidth() == 0);
8260b57cec5SDimitry Andric return Context.toCharUnitsFromBits(DataSize);
8270b57cec5SDimitry Andric }
getDataSizeInBits() const8280b57cec5SDimitry Andric uint64_t getDataSizeInBits() const { return DataSize; }
8290b57cec5SDimitry Andric
setDataSize(CharUnits NewSize)8300b57cec5SDimitry Andric void setDataSize(CharUnits NewSize) { DataSize = Context.toBits(NewSize); }
setDataSize(uint64_t NewSize)8310b57cec5SDimitry Andric void setDataSize(uint64_t NewSize) { DataSize = NewSize; }
8320b57cec5SDimitry Andric
8330b57cec5SDimitry Andric ItaniumRecordLayoutBuilder(const ItaniumRecordLayoutBuilder &) = delete;
8340b57cec5SDimitry Andric void operator=(const ItaniumRecordLayoutBuilder &) = delete;
8350b57cec5SDimitry Andric };
8360b57cec5SDimitry Andric } // end anonymous namespace
8370b57cec5SDimitry Andric
SelectPrimaryVBase(const CXXRecordDecl * RD)8380b57cec5SDimitry Andric void ItaniumRecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD) {
8390b57cec5SDimitry Andric for (const auto &I : RD->bases()) {
8400b57cec5SDimitry Andric assert(!I.getType()->isDependentType() &&
8410b57cec5SDimitry Andric "Cannot layout class with dependent bases.");
8420b57cec5SDimitry Andric
8430b57cec5SDimitry Andric const CXXRecordDecl *Base = I.getType()->getAsCXXRecordDecl();
8440b57cec5SDimitry Andric
8450b57cec5SDimitry Andric // Check if this is a nearly empty virtual base.
8460b57cec5SDimitry Andric if (I.isVirtual() && Context.isNearlyEmpty(Base)) {
8470b57cec5SDimitry Andric // If it's not an indirect primary base, then we've found our primary
8480b57cec5SDimitry Andric // base.
8490b57cec5SDimitry Andric if (!IndirectPrimaryBases.count(Base)) {
8500b57cec5SDimitry Andric PrimaryBase = Base;
8510b57cec5SDimitry Andric PrimaryBaseIsVirtual = true;
8520b57cec5SDimitry Andric return;
8530b57cec5SDimitry Andric }
8540b57cec5SDimitry Andric
8550b57cec5SDimitry Andric // Is this the first nearly empty virtual base?
8560b57cec5SDimitry Andric if (!FirstNearlyEmptyVBase)
8570b57cec5SDimitry Andric FirstNearlyEmptyVBase = Base;
8580b57cec5SDimitry Andric }
8590b57cec5SDimitry Andric
8600b57cec5SDimitry Andric SelectPrimaryVBase(Base);
8610b57cec5SDimitry Andric if (PrimaryBase)
8620b57cec5SDimitry Andric return;
8630b57cec5SDimitry Andric }
8640b57cec5SDimitry Andric }
8650b57cec5SDimitry Andric
8660b57cec5SDimitry Andric /// DeterminePrimaryBase - Determine the primary base of the given class.
DeterminePrimaryBase(const CXXRecordDecl * RD)8670b57cec5SDimitry Andric void ItaniumRecordLayoutBuilder::DeterminePrimaryBase(const CXXRecordDecl *RD) {
8680b57cec5SDimitry Andric // If the class isn't dynamic, it won't have a primary base.
8690b57cec5SDimitry Andric if (!RD->isDynamicClass())
8700b57cec5SDimitry Andric return;
8710b57cec5SDimitry Andric
8720b57cec5SDimitry Andric // Compute all the primary virtual bases for all of our direct and
8730b57cec5SDimitry Andric // indirect bases, and record all their primary virtual base classes.
8740b57cec5SDimitry Andric RD->getIndirectPrimaryBases(IndirectPrimaryBases);
8750b57cec5SDimitry Andric
8760b57cec5SDimitry Andric // If the record has a dynamic base class, attempt to choose a primary base
8770b57cec5SDimitry Andric // class. It is the first (in direct base class order) non-virtual dynamic
8780b57cec5SDimitry Andric // base class, if one exists.
8790b57cec5SDimitry Andric for (const auto &I : RD->bases()) {
8800b57cec5SDimitry Andric // Ignore virtual bases.
8810b57cec5SDimitry Andric if (I.isVirtual())
8820b57cec5SDimitry Andric continue;
8830b57cec5SDimitry Andric
8840b57cec5SDimitry Andric const CXXRecordDecl *Base = I.getType()->getAsCXXRecordDecl();
8850b57cec5SDimitry Andric
8860b57cec5SDimitry Andric if (Base->isDynamicClass()) {
8870b57cec5SDimitry Andric // We found it.
8880b57cec5SDimitry Andric PrimaryBase = Base;
8890b57cec5SDimitry Andric PrimaryBaseIsVirtual = false;
8900b57cec5SDimitry Andric return;
8910b57cec5SDimitry Andric }
8920b57cec5SDimitry Andric }
8930b57cec5SDimitry Andric
8940b57cec5SDimitry Andric // Under the Itanium ABI, if there is no non-virtual primary base class,
8950b57cec5SDimitry Andric // try to compute the primary virtual base. The primary virtual base is
8960b57cec5SDimitry Andric // the first nearly empty virtual base that is not an indirect primary
8970b57cec5SDimitry Andric // virtual base class, if one exists.
8980b57cec5SDimitry Andric if (RD->getNumVBases() != 0) {
8990b57cec5SDimitry Andric SelectPrimaryVBase(RD);
9000b57cec5SDimitry Andric if (PrimaryBase)
9010b57cec5SDimitry Andric return;
9020b57cec5SDimitry Andric }
9030b57cec5SDimitry Andric
9040b57cec5SDimitry Andric // Otherwise, it is the first indirect primary base class, if one exists.
9050b57cec5SDimitry Andric if (FirstNearlyEmptyVBase) {
9060b57cec5SDimitry Andric PrimaryBase = FirstNearlyEmptyVBase;
9070b57cec5SDimitry Andric PrimaryBaseIsVirtual = true;
9080b57cec5SDimitry Andric return;
9090b57cec5SDimitry Andric }
9100b57cec5SDimitry Andric
9110b57cec5SDimitry Andric assert(!PrimaryBase && "Should not get here with a primary base!");
9120b57cec5SDimitry Andric }
9130b57cec5SDimitry Andric
ComputeBaseSubobjectInfo(const CXXRecordDecl * RD,bool IsVirtual,BaseSubobjectInfo * Derived)9140b57cec5SDimitry Andric BaseSubobjectInfo *ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo(
9150b57cec5SDimitry Andric const CXXRecordDecl *RD, bool IsVirtual, BaseSubobjectInfo *Derived) {
9160b57cec5SDimitry Andric BaseSubobjectInfo *Info;
9170b57cec5SDimitry Andric
9180b57cec5SDimitry Andric if (IsVirtual) {
9190b57cec5SDimitry Andric // Check if we already have info about this virtual base.
9200b57cec5SDimitry Andric BaseSubobjectInfo *&InfoSlot = VirtualBaseInfo[RD];
9210b57cec5SDimitry Andric if (InfoSlot) {
9220b57cec5SDimitry Andric assert(InfoSlot->Class == RD && "Wrong class for virtual base info!");
9230b57cec5SDimitry Andric return InfoSlot;
9240b57cec5SDimitry Andric }
9250b57cec5SDimitry Andric
9260b57cec5SDimitry Andric // We don't, create it.
9270b57cec5SDimitry Andric InfoSlot = new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo;
9280b57cec5SDimitry Andric Info = InfoSlot;
9290b57cec5SDimitry Andric } else {
9300b57cec5SDimitry Andric Info = new (BaseSubobjectInfoAllocator.Allocate()) BaseSubobjectInfo;
9310b57cec5SDimitry Andric }
9320b57cec5SDimitry Andric
9330b57cec5SDimitry Andric Info->Class = RD;
9340b57cec5SDimitry Andric Info->IsVirtual = IsVirtual;
9350b57cec5SDimitry Andric Info->Derived = nullptr;
9360b57cec5SDimitry Andric Info->PrimaryVirtualBaseInfo = nullptr;
9370b57cec5SDimitry Andric
9380b57cec5SDimitry Andric const CXXRecordDecl *PrimaryVirtualBase = nullptr;
9390b57cec5SDimitry Andric BaseSubobjectInfo *PrimaryVirtualBaseInfo = nullptr;
9400b57cec5SDimitry Andric
9410b57cec5SDimitry Andric // Check if this base has a primary virtual base.
9420b57cec5SDimitry Andric if (RD->getNumVBases()) {
9430b57cec5SDimitry Andric const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
9440b57cec5SDimitry Andric if (Layout.isPrimaryBaseVirtual()) {
9450b57cec5SDimitry Andric // This base does have a primary virtual base.
9460b57cec5SDimitry Andric PrimaryVirtualBase = Layout.getPrimaryBase();
9470b57cec5SDimitry Andric assert(PrimaryVirtualBase && "Didn't have a primary virtual base!");
9480b57cec5SDimitry Andric
9490b57cec5SDimitry Andric // Now check if we have base subobject info about this primary base.
9500b57cec5SDimitry Andric PrimaryVirtualBaseInfo = VirtualBaseInfo.lookup(PrimaryVirtualBase);
9510b57cec5SDimitry Andric
9520b57cec5SDimitry Andric if (PrimaryVirtualBaseInfo) {
9530b57cec5SDimitry Andric if (PrimaryVirtualBaseInfo->Derived) {
9540b57cec5SDimitry Andric // We did have info about this primary base, and it turns out that it
9550b57cec5SDimitry Andric // has already been claimed as a primary virtual base for another
9560b57cec5SDimitry Andric // base.
9570b57cec5SDimitry Andric PrimaryVirtualBase = nullptr;
9580b57cec5SDimitry Andric } else {
9590b57cec5SDimitry Andric // We can claim this base as our primary base.
9600b57cec5SDimitry Andric Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;
9610b57cec5SDimitry Andric PrimaryVirtualBaseInfo->Derived = Info;
9620b57cec5SDimitry Andric }
9630b57cec5SDimitry Andric }
9640b57cec5SDimitry Andric }
9650b57cec5SDimitry Andric }
9660b57cec5SDimitry Andric
9670b57cec5SDimitry Andric // Now go through all direct bases.
9680b57cec5SDimitry Andric for (const auto &I : RD->bases()) {
9690b57cec5SDimitry Andric bool IsVirtual = I.isVirtual();
9700b57cec5SDimitry Andric
9710b57cec5SDimitry Andric const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
9720b57cec5SDimitry Andric
9730b57cec5SDimitry Andric Info->Bases.push_back(ComputeBaseSubobjectInfo(BaseDecl, IsVirtual, Info));
9740b57cec5SDimitry Andric }
9750b57cec5SDimitry Andric
9760b57cec5SDimitry Andric if (PrimaryVirtualBase && !PrimaryVirtualBaseInfo) {
9770b57cec5SDimitry Andric // Traversing the bases must have created the base info for our primary
9780b57cec5SDimitry Andric // virtual base.
9790b57cec5SDimitry Andric PrimaryVirtualBaseInfo = VirtualBaseInfo.lookup(PrimaryVirtualBase);
9800b57cec5SDimitry Andric assert(PrimaryVirtualBaseInfo &&
9810b57cec5SDimitry Andric "Did not create a primary virtual base!");
9820b57cec5SDimitry Andric
9830b57cec5SDimitry Andric // Claim the primary virtual base as our primary virtual base.
9840b57cec5SDimitry Andric Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo;
9850b57cec5SDimitry Andric PrimaryVirtualBaseInfo->Derived = Info;
9860b57cec5SDimitry Andric }
9870b57cec5SDimitry Andric
9880b57cec5SDimitry Andric return Info;
9890b57cec5SDimitry Andric }
9900b57cec5SDimitry Andric
ComputeBaseSubobjectInfo(const CXXRecordDecl * RD)9910b57cec5SDimitry Andric void ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo(
9920b57cec5SDimitry Andric const CXXRecordDecl *RD) {
9930b57cec5SDimitry Andric for (const auto &I : RD->bases()) {
9940b57cec5SDimitry Andric bool IsVirtual = I.isVirtual();
9950b57cec5SDimitry Andric
9960b57cec5SDimitry Andric const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
9970b57cec5SDimitry Andric
9980b57cec5SDimitry Andric // Compute the base subobject info for this base.
9990b57cec5SDimitry Andric BaseSubobjectInfo *Info = ComputeBaseSubobjectInfo(BaseDecl, IsVirtual,
10000b57cec5SDimitry Andric nullptr);
10010b57cec5SDimitry Andric
10020b57cec5SDimitry Andric if (IsVirtual) {
10030b57cec5SDimitry Andric // ComputeBaseInfo has already added this base for us.
10040b57cec5SDimitry Andric assert(VirtualBaseInfo.count(BaseDecl) &&
10050b57cec5SDimitry Andric "Did not add virtual base!");
10060b57cec5SDimitry Andric } else {
10070b57cec5SDimitry Andric // Add the base info to the map of non-virtual bases.
10080b57cec5SDimitry Andric assert(!NonVirtualBaseInfo.count(BaseDecl) &&
10090b57cec5SDimitry Andric "Non-virtual base already exists!");
10100b57cec5SDimitry Andric NonVirtualBaseInfo.insert(std::make_pair(BaseDecl, Info));
10110b57cec5SDimitry Andric }
10120b57cec5SDimitry Andric }
10130b57cec5SDimitry Andric }
10140b57cec5SDimitry Andric
EnsureVTablePointerAlignment(CharUnits UnpackedBaseAlign)10150b57cec5SDimitry Andric void ItaniumRecordLayoutBuilder::EnsureVTablePointerAlignment(
10160b57cec5SDimitry Andric CharUnits UnpackedBaseAlign) {
10170b57cec5SDimitry Andric CharUnits BaseAlign = Packed ? CharUnits::One() : UnpackedBaseAlign;
10180b57cec5SDimitry Andric
10190b57cec5SDimitry Andric // The maximum field alignment overrides base align.
10200b57cec5SDimitry Andric if (!MaxFieldAlignment.isZero()) {
10210b57cec5SDimitry Andric BaseAlign = std::min(BaseAlign, MaxFieldAlignment);
10220b57cec5SDimitry Andric UnpackedBaseAlign = std::min(UnpackedBaseAlign, MaxFieldAlignment);
10230b57cec5SDimitry Andric }
10240b57cec5SDimitry Andric
10250b57cec5SDimitry Andric // Round up the current record size to pointer alignment.
10260b57cec5SDimitry Andric setSize(getSize().alignTo(BaseAlign));
10270b57cec5SDimitry Andric
10280b57cec5SDimitry Andric // Update the alignment.
1029e8d8bef9SDimitry Andric UpdateAlignment(BaseAlign, UnpackedBaseAlign, BaseAlign);
10300b57cec5SDimitry Andric }
10310b57cec5SDimitry Andric
LayoutNonVirtualBases(const CXXRecordDecl * RD)10320b57cec5SDimitry Andric void ItaniumRecordLayoutBuilder::LayoutNonVirtualBases(
10330b57cec5SDimitry Andric const CXXRecordDecl *RD) {
10340b57cec5SDimitry Andric // Then, determine the primary base class.
10350b57cec5SDimitry Andric DeterminePrimaryBase(RD);
10360b57cec5SDimitry Andric
10370b57cec5SDimitry Andric // Compute base subobject info.
10380b57cec5SDimitry Andric ComputeBaseSubobjectInfo(RD);
10390b57cec5SDimitry Andric
10400b57cec5SDimitry Andric // If we have a primary base class, lay it out.
10410b57cec5SDimitry Andric if (PrimaryBase) {
10420b57cec5SDimitry Andric if (PrimaryBaseIsVirtual) {
10430b57cec5SDimitry Andric // If the primary virtual base was a primary virtual base of some other
10440b57cec5SDimitry Andric // base class we'll have to steal it.
10450b57cec5SDimitry Andric BaseSubobjectInfo *PrimaryBaseInfo = VirtualBaseInfo.lookup(PrimaryBase);
10460b57cec5SDimitry Andric PrimaryBaseInfo->Derived = nullptr;
10470b57cec5SDimitry Andric
10480b57cec5SDimitry Andric // We have a virtual primary base, insert it as an indirect primary base.
10490b57cec5SDimitry Andric IndirectPrimaryBases.insert(PrimaryBase);
10500b57cec5SDimitry Andric
10510b57cec5SDimitry Andric assert(!VisitedVirtualBases.count(PrimaryBase) &&
10520b57cec5SDimitry Andric "vbase already visited!");
10530b57cec5SDimitry Andric VisitedVirtualBases.insert(PrimaryBase);
10540b57cec5SDimitry Andric
10550b57cec5SDimitry Andric LayoutVirtualBase(PrimaryBaseInfo);
10560b57cec5SDimitry Andric } else {
10570b57cec5SDimitry Andric BaseSubobjectInfo *PrimaryBaseInfo =
10580b57cec5SDimitry Andric NonVirtualBaseInfo.lookup(PrimaryBase);
10590b57cec5SDimitry Andric assert(PrimaryBaseInfo &&
10600b57cec5SDimitry Andric "Did not find base info for non-virtual primary base!");
10610b57cec5SDimitry Andric
10620b57cec5SDimitry Andric LayoutNonVirtualBase(PrimaryBaseInfo);
10630b57cec5SDimitry Andric }
10640b57cec5SDimitry Andric
10650b57cec5SDimitry Andric // If this class needs a vtable/vf-table and didn't get one from a
10660b57cec5SDimitry Andric // primary base, add it in now.
10670b57cec5SDimitry Andric } else if (RD->isDynamicClass()) {
10680b57cec5SDimitry Andric assert(DataSize == 0 && "Vtable pointer must be at offset zero!");
1069bdd1243dSDimitry Andric CharUnits PtrWidth = Context.toCharUnitsFromBits(
1070bdd1243dSDimitry Andric Context.getTargetInfo().getPointerWidth(LangAS::Default));
1071bdd1243dSDimitry Andric CharUnits PtrAlign = Context.toCharUnitsFromBits(
1072bdd1243dSDimitry Andric Context.getTargetInfo().getPointerAlign(LangAS::Default));
10730b57cec5SDimitry Andric EnsureVTablePointerAlignment(PtrAlign);
10740b57cec5SDimitry Andric HasOwnVFPtr = true;
1075e8d8bef9SDimitry Andric
1076e8d8bef9SDimitry Andric assert(!IsUnion && "Unions cannot be dynamic classes.");
1077e8d8bef9SDimitry Andric HandledFirstNonOverlappingEmptyField = true;
1078e8d8bef9SDimitry Andric
10790b57cec5SDimitry Andric setSize(getSize() + PtrWidth);
10800b57cec5SDimitry Andric setDataSize(getSize());
10810b57cec5SDimitry Andric }
10820b57cec5SDimitry Andric
10830b57cec5SDimitry Andric // Now lay out the non-virtual bases.
10840b57cec5SDimitry Andric for (const auto &I : RD->bases()) {
10850b57cec5SDimitry Andric
10860b57cec5SDimitry Andric // Ignore virtual bases.
10870b57cec5SDimitry Andric if (I.isVirtual())
10880b57cec5SDimitry Andric continue;
10890b57cec5SDimitry Andric
10900b57cec5SDimitry Andric const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl();
10910b57cec5SDimitry Andric
10920b57cec5SDimitry Andric // Skip the primary base, because we've already laid it out. The
10930b57cec5SDimitry Andric // !PrimaryBaseIsVirtual check is required because we might have a
10940b57cec5SDimitry Andric // non-virtual base of the same type as a primary virtual base.
10950b57cec5SDimitry Andric if (BaseDecl == PrimaryBase && !PrimaryBaseIsVirtual)
10960b57cec5SDimitry Andric continue;
10970b57cec5SDimitry Andric
10980b57cec5SDimitry Andric // Lay out the base.
10990b57cec5SDimitry Andric BaseSubobjectInfo *BaseInfo = NonVirtualBaseInfo.lookup(BaseDecl);
11000b57cec5SDimitry Andric assert(BaseInfo && "Did not find base info for non-virtual base!");
11010b57cec5SDimitry Andric
11020b57cec5SDimitry Andric LayoutNonVirtualBase(BaseInfo);
11030b57cec5SDimitry Andric }
11040b57cec5SDimitry Andric }
11050b57cec5SDimitry Andric
LayoutNonVirtualBase(const BaseSubobjectInfo * Base)11060b57cec5SDimitry Andric void ItaniumRecordLayoutBuilder::LayoutNonVirtualBase(
11070b57cec5SDimitry Andric const BaseSubobjectInfo *Base) {
11080b57cec5SDimitry Andric // Layout the base.
11090b57cec5SDimitry Andric CharUnits Offset = LayoutBase(Base);
11100b57cec5SDimitry Andric
11110b57cec5SDimitry Andric // Add its base class offset.
11120b57cec5SDimitry Andric assert(!Bases.count(Base->Class) && "base offset already exists!");
11130b57cec5SDimitry Andric Bases.insert(std::make_pair(Base->Class, Offset));
11140b57cec5SDimitry Andric
11150b57cec5SDimitry Andric AddPrimaryVirtualBaseOffsets(Base, Offset);
11160b57cec5SDimitry Andric }
11170b57cec5SDimitry Andric
AddPrimaryVirtualBaseOffsets(const BaseSubobjectInfo * Info,CharUnits Offset)11180b57cec5SDimitry Andric void ItaniumRecordLayoutBuilder::AddPrimaryVirtualBaseOffsets(
11190b57cec5SDimitry Andric const BaseSubobjectInfo *Info, CharUnits Offset) {
11200b57cec5SDimitry Andric // This base isn't interesting, it has no virtual bases.
11210b57cec5SDimitry Andric if (!Info->Class->getNumVBases())
11220b57cec5SDimitry Andric return;
11230b57cec5SDimitry Andric
11240b57cec5SDimitry Andric // First, check if we have a virtual primary base to add offsets for.
11250b57cec5SDimitry Andric if (Info->PrimaryVirtualBaseInfo) {
11260b57cec5SDimitry Andric assert(Info->PrimaryVirtualBaseInfo->IsVirtual &&
11270b57cec5SDimitry Andric "Primary virtual base is not virtual!");
11280b57cec5SDimitry Andric if (Info->PrimaryVirtualBaseInfo->Derived == Info) {
11290b57cec5SDimitry Andric // Add the offset.
11300b57cec5SDimitry Andric assert(!VBases.count(Info->PrimaryVirtualBaseInfo->Class) &&
11310b57cec5SDimitry Andric "primary vbase offset already exists!");
11320b57cec5SDimitry Andric VBases.insert(std::make_pair(Info->PrimaryVirtualBaseInfo->Class,
11330b57cec5SDimitry Andric ASTRecordLayout::VBaseInfo(Offset, false)));
11340b57cec5SDimitry Andric
11350b57cec5SDimitry Andric // Traverse the primary virtual base.
11360b57cec5SDimitry Andric AddPrimaryVirtualBaseOffsets(Info->PrimaryVirtualBaseInfo, Offset);
11370b57cec5SDimitry Andric }
11380b57cec5SDimitry Andric }
11390b57cec5SDimitry Andric
11400b57cec5SDimitry Andric // Now go through all direct non-virtual bases.
11410b57cec5SDimitry Andric const ASTRecordLayout &Layout = Context.getASTRecordLayout(Info->Class);
11420b57cec5SDimitry Andric for (const BaseSubobjectInfo *Base : Info->Bases) {
11430b57cec5SDimitry Andric if (Base->IsVirtual)
11440b57cec5SDimitry Andric continue;
11450b57cec5SDimitry Andric
11460b57cec5SDimitry Andric CharUnits BaseOffset = Offset + Layout.getBaseClassOffset(Base->Class);
11470b57cec5SDimitry Andric AddPrimaryVirtualBaseOffsets(Base, BaseOffset);
11480b57cec5SDimitry Andric }
11490b57cec5SDimitry Andric }
11500b57cec5SDimitry Andric
LayoutVirtualBases(const CXXRecordDecl * RD,const CXXRecordDecl * MostDerivedClass)11510b57cec5SDimitry Andric void ItaniumRecordLayoutBuilder::LayoutVirtualBases(
11520b57cec5SDimitry Andric const CXXRecordDecl *RD, const CXXRecordDecl *MostDerivedClass) {
11530b57cec5SDimitry Andric const CXXRecordDecl *PrimaryBase;
11540b57cec5SDimitry Andric bool PrimaryBaseIsVirtual;
11550b57cec5SDimitry Andric
11560b57cec5SDimitry Andric if (MostDerivedClass == RD) {
11570b57cec5SDimitry Andric PrimaryBase = this->PrimaryBase;
11580b57cec5SDimitry Andric PrimaryBaseIsVirtual = this->PrimaryBaseIsVirtual;
11590b57cec5SDimitry Andric } else {
11600b57cec5SDimitry Andric const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
11610b57cec5SDimitry Andric PrimaryBase = Layout.getPrimaryBase();
11620b57cec5SDimitry Andric PrimaryBaseIsVirtual = Layout.isPrimaryBaseVirtual();
11630b57cec5SDimitry Andric }
11640b57cec5SDimitry Andric
11650b57cec5SDimitry Andric for (const CXXBaseSpecifier &Base : RD->bases()) {
11660b57cec5SDimitry Andric assert(!Base.getType()->isDependentType() &&
11670b57cec5SDimitry Andric "Cannot layout class with dependent bases.");
11680b57cec5SDimitry Andric
11690b57cec5SDimitry Andric const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
11700b57cec5SDimitry Andric
11710b57cec5SDimitry Andric if (Base.isVirtual()) {
11720b57cec5SDimitry Andric if (PrimaryBase != BaseDecl || !PrimaryBaseIsVirtual) {
11730b57cec5SDimitry Andric bool IndirectPrimaryBase = IndirectPrimaryBases.count(BaseDecl);
11740b57cec5SDimitry Andric
11750b57cec5SDimitry Andric // Only lay out the virtual base if it's not an indirect primary base.
11760b57cec5SDimitry Andric if (!IndirectPrimaryBase) {
11770b57cec5SDimitry Andric // Only visit virtual bases once.
11780b57cec5SDimitry Andric if (!VisitedVirtualBases.insert(BaseDecl).second)
11790b57cec5SDimitry Andric continue;
11800b57cec5SDimitry Andric
11810b57cec5SDimitry Andric const BaseSubobjectInfo *BaseInfo = VirtualBaseInfo.lookup(BaseDecl);
11820b57cec5SDimitry Andric assert(BaseInfo && "Did not find virtual base info!");
11830b57cec5SDimitry Andric LayoutVirtualBase(BaseInfo);
11840b57cec5SDimitry Andric }
11850b57cec5SDimitry Andric }
11860b57cec5SDimitry Andric }
11870b57cec5SDimitry Andric
11880b57cec5SDimitry Andric if (!BaseDecl->getNumVBases()) {
11890b57cec5SDimitry Andric // This base isn't interesting since it doesn't have any virtual bases.
11900b57cec5SDimitry Andric continue;
11910b57cec5SDimitry Andric }
11920b57cec5SDimitry Andric
11930b57cec5SDimitry Andric LayoutVirtualBases(BaseDecl, MostDerivedClass);
11940b57cec5SDimitry Andric }
11950b57cec5SDimitry Andric }
11960b57cec5SDimitry Andric
LayoutVirtualBase(const BaseSubobjectInfo * Base)11970b57cec5SDimitry Andric void ItaniumRecordLayoutBuilder::LayoutVirtualBase(
11980b57cec5SDimitry Andric const BaseSubobjectInfo *Base) {
11990b57cec5SDimitry Andric assert(!Base->Derived && "Trying to lay out a primary virtual base!");
12000b57cec5SDimitry Andric
12010b57cec5SDimitry Andric // Layout the base.
12020b57cec5SDimitry Andric CharUnits Offset = LayoutBase(Base);
12030b57cec5SDimitry Andric
12040b57cec5SDimitry Andric // Add its base class offset.
12050b57cec5SDimitry Andric assert(!VBases.count(Base->Class) && "vbase offset already exists!");
12060b57cec5SDimitry Andric VBases.insert(std::make_pair(Base->Class,
12070b57cec5SDimitry Andric ASTRecordLayout::VBaseInfo(Offset, false)));
12080b57cec5SDimitry Andric
12090b57cec5SDimitry Andric AddPrimaryVirtualBaseOffsets(Base, Offset);
12100b57cec5SDimitry Andric }
12110b57cec5SDimitry Andric
12120b57cec5SDimitry Andric CharUnits
LayoutBase(const BaseSubobjectInfo * Base)12130b57cec5SDimitry Andric ItaniumRecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) {
1214e8d8bef9SDimitry Andric assert(!IsUnion && "Unions cannot have base classes.");
1215e8d8bef9SDimitry Andric
12160b57cec5SDimitry Andric const ASTRecordLayout &Layout = Context.getASTRecordLayout(Base->Class);
12170b57cec5SDimitry Andric CharUnits Offset;
12180b57cec5SDimitry Andric
12190b57cec5SDimitry Andric // Query the external layout to see if it provides an offset.
12200b57cec5SDimitry Andric bool HasExternalLayout = false;
12210b57cec5SDimitry Andric if (UseExternalLayout) {
12220b57cec5SDimitry Andric if (Base->IsVirtual)
12230b57cec5SDimitry Andric HasExternalLayout = External.getExternalVBaseOffset(Base->Class, Offset);
12245ffd83dbSDimitry Andric else
12255ffd83dbSDimitry Andric HasExternalLayout = External.getExternalNVBaseOffset(Base->Class, Offset);
12260b57cec5SDimitry Andric }
12270b57cec5SDimitry Andric
1228e8d8bef9SDimitry Andric auto getBaseOrPreferredBaseAlignFromUnpacked = [&](CharUnits UnpackedAlign) {
12290b57cec5SDimitry Andric // Clang <= 6 incorrectly applied the 'packed' attribute to base classes.
12300b57cec5SDimitry Andric // Per GCC's documentation, it only applies to non-static data members.
1231e8d8bef9SDimitry Andric return (Packed && ((Context.getLangOpts().getClangABICompat() <=
12320b57cec5SDimitry Andric LangOptions::ClangABI::Ver6) ||
123381ad6265SDimitry Andric Context.getTargetInfo().getTriple().isPS() ||
1234e8d8bef9SDimitry Andric Context.getTargetInfo().getTriple().isOSAIX()))
12350b57cec5SDimitry Andric ? CharUnits::One()
1236e8d8bef9SDimitry Andric : UnpackedAlign;
1237e8d8bef9SDimitry Andric };
12380b57cec5SDimitry Andric
1239e8d8bef9SDimitry Andric CharUnits UnpackedBaseAlign = Layout.getNonVirtualAlignment();
1240e8d8bef9SDimitry Andric CharUnits UnpackedPreferredBaseAlign = Layout.getPreferredNVAlignment();
1241e8d8bef9SDimitry Andric CharUnits BaseAlign =
1242e8d8bef9SDimitry Andric getBaseOrPreferredBaseAlignFromUnpacked(UnpackedBaseAlign);
1243e8d8bef9SDimitry Andric CharUnits PreferredBaseAlign =
1244e8d8bef9SDimitry Andric getBaseOrPreferredBaseAlignFromUnpacked(UnpackedPreferredBaseAlign);
1245e8d8bef9SDimitry Andric
1246e8d8bef9SDimitry Andric const bool DefaultsToAIXPowerAlignment =
1247e8d8bef9SDimitry Andric Context.getTargetInfo().defaultsToAIXPowerAlignment();
1248e8d8bef9SDimitry Andric if (DefaultsToAIXPowerAlignment) {
1249e8d8bef9SDimitry Andric // AIX `power` alignment does not apply the preferred alignment for
1250e8d8bef9SDimitry Andric // non-union classes if the source of the alignment (the current base in
1251e8d8bef9SDimitry Andric // this context) follows introduction of the first subobject with
1252e8d8bef9SDimitry Andric // exclusively allocated space or zero-extent array.
1253e8d8bef9SDimitry Andric if (!Base->Class->isEmpty() && !HandledFirstNonOverlappingEmptyField) {
1254e8d8bef9SDimitry Andric // By handling a base class that is not empty, we're handling the
1255e8d8bef9SDimitry Andric // "first (inherited) member".
1256e8d8bef9SDimitry Andric HandledFirstNonOverlappingEmptyField = true;
1257e8d8bef9SDimitry Andric } else if (!IsNaturalAlign) {
1258e8d8bef9SDimitry Andric UnpackedPreferredBaseAlign = UnpackedBaseAlign;
1259e8d8bef9SDimitry Andric PreferredBaseAlign = BaseAlign;
1260e8d8bef9SDimitry Andric }
1261e8d8bef9SDimitry Andric }
1262e8d8bef9SDimitry Andric
1263e8d8bef9SDimitry Andric CharUnits UnpackedAlignTo = !DefaultsToAIXPowerAlignment
1264e8d8bef9SDimitry Andric ? UnpackedBaseAlign
1265e8d8bef9SDimitry Andric : UnpackedPreferredBaseAlign;
12660b57cec5SDimitry Andric // If we have an empty base class, try to place it at offset 0.
12670b57cec5SDimitry Andric if (Base->Class->isEmpty() &&
12680b57cec5SDimitry Andric (!HasExternalLayout || Offset == CharUnits::Zero()) &&
12690b57cec5SDimitry Andric EmptySubobjects->CanPlaceBaseAtOffset(Base, CharUnits::Zero())) {
12700b57cec5SDimitry Andric setSize(std::max(getSize(), Layout.getSize()));
127181ad6265SDimitry Andric // On PS4/PS5, don't update the alignment, to preserve compatibility.
127281ad6265SDimitry Andric if (!Context.getTargetInfo().getTriple().isPS())
1273e8d8bef9SDimitry Andric UpdateAlignment(BaseAlign, UnpackedAlignTo, PreferredBaseAlign);
12740b57cec5SDimitry Andric
12750b57cec5SDimitry Andric return CharUnits::Zero();
12760b57cec5SDimitry Andric }
12770b57cec5SDimitry Andric
1278e8d8bef9SDimitry Andric // The maximum field alignment overrides the base align/(AIX-only) preferred
1279e8d8bef9SDimitry Andric // base align.
12800b57cec5SDimitry Andric if (!MaxFieldAlignment.isZero()) {
12810b57cec5SDimitry Andric BaseAlign = std::min(BaseAlign, MaxFieldAlignment);
1282e8d8bef9SDimitry Andric PreferredBaseAlign = std::min(PreferredBaseAlign, MaxFieldAlignment);
1283e8d8bef9SDimitry Andric UnpackedAlignTo = std::min(UnpackedAlignTo, MaxFieldAlignment);
12840b57cec5SDimitry Andric }
12850b57cec5SDimitry Andric
1286e8d8bef9SDimitry Andric CharUnits AlignTo =
1287e8d8bef9SDimitry Andric !DefaultsToAIXPowerAlignment ? BaseAlign : PreferredBaseAlign;
12880b57cec5SDimitry Andric if (!HasExternalLayout) {
12890b57cec5SDimitry Andric // Round up the current record size to the base's alignment boundary.
1290e8d8bef9SDimitry Andric Offset = getDataSize().alignTo(AlignTo);
12910b57cec5SDimitry Andric
12920b57cec5SDimitry Andric // Try to place the base.
12930b57cec5SDimitry Andric while (!EmptySubobjects->CanPlaceBaseAtOffset(Base, Offset))
1294e8d8bef9SDimitry Andric Offset += AlignTo;
12950b57cec5SDimitry Andric } else {
12960b57cec5SDimitry Andric bool Allowed = EmptySubobjects->CanPlaceBaseAtOffset(Base, Offset);
12970b57cec5SDimitry Andric (void)Allowed;
12980b57cec5SDimitry Andric assert(Allowed && "Base subobject externally placed at overlapping offset");
12990b57cec5SDimitry Andric
1300e8d8bef9SDimitry Andric if (InferAlignment && Offset < getDataSize().alignTo(AlignTo)) {
13010b57cec5SDimitry Andric // The externally-supplied base offset is before the base offset we
13020b57cec5SDimitry Andric // computed. Assume that the structure is packed.
13030b57cec5SDimitry Andric Alignment = CharUnits::One();
13040b57cec5SDimitry Andric InferAlignment = false;
13050b57cec5SDimitry Andric }
13060b57cec5SDimitry Andric }
13070b57cec5SDimitry Andric
13080b57cec5SDimitry Andric if (!Base->Class->isEmpty()) {
13090b57cec5SDimitry Andric // Update the data size.
13100b57cec5SDimitry Andric setDataSize(Offset + Layout.getNonVirtualSize());
13110b57cec5SDimitry Andric
13120b57cec5SDimitry Andric setSize(std::max(getSize(), getDataSize()));
13130b57cec5SDimitry Andric } else
13140b57cec5SDimitry Andric setSize(std::max(getSize(), Offset + Layout.getSize()));
13150b57cec5SDimitry Andric
13160b57cec5SDimitry Andric // Remember max struct/class alignment.
1317e8d8bef9SDimitry Andric UpdateAlignment(BaseAlign, UnpackedAlignTo, PreferredBaseAlign);
13180b57cec5SDimitry Andric
13190b57cec5SDimitry Andric return Offset;
13200b57cec5SDimitry Andric }
13210b57cec5SDimitry Andric
InitializeLayout(const Decl * D)13220b57cec5SDimitry Andric void ItaniumRecordLayoutBuilder::InitializeLayout(const Decl *D) {
13230b57cec5SDimitry Andric if (const RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
13240b57cec5SDimitry Andric IsUnion = RD->isUnion();
13250b57cec5SDimitry Andric IsMsStruct = RD->isMsStruct(Context);
13260b57cec5SDimitry Andric }
13270b57cec5SDimitry Andric
13280b57cec5SDimitry Andric Packed = D->hasAttr<PackedAttr>();
13290b57cec5SDimitry Andric
13300b57cec5SDimitry Andric // Honor the default struct packing maximum alignment flag.
13310b57cec5SDimitry Andric if (unsigned DefaultMaxFieldAlignment = Context.getLangOpts().PackStruct) {
13320b57cec5SDimitry Andric MaxFieldAlignment = CharUnits::fromQuantity(DefaultMaxFieldAlignment);
13330b57cec5SDimitry Andric }
13340b57cec5SDimitry Andric
13350b57cec5SDimitry Andric // mac68k alignment supersedes maximum field alignment and attribute aligned,
13360b57cec5SDimitry Andric // and forces all structures to have 2-byte alignment. The IBM docs on it
13370b57cec5SDimitry Andric // allude to additional (more complicated) semantics, especially with regard
13380b57cec5SDimitry Andric // to bit-fields, but gcc appears not to follow that.
13390b57cec5SDimitry Andric if (D->hasAttr<AlignMac68kAttr>()) {
1340e8d8bef9SDimitry Andric assert(
1341e8d8bef9SDimitry Andric !D->hasAttr<AlignNaturalAttr>() &&
1342e8d8bef9SDimitry Andric "Having both mac68k and natural alignment on a decl is not allowed.");
13430b57cec5SDimitry Andric IsMac68kAlign = true;
13440b57cec5SDimitry Andric MaxFieldAlignment = CharUnits::fromQuantity(2);
13450b57cec5SDimitry Andric Alignment = CharUnits::fromQuantity(2);
1346e8d8bef9SDimitry Andric PreferredAlignment = CharUnits::fromQuantity(2);
13470b57cec5SDimitry Andric } else {
1348e8d8bef9SDimitry Andric if (D->hasAttr<AlignNaturalAttr>())
1349e8d8bef9SDimitry Andric IsNaturalAlign = true;
1350e8d8bef9SDimitry Andric
13510b57cec5SDimitry Andric if (const MaxFieldAlignmentAttr *MFAA = D->getAttr<MaxFieldAlignmentAttr>())
13520b57cec5SDimitry Andric MaxFieldAlignment = Context.toCharUnitsFromBits(MFAA->getAlignment());
13530b57cec5SDimitry Andric
13540b57cec5SDimitry Andric if (unsigned MaxAlign = D->getMaxAlignment())
13550b57cec5SDimitry Andric UpdateAlignment(Context.toCharUnitsFromBits(MaxAlign));
13560b57cec5SDimitry Andric }
13570b57cec5SDimitry Andric
1358e8d8bef9SDimitry Andric HandledFirstNonOverlappingEmptyField =
1359e8d8bef9SDimitry Andric !Context.getTargetInfo().defaultsToAIXPowerAlignment() || IsNaturalAlign;
1360e8d8bef9SDimitry Andric
13610b57cec5SDimitry Andric // If there is an external AST source, ask it for the various offsets.
13620b57cec5SDimitry Andric if (const RecordDecl *RD = dyn_cast<RecordDecl>(D))
13630b57cec5SDimitry Andric if (ExternalASTSource *Source = Context.getExternalSource()) {
13640b57cec5SDimitry Andric UseExternalLayout = Source->layoutRecordType(
13650b57cec5SDimitry Andric RD, External.Size, External.Align, External.FieldOffsets,
13660b57cec5SDimitry Andric External.BaseOffsets, External.VirtualBaseOffsets);
13670b57cec5SDimitry Andric
13680b57cec5SDimitry Andric // Update based on external alignment.
13690b57cec5SDimitry Andric if (UseExternalLayout) {
13700b57cec5SDimitry Andric if (External.Align > 0) {
13710b57cec5SDimitry Andric Alignment = Context.toCharUnitsFromBits(External.Align);
1372e8d8bef9SDimitry Andric PreferredAlignment = Context.toCharUnitsFromBits(External.Align);
13730b57cec5SDimitry Andric } else {
13740b57cec5SDimitry Andric // The external source didn't have alignment information; infer it.
13750b57cec5SDimitry Andric InferAlignment = true;
13760b57cec5SDimitry Andric }
13770b57cec5SDimitry Andric }
13780b57cec5SDimitry Andric }
13790b57cec5SDimitry Andric }
13800b57cec5SDimitry Andric
Layout(const RecordDecl * D)13810b57cec5SDimitry Andric void ItaniumRecordLayoutBuilder::Layout(const RecordDecl *D) {
13820b57cec5SDimitry Andric InitializeLayout(D);
13830b57cec5SDimitry Andric LayoutFields(D);
13840b57cec5SDimitry Andric
13850b57cec5SDimitry Andric // Finally, round the size of the total struct up to the alignment of the
13860b57cec5SDimitry Andric // struct itself.
13870b57cec5SDimitry Andric FinishLayout(D);
13880b57cec5SDimitry Andric }
13890b57cec5SDimitry Andric
Layout(const CXXRecordDecl * RD)13900b57cec5SDimitry Andric void ItaniumRecordLayoutBuilder::Layout(const CXXRecordDecl *RD) {
13910b57cec5SDimitry Andric InitializeLayout(RD);
13920b57cec5SDimitry Andric
13930b57cec5SDimitry Andric // Lay out the vtable and the non-virtual bases.
13940b57cec5SDimitry Andric LayoutNonVirtualBases(RD);
13950b57cec5SDimitry Andric
13960b57cec5SDimitry Andric LayoutFields(RD);
13970b57cec5SDimitry Andric
13980b57cec5SDimitry Andric NonVirtualSize = Context.toCharUnitsFromBits(
13990b57cec5SDimitry Andric llvm::alignTo(getSizeInBits(), Context.getTargetInfo().getCharAlign()));
14000b57cec5SDimitry Andric NonVirtualAlignment = Alignment;
1401e8d8bef9SDimitry Andric PreferredNVAlignment = PreferredAlignment;
14020b57cec5SDimitry Andric
14030b57cec5SDimitry Andric // Lay out the virtual bases and add the primary virtual base offsets.
14040b57cec5SDimitry Andric LayoutVirtualBases(RD, RD);
14050b57cec5SDimitry Andric
14060b57cec5SDimitry Andric // Finally, round the size of the total struct up to the alignment
14070b57cec5SDimitry Andric // of the struct itself.
14080b57cec5SDimitry Andric FinishLayout(RD);
14090b57cec5SDimitry Andric
14100b57cec5SDimitry Andric #ifndef NDEBUG
14110b57cec5SDimitry Andric // Check that we have base offsets for all bases.
14120b57cec5SDimitry Andric for (const CXXBaseSpecifier &Base : RD->bases()) {
14130b57cec5SDimitry Andric if (Base.isVirtual())
14140b57cec5SDimitry Andric continue;
14150b57cec5SDimitry Andric
14160b57cec5SDimitry Andric const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
14170b57cec5SDimitry Andric
14180b57cec5SDimitry Andric assert(Bases.count(BaseDecl) && "Did not find base offset!");
14190b57cec5SDimitry Andric }
14200b57cec5SDimitry Andric
14210b57cec5SDimitry Andric // And all virtual bases.
14220b57cec5SDimitry Andric for (const CXXBaseSpecifier &Base : RD->vbases()) {
14230b57cec5SDimitry Andric const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
14240b57cec5SDimitry Andric
14250b57cec5SDimitry Andric assert(VBases.count(BaseDecl) && "Did not find base offset!");
14260b57cec5SDimitry Andric }
14270b57cec5SDimitry Andric #endif
14280b57cec5SDimitry Andric }
14290b57cec5SDimitry Andric
Layout(const ObjCInterfaceDecl * D)14300b57cec5SDimitry Andric void ItaniumRecordLayoutBuilder::Layout(const ObjCInterfaceDecl *D) {
14310b57cec5SDimitry Andric if (ObjCInterfaceDecl *SD = D->getSuperClass()) {
14320b57cec5SDimitry Andric const ASTRecordLayout &SL = Context.getASTObjCInterfaceLayout(SD);
14330b57cec5SDimitry Andric
14340b57cec5SDimitry Andric UpdateAlignment(SL.getAlignment());
14350b57cec5SDimitry Andric
14360b57cec5SDimitry Andric // We start laying out ivars not at the end of the superclass
14370b57cec5SDimitry Andric // structure, but at the next byte following the last field.
14380b57cec5SDimitry Andric setDataSize(SL.getDataSize());
14390b57cec5SDimitry Andric setSize(getDataSize());
14400b57cec5SDimitry Andric }
14410b57cec5SDimitry Andric
14420b57cec5SDimitry Andric InitializeLayout(D);
14430b57cec5SDimitry Andric // Layout each ivar sequentially.
14440b57cec5SDimitry Andric for (const ObjCIvarDecl *IVD = D->all_declared_ivar_begin(); IVD;
14450b57cec5SDimitry Andric IVD = IVD->getNextIvar())
14460b57cec5SDimitry Andric LayoutField(IVD, false);
14470b57cec5SDimitry Andric
14480b57cec5SDimitry Andric // Finally, round the size of the total struct up to the alignment of the
14490b57cec5SDimitry Andric // struct itself.
14500b57cec5SDimitry Andric FinishLayout(D);
14510b57cec5SDimitry Andric }
14520b57cec5SDimitry Andric
LayoutFields(const RecordDecl * D)14530b57cec5SDimitry Andric void ItaniumRecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
14540b57cec5SDimitry Andric // Layout each field, for now, just sequentially, respecting alignment. In
14550b57cec5SDimitry Andric // the future, this will need to be tweakable by targets.
14560b57cec5SDimitry Andric bool InsertExtraPadding = D->mayInsertExtraPadding(/*EmitRemark=*/true);
14570b57cec5SDimitry Andric bool HasFlexibleArrayMember = D->hasFlexibleArrayMember();
14580b57cec5SDimitry Andric for (auto I = D->field_begin(), End = D->field_end(); I != End; ++I) {
14590b57cec5SDimitry Andric auto Next(I);
14600b57cec5SDimitry Andric ++Next;
14610b57cec5SDimitry Andric LayoutField(*I,
14620b57cec5SDimitry Andric InsertExtraPadding && (Next != End || !HasFlexibleArrayMember));
14630b57cec5SDimitry Andric }
14640b57cec5SDimitry Andric }
14650b57cec5SDimitry Andric
14660b57cec5SDimitry Andric // Rounds the specified size to have it a multiple of the char size.
14670b57cec5SDimitry Andric static uint64_t
roundUpSizeToCharAlignment(uint64_t Size,const ASTContext & Context)14680b57cec5SDimitry Andric roundUpSizeToCharAlignment(uint64_t Size,
14690b57cec5SDimitry Andric const ASTContext &Context) {
14700b57cec5SDimitry Andric uint64_t CharAlignment = Context.getTargetInfo().getCharAlign();
14710b57cec5SDimitry Andric return llvm::alignTo(Size, CharAlignment);
14720b57cec5SDimitry Andric }
14730b57cec5SDimitry Andric
LayoutWideBitField(uint64_t FieldSize,uint64_t StorageUnitSize,bool FieldPacked,const FieldDecl * D)14740b57cec5SDimitry Andric void ItaniumRecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize,
1475e8d8bef9SDimitry Andric uint64_t StorageUnitSize,
14760b57cec5SDimitry Andric bool FieldPacked,
14770b57cec5SDimitry Andric const FieldDecl *D) {
14780b57cec5SDimitry Andric assert(Context.getLangOpts().CPlusPlus &&
14790b57cec5SDimitry Andric "Can only have wide bit-fields in C++!");
14800b57cec5SDimitry Andric
14810b57cec5SDimitry Andric // Itanium C++ ABI 2.4:
14820b57cec5SDimitry Andric // If sizeof(T)*8 < n, let T' be the largest integral POD type with
14830b57cec5SDimitry Andric // sizeof(T')*8 <= n.
14840b57cec5SDimitry Andric
14850b57cec5SDimitry Andric QualType IntegralPODTypes[] = {
14860b57cec5SDimitry Andric Context.UnsignedCharTy, Context.UnsignedShortTy, Context.UnsignedIntTy,
14870b57cec5SDimitry Andric Context.UnsignedLongTy, Context.UnsignedLongLongTy
14880b57cec5SDimitry Andric };
14890b57cec5SDimitry Andric
14900b57cec5SDimitry Andric QualType Type;
14910b57cec5SDimitry Andric for (const QualType &QT : IntegralPODTypes) {
14920b57cec5SDimitry Andric uint64_t Size = Context.getTypeSize(QT);
14930b57cec5SDimitry Andric
14940b57cec5SDimitry Andric if (Size > FieldSize)
14950b57cec5SDimitry Andric break;
14960b57cec5SDimitry Andric
14970b57cec5SDimitry Andric Type = QT;
14980b57cec5SDimitry Andric }
14990b57cec5SDimitry Andric assert(!Type.isNull() && "Did not find a type!");
15000b57cec5SDimitry Andric
15010b57cec5SDimitry Andric CharUnits TypeAlign = Context.getTypeAlignInChars(Type);
15020b57cec5SDimitry Andric
15030b57cec5SDimitry Andric // We're not going to use any of the unfilled bits in the last byte.
15040b57cec5SDimitry Andric UnfilledBitsInLastUnit = 0;
1505e8d8bef9SDimitry Andric LastBitfieldStorageUnitSize = 0;
15060b57cec5SDimitry Andric
15070b57cec5SDimitry Andric uint64_t FieldOffset;
15080b57cec5SDimitry Andric uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;
15090b57cec5SDimitry Andric
15100b57cec5SDimitry Andric if (IsUnion) {
15110b57cec5SDimitry Andric uint64_t RoundedFieldSize = roundUpSizeToCharAlignment(FieldSize,
15120b57cec5SDimitry Andric Context);
15130b57cec5SDimitry Andric setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize));
15140b57cec5SDimitry Andric FieldOffset = 0;
15150b57cec5SDimitry Andric } else {
15160b57cec5SDimitry Andric // The bitfield is allocated starting at the next offset aligned
15170b57cec5SDimitry Andric // appropriately for T', with length n bits.
15180b57cec5SDimitry Andric FieldOffset = llvm::alignTo(getDataSizeInBits(), Context.toBits(TypeAlign));
15190b57cec5SDimitry Andric
15200b57cec5SDimitry Andric uint64_t NewSizeInBits = FieldOffset + FieldSize;
15210b57cec5SDimitry Andric
15220b57cec5SDimitry Andric setDataSize(
15230b57cec5SDimitry Andric llvm::alignTo(NewSizeInBits, Context.getTargetInfo().getCharAlign()));
15240b57cec5SDimitry Andric UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits;
15250b57cec5SDimitry Andric }
15260b57cec5SDimitry Andric
15270b57cec5SDimitry Andric // Place this field at the current location.
15280b57cec5SDimitry Andric FieldOffsets.push_back(FieldOffset);
15290b57cec5SDimitry Andric
15300b57cec5SDimitry Andric CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, FieldOffset,
15310b57cec5SDimitry Andric Context.toBits(TypeAlign), FieldPacked, D);
15320b57cec5SDimitry Andric
15330b57cec5SDimitry Andric // Update the size.
15340b57cec5SDimitry Andric setSize(std::max(getSizeInBits(), getDataSizeInBits()));
15350b57cec5SDimitry Andric
15360b57cec5SDimitry Andric // Remember max struct/class alignment.
15370b57cec5SDimitry Andric UpdateAlignment(TypeAlign);
15380b57cec5SDimitry Andric }
15390b57cec5SDimitry Andric
isAIXLayout(const ASTContext & Context)1540fe6060f1SDimitry Andric static bool isAIXLayout(const ASTContext &Context) {
1541fe6060f1SDimitry Andric return Context.getTargetInfo().getTriple().getOS() == llvm::Triple::AIX;
1542fe6060f1SDimitry Andric }
1543fe6060f1SDimitry Andric
LayoutBitField(const FieldDecl * D)15440b57cec5SDimitry Andric void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
15450b57cec5SDimitry Andric bool FieldPacked = Packed || D->hasAttr<PackedAttr>();
15460b57cec5SDimitry Andric uint64_t FieldSize = D->getBitWidthValue(Context);
15470b57cec5SDimitry Andric TypeInfo FieldInfo = Context.getTypeInfo(D->getType());
1548e8d8bef9SDimitry Andric uint64_t StorageUnitSize = FieldInfo.Width;
15490b57cec5SDimitry Andric unsigned FieldAlign = FieldInfo.Align;
1550349cc55cSDimitry Andric bool AlignIsRequired = FieldInfo.isAlignRequired();
15510b57cec5SDimitry Andric
15520b57cec5SDimitry Andric // UnfilledBitsInLastUnit is the difference between the end of the
15530b57cec5SDimitry Andric // last allocated bitfield (i.e. the first bit offset available for
15540b57cec5SDimitry Andric // bitfields) and the end of the current data size in bits (i.e. the
15550b57cec5SDimitry Andric // first bit offset available for non-bitfields). The current data
15560b57cec5SDimitry Andric // size in bits is always a multiple of the char size; additionally,
15570b57cec5SDimitry Andric // for ms_struct records it's also a multiple of the
1558e8d8bef9SDimitry Andric // LastBitfieldStorageUnitSize (if set).
15590b57cec5SDimitry Andric
15600b57cec5SDimitry Andric // The struct-layout algorithm is dictated by the platform ABI,
15610b57cec5SDimitry Andric // which in principle could use almost any rules it likes. In
15620b57cec5SDimitry Andric // practice, UNIXy targets tend to inherit the algorithm described
15630b57cec5SDimitry Andric // in the System V generic ABI. The basic bitfield layout rule in
15640b57cec5SDimitry Andric // System V is to place bitfields at the next available bit offset
15650b57cec5SDimitry Andric // where the entire bitfield would fit in an aligned storage unit of
15660b57cec5SDimitry Andric // the declared type; it's okay if an earlier or later non-bitfield
15670b57cec5SDimitry Andric // is allocated in the same storage unit. However, some targets
15680b57cec5SDimitry Andric // (those that !useBitFieldTypeAlignment(), e.g. ARM APCS) don't
15690b57cec5SDimitry Andric // require this storage unit to be aligned, and therefore always put
15700b57cec5SDimitry Andric // the bitfield at the next available bit offset.
15710b57cec5SDimitry Andric
15720b57cec5SDimitry Andric // ms_struct basically requests a complete replacement of the
15730b57cec5SDimitry Andric // platform ABI's struct-layout algorithm, with the high-level goal
15740b57cec5SDimitry Andric // of duplicating MSVC's layout. For non-bitfields, this follows
15750b57cec5SDimitry Andric // the standard algorithm. The basic bitfield layout rule is to
15760b57cec5SDimitry Andric // allocate an entire unit of the bitfield's declared type
15770b57cec5SDimitry Andric // (e.g. 'unsigned long'), then parcel it up among successive
15780b57cec5SDimitry Andric // bitfields whose declared types have the same size, making a new
15790b57cec5SDimitry Andric // unit as soon as the last can no longer store the whole value.
15800b57cec5SDimitry Andric // Since it completely replaces the platform ABI's algorithm,
15810b57cec5SDimitry Andric // settings like !useBitFieldTypeAlignment() do not apply.
15820b57cec5SDimitry Andric
15830b57cec5SDimitry Andric // A zero-width bitfield forces the use of a new storage unit for
15840b57cec5SDimitry Andric // later bitfields. In general, this occurs by rounding up the
15850b57cec5SDimitry Andric // current size of the struct as if the algorithm were about to
15860b57cec5SDimitry Andric // place a non-bitfield of the field's formal type. Usually this
15870b57cec5SDimitry Andric // does not change the alignment of the struct itself, but it does
15880b57cec5SDimitry Andric // on some targets (those that useZeroLengthBitfieldAlignment(),
15890b57cec5SDimitry Andric // e.g. ARM). In ms_struct layout, zero-width bitfields are
15900b57cec5SDimitry Andric // ignored unless they follow a non-zero-width bitfield.
15910b57cec5SDimitry Andric
15920b57cec5SDimitry Andric // A field alignment restriction (e.g. from #pragma pack) or
15930b57cec5SDimitry Andric // specification (e.g. from __attribute__((aligned))) changes the
15940b57cec5SDimitry Andric // formal alignment of the field. For System V, this alters the
15950b57cec5SDimitry Andric // required alignment of the notional storage unit that must contain
15960b57cec5SDimitry Andric // the bitfield. For ms_struct, this only affects the placement of
15970b57cec5SDimitry Andric // new storage units. In both cases, the effect of #pragma pack is
15980b57cec5SDimitry Andric // ignored on zero-width bitfields.
15990b57cec5SDimitry Andric
16000b57cec5SDimitry Andric // On System V, a packed field (e.g. from #pragma pack or
16010b57cec5SDimitry Andric // __attribute__((packed))) always uses the next available bit
16020b57cec5SDimitry Andric // offset.
16030b57cec5SDimitry Andric
16040b57cec5SDimitry Andric // In an ms_struct struct, the alignment of a fundamental type is
16050b57cec5SDimitry Andric // always equal to its size. This is necessary in order to mimic
16060b57cec5SDimitry Andric // the i386 alignment rules on targets which might not fully align
16070b57cec5SDimitry Andric // all types (e.g. Darwin PPC32, where alignof(long long) == 4).
16080b57cec5SDimitry Andric
16090b57cec5SDimitry Andric // First, some simple bookkeeping to perform for ms_struct structs.
16100b57cec5SDimitry Andric if (IsMsStruct) {
16110b57cec5SDimitry Andric // The field alignment for integer types is always the size.
1612e8d8bef9SDimitry Andric FieldAlign = StorageUnitSize;
16130b57cec5SDimitry Andric
16140b57cec5SDimitry Andric // If the previous field was not a bitfield, or was a bitfield
16150b57cec5SDimitry Andric // with a different storage unit size, or if this field doesn't fit into
16160b57cec5SDimitry Andric // the current storage unit, we're done with that storage unit.
1617e8d8bef9SDimitry Andric if (LastBitfieldStorageUnitSize != StorageUnitSize ||
16180b57cec5SDimitry Andric UnfilledBitsInLastUnit < FieldSize) {
16190b57cec5SDimitry Andric // Also, ignore zero-length bitfields after non-bitfields.
1620e8d8bef9SDimitry Andric if (!LastBitfieldStorageUnitSize && !FieldSize)
16210b57cec5SDimitry Andric FieldAlign = 1;
16220b57cec5SDimitry Andric
16230b57cec5SDimitry Andric UnfilledBitsInLastUnit = 0;
1624e8d8bef9SDimitry Andric LastBitfieldStorageUnitSize = 0;
16250b57cec5SDimitry Andric }
16260b57cec5SDimitry Andric }
16270b57cec5SDimitry Andric
1628fe6060f1SDimitry Andric if (isAIXLayout(Context)) {
1629fe6060f1SDimitry Andric if (StorageUnitSize < Context.getTypeSize(Context.UnsignedIntTy)) {
1630fe6060f1SDimitry Andric // On AIX, [bool, char, short] bitfields have the same alignment
1631fe6060f1SDimitry Andric // as [unsigned].
1632fe6060f1SDimitry Andric StorageUnitSize = Context.getTypeSize(Context.UnsignedIntTy);
1633fe6060f1SDimitry Andric } else if (StorageUnitSize > Context.getTypeSize(Context.UnsignedIntTy) &&
1634fe6060f1SDimitry Andric Context.getTargetInfo().getTriple().isArch32Bit() &&
1635fe6060f1SDimitry Andric FieldSize <= 32) {
1636fe6060f1SDimitry Andric // Under 32-bit compile mode, the bitcontainer is 32 bits if a single
1637fe6060f1SDimitry Andric // long long bitfield has length no greater than 32 bits.
1638fe6060f1SDimitry Andric StorageUnitSize = 32;
1639fe6060f1SDimitry Andric
1640fe6060f1SDimitry Andric if (!AlignIsRequired)
1641fe6060f1SDimitry Andric FieldAlign = 32;
1642fe6060f1SDimitry Andric }
1643fe6060f1SDimitry Andric
1644fe6060f1SDimitry Andric if (FieldAlign < StorageUnitSize) {
1645fe6060f1SDimitry Andric // The bitfield alignment should always be greater than or equal to
1646fe6060f1SDimitry Andric // bitcontainer size.
1647fe6060f1SDimitry Andric FieldAlign = StorageUnitSize;
1648fe6060f1SDimitry Andric }
1649fe6060f1SDimitry Andric }
1650fe6060f1SDimitry Andric
16510b57cec5SDimitry Andric // If the field is wider than its declared type, it follows
1652fe6060f1SDimitry Andric // different rules in all cases, except on AIX.
1653fe6060f1SDimitry Andric // On AIX, wide bitfield follows the same rules as normal bitfield.
1654fe6060f1SDimitry Andric if (FieldSize > StorageUnitSize && !isAIXLayout(Context)) {
1655e8d8bef9SDimitry Andric LayoutWideBitField(FieldSize, StorageUnitSize, FieldPacked, D);
16560b57cec5SDimitry Andric return;
16570b57cec5SDimitry Andric }
16580b57cec5SDimitry Andric
16590b57cec5SDimitry Andric // Compute the next available bit offset.
16600b57cec5SDimitry Andric uint64_t FieldOffset =
16610b57cec5SDimitry Andric IsUnion ? 0 : (getDataSizeInBits() - UnfilledBitsInLastUnit);
16620b57cec5SDimitry Andric
16630b57cec5SDimitry Andric // Handle targets that don't honor bitfield type alignment.
16640b57cec5SDimitry Andric if (!IsMsStruct && !Context.getTargetInfo().useBitFieldTypeAlignment()) {
16650b57cec5SDimitry Andric // Some such targets do honor it on zero-width bitfields.
16660b57cec5SDimitry Andric if (FieldSize == 0 &&
16670b57cec5SDimitry Andric Context.getTargetInfo().useZeroLengthBitfieldAlignment()) {
1668fe6060f1SDimitry Andric // Some targets don't honor leading zero-width bitfield.
1669fe6060f1SDimitry Andric if (!IsUnion && FieldOffset == 0 &&
1670fe6060f1SDimitry Andric !Context.getTargetInfo().useLeadingZeroLengthBitfield())
1671fe6060f1SDimitry Andric FieldAlign = 1;
1672fe6060f1SDimitry Andric else {
16730b57cec5SDimitry Andric // The alignment to round up to is the max of the field's natural
16740b57cec5SDimitry Andric // alignment and a target-specific fixed value (sometimes zero).
16750b57cec5SDimitry Andric unsigned ZeroLengthBitfieldBoundary =
16760b57cec5SDimitry Andric Context.getTargetInfo().getZeroLengthBitfieldBoundary();
16770b57cec5SDimitry Andric FieldAlign = std::max(FieldAlign, ZeroLengthBitfieldBoundary);
1678fe6060f1SDimitry Andric }
16790b57cec5SDimitry Andric // If that doesn't apply, just ignore the field alignment.
16800b57cec5SDimitry Andric } else {
16810b57cec5SDimitry Andric FieldAlign = 1;
16820b57cec5SDimitry Andric }
16830b57cec5SDimitry Andric }
16840b57cec5SDimitry Andric
16850b57cec5SDimitry Andric // Remember the alignment we would have used if the field were not packed.
16860b57cec5SDimitry Andric unsigned UnpackedFieldAlign = FieldAlign;
16870b57cec5SDimitry Andric
16880b57cec5SDimitry Andric // Ignore the field alignment if the field is packed unless it has zero-size.
16890b57cec5SDimitry Andric if (!IsMsStruct && FieldPacked && FieldSize != 0)
16900b57cec5SDimitry Andric FieldAlign = 1;
16910b57cec5SDimitry Andric
16920b57cec5SDimitry Andric // But, if there's an 'aligned' attribute on the field, honor that.
16930b57cec5SDimitry Andric unsigned ExplicitFieldAlign = D->getMaxAlignment();
16940b57cec5SDimitry Andric if (ExplicitFieldAlign) {
16950b57cec5SDimitry Andric FieldAlign = std::max(FieldAlign, ExplicitFieldAlign);
16960b57cec5SDimitry Andric UnpackedFieldAlign = std::max(UnpackedFieldAlign, ExplicitFieldAlign);
16970b57cec5SDimitry Andric }
16980b57cec5SDimitry Andric
16990b57cec5SDimitry Andric // But, if there's a #pragma pack in play, that takes precedent over
17000b57cec5SDimitry Andric // even the 'aligned' attribute, for non-zero-width bitfields.
17010b57cec5SDimitry Andric unsigned MaxFieldAlignmentInBits = Context.toBits(MaxFieldAlignment);
17020b57cec5SDimitry Andric if (!MaxFieldAlignment.isZero() && FieldSize) {
17030b57cec5SDimitry Andric UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits);
17040b57cec5SDimitry Andric if (FieldPacked)
17050b57cec5SDimitry Andric FieldAlign = UnpackedFieldAlign;
17060b57cec5SDimitry Andric else
17070b57cec5SDimitry Andric FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits);
17080b57cec5SDimitry Andric }
17090b57cec5SDimitry Andric
17100b57cec5SDimitry Andric // But, ms_struct just ignores all of that in unions, even explicit
17110b57cec5SDimitry Andric // alignment attributes.
17120b57cec5SDimitry Andric if (IsMsStruct && IsUnion) {
17130b57cec5SDimitry Andric FieldAlign = UnpackedFieldAlign = 1;
17140b57cec5SDimitry Andric }
17150b57cec5SDimitry Andric
17160b57cec5SDimitry Andric // For purposes of diagnostics, we're going to simultaneously
17170b57cec5SDimitry Andric // compute the field offsets that we would have used if we weren't
17180b57cec5SDimitry Andric // adding any alignment padding or if the field weren't packed.
17190b57cec5SDimitry Andric uint64_t UnpaddedFieldOffset = FieldOffset;
17200b57cec5SDimitry Andric uint64_t UnpackedFieldOffset = FieldOffset;
17210b57cec5SDimitry Andric
17220b57cec5SDimitry Andric // Check if we need to add padding to fit the bitfield within an
17230b57cec5SDimitry Andric // allocation unit with the right size and alignment. The rules are
17240b57cec5SDimitry Andric // somewhat different here for ms_struct structs.
17250b57cec5SDimitry Andric if (IsMsStruct) {
17260b57cec5SDimitry Andric // If it's not a zero-width bitfield, and we can fit the bitfield
17270b57cec5SDimitry Andric // into the active storage unit (and we haven't already decided to
17280b57cec5SDimitry Andric // start a new storage unit), just do so, regardless of any other
17290b57cec5SDimitry Andric // other consideration. Otherwise, round up to the right alignment.
17300b57cec5SDimitry Andric if (FieldSize == 0 || FieldSize > UnfilledBitsInLastUnit) {
17310b57cec5SDimitry Andric FieldOffset = llvm::alignTo(FieldOffset, FieldAlign);
17320b57cec5SDimitry Andric UnpackedFieldOffset =
17330b57cec5SDimitry Andric llvm::alignTo(UnpackedFieldOffset, UnpackedFieldAlign);
17340b57cec5SDimitry Andric UnfilledBitsInLastUnit = 0;
17350b57cec5SDimitry Andric }
17360b57cec5SDimitry Andric
17370b57cec5SDimitry Andric } else {
17380b57cec5SDimitry Andric // #pragma pack, with any value, suppresses the insertion of padding.
17390b57cec5SDimitry Andric bool AllowPadding = MaxFieldAlignment.isZero();
17400b57cec5SDimitry Andric
17410b57cec5SDimitry Andric // Compute the real offset.
17420b57cec5SDimitry Andric if (FieldSize == 0 ||
17430b57cec5SDimitry Andric (AllowPadding &&
1744e8d8bef9SDimitry Andric (FieldOffset & (FieldAlign - 1)) + FieldSize > StorageUnitSize)) {
17450b57cec5SDimitry Andric FieldOffset = llvm::alignTo(FieldOffset, FieldAlign);
17460b57cec5SDimitry Andric } else if (ExplicitFieldAlign &&
17470b57cec5SDimitry Andric (MaxFieldAlignmentInBits == 0 ||
17480b57cec5SDimitry Andric ExplicitFieldAlign <= MaxFieldAlignmentInBits) &&
17490b57cec5SDimitry Andric Context.getTargetInfo().useExplicitBitFieldAlignment()) {
17500b57cec5SDimitry Andric // TODO: figure it out what needs to be done on targets that don't honor
17510b57cec5SDimitry Andric // bit-field type alignment like ARM APCS ABI.
17520b57cec5SDimitry Andric FieldOffset = llvm::alignTo(FieldOffset, ExplicitFieldAlign);
17530b57cec5SDimitry Andric }
17540b57cec5SDimitry Andric
17550b57cec5SDimitry Andric // Repeat the computation for diagnostic purposes.
17560b57cec5SDimitry Andric if (FieldSize == 0 ||
17570b57cec5SDimitry Andric (AllowPadding &&
1758e8d8bef9SDimitry Andric (UnpackedFieldOffset & (UnpackedFieldAlign - 1)) + FieldSize >
1759e8d8bef9SDimitry Andric StorageUnitSize))
17600b57cec5SDimitry Andric UnpackedFieldOffset =
17610b57cec5SDimitry Andric llvm::alignTo(UnpackedFieldOffset, UnpackedFieldAlign);
17620b57cec5SDimitry Andric else if (ExplicitFieldAlign &&
17630b57cec5SDimitry Andric (MaxFieldAlignmentInBits == 0 ||
17640b57cec5SDimitry Andric ExplicitFieldAlign <= MaxFieldAlignmentInBits) &&
17650b57cec5SDimitry Andric Context.getTargetInfo().useExplicitBitFieldAlignment())
17660b57cec5SDimitry Andric UnpackedFieldOffset =
17670b57cec5SDimitry Andric llvm::alignTo(UnpackedFieldOffset, ExplicitFieldAlign);
17680b57cec5SDimitry Andric }
17690b57cec5SDimitry Andric
17700b57cec5SDimitry Andric // If we're using external layout, give the external layout a chance
17710b57cec5SDimitry Andric // to override this information.
17720b57cec5SDimitry Andric if (UseExternalLayout)
17730b57cec5SDimitry Andric FieldOffset = updateExternalFieldOffset(D, FieldOffset);
17740b57cec5SDimitry Andric
17750b57cec5SDimitry Andric // Okay, place the bitfield at the calculated offset.
17760b57cec5SDimitry Andric FieldOffsets.push_back(FieldOffset);
17770b57cec5SDimitry Andric
17780b57cec5SDimitry Andric // Bookkeeping:
17790b57cec5SDimitry Andric
17800b57cec5SDimitry Andric // Anonymous members don't affect the overall record alignment,
17810b57cec5SDimitry Andric // except on targets where they do.
17820b57cec5SDimitry Andric if (!IsMsStruct &&
17830b57cec5SDimitry Andric !Context.getTargetInfo().useZeroLengthBitfieldAlignment() &&
17840b57cec5SDimitry Andric !D->getIdentifier())
17850b57cec5SDimitry Andric FieldAlign = UnpackedFieldAlign = 1;
17860b57cec5SDimitry Andric
1787349cc55cSDimitry Andric // On AIX, zero-width bitfields pad out to the natural alignment boundary,
1788349cc55cSDimitry Andric // but do not increase the alignment greater than the MaxFieldAlignment, or 1
1789349cc55cSDimitry Andric // if packed.
1790349cc55cSDimitry Andric if (isAIXLayout(Context) && !FieldSize) {
1791349cc55cSDimitry Andric if (FieldPacked)
1792349cc55cSDimitry Andric FieldAlign = 1;
1793349cc55cSDimitry Andric if (!MaxFieldAlignment.isZero()) {
1794349cc55cSDimitry Andric UnpackedFieldAlign =
1795349cc55cSDimitry Andric std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits);
1796fe6060f1SDimitry Andric FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits);
1797349cc55cSDimitry Andric }
1798349cc55cSDimitry Andric }
1799fe6060f1SDimitry Andric
18000b57cec5SDimitry Andric // Diagnose differences in layout due to padding or packing.
18010b57cec5SDimitry Andric if (!UseExternalLayout)
18020b57cec5SDimitry Andric CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, UnpackedFieldOffset,
18030b57cec5SDimitry Andric UnpackedFieldAlign, FieldPacked, D);
18040b57cec5SDimitry Andric
18050b57cec5SDimitry Andric // Update DataSize to include the last byte containing (part of) the bitfield.
18060b57cec5SDimitry Andric
18070b57cec5SDimitry Andric // For unions, this is just a max operation, as usual.
18080b57cec5SDimitry Andric if (IsUnion) {
18090b57cec5SDimitry Andric // For ms_struct, allocate the entire storage unit --- unless this
18100b57cec5SDimitry Andric // is a zero-width bitfield, in which case just use a size of 1.
18110b57cec5SDimitry Andric uint64_t RoundedFieldSize;
18120b57cec5SDimitry Andric if (IsMsStruct) {
1813e8d8bef9SDimitry Andric RoundedFieldSize = (FieldSize ? StorageUnitSize
1814e8d8bef9SDimitry Andric : Context.getTargetInfo().getCharWidth());
18150b57cec5SDimitry Andric
18160b57cec5SDimitry Andric // Otherwise, allocate just the number of bytes required to store
18170b57cec5SDimitry Andric // the bitfield.
18180b57cec5SDimitry Andric } else {
18190b57cec5SDimitry Andric RoundedFieldSize = roundUpSizeToCharAlignment(FieldSize, Context);
18200b57cec5SDimitry Andric }
18210b57cec5SDimitry Andric setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize));
18220b57cec5SDimitry Andric
18230b57cec5SDimitry Andric // For non-zero-width bitfields in ms_struct structs, allocate a new
18240b57cec5SDimitry Andric // storage unit if necessary.
18250b57cec5SDimitry Andric } else if (IsMsStruct && FieldSize) {
18260b57cec5SDimitry Andric // We should have cleared UnfilledBitsInLastUnit in every case
18270b57cec5SDimitry Andric // where we changed storage units.
18280b57cec5SDimitry Andric if (!UnfilledBitsInLastUnit) {
1829e8d8bef9SDimitry Andric setDataSize(FieldOffset + StorageUnitSize);
1830e8d8bef9SDimitry Andric UnfilledBitsInLastUnit = StorageUnitSize;
18310b57cec5SDimitry Andric }
18320b57cec5SDimitry Andric UnfilledBitsInLastUnit -= FieldSize;
1833e8d8bef9SDimitry Andric LastBitfieldStorageUnitSize = StorageUnitSize;
18340b57cec5SDimitry Andric
18350b57cec5SDimitry Andric // Otherwise, bump the data size up to include the bitfield,
18360b57cec5SDimitry Andric // including padding up to char alignment, and then remember how
18370b57cec5SDimitry Andric // bits we didn't use.
18380b57cec5SDimitry Andric } else {
18390b57cec5SDimitry Andric uint64_t NewSizeInBits = FieldOffset + FieldSize;
18400b57cec5SDimitry Andric uint64_t CharAlignment = Context.getTargetInfo().getCharAlign();
18410b57cec5SDimitry Andric setDataSize(llvm::alignTo(NewSizeInBits, CharAlignment));
18420b57cec5SDimitry Andric UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits;
18430b57cec5SDimitry Andric
18440b57cec5SDimitry Andric // The only time we can get here for an ms_struct is if this is a
18450b57cec5SDimitry Andric // zero-width bitfield, which doesn't count as anything for the
18460b57cec5SDimitry Andric // purposes of unfilled bits.
1847e8d8bef9SDimitry Andric LastBitfieldStorageUnitSize = 0;
18480b57cec5SDimitry Andric }
18490b57cec5SDimitry Andric
18500b57cec5SDimitry Andric // Update the size.
18510b57cec5SDimitry Andric setSize(std::max(getSizeInBits(), getDataSizeInBits()));
18520b57cec5SDimitry Andric
18530b57cec5SDimitry Andric // Remember max struct/class alignment.
18540b57cec5SDimitry Andric UnadjustedAlignment =
18550b57cec5SDimitry Andric std::max(UnadjustedAlignment, Context.toCharUnitsFromBits(FieldAlign));
18560b57cec5SDimitry Andric UpdateAlignment(Context.toCharUnitsFromBits(FieldAlign),
18570b57cec5SDimitry Andric Context.toCharUnitsFromBits(UnpackedFieldAlign));
18580b57cec5SDimitry Andric }
18590b57cec5SDimitry Andric
LayoutField(const FieldDecl * D,bool InsertExtraPadding)18600b57cec5SDimitry Andric void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D,
18610b57cec5SDimitry Andric bool InsertExtraPadding) {
1862e8d8bef9SDimitry Andric auto *FieldClass = D->getType()->getAsCXXRecordDecl();
1863e8d8bef9SDimitry Andric bool IsOverlappingEmptyField =
186406c3fb27SDimitry Andric D->isPotentiallyOverlapping() && FieldClass->isEmpty();
1865e8d8bef9SDimitry Andric
1866e8d8bef9SDimitry Andric CharUnits FieldOffset =
1867e8d8bef9SDimitry Andric (IsUnion || IsOverlappingEmptyField) ? CharUnits::Zero() : getDataSize();
1868e8d8bef9SDimitry Andric
1869e8d8bef9SDimitry Andric const bool DefaultsToAIXPowerAlignment =
1870e8d8bef9SDimitry Andric Context.getTargetInfo().defaultsToAIXPowerAlignment();
1871e8d8bef9SDimitry Andric bool FoundFirstNonOverlappingEmptyFieldForAIX = false;
1872e8d8bef9SDimitry Andric if (DefaultsToAIXPowerAlignment && !HandledFirstNonOverlappingEmptyField) {
1873e8d8bef9SDimitry Andric assert(FieldOffset == CharUnits::Zero() &&
1874e8d8bef9SDimitry Andric "The first non-overlapping empty field should have been handled.");
1875e8d8bef9SDimitry Andric
1876e8d8bef9SDimitry Andric if (!IsOverlappingEmptyField) {
1877e8d8bef9SDimitry Andric FoundFirstNonOverlappingEmptyFieldForAIX = true;
1878e8d8bef9SDimitry Andric
1879e8d8bef9SDimitry Andric // We're going to handle the "first member" based on
1880e8d8bef9SDimitry Andric // `FoundFirstNonOverlappingEmptyFieldForAIX` during the current
1881e8d8bef9SDimitry Andric // invocation of this function; record it as handled for future
1882e8d8bef9SDimitry Andric // invocations (except for unions, because the current field does not
1883e8d8bef9SDimitry Andric // represent all "firsts").
1884e8d8bef9SDimitry Andric HandledFirstNonOverlappingEmptyField = !IsUnion;
1885e8d8bef9SDimitry Andric }
1886e8d8bef9SDimitry Andric }
1887e8d8bef9SDimitry Andric
18880b57cec5SDimitry Andric if (D->isBitField()) {
18890b57cec5SDimitry Andric LayoutBitField(D);
18900b57cec5SDimitry Andric return;
18910b57cec5SDimitry Andric }
18920b57cec5SDimitry Andric
18930b57cec5SDimitry Andric uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;
18940b57cec5SDimitry Andric // Reset the unfilled bits.
18950b57cec5SDimitry Andric UnfilledBitsInLastUnit = 0;
1896e8d8bef9SDimitry Andric LastBitfieldStorageUnitSize = 0;
18970b57cec5SDimitry Andric
1898bdd1243dSDimitry Andric llvm::Triple Target = Context.getTargetInfo().getTriple();
18990b57cec5SDimitry Andric
1900349cc55cSDimitry Andric AlignRequirementKind AlignRequirement = AlignRequirementKind::None;
19010b57cec5SDimitry Andric CharUnits FieldSize;
19020b57cec5SDimitry Andric CharUnits FieldAlign;
19030b57cec5SDimitry Andric // The amount of this class's dsize occupied by the field.
19040b57cec5SDimitry Andric // This is equal to FieldSize unless we're permitted to pack
19050b57cec5SDimitry Andric // into the field's tail padding.
19060b57cec5SDimitry Andric CharUnits EffectiveFieldSize;
19070b57cec5SDimitry Andric
1908e8d8bef9SDimitry Andric auto setDeclInfo = [&](bool IsIncompleteArrayType) {
1909e8d8bef9SDimitry Andric auto TI = Context.getTypeInfoInChars(D->getType());
1910e8d8bef9SDimitry Andric FieldAlign = TI.Align;
1911e8d8bef9SDimitry Andric // Flexible array members don't have any size, but they have to be
1912e8d8bef9SDimitry Andric // aligned appropriately for their element type.
1913e8d8bef9SDimitry Andric EffectiveFieldSize = FieldSize =
1914e8d8bef9SDimitry Andric IsIncompleteArrayType ? CharUnits::Zero() : TI.Width;
1915349cc55cSDimitry Andric AlignRequirement = TI.AlignRequirement;
1916e8d8bef9SDimitry Andric };
1917e8d8bef9SDimitry Andric
19180b57cec5SDimitry Andric if (D->getType()->isIncompleteArrayType()) {
1919e8d8bef9SDimitry Andric setDeclInfo(true /* IsIncompleteArrayType */);
19200b57cec5SDimitry Andric } else {
1921e8d8bef9SDimitry Andric setDeclInfo(false /* IsIncompleteArrayType */);
19220b57cec5SDimitry Andric
19230b57cec5SDimitry Andric // A potentially-overlapping field occupies its dsize or nvsize, whichever
19240b57cec5SDimitry Andric // is larger.
192506c3fb27SDimitry Andric if (D->isPotentiallyOverlapping()) {
19260b57cec5SDimitry Andric const ASTRecordLayout &Layout = Context.getASTRecordLayout(FieldClass);
19270b57cec5SDimitry Andric EffectiveFieldSize =
19280b57cec5SDimitry Andric std::max(Layout.getNonVirtualSize(), Layout.getDataSize());
19290b57cec5SDimitry Andric }
19300b57cec5SDimitry Andric
19310b57cec5SDimitry Andric if (IsMsStruct) {
19320b57cec5SDimitry Andric // If MS bitfield layout is required, figure out what type is being
19330b57cec5SDimitry Andric // laid out and align the field to the width of that type.
19340b57cec5SDimitry Andric
19350b57cec5SDimitry Andric // Resolve all typedefs down to their base type and round up the field
19360b57cec5SDimitry Andric // alignment if necessary.
19370b57cec5SDimitry Andric QualType T = Context.getBaseElementType(D->getType());
19380b57cec5SDimitry Andric if (const BuiltinType *BTy = T->getAs<BuiltinType>()) {
19390b57cec5SDimitry Andric CharUnits TypeSize = Context.getTypeSizeInChars(BTy);
19400b57cec5SDimitry Andric
19410b57cec5SDimitry Andric if (!llvm::isPowerOf2_64(TypeSize.getQuantity())) {
19420b57cec5SDimitry Andric assert(
19430b57cec5SDimitry Andric !Context.getTargetInfo().getTriple().isWindowsMSVCEnvironment() &&
19440b57cec5SDimitry Andric "Non PowerOf2 size in MSVC mode");
19450b57cec5SDimitry Andric // Base types with sizes that aren't a power of two don't work
19460b57cec5SDimitry Andric // with the layout rules for MS structs. This isn't an issue in
19470b57cec5SDimitry Andric // MSVC itself since there are no such base data types there.
19480b57cec5SDimitry Andric // On e.g. x86_32 mingw and linux, long double is 12 bytes though.
19490b57cec5SDimitry Andric // Any structs involving that data type obviously can't be ABI
19500b57cec5SDimitry Andric // compatible with MSVC regardless of how it is laid out.
19510b57cec5SDimitry Andric
19520b57cec5SDimitry Andric // Since ms_struct can be mass enabled (via a pragma or via the
19530b57cec5SDimitry Andric // -mms-bitfields command line parameter), this can trigger for
19540b57cec5SDimitry Andric // structs that don't actually need MSVC compatibility, so we
19550b57cec5SDimitry Andric // need to be able to sidestep the ms_struct layout for these types.
19560b57cec5SDimitry Andric
19570b57cec5SDimitry Andric // Since the combination of -mms-bitfields together with structs
19580b57cec5SDimitry Andric // like max_align_t (which contains a long double) for mingw is
1959349cc55cSDimitry Andric // quite common (and GCC handles it silently), just handle it
19600b57cec5SDimitry Andric // silently there. For other targets that have ms_struct enabled
19610b57cec5SDimitry Andric // (most probably via a pragma or attribute), trigger a diagnostic
19620b57cec5SDimitry Andric // that defaults to an error.
19630b57cec5SDimitry Andric if (!Context.getTargetInfo().getTriple().isWindowsGNUEnvironment())
19640b57cec5SDimitry Andric Diag(D->getLocation(), diag::warn_npot_ms_struct);
19650b57cec5SDimitry Andric }
19660b57cec5SDimitry Andric if (TypeSize > FieldAlign &&
19670b57cec5SDimitry Andric llvm::isPowerOf2_64(TypeSize.getQuantity()))
19680b57cec5SDimitry Andric FieldAlign = TypeSize;
19690b57cec5SDimitry Andric }
19700b57cec5SDimitry Andric }
19710b57cec5SDimitry Andric }
19720b57cec5SDimitry Andric
1973bdd1243dSDimitry Andric bool FieldPacked = (Packed && (!FieldClass || FieldClass->isPOD() ||
1974bdd1243dSDimitry Andric FieldClass->hasAttr<PackedAttr>() ||
1975bdd1243dSDimitry Andric Context.getLangOpts().getClangABICompat() <=
1976bdd1243dSDimitry Andric LangOptions::ClangABI::Ver15 ||
1977bdd1243dSDimitry Andric Target.isPS() || Target.isOSDarwin() ||
1978bdd1243dSDimitry Andric Target.isOSAIX())) ||
1979bdd1243dSDimitry Andric D->hasAttr<PackedAttr>();
1980bdd1243dSDimitry Andric
1981349cc55cSDimitry Andric // When used as part of a typedef, or together with a 'packed' attribute, the
1982349cc55cSDimitry Andric // 'aligned' attribute can be used to decrease alignment. In that case, it
1983349cc55cSDimitry Andric // overrides any computed alignment we have, and there is no need to upgrade
1984349cc55cSDimitry Andric // the alignment.
1985349cc55cSDimitry Andric auto alignedAttrCanDecreaseAIXAlignment = [AlignRequirement, FieldPacked] {
1986349cc55cSDimitry Andric // Enum alignment sources can be safely ignored here, because this only
1987349cc55cSDimitry Andric // helps decide whether we need the AIX alignment upgrade, which only
1988349cc55cSDimitry Andric // applies to floating-point types.
1989349cc55cSDimitry Andric return AlignRequirement == AlignRequirementKind::RequiredByTypedef ||
1990349cc55cSDimitry Andric (AlignRequirement == AlignRequirementKind::RequiredByRecord &&
1991349cc55cSDimitry Andric FieldPacked);
1992349cc55cSDimitry Andric };
1993349cc55cSDimitry Andric
1994e8d8bef9SDimitry Andric // The AIX `power` alignment rules apply the natural alignment of the
1995e8d8bef9SDimitry Andric // "first member" if it is of a floating-point data type (or is an aggregate
1996e8d8bef9SDimitry Andric // whose recursively "first" member or element is such a type). The alignment
1997e8d8bef9SDimitry Andric // associated with these types for subsequent members use an alignment value
1998e8d8bef9SDimitry Andric // where the floating-point data type is considered to have 4-byte alignment.
1999e8d8bef9SDimitry Andric //
2000e8d8bef9SDimitry Andric // For the purposes of the foregoing: vtable pointers, non-empty base classes,
2001e8d8bef9SDimitry Andric // and zero-width bit-fields count as prior members; members of empty class
2002e8d8bef9SDimitry Andric // types marked `no_unique_address` are not considered to be prior members.
2003e8d8bef9SDimitry Andric CharUnits PreferredAlign = FieldAlign;
2004349cc55cSDimitry Andric if (DefaultsToAIXPowerAlignment && !alignedAttrCanDecreaseAIXAlignment() &&
2005e8d8bef9SDimitry Andric (FoundFirstNonOverlappingEmptyFieldForAIX || IsNaturalAlign)) {
2006e8d8bef9SDimitry Andric auto performBuiltinTypeAlignmentUpgrade = [&](const BuiltinType *BTy) {
2007e8d8bef9SDimitry Andric if (BTy->getKind() == BuiltinType::Double ||
2008e8d8bef9SDimitry Andric BTy->getKind() == BuiltinType::LongDouble) {
2009e8d8bef9SDimitry Andric assert(PreferredAlign == CharUnits::fromQuantity(4) &&
2010e8d8bef9SDimitry Andric "No need to upgrade the alignment value.");
2011e8d8bef9SDimitry Andric PreferredAlign = CharUnits::fromQuantity(8);
2012e8d8bef9SDimitry Andric }
2013e8d8bef9SDimitry Andric };
2014e8d8bef9SDimitry Andric
2015349cc55cSDimitry Andric const Type *BaseTy = D->getType()->getBaseElementTypeUnsafe();
2016349cc55cSDimitry Andric if (const ComplexType *CTy = BaseTy->getAs<ComplexType>()) {
2017349cc55cSDimitry Andric performBuiltinTypeAlignmentUpgrade(
2018349cc55cSDimitry Andric CTy->getElementType()->castAs<BuiltinType>());
2019349cc55cSDimitry Andric } else if (const BuiltinType *BTy = BaseTy->getAs<BuiltinType>()) {
2020e8d8bef9SDimitry Andric performBuiltinTypeAlignmentUpgrade(BTy);
2021349cc55cSDimitry Andric } else if (const RecordType *RT = BaseTy->getAs<RecordType>()) {
2022e8d8bef9SDimitry Andric const RecordDecl *RD = RT->getDecl();
2023e8d8bef9SDimitry Andric assert(RD && "Expected non-null RecordDecl.");
2024e8d8bef9SDimitry Andric const ASTRecordLayout &FieldRecord = Context.getASTRecordLayout(RD);
2025e8d8bef9SDimitry Andric PreferredAlign = FieldRecord.getPreferredAlignment();
2026e8d8bef9SDimitry Andric }
2027e8d8bef9SDimitry Andric }
2028e8d8bef9SDimitry Andric
20290b57cec5SDimitry Andric // The align if the field is not packed. This is to check if the attribute
20300b57cec5SDimitry Andric // was unnecessary (-Wpacked).
2031bdd1243dSDimitry Andric CharUnits UnpackedFieldAlign = FieldAlign;
2032bdd1243dSDimitry Andric CharUnits PackedFieldAlign = CharUnits::One();
20330b57cec5SDimitry Andric CharUnits UnpackedFieldOffset = FieldOffset;
203404eeddc0SDimitry Andric CharUnits OriginalFieldAlign = UnpackedFieldAlign;
20350b57cec5SDimitry Andric
20360b57cec5SDimitry Andric CharUnits MaxAlignmentInChars =
20370b57cec5SDimitry Andric Context.toCharUnitsFromBits(D->getMaxAlignment());
2038bdd1243dSDimitry Andric PackedFieldAlign = std::max(PackedFieldAlign, MaxAlignmentInChars);
2039e8d8bef9SDimitry Andric PreferredAlign = std::max(PreferredAlign, MaxAlignmentInChars);
20400b57cec5SDimitry Andric UnpackedFieldAlign = std::max(UnpackedFieldAlign, MaxAlignmentInChars);
20410b57cec5SDimitry Andric
20420b57cec5SDimitry Andric // The maximum field alignment overrides the aligned attribute.
20430b57cec5SDimitry Andric if (!MaxFieldAlignment.isZero()) {
2044bdd1243dSDimitry Andric PackedFieldAlign = std::min(PackedFieldAlign, MaxFieldAlignment);
2045e8d8bef9SDimitry Andric PreferredAlign = std::min(PreferredAlign, MaxFieldAlignment);
20460b57cec5SDimitry Andric UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignment);
20470b57cec5SDimitry Andric }
20480b57cec5SDimitry Andric
2049bdd1243dSDimitry Andric
2050bdd1243dSDimitry Andric if (!FieldPacked)
2051bdd1243dSDimitry Andric FieldAlign = UnpackedFieldAlign;
2052bdd1243dSDimitry Andric if (DefaultsToAIXPowerAlignment)
2053bdd1243dSDimitry Andric UnpackedFieldAlign = PreferredAlign;
2054bdd1243dSDimitry Andric if (FieldPacked) {
2055bdd1243dSDimitry Andric PreferredAlign = PackedFieldAlign;
2056bdd1243dSDimitry Andric FieldAlign = PackedFieldAlign;
2057bdd1243dSDimitry Andric }
2058bdd1243dSDimitry Andric
2059e8d8bef9SDimitry Andric CharUnits AlignTo =
2060e8d8bef9SDimitry Andric !DefaultsToAIXPowerAlignment ? FieldAlign : PreferredAlign;
20610b57cec5SDimitry Andric // Round up the current record size to the field's alignment boundary.
2062e8d8bef9SDimitry Andric FieldOffset = FieldOffset.alignTo(AlignTo);
20630b57cec5SDimitry Andric UnpackedFieldOffset = UnpackedFieldOffset.alignTo(UnpackedFieldAlign);
20640b57cec5SDimitry Andric
20650b57cec5SDimitry Andric if (UseExternalLayout) {
20660b57cec5SDimitry Andric FieldOffset = Context.toCharUnitsFromBits(
20670b57cec5SDimitry Andric updateExternalFieldOffset(D, Context.toBits(FieldOffset)));
20680b57cec5SDimitry Andric
20690b57cec5SDimitry Andric if (!IsUnion && EmptySubobjects) {
20700b57cec5SDimitry Andric // Record the fact that we're placing a field at this offset.
20710b57cec5SDimitry Andric bool Allowed = EmptySubobjects->CanPlaceFieldAtOffset(D, FieldOffset);
20720b57cec5SDimitry Andric (void)Allowed;
20730b57cec5SDimitry Andric assert(Allowed && "Externally-placed field cannot be placed here");
20740b57cec5SDimitry Andric }
20750b57cec5SDimitry Andric } else {
20760b57cec5SDimitry Andric if (!IsUnion && EmptySubobjects) {
20770b57cec5SDimitry Andric // Check if we can place the field at this offset.
20780b57cec5SDimitry Andric while (!EmptySubobjects->CanPlaceFieldAtOffset(D, FieldOffset)) {
20790b57cec5SDimitry Andric // We couldn't place the field at the offset. Try again at a new offset.
20800b57cec5SDimitry Andric // We try offset 0 (for an empty field) and then dsize(C) onwards.
20810b57cec5SDimitry Andric if (FieldOffset == CharUnits::Zero() &&
20820b57cec5SDimitry Andric getDataSize() != CharUnits::Zero())
2083e8d8bef9SDimitry Andric FieldOffset = getDataSize().alignTo(AlignTo);
20840b57cec5SDimitry Andric else
2085e8d8bef9SDimitry Andric FieldOffset += AlignTo;
20860b57cec5SDimitry Andric }
20870b57cec5SDimitry Andric }
20880b57cec5SDimitry Andric }
20890b57cec5SDimitry Andric
20900b57cec5SDimitry Andric // Place this field at the current location.
20910b57cec5SDimitry Andric FieldOffsets.push_back(Context.toBits(FieldOffset));
20920b57cec5SDimitry Andric
20930b57cec5SDimitry Andric if (!UseExternalLayout)
20940b57cec5SDimitry Andric CheckFieldPadding(Context.toBits(FieldOffset), UnpaddedFieldOffset,
20950b57cec5SDimitry Andric Context.toBits(UnpackedFieldOffset),
20960b57cec5SDimitry Andric Context.toBits(UnpackedFieldAlign), FieldPacked, D);
20970b57cec5SDimitry Andric
20980b57cec5SDimitry Andric if (InsertExtraPadding) {
20990b57cec5SDimitry Andric CharUnits ASanAlignment = CharUnits::fromQuantity(8);
21000b57cec5SDimitry Andric CharUnits ExtraSizeForAsan = ASanAlignment;
21010b57cec5SDimitry Andric if (FieldSize % ASanAlignment)
21020b57cec5SDimitry Andric ExtraSizeForAsan +=
21030b57cec5SDimitry Andric ASanAlignment - CharUnits::fromQuantity(FieldSize % ASanAlignment);
21040b57cec5SDimitry Andric EffectiveFieldSize = FieldSize = FieldSize + ExtraSizeForAsan;
21050b57cec5SDimitry Andric }
21060b57cec5SDimitry Andric
21070b57cec5SDimitry Andric // Reserve space for this field.
21080b57cec5SDimitry Andric if (!IsOverlappingEmptyField) {
21090b57cec5SDimitry Andric uint64_t EffectiveFieldSizeInBits = Context.toBits(EffectiveFieldSize);
21100b57cec5SDimitry Andric if (IsUnion)
21110b57cec5SDimitry Andric setDataSize(std::max(getDataSizeInBits(), EffectiveFieldSizeInBits));
21120b57cec5SDimitry Andric else
21130b57cec5SDimitry Andric setDataSize(FieldOffset + EffectiveFieldSize);
21140b57cec5SDimitry Andric
21150b57cec5SDimitry Andric PaddedFieldSize = std::max(PaddedFieldSize, FieldOffset + FieldSize);
21160b57cec5SDimitry Andric setSize(std::max(getSizeInBits(), getDataSizeInBits()));
21170b57cec5SDimitry Andric } else {
21180b57cec5SDimitry Andric setSize(std::max(getSizeInBits(),
21190b57cec5SDimitry Andric (uint64_t)Context.toBits(FieldOffset + FieldSize)));
21200b57cec5SDimitry Andric }
21210b57cec5SDimitry Andric
2122e8d8bef9SDimitry Andric // Remember max struct/class ABI-specified alignment.
21230b57cec5SDimitry Andric UnadjustedAlignment = std::max(UnadjustedAlignment, FieldAlign);
2124e8d8bef9SDimitry Andric UpdateAlignment(FieldAlign, UnpackedFieldAlign, PreferredAlign);
212504eeddc0SDimitry Andric
212604eeddc0SDimitry Andric // For checking the alignment of inner fields against
212704eeddc0SDimitry Andric // the alignment of its parent record.
212804eeddc0SDimitry Andric if (const RecordDecl *RD = D->getParent()) {
212904eeddc0SDimitry Andric // Check if packed attribute or pragma pack is present.
213004eeddc0SDimitry Andric if (RD->hasAttr<PackedAttr>() || !MaxFieldAlignment.isZero())
213104eeddc0SDimitry Andric if (FieldAlign < OriginalFieldAlign)
213204eeddc0SDimitry Andric if (D->getType()->isRecordType()) {
213304eeddc0SDimitry Andric // If the offset is a multiple of the alignment of
213404eeddc0SDimitry Andric // the type, raise the warning.
213504eeddc0SDimitry Andric // TODO: Takes no account the alignment of the outer struct
213604eeddc0SDimitry Andric if (FieldOffset % OriginalFieldAlign != 0)
213704eeddc0SDimitry Andric Diag(D->getLocation(), diag::warn_unaligned_access)
213804eeddc0SDimitry Andric << Context.getTypeDeclType(RD) << D->getName() << D->getType();
213904eeddc0SDimitry Andric }
214004eeddc0SDimitry Andric }
2141bdd1243dSDimitry Andric
2142bdd1243dSDimitry Andric if (Packed && !FieldPacked && PackedFieldAlign < FieldAlign)
2143bdd1243dSDimitry Andric Diag(D->getLocation(), diag::warn_unpacked_field) << D;
21440b57cec5SDimitry Andric }
21450b57cec5SDimitry Andric
FinishLayout(const NamedDecl * D)21460b57cec5SDimitry Andric void ItaniumRecordLayoutBuilder::FinishLayout(const NamedDecl *D) {
21470b57cec5SDimitry Andric // In C++, records cannot be of size 0.
21480b57cec5SDimitry Andric if (Context.getLangOpts().CPlusPlus && getSizeInBits() == 0) {
21490b57cec5SDimitry Andric if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
21500b57cec5SDimitry Andric // Compatibility with gcc requires a class (pod or non-pod)
21510b57cec5SDimitry Andric // which is not empty but of size 0; such as having fields of
21520b57cec5SDimitry Andric // array of zero-length, remains of Size 0
21530b57cec5SDimitry Andric if (RD->isEmpty())
21540b57cec5SDimitry Andric setSize(CharUnits::One());
21550b57cec5SDimitry Andric }
21560b57cec5SDimitry Andric else
21570b57cec5SDimitry Andric setSize(CharUnits::One());
21580b57cec5SDimitry Andric }
21590b57cec5SDimitry Andric
21600b57cec5SDimitry Andric // If we have any remaining field tail padding, include that in the overall
21610b57cec5SDimitry Andric // size.
21620b57cec5SDimitry Andric setSize(std::max(getSizeInBits(), (uint64_t)Context.toBits(PaddedFieldSize)));
21630b57cec5SDimitry Andric
21640b57cec5SDimitry Andric // Finally, round the size of the record up to the alignment of the
21650b57cec5SDimitry Andric // record itself.
21660b57cec5SDimitry Andric uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastUnit;
21670b57cec5SDimitry Andric uint64_t UnpackedSizeInBits =
21680b57cec5SDimitry Andric llvm::alignTo(getSizeInBits(), Context.toBits(UnpackedAlignment));
2169e8d8bef9SDimitry Andric
2170e8d8bef9SDimitry Andric uint64_t RoundedSize = llvm::alignTo(
2171e8d8bef9SDimitry Andric getSizeInBits(),
2172e8d8bef9SDimitry Andric Context.toBits(!Context.getTargetInfo().defaultsToAIXPowerAlignment()
2173e8d8bef9SDimitry Andric ? Alignment
2174e8d8bef9SDimitry Andric : PreferredAlignment));
21750b57cec5SDimitry Andric
21760b57cec5SDimitry Andric if (UseExternalLayout) {
21770b57cec5SDimitry Andric // If we're inferring alignment, and the external size is smaller than
21780b57cec5SDimitry Andric // our size after we've rounded up to alignment, conservatively set the
21790b57cec5SDimitry Andric // alignment to 1.
21800b57cec5SDimitry Andric if (InferAlignment && External.Size < RoundedSize) {
21810b57cec5SDimitry Andric Alignment = CharUnits::One();
2182e8d8bef9SDimitry Andric PreferredAlignment = CharUnits::One();
21830b57cec5SDimitry Andric InferAlignment = false;
21840b57cec5SDimitry Andric }
21850b57cec5SDimitry Andric setSize(External.Size);
21860b57cec5SDimitry Andric return;
21870b57cec5SDimitry Andric }
21880b57cec5SDimitry Andric
21890b57cec5SDimitry Andric // Set the size to the final size.
21900b57cec5SDimitry Andric setSize(RoundedSize);
21910b57cec5SDimitry Andric
21920b57cec5SDimitry Andric unsigned CharBitNum = Context.getTargetInfo().getCharWidth();
21930b57cec5SDimitry Andric if (const RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
21940b57cec5SDimitry Andric // Warn if padding was introduced to the struct/class/union.
21950b57cec5SDimitry Andric if (getSizeInBits() > UnpaddedSize) {
21960b57cec5SDimitry Andric unsigned PadSize = getSizeInBits() - UnpaddedSize;
21970b57cec5SDimitry Andric bool InBits = true;
21980b57cec5SDimitry Andric if (PadSize % CharBitNum == 0) {
21990b57cec5SDimitry Andric PadSize = PadSize / CharBitNum;
22000b57cec5SDimitry Andric InBits = false;
22010b57cec5SDimitry Andric }
22020b57cec5SDimitry Andric Diag(RD->getLocation(), diag::warn_padded_struct_size)
22030b57cec5SDimitry Andric << Context.getTypeDeclType(RD)
22040b57cec5SDimitry Andric << PadSize
22050b57cec5SDimitry Andric << (InBits ? 1 : 0); // (byte|bit)
22060b57cec5SDimitry Andric }
22070b57cec5SDimitry Andric
220806c3fb27SDimitry Andric const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD);
220906c3fb27SDimitry Andric
22100b57cec5SDimitry Andric // Warn if we packed it unnecessarily, when the unpacked alignment is not
22110b57cec5SDimitry Andric // greater than the one after packing, the size in bits doesn't change and
22120b57cec5SDimitry Andric // the offset of each field is identical.
221306c3fb27SDimitry Andric // Unless the type is non-POD (for Clang ABI > 15), where the packed
221406c3fb27SDimitry Andric // attribute on such a type does allow the type to be packed into other
221506c3fb27SDimitry Andric // structures that use the packed attribute.
22160b57cec5SDimitry Andric if (Packed && UnpackedAlignment <= Alignment &&
221706c3fb27SDimitry Andric UnpackedSizeInBits == getSizeInBits() && !HasPackedField &&
221806c3fb27SDimitry Andric (!CXXRD || CXXRD->isPOD() ||
221906c3fb27SDimitry Andric Context.getLangOpts().getClangABICompat() <=
222006c3fb27SDimitry Andric LangOptions::ClangABI::Ver15))
22210b57cec5SDimitry Andric Diag(D->getLocation(), diag::warn_unnecessary_packed)
22220b57cec5SDimitry Andric << Context.getTypeDeclType(RD);
22230b57cec5SDimitry Andric }
22240b57cec5SDimitry Andric }
22250b57cec5SDimitry Andric
UpdateAlignment(CharUnits NewAlignment,CharUnits UnpackedNewAlignment,CharUnits PreferredNewAlignment)22260b57cec5SDimitry Andric void ItaniumRecordLayoutBuilder::UpdateAlignment(
2227e8d8bef9SDimitry Andric CharUnits NewAlignment, CharUnits UnpackedNewAlignment,
2228e8d8bef9SDimitry Andric CharUnits PreferredNewAlignment) {
22290b57cec5SDimitry Andric // The alignment is not modified when using 'mac68k' alignment or when
22300b57cec5SDimitry Andric // we have an externally-supplied layout that also provides overall alignment.
22310b57cec5SDimitry Andric if (IsMac68kAlign || (UseExternalLayout && !InferAlignment))
22320b57cec5SDimitry Andric return;
22330b57cec5SDimitry Andric
22340b57cec5SDimitry Andric if (NewAlignment > Alignment) {
22350b57cec5SDimitry Andric assert(llvm::isPowerOf2_64(NewAlignment.getQuantity()) &&
22360b57cec5SDimitry Andric "Alignment not a power of 2");
22370b57cec5SDimitry Andric Alignment = NewAlignment;
22380b57cec5SDimitry Andric }
22390b57cec5SDimitry Andric
22400b57cec5SDimitry Andric if (UnpackedNewAlignment > UnpackedAlignment) {
22410b57cec5SDimitry Andric assert(llvm::isPowerOf2_64(UnpackedNewAlignment.getQuantity()) &&
22420b57cec5SDimitry Andric "Alignment not a power of 2");
22430b57cec5SDimitry Andric UnpackedAlignment = UnpackedNewAlignment;
22440b57cec5SDimitry Andric }
2245e8d8bef9SDimitry Andric
2246e8d8bef9SDimitry Andric if (PreferredNewAlignment > PreferredAlignment) {
2247e8d8bef9SDimitry Andric assert(llvm::isPowerOf2_64(PreferredNewAlignment.getQuantity()) &&
2248e8d8bef9SDimitry Andric "Alignment not a power of 2");
2249e8d8bef9SDimitry Andric PreferredAlignment = PreferredNewAlignment;
2250e8d8bef9SDimitry Andric }
22510b57cec5SDimitry Andric }
22520b57cec5SDimitry Andric
22530b57cec5SDimitry Andric uint64_t
updateExternalFieldOffset(const FieldDecl * Field,uint64_t ComputedOffset)22540b57cec5SDimitry Andric ItaniumRecordLayoutBuilder::updateExternalFieldOffset(const FieldDecl *Field,
22550b57cec5SDimitry Andric uint64_t ComputedOffset) {
22560b57cec5SDimitry Andric uint64_t ExternalFieldOffset = External.getExternalFieldOffset(Field);
22570b57cec5SDimitry Andric
22580b57cec5SDimitry Andric if (InferAlignment && ExternalFieldOffset < ComputedOffset) {
22590b57cec5SDimitry Andric // The externally-supplied field offset is before the field offset we
22600b57cec5SDimitry Andric // computed. Assume that the structure is packed.
22610b57cec5SDimitry Andric Alignment = CharUnits::One();
2262e8d8bef9SDimitry Andric PreferredAlignment = CharUnits::One();
22630b57cec5SDimitry Andric InferAlignment = false;
22640b57cec5SDimitry Andric }
22650b57cec5SDimitry Andric
22660b57cec5SDimitry Andric // Use the externally-supplied field offset.
22670b57cec5SDimitry Andric return ExternalFieldOffset;
22680b57cec5SDimitry Andric }
22690b57cec5SDimitry Andric
22700b57cec5SDimitry Andric /// Get diagnostic %select index for tag kind for
22710b57cec5SDimitry Andric /// field padding diagnostic message.
22720b57cec5SDimitry Andric /// WARNING: Indexes apply to particular diagnostics only!
22730b57cec5SDimitry Andric ///
22740b57cec5SDimitry Andric /// \returns diagnostic %select index.
getPaddingDiagFromTagKind(TagTypeKind Tag)22750b57cec5SDimitry Andric static unsigned getPaddingDiagFromTagKind(TagTypeKind Tag) {
22760b57cec5SDimitry Andric switch (Tag) {
22775f757f3fSDimitry Andric case TagTypeKind::Struct:
22785f757f3fSDimitry Andric return 0;
22795f757f3fSDimitry Andric case TagTypeKind::Interface:
22805f757f3fSDimitry Andric return 1;
22815f757f3fSDimitry Andric case TagTypeKind::Class:
22825f757f3fSDimitry Andric return 2;
22830b57cec5SDimitry Andric default: llvm_unreachable("Invalid tag kind for field padding diagnostic!");
22840b57cec5SDimitry Andric }
22850b57cec5SDimitry Andric }
22860b57cec5SDimitry Andric
CheckFieldPadding(uint64_t Offset,uint64_t UnpaddedOffset,uint64_t UnpackedOffset,unsigned UnpackedAlign,bool isPacked,const FieldDecl * D)22870b57cec5SDimitry Andric void ItaniumRecordLayoutBuilder::CheckFieldPadding(
22880b57cec5SDimitry Andric uint64_t Offset, uint64_t UnpaddedOffset, uint64_t UnpackedOffset,
22890b57cec5SDimitry Andric unsigned UnpackedAlign, bool isPacked, const FieldDecl *D) {
22900b57cec5SDimitry Andric // We let objc ivars without warning, objc interfaces generally are not used
22910b57cec5SDimitry Andric // for padding tricks.
22920b57cec5SDimitry Andric if (isa<ObjCIvarDecl>(D))
22930b57cec5SDimitry Andric return;
22940b57cec5SDimitry Andric
22950b57cec5SDimitry Andric // Don't warn about structs created without a SourceLocation. This can
22960b57cec5SDimitry Andric // be done by clients of the AST, such as codegen.
22970b57cec5SDimitry Andric if (D->getLocation().isInvalid())
22980b57cec5SDimitry Andric return;
22990b57cec5SDimitry Andric
23000b57cec5SDimitry Andric unsigned CharBitNum = Context.getTargetInfo().getCharWidth();
23010b57cec5SDimitry Andric
23020b57cec5SDimitry Andric // Warn if padding was introduced to the struct/class.
23030b57cec5SDimitry Andric if (!IsUnion && Offset > UnpaddedOffset) {
23040b57cec5SDimitry Andric unsigned PadSize = Offset - UnpaddedOffset;
23050b57cec5SDimitry Andric bool InBits = true;
23060b57cec5SDimitry Andric if (PadSize % CharBitNum == 0) {
23070b57cec5SDimitry Andric PadSize = PadSize / CharBitNum;
23080b57cec5SDimitry Andric InBits = false;
23090b57cec5SDimitry Andric }
23105f757f3fSDimitry Andric if (D->getIdentifier()) {
23115f757f3fSDimitry Andric auto Diagnostic = D->isBitField() ? diag::warn_padded_struct_bitfield
23125f757f3fSDimitry Andric : diag::warn_padded_struct_field;
23135f757f3fSDimitry Andric Diag(D->getLocation(), Diagnostic)
23140b57cec5SDimitry Andric << getPaddingDiagFromTagKind(D->getParent()->getTagKind())
23155f757f3fSDimitry Andric << Context.getTypeDeclType(D->getParent()) << PadSize
23160b57cec5SDimitry Andric << (InBits ? 1 : 0) // (byte|bit)
23170b57cec5SDimitry Andric << D->getIdentifier();
23185f757f3fSDimitry Andric } else {
23195f757f3fSDimitry Andric auto Diagnostic = D->isBitField() ? diag::warn_padded_struct_anon_bitfield
23205f757f3fSDimitry Andric : diag::warn_padded_struct_anon_field;
23215f757f3fSDimitry Andric Diag(D->getLocation(), Diagnostic)
23220b57cec5SDimitry Andric << getPaddingDiagFromTagKind(D->getParent()->getTagKind())
23235f757f3fSDimitry Andric << Context.getTypeDeclType(D->getParent()) << PadSize
23240b57cec5SDimitry Andric << (InBits ? 1 : 0); // (byte|bit)
23250b57cec5SDimitry Andric }
23265f757f3fSDimitry Andric }
23270b57cec5SDimitry Andric if (isPacked && Offset != UnpackedOffset) {
23280b57cec5SDimitry Andric HasPackedField = true;
23290b57cec5SDimitry Andric }
23300b57cec5SDimitry Andric }
23310b57cec5SDimitry Andric
computeKeyFunction(ASTContext & Context,const CXXRecordDecl * RD)23320b57cec5SDimitry Andric static const CXXMethodDecl *computeKeyFunction(ASTContext &Context,
23330b57cec5SDimitry Andric const CXXRecordDecl *RD) {
23340b57cec5SDimitry Andric // If a class isn't polymorphic it doesn't have a key function.
23350b57cec5SDimitry Andric if (!RD->isPolymorphic())
23360b57cec5SDimitry Andric return nullptr;
23370b57cec5SDimitry Andric
23380b57cec5SDimitry Andric // A class that is not externally visible doesn't have a key function. (Or
23390b57cec5SDimitry Andric // at least, there's no point to assigning a key function to such a class;
23400b57cec5SDimitry Andric // this doesn't affect the ABI.)
23410b57cec5SDimitry Andric if (!RD->isExternallyVisible())
23420b57cec5SDimitry Andric return nullptr;
23430b57cec5SDimitry Andric
23440b57cec5SDimitry Andric // Template instantiations don't have key functions per Itanium C++ ABI 5.2.6.
23450b57cec5SDimitry Andric // Same behavior as GCC.
23460b57cec5SDimitry Andric TemplateSpecializationKind TSK = RD->getTemplateSpecializationKind();
23470b57cec5SDimitry Andric if (TSK == TSK_ImplicitInstantiation ||
23480b57cec5SDimitry Andric TSK == TSK_ExplicitInstantiationDeclaration ||
23490b57cec5SDimitry Andric TSK == TSK_ExplicitInstantiationDefinition)
23500b57cec5SDimitry Andric return nullptr;
23510b57cec5SDimitry Andric
23520b57cec5SDimitry Andric bool allowInlineFunctions =
23530b57cec5SDimitry Andric Context.getTargetInfo().getCXXABI().canKeyFunctionBeInline();
23540b57cec5SDimitry Andric
23550b57cec5SDimitry Andric for (const CXXMethodDecl *MD : RD->methods()) {
23560b57cec5SDimitry Andric if (!MD->isVirtual())
23570b57cec5SDimitry Andric continue;
23580b57cec5SDimitry Andric
23597a6dacacSDimitry Andric if (MD->isPureVirtual())
23600b57cec5SDimitry Andric continue;
23610b57cec5SDimitry Andric
23620b57cec5SDimitry Andric // Ignore implicit member functions, they are always marked as inline, but
23630b57cec5SDimitry Andric // they don't have a body until they're defined.
23640b57cec5SDimitry Andric if (MD->isImplicit())
23650b57cec5SDimitry Andric continue;
23660b57cec5SDimitry Andric
23675ffd83dbSDimitry Andric if (MD->isInlineSpecified() || MD->isConstexpr())
23680b57cec5SDimitry Andric continue;
23690b57cec5SDimitry Andric
23700b57cec5SDimitry Andric if (MD->hasInlineBody())
23710b57cec5SDimitry Andric continue;
23720b57cec5SDimitry Andric
23730b57cec5SDimitry Andric // Ignore inline deleted or defaulted functions.
23740b57cec5SDimitry Andric if (!MD->isUserProvided())
23750b57cec5SDimitry Andric continue;
23760b57cec5SDimitry Andric
23770b57cec5SDimitry Andric // In certain ABIs, ignore functions with out-of-line inline definitions.
23780b57cec5SDimitry Andric if (!allowInlineFunctions) {
23790b57cec5SDimitry Andric const FunctionDecl *Def;
23800b57cec5SDimitry Andric if (MD->hasBody(Def) && Def->isInlineSpecified())
23810b57cec5SDimitry Andric continue;
23820b57cec5SDimitry Andric }
23830b57cec5SDimitry Andric
23840b57cec5SDimitry Andric if (Context.getLangOpts().CUDA) {
23850b57cec5SDimitry Andric // While compiler may see key method in this TU, during CUDA
23860b57cec5SDimitry Andric // compilation we should ignore methods that are not accessible
23870b57cec5SDimitry Andric // on this side of compilation.
23880b57cec5SDimitry Andric if (Context.getLangOpts().CUDAIsDevice) {
23890b57cec5SDimitry Andric // In device mode ignore methods without __device__ attribute.
23900b57cec5SDimitry Andric if (!MD->hasAttr<CUDADeviceAttr>())
23910b57cec5SDimitry Andric continue;
23920b57cec5SDimitry Andric } else {
23930b57cec5SDimitry Andric // In host mode ignore __device__-only methods.
23940b57cec5SDimitry Andric if (!MD->hasAttr<CUDAHostAttr>() && MD->hasAttr<CUDADeviceAttr>())
23950b57cec5SDimitry Andric continue;
23960b57cec5SDimitry Andric }
23970b57cec5SDimitry Andric }
23980b57cec5SDimitry Andric
23990b57cec5SDimitry Andric // If the key function is dllimport but the class isn't, then the class has
24000b57cec5SDimitry Andric // no key function. The DLL that exports the key function won't export the
24010b57cec5SDimitry Andric // vtable in this case.
2402fe6060f1SDimitry Andric if (MD->hasAttr<DLLImportAttr>() && !RD->hasAttr<DLLImportAttr>() &&
2403fe6060f1SDimitry Andric !Context.getTargetInfo().hasPS4DLLImportExport())
24040b57cec5SDimitry Andric return nullptr;
24050b57cec5SDimitry Andric
24060b57cec5SDimitry Andric // We found it.
24070b57cec5SDimitry Andric return MD;
24080b57cec5SDimitry Andric }
24090b57cec5SDimitry Andric
24100b57cec5SDimitry Andric return nullptr;
24110b57cec5SDimitry Andric }
24120b57cec5SDimitry Andric
Diag(SourceLocation Loc,unsigned DiagID)24130b57cec5SDimitry Andric DiagnosticBuilder ItaniumRecordLayoutBuilder::Diag(SourceLocation Loc,
24140b57cec5SDimitry Andric unsigned DiagID) {
24150b57cec5SDimitry Andric return Context.getDiagnostics().Report(Loc, DiagID);
24160b57cec5SDimitry Andric }
24170b57cec5SDimitry Andric
24180b57cec5SDimitry Andric /// Does the target C++ ABI require us to skip over the tail-padding
24190b57cec5SDimitry Andric /// of the given class (considering it as a base class) when allocating
24200b57cec5SDimitry Andric /// objects?
mustSkipTailPadding(TargetCXXABI ABI,const CXXRecordDecl * RD)24210b57cec5SDimitry Andric static bool mustSkipTailPadding(TargetCXXABI ABI, const CXXRecordDecl *RD) {
24220b57cec5SDimitry Andric switch (ABI.getTailPaddingUseRules()) {
24230b57cec5SDimitry Andric case TargetCXXABI::AlwaysUseTailPadding:
24240b57cec5SDimitry Andric return false;
24250b57cec5SDimitry Andric
24260b57cec5SDimitry Andric case TargetCXXABI::UseTailPaddingUnlessPOD03:
24270b57cec5SDimitry Andric // FIXME: To the extent that this is meant to cover the Itanium ABI
24280b57cec5SDimitry Andric // rules, we should implement the restrictions about over-sized
24290b57cec5SDimitry Andric // bitfields:
24300b57cec5SDimitry Andric //
24310b57cec5SDimitry Andric // http://itanium-cxx-abi.github.io/cxx-abi/abi.html#POD :
24320b57cec5SDimitry Andric // In general, a type is considered a POD for the purposes of
24330b57cec5SDimitry Andric // layout if it is a POD type (in the sense of ISO C++
24340b57cec5SDimitry Andric // [basic.types]). However, a POD-struct or POD-union (in the
24350b57cec5SDimitry Andric // sense of ISO C++ [class]) with a bitfield member whose
24360b57cec5SDimitry Andric // declared width is wider than the declared type of the
24370b57cec5SDimitry Andric // bitfield is not a POD for the purpose of layout. Similarly,
24380b57cec5SDimitry Andric // an array type is not a POD for the purpose of layout if the
24390b57cec5SDimitry Andric // element type of the array is not a POD for the purpose of
24400b57cec5SDimitry Andric // layout.
24410b57cec5SDimitry Andric //
24420b57cec5SDimitry Andric // Where references to the ISO C++ are made in this paragraph,
24430b57cec5SDimitry Andric // the Technical Corrigendum 1 version of the standard is
24440b57cec5SDimitry Andric // intended.
24450b57cec5SDimitry Andric return RD->isPOD();
24460b57cec5SDimitry Andric
24470b57cec5SDimitry Andric case TargetCXXABI::UseTailPaddingUnlessPOD11:
24480b57cec5SDimitry Andric // This is equivalent to RD->getTypeForDecl().isCXX11PODType(),
24490b57cec5SDimitry Andric // but with a lot of abstraction penalty stripped off. This does
24500b57cec5SDimitry Andric // assume that these properties are set correctly even in C++98
24510b57cec5SDimitry Andric // mode; fortunately, that is true because we want to assign
24520b57cec5SDimitry Andric // consistently semantics to the type-traits intrinsics (or at
24530b57cec5SDimitry Andric // least as many of them as possible).
24540b57cec5SDimitry Andric return RD->isTrivial() && RD->isCXX11StandardLayout();
24550b57cec5SDimitry Andric }
24560b57cec5SDimitry Andric
24570b57cec5SDimitry Andric llvm_unreachable("bad tail-padding use kind");
24580b57cec5SDimitry Andric }
24590b57cec5SDimitry Andric
isMsLayout(const ASTContext & Context)24600b57cec5SDimitry Andric static bool isMsLayout(const ASTContext &Context) {
2461*0fca6ea1SDimitry Andric // Check if it's CUDA device compilation; ensure layout consistency with host.
2462*0fca6ea1SDimitry Andric if (Context.getLangOpts().CUDA && Context.getLangOpts().CUDAIsDevice &&
2463*0fca6ea1SDimitry Andric Context.getAuxTargetInfo())
2464*0fca6ea1SDimitry Andric return Context.getAuxTargetInfo()->getCXXABI().isMicrosoft();
2465*0fca6ea1SDimitry Andric
24660b57cec5SDimitry Andric return Context.getTargetInfo().getCXXABI().isMicrosoft();
24670b57cec5SDimitry Andric }
24680b57cec5SDimitry Andric
24690b57cec5SDimitry Andric // This section contains an implementation of struct layout that is, up to the
24700b57cec5SDimitry Andric // included tests, compatible with cl.exe (2013). The layout produced is
24710b57cec5SDimitry Andric // significantly different than those produced by the Itanium ABI. Here we note
24720b57cec5SDimitry Andric // the most important differences.
24730b57cec5SDimitry Andric //
24740b57cec5SDimitry Andric // * The alignment of bitfields in unions is ignored when computing the
24750b57cec5SDimitry Andric // alignment of the union.
24760b57cec5SDimitry Andric // * The existence of zero-width bitfield that occurs after anything other than
24770b57cec5SDimitry Andric // a non-zero length bitfield is ignored.
24780b57cec5SDimitry Andric // * There is no explicit primary base for the purposes of layout. All bases
24790b57cec5SDimitry Andric // with vfptrs are laid out first, followed by all bases without vfptrs.
24800b57cec5SDimitry Andric // * The Itanium equivalent vtable pointers are split into a vfptr (virtual
24810b57cec5SDimitry Andric // function pointer) and a vbptr (virtual base pointer). They can each be
24820b57cec5SDimitry Andric // shared with a, non-virtual bases. These bases need not be the same. vfptrs
24830b57cec5SDimitry Andric // always occur at offset 0. vbptrs can occur at an arbitrary offset and are
24840b57cec5SDimitry Andric // placed after the lexicographically last non-virtual base. This placement
24850b57cec5SDimitry Andric // is always before fields but can be in the middle of the non-virtual bases
24860b57cec5SDimitry Andric // due to the two-pass layout scheme for non-virtual-bases.
24870b57cec5SDimitry Andric // * Virtual bases sometimes require a 'vtordisp' field that is laid out before
24880b57cec5SDimitry Andric // the virtual base and is used in conjunction with virtual overrides during
24890b57cec5SDimitry Andric // construction and destruction. This is always a 4 byte value and is used as
24900b57cec5SDimitry Andric // an alternative to constructor vtables.
24910b57cec5SDimitry Andric // * vtordisps are allocated in a block of memory with size and alignment equal
24920b57cec5SDimitry Andric // to the alignment of the completed structure (before applying __declspec(
24930b57cec5SDimitry Andric // align())). The vtordisp always occur at the end of the allocation block,
24940b57cec5SDimitry Andric // immediately prior to the virtual base.
24950b57cec5SDimitry Andric // * vfptrs are injected after all bases and fields have been laid out. In
24960b57cec5SDimitry Andric // order to guarantee proper alignment of all fields, the vfptr injection
24970b57cec5SDimitry Andric // pushes all bases and fields back by the alignment imposed by those bases
24980b57cec5SDimitry Andric // and fields. This can potentially add a significant amount of padding.
24990b57cec5SDimitry Andric // vfptrs are always injected at offset 0.
25000b57cec5SDimitry Andric // * vbptrs are injected after all bases and fields have been laid out. In
25010b57cec5SDimitry Andric // order to guarantee proper alignment of all fields, the vfptr injection
25020b57cec5SDimitry Andric // pushes all bases and fields back by the alignment imposed by those bases
25030b57cec5SDimitry Andric // and fields. This can potentially add a significant amount of padding.
25040b57cec5SDimitry Andric // vbptrs are injected immediately after the last non-virtual base as
25050b57cec5SDimitry Andric // lexicographically ordered in the code. If this site isn't pointer aligned
25060b57cec5SDimitry Andric // the vbptr is placed at the next properly aligned location. Enough padding
25070b57cec5SDimitry Andric // is added to guarantee a fit.
25080b57cec5SDimitry Andric // * The last zero sized non-virtual base can be placed at the end of the
25090b57cec5SDimitry Andric // struct (potentially aliasing another object), or may alias with the first
25100b57cec5SDimitry Andric // field, even if they are of the same type.
25110b57cec5SDimitry Andric // * The last zero size virtual base may be placed at the end of the struct
25120b57cec5SDimitry Andric // potentially aliasing another object.
25130b57cec5SDimitry Andric // * The ABI attempts to avoid aliasing of zero sized bases by adding padding
25140b57cec5SDimitry Andric // between bases or vbases with specific properties. The criteria for
25150b57cec5SDimitry Andric // additional padding between two bases is that the first base is zero sized
25160b57cec5SDimitry Andric // or ends with a zero sized subobject and the second base is zero sized or
25170b57cec5SDimitry Andric // trails with a zero sized base or field (sharing of vfptrs can reorder the
25180b57cec5SDimitry Andric // layout of the so the leading base is not always the first one declared).
25190b57cec5SDimitry Andric // This rule does take into account fields that are not records, so padding
25200b57cec5SDimitry Andric // will occur even if the last field is, e.g. an int. The padding added for
25210b57cec5SDimitry Andric // bases is 1 byte. The padding added between vbases depends on the alignment
25220b57cec5SDimitry Andric // of the object but is at least 4 bytes (in both 32 and 64 bit modes).
25230b57cec5SDimitry Andric // * There is no concept of non-virtual alignment, non-virtual alignment and
25240b57cec5SDimitry Andric // alignment are always identical.
25250b57cec5SDimitry Andric // * There is a distinction between alignment and required alignment.
25260b57cec5SDimitry Andric // __declspec(align) changes the required alignment of a struct. This
25270b57cec5SDimitry Andric // alignment is _always_ obeyed, even in the presence of #pragma pack. A
25280b57cec5SDimitry Andric // record inherits required alignment from all of its fields and bases.
25290b57cec5SDimitry Andric // * __declspec(align) on bitfields has the effect of changing the bitfield's
25300b57cec5SDimitry Andric // alignment instead of its required alignment. This is the only known way
25310b57cec5SDimitry Andric // to make the alignment of a struct bigger than 8. Interestingly enough
25320b57cec5SDimitry Andric // this alignment is also immune to the effects of #pragma pack and can be
25330b57cec5SDimitry Andric // used to create structures with large alignment under #pragma pack.
25340b57cec5SDimitry Andric // However, because it does not impact required alignment, such a structure,
25350b57cec5SDimitry Andric // when used as a field or base, will not be aligned if #pragma pack is
25360b57cec5SDimitry Andric // still active at the time of use.
25370b57cec5SDimitry Andric //
25380b57cec5SDimitry Andric // Known incompatibilities:
25390b57cec5SDimitry Andric // * all: #pragma pack between fields in a record
25400b57cec5SDimitry Andric // * 2010 and back: If the last field in a record is a bitfield, every object
25410b57cec5SDimitry Andric // laid out after the record will have extra padding inserted before it. The
25420b57cec5SDimitry Andric // extra padding will have size equal to the size of the storage class of the
25430b57cec5SDimitry Andric // bitfield. 0 sized bitfields don't exhibit this behavior and the extra
25440b57cec5SDimitry Andric // padding can be avoided by adding a 0 sized bitfield after the non-zero-
25450b57cec5SDimitry Andric // sized bitfield.
25460b57cec5SDimitry Andric // * 2012 and back: In 64-bit mode, if the alignment of a record is 16 or
25470b57cec5SDimitry Andric // greater due to __declspec(align()) then a second layout phase occurs after
25480b57cec5SDimitry Andric // The locations of the vf and vb pointers are known. This layout phase
25490b57cec5SDimitry Andric // suffers from the "last field is a bitfield" bug in 2010 and results in
25500b57cec5SDimitry Andric // _every_ field getting padding put in front of it, potentially including the
25510b57cec5SDimitry Andric // vfptr, leaving the vfprt at a non-zero location which results in a fault if
25520b57cec5SDimitry Andric // anything tries to read the vftbl. The second layout phase also treats
25530b57cec5SDimitry Andric // bitfields as separate entities and gives them each storage rather than
25540b57cec5SDimitry Andric // packing them. Additionally, because this phase appears to perform a
25550b57cec5SDimitry Andric // (an unstable) sort on the members before laying them out and because merged
25560b57cec5SDimitry Andric // bitfields have the same address, the bitfields end up in whatever order
25570b57cec5SDimitry Andric // the sort left them in, a behavior we could never hope to replicate.
25580b57cec5SDimitry Andric
25590b57cec5SDimitry Andric namespace {
25600b57cec5SDimitry Andric struct MicrosoftRecordLayoutBuilder {
25610b57cec5SDimitry Andric struct ElementInfo {
25620b57cec5SDimitry Andric CharUnits Size;
25630b57cec5SDimitry Andric CharUnits Alignment;
25640b57cec5SDimitry Andric };
25650b57cec5SDimitry Andric typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
MicrosoftRecordLayoutBuilder__anonbcc347f50611::MicrosoftRecordLayoutBuilder25665f757f3fSDimitry Andric MicrosoftRecordLayoutBuilder(const ASTContext &Context,
25675f757f3fSDimitry Andric EmptySubobjectMap *EmptySubobjects)
25685f757f3fSDimitry Andric : Context(Context), EmptySubobjects(EmptySubobjects) {}
25695f757f3fSDimitry Andric
25700b57cec5SDimitry Andric private:
25710b57cec5SDimitry Andric MicrosoftRecordLayoutBuilder(const MicrosoftRecordLayoutBuilder &) = delete;
25720b57cec5SDimitry Andric void operator=(const MicrosoftRecordLayoutBuilder &) = delete;
25730b57cec5SDimitry Andric public:
25740b57cec5SDimitry Andric void layout(const RecordDecl *RD);
25750b57cec5SDimitry Andric void cxxLayout(const CXXRecordDecl *RD);
25760b57cec5SDimitry Andric /// Initializes size and alignment and honors some flags.
25770b57cec5SDimitry Andric void initializeLayout(const RecordDecl *RD);
25780b57cec5SDimitry Andric /// Initialized C++ layout, compute alignment and virtual alignment and
25790b57cec5SDimitry Andric /// existence of vfptrs and vbptrs. Alignment is needed before the vfptr is
25800b57cec5SDimitry Andric /// laid out.
25810b57cec5SDimitry Andric void initializeCXXLayout(const CXXRecordDecl *RD);
25820b57cec5SDimitry Andric void layoutNonVirtualBases(const CXXRecordDecl *RD);
25830b57cec5SDimitry Andric void layoutNonVirtualBase(const CXXRecordDecl *RD,
25840b57cec5SDimitry Andric const CXXRecordDecl *BaseDecl,
25850b57cec5SDimitry Andric const ASTRecordLayout &BaseLayout,
25860b57cec5SDimitry Andric const ASTRecordLayout *&PreviousBaseLayout);
25870b57cec5SDimitry Andric void injectVFPtr(const CXXRecordDecl *RD);
25880b57cec5SDimitry Andric void injectVBPtr(const CXXRecordDecl *RD);
25890b57cec5SDimitry Andric /// Lays out the fields of the record. Also rounds size up to
25900b57cec5SDimitry Andric /// alignment.
25910b57cec5SDimitry Andric void layoutFields(const RecordDecl *RD);
25920b57cec5SDimitry Andric void layoutField(const FieldDecl *FD);
25930b57cec5SDimitry Andric void layoutBitField(const FieldDecl *FD);
25940b57cec5SDimitry Andric /// Lays out a single zero-width bit-field in the record and handles
25950b57cec5SDimitry Andric /// special cases associated with zero-width bit-fields.
25960b57cec5SDimitry Andric void layoutZeroWidthBitField(const FieldDecl *FD);
25970b57cec5SDimitry Andric void layoutVirtualBases(const CXXRecordDecl *RD);
25980b57cec5SDimitry Andric void finalizeLayout(const RecordDecl *RD);
25990b57cec5SDimitry Andric /// Gets the size and alignment of a base taking pragma pack and
26000b57cec5SDimitry Andric /// __declspec(align) into account.
26010b57cec5SDimitry Andric ElementInfo getAdjustedElementInfo(const ASTRecordLayout &Layout);
26020b57cec5SDimitry Andric /// Gets the size and alignment of a field taking pragma pack and
26030b57cec5SDimitry Andric /// __declspec(align) into account. It also updates RequiredAlignment as a
26040b57cec5SDimitry Andric /// side effect because it is most convenient to do so here.
26050b57cec5SDimitry Andric ElementInfo getAdjustedElementInfo(const FieldDecl *FD);
26060b57cec5SDimitry Andric /// Places a field at an offset in CharUnits.
placeFieldAtOffset__anonbcc347f50611::MicrosoftRecordLayoutBuilder26070b57cec5SDimitry Andric void placeFieldAtOffset(CharUnits FieldOffset) {
26080b57cec5SDimitry Andric FieldOffsets.push_back(Context.toBits(FieldOffset));
26090b57cec5SDimitry Andric }
26100b57cec5SDimitry Andric /// Places a bitfield at a bit offset.
placeFieldAtBitOffset__anonbcc347f50611::MicrosoftRecordLayoutBuilder26110b57cec5SDimitry Andric void placeFieldAtBitOffset(uint64_t FieldOffset) {
26120b57cec5SDimitry Andric FieldOffsets.push_back(FieldOffset);
26130b57cec5SDimitry Andric }
26140b57cec5SDimitry Andric /// Compute the set of virtual bases for which vtordisps are required.
26150b57cec5SDimitry Andric void computeVtorDispSet(
26160b57cec5SDimitry Andric llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtorDispSet,
26170b57cec5SDimitry Andric const CXXRecordDecl *RD) const;
26180b57cec5SDimitry Andric const ASTContext &Context;
26195f757f3fSDimitry Andric EmptySubobjectMap *EmptySubobjects;
26205f757f3fSDimitry Andric
26210b57cec5SDimitry Andric /// The size of the record being laid out.
26220b57cec5SDimitry Andric CharUnits Size;
26230b57cec5SDimitry Andric /// The non-virtual size of the record layout.
26240b57cec5SDimitry Andric CharUnits NonVirtualSize;
26250b57cec5SDimitry Andric /// The data size of the record layout.
26260b57cec5SDimitry Andric CharUnits DataSize;
26270b57cec5SDimitry Andric /// The current alignment of the record layout.
26280b57cec5SDimitry Andric CharUnits Alignment;
26290b57cec5SDimitry Andric /// The maximum allowed field alignment. This is set by #pragma pack.
26300b57cec5SDimitry Andric CharUnits MaxFieldAlignment;
26310b57cec5SDimitry Andric /// The alignment that this record must obey. This is imposed by
26320b57cec5SDimitry Andric /// __declspec(align()) on the record itself or one of its fields or bases.
26330b57cec5SDimitry Andric CharUnits RequiredAlignment;
26340b57cec5SDimitry Andric /// The size of the allocation of the currently active bitfield.
26350b57cec5SDimitry Andric /// This value isn't meaningful unless LastFieldIsNonZeroWidthBitfield
26360b57cec5SDimitry Andric /// is true.
26370b57cec5SDimitry Andric CharUnits CurrentBitfieldSize;
26380b57cec5SDimitry Andric /// Offset to the virtual base table pointer (if one exists).
26390b57cec5SDimitry Andric CharUnits VBPtrOffset;
26400b57cec5SDimitry Andric /// Minimum record size possible.
26410b57cec5SDimitry Andric CharUnits MinEmptyStructSize;
26420b57cec5SDimitry Andric /// The size and alignment info of a pointer.
26430b57cec5SDimitry Andric ElementInfo PointerInfo;
26440b57cec5SDimitry Andric /// The primary base class (if one exists).
26450b57cec5SDimitry Andric const CXXRecordDecl *PrimaryBase;
26460b57cec5SDimitry Andric /// The class we share our vb-pointer with.
26470b57cec5SDimitry Andric const CXXRecordDecl *SharedVBPtrBase;
26480b57cec5SDimitry Andric /// The collection of field offsets.
26490b57cec5SDimitry Andric SmallVector<uint64_t, 16> FieldOffsets;
26500b57cec5SDimitry Andric /// Base classes and their offsets in the record.
26510b57cec5SDimitry Andric BaseOffsetsMapTy Bases;
26520b57cec5SDimitry Andric /// virtual base classes and their offsets in the record.
26530b57cec5SDimitry Andric ASTRecordLayout::VBaseOffsetsMapTy VBases;
26540b57cec5SDimitry Andric /// The number of remaining bits in our last bitfield allocation.
26550b57cec5SDimitry Andric /// This value isn't meaningful unless LastFieldIsNonZeroWidthBitfield is
26560b57cec5SDimitry Andric /// true.
26570b57cec5SDimitry Andric unsigned RemainingBitsInField;
26580b57cec5SDimitry Andric bool IsUnion : 1;
26590b57cec5SDimitry Andric /// True if the last field laid out was a bitfield and was not 0
26600b57cec5SDimitry Andric /// width.
26610b57cec5SDimitry Andric bool LastFieldIsNonZeroWidthBitfield : 1;
26620b57cec5SDimitry Andric /// True if the class has its own vftable pointer.
26630b57cec5SDimitry Andric bool HasOwnVFPtr : 1;
26640b57cec5SDimitry Andric /// True if the class has a vbtable pointer.
26650b57cec5SDimitry Andric bool HasVBPtr : 1;
26660b57cec5SDimitry Andric /// True if the last sub-object within the type is zero sized or the
26670b57cec5SDimitry Andric /// object itself is zero sized. This *does not* count members that are not
26680b57cec5SDimitry Andric /// records. Only used for MS-ABI.
26690b57cec5SDimitry Andric bool EndsWithZeroSizedObject : 1;
26700b57cec5SDimitry Andric /// True if this class is zero sized or first base is zero sized or
26710b57cec5SDimitry Andric /// has this property. Only used for MS-ABI.
26720b57cec5SDimitry Andric bool LeadsWithZeroSizedBase : 1;
26730b57cec5SDimitry Andric
26740b57cec5SDimitry Andric /// True if the external AST source provided a layout for this record.
26750b57cec5SDimitry Andric bool UseExternalLayout : 1;
26760b57cec5SDimitry Andric
26770b57cec5SDimitry Andric /// The layout provided by the external AST source. Only active if
26780b57cec5SDimitry Andric /// UseExternalLayout is true.
26790b57cec5SDimitry Andric ExternalLayout External;
26800b57cec5SDimitry Andric };
26810b57cec5SDimitry Andric } // namespace
26820b57cec5SDimitry Andric
26830b57cec5SDimitry Andric MicrosoftRecordLayoutBuilder::ElementInfo
getAdjustedElementInfo(const ASTRecordLayout & Layout)26840b57cec5SDimitry Andric MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
26850b57cec5SDimitry Andric const ASTRecordLayout &Layout) {
26860b57cec5SDimitry Andric ElementInfo Info;
26870b57cec5SDimitry Andric Info.Alignment = Layout.getAlignment();
26880b57cec5SDimitry Andric // Respect pragma pack.
26890b57cec5SDimitry Andric if (!MaxFieldAlignment.isZero())
26900b57cec5SDimitry Andric Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment);
26910b57cec5SDimitry Andric // Track zero-sized subobjects here where it's already available.
26920b57cec5SDimitry Andric EndsWithZeroSizedObject = Layout.endsWithZeroSizedObject();
26930b57cec5SDimitry Andric // Respect required alignment, this is necessary because we may have adjusted
2694349cc55cSDimitry Andric // the alignment in the case of pragma pack. Note that the required alignment
26950b57cec5SDimitry Andric // doesn't actually apply to the struct alignment at this point.
26960b57cec5SDimitry Andric Alignment = std::max(Alignment, Info.Alignment);
26970b57cec5SDimitry Andric RequiredAlignment = std::max(RequiredAlignment, Layout.getRequiredAlignment());
26980b57cec5SDimitry Andric Info.Alignment = std::max(Info.Alignment, Layout.getRequiredAlignment());
26990b57cec5SDimitry Andric Info.Size = Layout.getNonVirtualSize();
27000b57cec5SDimitry Andric return Info;
27010b57cec5SDimitry Andric }
27020b57cec5SDimitry Andric
27030b57cec5SDimitry Andric MicrosoftRecordLayoutBuilder::ElementInfo
getAdjustedElementInfo(const FieldDecl * FD)27040b57cec5SDimitry Andric MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
27050b57cec5SDimitry Andric const FieldDecl *FD) {
27060b57cec5SDimitry Andric // Get the alignment of the field type's natural alignment, ignore any
27070b57cec5SDimitry Andric // alignment attributes.
2708e8d8bef9SDimitry Andric auto TInfo =
27090b57cec5SDimitry Andric Context.getTypeInfoInChars(FD->getType()->getUnqualifiedDesugaredType());
2710e8d8bef9SDimitry Andric ElementInfo Info{TInfo.Width, TInfo.Align};
27110b57cec5SDimitry Andric // Respect align attributes on the field.
27120b57cec5SDimitry Andric CharUnits FieldRequiredAlignment =
27130b57cec5SDimitry Andric Context.toCharUnitsFromBits(FD->getMaxAlignment());
27140b57cec5SDimitry Andric // Respect align attributes on the type.
27150b57cec5SDimitry Andric if (Context.isAlignmentRequired(FD->getType()))
27160b57cec5SDimitry Andric FieldRequiredAlignment = std::max(
27170b57cec5SDimitry Andric Context.getTypeAlignInChars(FD->getType()), FieldRequiredAlignment);
27180b57cec5SDimitry Andric // Respect attributes applied to subobjects of the field.
27190b57cec5SDimitry Andric if (FD->isBitField())
27200b57cec5SDimitry Andric // For some reason __declspec align impacts alignment rather than required
27210b57cec5SDimitry Andric // alignment when it is applied to bitfields.
27220b57cec5SDimitry Andric Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment);
27230b57cec5SDimitry Andric else {
27240b57cec5SDimitry Andric if (auto RT =
27250b57cec5SDimitry Andric FD->getType()->getBaseElementTypeUnsafe()->getAs<RecordType>()) {
27260b57cec5SDimitry Andric auto const &Layout = Context.getASTRecordLayout(RT->getDecl());
27270b57cec5SDimitry Andric EndsWithZeroSizedObject = Layout.endsWithZeroSizedObject();
27280b57cec5SDimitry Andric FieldRequiredAlignment = std::max(FieldRequiredAlignment,
27290b57cec5SDimitry Andric Layout.getRequiredAlignment());
27300b57cec5SDimitry Andric }
27310b57cec5SDimitry Andric // Capture required alignment as a side-effect.
27320b57cec5SDimitry Andric RequiredAlignment = std::max(RequiredAlignment, FieldRequiredAlignment);
27330b57cec5SDimitry Andric }
27340b57cec5SDimitry Andric // Respect pragma pack, attribute pack and declspec align
27350b57cec5SDimitry Andric if (!MaxFieldAlignment.isZero())
27360b57cec5SDimitry Andric Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment);
27370b57cec5SDimitry Andric if (FD->hasAttr<PackedAttr>())
27380b57cec5SDimitry Andric Info.Alignment = CharUnits::One();
27390b57cec5SDimitry Andric Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment);
27400b57cec5SDimitry Andric return Info;
27410b57cec5SDimitry Andric }
27420b57cec5SDimitry Andric
layout(const RecordDecl * RD)27430b57cec5SDimitry Andric void MicrosoftRecordLayoutBuilder::layout(const RecordDecl *RD) {
27440b57cec5SDimitry Andric // For C record layout, zero-sized records always have size 4.
27450b57cec5SDimitry Andric MinEmptyStructSize = CharUnits::fromQuantity(4);
27460b57cec5SDimitry Andric initializeLayout(RD);
27470b57cec5SDimitry Andric layoutFields(RD);
27480b57cec5SDimitry Andric DataSize = Size = Size.alignTo(Alignment);
27490b57cec5SDimitry Andric RequiredAlignment = std::max(
27500b57cec5SDimitry Andric RequiredAlignment, Context.toCharUnitsFromBits(RD->getMaxAlignment()));
27510b57cec5SDimitry Andric finalizeLayout(RD);
27520b57cec5SDimitry Andric }
27530b57cec5SDimitry Andric
cxxLayout(const CXXRecordDecl * RD)27540b57cec5SDimitry Andric void MicrosoftRecordLayoutBuilder::cxxLayout(const CXXRecordDecl *RD) {
27550b57cec5SDimitry Andric // The C++ standard says that empty structs have size 1.
27560b57cec5SDimitry Andric MinEmptyStructSize = CharUnits::One();
27570b57cec5SDimitry Andric initializeLayout(RD);
27580b57cec5SDimitry Andric initializeCXXLayout(RD);
27590b57cec5SDimitry Andric layoutNonVirtualBases(RD);
27600b57cec5SDimitry Andric layoutFields(RD);
27610b57cec5SDimitry Andric injectVBPtr(RD);
27620b57cec5SDimitry Andric injectVFPtr(RD);
27630b57cec5SDimitry Andric if (HasOwnVFPtr || (HasVBPtr && !SharedVBPtrBase))
27640b57cec5SDimitry Andric Alignment = std::max(Alignment, PointerInfo.Alignment);
27650b57cec5SDimitry Andric auto RoundingAlignment = Alignment;
27660b57cec5SDimitry Andric if (!MaxFieldAlignment.isZero())
27670b57cec5SDimitry Andric RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment);
27680b57cec5SDimitry Andric if (!UseExternalLayout)
27690b57cec5SDimitry Andric Size = Size.alignTo(RoundingAlignment);
27700b57cec5SDimitry Andric NonVirtualSize = Size;
27710b57cec5SDimitry Andric RequiredAlignment = std::max(
27720b57cec5SDimitry Andric RequiredAlignment, Context.toCharUnitsFromBits(RD->getMaxAlignment()));
27730b57cec5SDimitry Andric layoutVirtualBases(RD);
27740b57cec5SDimitry Andric finalizeLayout(RD);
27750b57cec5SDimitry Andric }
27760b57cec5SDimitry Andric
initializeLayout(const RecordDecl * RD)27770b57cec5SDimitry Andric void MicrosoftRecordLayoutBuilder::initializeLayout(const RecordDecl *RD) {
27780b57cec5SDimitry Andric IsUnion = RD->isUnion();
27790b57cec5SDimitry Andric Size = CharUnits::Zero();
27800b57cec5SDimitry Andric Alignment = CharUnits::One();
27810b57cec5SDimitry Andric // In 64-bit mode we always perform an alignment step after laying out vbases.
27820b57cec5SDimitry Andric // In 32-bit mode we do not. The check to see if we need to perform alignment
27830b57cec5SDimitry Andric // checks the RequiredAlignment field and performs alignment if it isn't 0.
27840b57cec5SDimitry Andric RequiredAlignment = Context.getTargetInfo().getTriple().isArch64Bit()
27850b57cec5SDimitry Andric ? CharUnits::One()
27860b57cec5SDimitry Andric : CharUnits::Zero();
27870b57cec5SDimitry Andric // Compute the maximum field alignment.
27880b57cec5SDimitry Andric MaxFieldAlignment = CharUnits::Zero();
27890b57cec5SDimitry Andric // Honor the default struct packing maximum alignment flag.
27900b57cec5SDimitry Andric if (unsigned DefaultMaxFieldAlignment = Context.getLangOpts().PackStruct)
27910b57cec5SDimitry Andric MaxFieldAlignment = CharUnits::fromQuantity(DefaultMaxFieldAlignment);
27920b57cec5SDimitry Andric // Honor the packing attribute. The MS-ABI ignores pragma pack if its larger
27930b57cec5SDimitry Andric // than the pointer size.
27940b57cec5SDimitry Andric if (const MaxFieldAlignmentAttr *MFAA = RD->getAttr<MaxFieldAlignmentAttr>()){
27950b57cec5SDimitry Andric unsigned PackedAlignment = MFAA->getAlignment();
2796bdd1243dSDimitry Andric if (PackedAlignment <=
2797bdd1243dSDimitry Andric Context.getTargetInfo().getPointerWidth(LangAS::Default))
27980b57cec5SDimitry Andric MaxFieldAlignment = Context.toCharUnitsFromBits(PackedAlignment);
27990b57cec5SDimitry Andric }
28000b57cec5SDimitry Andric // Packed attribute forces max field alignment to be 1.
28010b57cec5SDimitry Andric if (RD->hasAttr<PackedAttr>())
28020b57cec5SDimitry Andric MaxFieldAlignment = CharUnits::One();
28030b57cec5SDimitry Andric
28040b57cec5SDimitry Andric // Try to respect the external layout if present.
28050b57cec5SDimitry Andric UseExternalLayout = false;
28060b57cec5SDimitry Andric if (ExternalASTSource *Source = Context.getExternalSource())
28070b57cec5SDimitry Andric UseExternalLayout = Source->layoutRecordType(
28080b57cec5SDimitry Andric RD, External.Size, External.Align, External.FieldOffsets,
28090b57cec5SDimitry Andric External.BaseOffsets, External.VirtualBaseOffsets);
28100b57cec5SDimitry Andric }
28110b57cec5SDimitry Andric
28120b57cec5SDimitry Andric void
initializeCXXLayout(const CXXRecordDecl * RD)28130b57cec5SDimitry Andric MicrosoftRecordLayoutBuilder::initializeCXXLayout(const CXXRecordDecl *RD) {
28140b57cec5SDimitry Andric EndsWithZeroSizedObject = false;
28150b57cec5SDimitry Andric LeadsWithZeroSizedBase = false;
28160b57cec5SDimitry Andric HasOwnVFPtr = false;
28170b57cec5SDimitry Andric HasVBPtr = false;
28180b57cec5SDimitry Andric PrimaryBase = nullptr;
28190b57cec5SDimitry Andric SharedVBPtrBase = nullptr;
28200b57cec5SDimitry Andric // Calculate pointer size and alignment. These are used for vfptr and vbprt
28210b57cec5SDimitry Andric // injection.
2822bdd1243dSDimitry Andric PointerInfo.Size = Context.toCharUnitsFromBits(
2823bdd1243dSDimitry Andric Context.getTargetInfo().getPointerWidth(LangAS::Default));
2824bdd1243dSDimitry Andric PointerInfo.Alignment = Context.toCharUnitsFromBits(
2825bdd1243dSDimitry Andric Context.getTargetInfo().getPointerAlign(LangAS::Default));
28260b57cec5SDimitry Andric // Respect pragma pack.
28270b57cec5SDimitry Andric if (!MaxFieldAlignment.isZero())
28280b57cec5SDimitry Andric PointerInfo.Alignment = std::min(PointerInfo.Alignment, MaxFieldAlignment);
28290b57cec5SDimitry Andric }
28300b57cec5SDimitry Andric
28310b57cec5SDimitry Andric void
layoutNonVirtualBases(const CXXRecordDecl * RD)28320b57cec5SDimitry Andric MicrosoftRecordLayoutBuilder::layoutNonVirtualBases(const CXXRecordDecl *RD) {
28330b57cec5SDimitry Andric // The MS-ABI lays out all bases that contain leading vfptrs before it lays
28340b57cec5SDimitry Andric // out any bases that do not contain vfptrs. We implement this as two passes
28350b57cec5SDimitry Andric // over the bases. This approach guarantees that the primary base is laid out
28360b57cec5SDimitry Andric // first. We use these passes to calculate some additional aggregated
28370b57cec5SDimitry Andric // information about the bases, such as required alignment and the presence of
28380b57cec5SDimitry Andric // zero sized members.
28390b57cec5SDimitry Andric const ASTRecordLayout *PreviousBaseLayout = nullptr;
28405ffd83dbSDimitry Andric bool HasPolymorphicBaseClass = false;
28410b57cec5SDimitry Andric // Iterate through the bases and lay out the non-virtual ones.
28420b57cec5SDimitry Andric for (const CXXBaseSpecifier &Base : RD->bases()) {
28430b57cec5SDimitry Andric const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
28445ffd83dbSDimitry Andric HasPolymorphicBaseClass |= BaseDecl->isPolymorphic();
28450b57cec5SDimitry Andric const ASTRecordLayout &BaseLayout = Context.getASTRecordLayout(BaseDecl);
28460b57cec5SDimitry Andric // Mark and skip virtual bases.
28470b57cec5SDimitry Andric if (Base.isVirtual()) {
28480b57cec5SDimitry Andric HasVBPtr = true;
28490b57cec5SDimitry Andric continue;
28500b57cec5SDimitry Andric }
28510b57cec5SDimitry Andric // Check for a base to share a VBPtr with.
28520b57cec5SDimitry Andric if (!SharedVBPtrBase && BaseLayout.hasVBPtr()) {
28530b57cec5SDimitry Andric SharedVBPtrBase = BaseDecl;
28540b57cec5SDimitry Andric HasVBPtr = true;
28550b57cec5SDimitry Andric }
28560b57cec5SDimitry Andric // Only lay out bases with extendable VFPtrs on the first pass.
28570b57cec5SDimitry Andric if (!BaseLayout.hasExtendableVFPtr())
28580b57cec5SDimitry Andric continue;
28590b57cec5SDimitry Andric // If we don't have a primary base, this one qualifies.
28600b57cec5SDimitry Andric if (!PrimaryBase) {
28610b57cec5SDimitry Andric PrimaryBase = BaseDecl;
28620b57cec5SDimitry Andric LeadsWithZeroSizedBase = BaseLayout.leadsWithZeroSizedBase();
28630b57cec5SDimitry Andric }
28640b57cec5SDimitry Andric // Lay out the base.
28650b57cec5SDimitry Andric layoutNonVirtualBase(RD, BaseDecl, BaseLayout, PreviousBaseLayout);
28660b57cec5SDimitry Andric }
28670b57cec5SDimitry Andric // Figure out if we need a fresh VFPtr for this class.
28685ffd83dbSDimitry Andric if (RD->isPolymorphic()) {
28695ffd83dbSDimitry Andric if (!HasPolymorphicBaseClass)
28705ffd83dbSDimitry Andric // This class introduces polymorphism, so we need a vftable to store the
28715ffd83dbSDimitry Andric // RTTI information.
28725ffd83dbSDimitry Andric HasOwnVFPtr = true;
28735ffd83dbSDimitry Andric else if (!PrimaryBase) {
28745ffd83dbSDimitry Andric // We have a polymorphic base class but can't extend its vftable. Add a
28755ffd83dbSDimitry Andric // new vfptr if we would use any vftable slots.
28765ffd83dbSDimitry Andric for (CXXMethodDecl *M : RD->methods()) {
28775ffd83dbSDimitry Andric if (MicrosoftVTableContext::hasVtableSlot(M) &&
28785ffd83dbSDimitry Andric M->size_overridden_methods() == 0) {
28795ffd83dbSDimitry Andric HasOwnVFPtr = true;
28805ffd83dbSDimitry Andric break;
28815ffd83dbSDimitry Andric }
28825ffd83dbSDimitry Andric }
28835ffd83dbSDimitry Andric }
28845ffd83dbSDimitry Andric }
28850b57cec5SDimitry Andric // If we don't have a primary base then we have a leading object that could
28860b57cec5SDimitry Andric // itself lead with a zero-sized object, something we track.
28870b57cec5SDimitry Andric bool CheckLeadingLayout = !PrimaryBase;
28880b57cec5SDimitry Andric // Iterate through the bases and lay out the non-virtual ones.
28890b57cec5SDimitry Andric for (const CXXBaseSpecifier &Base : RD->bases()) {
28900b57cec5SDimitry Andric if (Base.isVirtual())
28910b57cec5SDimitry Andric continue;
28920b57cec5SDimitry Andric const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
28930b57cec5SDimitry Andric const ASTRecordLayout &BaseLayout = Context.getASTRecordLayout(BaseDecl);
28940b57cec5SDimitry Andric // Only lay out bases without extendable VFPtrs on the second pass.
28950b57cec5SDimitry Andric if (BaseLayout.hasExtendableVFPtr()) {
28960b57cec5SDimitry Andric VBPtrOffset = Bases[BaseDecl] + BaseLayout.getNonVirtualSize();
28970b57cec5SDimitry Andric continue;
28980b57cec5SDimitry Andric }
28990b57cec5SDimitry Andric // If this is the first layout, check to see if it leads with a zero sized
29000b57cec5SDimitry Andric // object. If it does, so do we.
29010b57cec5SDimitry Andric if (CheckLeadingLayout) {
29020b57cec5SDimitry Andric CheckLeadingLayout = false;
29030b57cec5SDimitry Andric LeadsWithZeroSizedBase = BaseLayout.leadsWithZeroSizedBase();
29040b57cec5SDimitry Andric }
29050b57cec5SDimitry Andric // Lay out the base.
29060b57cec5SDimitry Andric layoutNonVirtualBase(RD, BaseDecl, BaseLayout, PreviousBaseLayout);
29070b57cec5SDimitry Andric VBPtrOffset = Bases[BaseDecl] + BaseLayout.getNonVirtualSize();
29080b57cec5SDimitry Andric }
29090b57cec5SDimitry Andric // Set our VBPtroffset if we know it at this point.
29100b57cec5SDimitry Andric if (!HasVBPtr)
29110b57cec5SDimitry Andric VBPtrOffset = CharUnits::fromQuantity(-1);
29120b57cec5SDimitry Andric else if (SharedVBPtrBase) {
29130b57cec5SDimitry Andric const ASTRecordLayout &Layout = Context.getASTRecordLayout(SharedVBPtrBase);
29140b57cec5SDimitry Andric VBPtrOffset = Bases[SharedVBPtrBase] + Layout.getVBPtrOffset();
29150b57cec5SDimitry Andric }
29160b57cec5SDimitry Andric }
29170b57cec5SDimitry Andric
recordUsesEBO(const RecordDecl * RD)29180b57cec5SDimitry Andric static bool recordUsesEBO(const RecordDecl *RD) {
29190b57cec5SDimitry Andric if (!isa<CXXRecordDecl>(RD))
29200b57cec5SDimitry Andric return false;
29210b57cec5SDimitry Andric if (RD->hasAttr<EmptyBasesAttr>())
29220b57cec5SDimitry Andric return true;
29230b57cec5SDimitry Andric if (auto *LVA = RD->getAttr<LayoutVersionAttr>())
29240b57cec5SDimitry Andric // TODO: Double check with the next version of MSVC.
29250b57cec5SDimitry Andric if (LVA->getVersion() <= LangOptions::MSVC2015)
29260b57cec5SDimitry Andric return false;
29270b57cec5SDimitry Andric // TODO: Some later version of MSVC will change the default behavior of the
29280b57cec5SDimitry Andric // compiler to enable EBO by default. When this happens, we will need an
29290b57cec5SDimitry Andric // additional isCompatibleWithMSVC check.
29300b57cec5SDimitry Andric return false;
29310b57cec5SDimitry Andric }
29320b57cec5SDimitry Andric
layoutNonVirtualBase(const CXXRecordDecl * RD,const CXXRecordDecl * BaseDecl,const ASTRecordLayout & BaseLayout,const ASTRecordLayout * & PreviousBaseLayout)29330b57cec5SDimitry Andric void MicrosoftRecordLayoutBuilder::layoutNonVirtualBase(
29345f757f3fSDimitry Andric const CXXRecordDecl *RD, const CXXRecordDecl *BaseDecl,
29350b57cec5SDimitry Andric const ASTRecordLayout &BaseLayout,
29360b57cec5SDimitry Andric const ASTRecordLayout *&PreviousBaseLayout) {
29370b57cec5SDimitry Andric // Insert padding between two bases if the left first one is zero sized or
29380b57cec5SDimitry Andric // contains a zero sized subobject and the right is zero sized or one leads
29390b57cec5SDimitry Andric // with a zero sized base.
29400b57cec5SDimitry Andric bool MDCUsesEBO = recordUsesEBO(RD);
29410b57cec5SDimitry Andric if (PreviousBaseLayout && PreviousBaseLayout->endsWithZeroSizedObject() &&
29420b57cec5SDimitry Andric BaseLayout.leadsWithZeroSizedBase() && !MDCUsesEBO)
29430b57cec5SDimitry Andric Size++;
29440b57cec5SDimitry Andric ElementInfo Info = getAdjustedElementInfo(BaseLayout);
29450b57cec5SDimitry Andric CharUnits BaseOffset;
29460b57cec5SDimitry Andric
29470b57cec5SDimitry Andric // Respect the external AST source base offset, if present.
29480b57cec5SDimitry Andric bool FoundBase = false;
29490b57cec5SDimitry Andric if (UseExternalLayout) {
29500b57cec5SDimitry Andric FoundBase = External.getExternalNVBaseOffset(BaseDecl, BaseOffset);
295106c3fb27SDimitry Andric if (BaseOffset > Size) {
29520b57cec5SDimitry Andric Size = BaseOffset;
29530b57cec5SDimitry Andric }
29540b57cec5SDimitry Andric }
29550b57cec5SDimitry Andric
29560b57cec5SDimitry Andric if (!FoundBase) {
29575f757f3fSDimitry Andric if (MDCUsesEBO && BaseDecl->isEmpty() &&
29585f757f3fSDimitry Andric (BaseLayout.getNonVirtualSize() == CharUnits::Zero())) {
29590b57cec5SDimitry Andric BaseOffset = CharUnits::Zero();
29600b57cec5SDimitry Andric } else {
29610b57cec5SDimitry Andric // Otherwise, lay the base out at the end of the MDC.
29620b57cec5SDimitry Andric BaseOffset = Size = Size.alignTo(Info.Alignment);
29630b57cec5SDimitry Andric }
29640b57cec5SDimitry Andric }
29650b57cec5SDimitry Andric Bases.insert(std::make_pair(BaseDecl, BaseOffset));
29660b57cec5SDimitry Andric Size += BaseLayout.getNonVirtualSize();
29675f757f3fSDimitry Andric DataSize = Size;
29680b57cec5SDimitry Andric PreviousBaseLayout = &BaseLayout;
29690b57cec5SDimitry Andric }
29700b57cec5SDimitry Andric
layoutFields(const RecordDecl * RD)29710b57cec5SDimitry Andric void MicrosoftRecordLayoutBuilder::layoutFields(const RecordDecl *RD) {
29720b57cec5SDimitry Andric LastFieldIsNonZeroWidthBitfield = false;
29730b57cec5SDimitry Andric for (const FieldDecl *Field : RD->fields())
29740b57cec5SDimitry Andric layoutField(Field);
29750b57cec5SDimitry Andric }
29760b57cec5SDimitry Andric
layoutField(const FieldDecl * FD)29770b57cec5SDimitry Andric void MicrosoftRecordLayoutBuilder::layoutField(const FieldDecl *FD) {
29780b57cec5SDimitry Andric if (FD->isBitField()) {
29790b57cec5SDimitry Andric layoutBitField(FD);
29800b57cec5SDimitry Andric return;
29810b57cec5SDimitry Andric }
29820b57cec5SDimitry Andric LastFieldIsNonZeroWidthBitfield = false;
29830b57cec5SDimitry Andric ElementInfo Info = getAdjustedElementInfo(FD);
29840b57cec5SDimitry Andric Alignment = std::max(Alignment, Info.Alignment);
29855f757f3fSDimitry Andric
29865f757f3fSDimitry Andric const CXXRecordDecl *FieldClass = FD->getType()->getAsCXXRecordDecl();
29875f757f3fSDimitry Andric bool IsOverlappingEmptyField = FD->isPotentiallyOverlapping() &&
29885f757f3fSDimitry Andric FieldClass->isEmpty() &&
29895f757f3fSDimitry Andric FieldClass->fields().empty();
29905f757f3fSDimitry Andric CharUnits FieldOffset = CharUnits::Zero();
29915f757f3fSDimitry Andric
29925f757f3fSDimitry Andric if (UseExternalLayout) {
29930b57cec5SDimitry Andric FieldOffset =
29940b57cec5SDimitry Andric Context.toCharUnitsFromBits(External.getExternalFieldOffset(FD));
29955f757f3fSDimitry Andric } else if (IsUnion) {
29960b57cec5SDimitry Andric FieldOffset = CharUnits::Zero();
29975f757f3fSDimitry Andric } else if (EmptySubobjects) {
29985f757f3fSDimitry Andric if (!IsOverlappingEmptyField)
29995f757f3fSDimitry Andric FieldOffset = DataSize.alignTo(Info.Alignment);
30005f757f3fSDimitry Andric
30015f757f3fSDimitry Andric while (!EmptySubobjects->CanPlaceFieldAtOffset(FD, FieldOffset)) {
30025f757f3fSDimitry Andric const CXXRecordDecl *ParentClass = cast<CXXRecordDecl>(FD->getParent());
30035f757f3fSDimitry Andric bool HasBases = ParentClass && (!ParentClass->bases().empty() ||
30045f757f3fSDimitry Andric !ParentClass->vbases().empty());
30055f757f3fSDimitry Andric if (FieldOffset == CharUnits::Zero() && DataSize != CharUnits::Zero() &&
30065f757f3fSDimitry Andric HasBases) {
30075f757f3fSDimitry Andric // MSVC appears to only do this when there are base classes;
30085f757f3fSDimitry Andric // otherwise it overlaps no_unique_address fields in non-zero offsets.
30095f757f3fSDimitry Andric FieldOffset = DataSize.alignTo(Info.Alignment);
30105f757f3fSDimitry Andric } else {
30115f757f3fSDimitry Andric FieldOffset += Info.Alignment;
30125f757f3fSDimitry Andric }
30135f757f3fSDimitry Andric }
30145f757f3fSDimitry Andric } else {
30150b57cec5SDimitry Andric FieldOffset = Size.alignTo(Info.Alignment);
30165f757f3fSDimitry Andric }
30170b57cec5SDimitry Andric placeFieldAtOffset(FieldOffset);
30185f757f3fSDimitry Andric
30195f757f3fSDimitry Andric if (!IsOverlappingEmptyField)
30205f757f3fSDimitry Andric DataSize = std::max(DataSize, FieldOffset + Info.Size);
30215f757f3fSDimitry Andric
30220b57cec5SDimitry Andric Size = std::max(Size, FieldOffset + Info.Size);
30230b57cec5SDimitry Andric }
30240b57cec5SDimitry Andric
layoutBitField(const FieldDecl * FD)30250b57cec5SDimitry Andric void MicrosoftRecordLayoutBuilder::layoutBitField(const FieldDecl *FD) {
30260b57cec5SDimitry Andric unsigned Width = FD->getBitWidthValue(Context);
30270b57cec5SDimitry Andric if (Width == 0) {
30280b57cec5SDimitry Andric layoutZeroWidthBitField(FD);
30290b57cec5SDimitry Andric return;
30300b57cec5SDimitry Andric }
30310b57cec5SDimitry Andric ElementInfo Info = getAdjustedElementInfo(FD);
30320b57cec5SDimitry Andric // Clamp the bitfield to a containable size for the sake of being able
30330b57cec5SDimitry Andric // to lay them out. Sema will throw an error.
30340b57cec5SDimitry Andric if (Width > Context.toBits(Info.Size))
30350b57cec5SDimitry Andric Width = Context.toBits(Info.Size);
30360b57cec5SDimitry Andric // Check to see if this bitfield fits into an existing allocation. Note:
30370b57cec5SDimitry Andric // MSVC refuses to pack bitfields of formal types with different sizes
30380b57cec5SDimitry Andric // into the same allocation.
30390b57cec5SDimitry Andric if (!UseExternalLayout && !IsUnion && LastFieldIsNonZeroWidthBitfield &&
30400b57cec5SDimitry Andric CurrentBitfieldSize == Info.Size && Width <= RemainingBitsInField) {
30410b57cec5SDimitry Andric placeFieldAtBitOffset(Context.toBits(Size) - RemainingBitsInField);
30420b57cec5SDimitry Andric RemainingBitsInField -= Width;
30430b57cec5SDimitry Andric return;
30440b57cec5SDimitry Andric }
30450b57cec5SDimitry Andric LastFieldIsNonZeroWidthBitfield = true;
30460b57cec5SDimitry Andric CurrentBitfieldSize = Info.Size;
30470b57cec5SDimitry Andric if (UseExternalLayout) {
30480b57cec5SDimitry Andric auto FieldBitOffset = External.getExternalFieldOffset(FD);
30490b57cec5SDimitry Andric placeFieldAtBitOffset(FieldBitOffset);
30500b57cec5SDimitry Andric auto NewSize = Context.toCharUnitsFromBits(
30510b57cec5SDimitry Andric llvm::alignDown(FieldBitOffset, Context.toBits(Info.Alignment)) +
30520b57cec5SDimitry Andric Context.toBits(Info.Size));
30530b57cec5SDimitry Andric Size = std::max(Size, NewSize);
30540b57cec5SDimitry Andric Alignment = std::max(Alignment, Info.Alignment);
30550b57cec5SDimitry Andric } else if (IsUnion) {
30560b57cec5SDimitry Andric placeFieldAtOffset(CharUnits::Zero());
30570b57cec5SDimitry Andric Size = std::max(Size, Info.Size);
30580b57cec5SDimitry Andric // TODO: Add a Sema warning that MS ignores bitfield alignment in unions.
30590b57cec5SDimitry Andric } else {
30600b57cec5SDimitry Andric // Allocate a new block of memory and place the bitfield in it.
30610b57cec5SDimitry Andric CharUnits FieldOffset = Size.alignTo(Info.Alignment);
30620b57cec5SDimitry Andric placeFieldAtOffset(FieldOffset);
30630b57cec5SDimitry Andric Size = FieldOffset + Info.Size;
30640b57cec5SDimitry Andric Alignment = std::max(Alignment, Info.Alignment);
30650b57cec5SDimitry Andric RemainingBitsInField = Context.toBits(Info.Size) - Width;
30660b57cec5SDimitry Andric }
30675f757f3fSDimitry Andric DataSize = Size;
30680b57cec5SDimitry Andric }
30690b57cec5SDimitry Andric
30700b57cec5SDimitry Andric void
layoutZeroWidthBitField(const FieldDecl * FD)30710b57cec5SDimitry Andric MicrosoftRecordLayoutBuilder::layoutZeroWidthBitField(const FieldDecl *FD) {
30720b57cec5SDimitry Andric // Zero-width bitfields are ignored unless they follow a non-zero-width
30730b57cec5SDimitry Andric // bitfield.
30740b57cec5SDimitry Andric if (!LastFieldIsNonZeroWidthBitfield) {
30750b57cec5SDimitry Andric placeFieldAtOffset(IsUnion ? CharUnits::Zero() : Size);
30760b57cec5SDimitry Andric // TODO: Add a Sema warning that MS ignores alignment for zero
30770b57cec5SDimitry Andric // sized bitfields that occur after zero-size bitfields or non-bitfields.
30780b57cec5SDimitry Andric return;
30790b57cec5SDimitry Andric }
30800b57cec5SDimitry Andric LastFieldIsNonZeroWidthBitfield = false;
30810b57cec5SDimitry Andric ElementInfo Info = getAdjustedElementInfo(FD);
30820b57cec5SDimitry Andric if (IsUnion) {
30830b57cec5SDimitry Andric placeFieldAtOffset(CharUnits::Zero());
30840b57cec5SDimitry Andric Size = std::max(Size, Info.Size);
30850b57cec5SDimitry Andric // TODO: Add a Sema warning that MS ignores bitfield alignment in unions.
30860b57cec5SDimitry Andric } else {
30870b57cec5SDimitry Andric // Round up the current record size to the field's alignment boundary.
30880b57cec5SDimitry Andric CharUnits FieldOffset = Size.alignTo(Info.Alignment);
30890b57cec5SDimitry Andric placeFieldAtOffset(FieldOffset);
30900b57cec5SDimitry Andric Size = FieldOffset;
30910b57cec5SDimitry Andric Alignment = std::max(Alignment, Info.Alignment);
30920b57cec5SDimitry Andric }
30935f757f3fSDimitry Andric DataSize = Size;
30940b57cec5SDimitry Andric }
30950b57cec5SDimitry Andric
injectVBPtr(const CXXRecordDecl * RD)30960b57cec5SDimitry Andric void MicrosoftRecordLayoutBuilder::injectVBPtr(const CXXRecordDecl *RD) {
30970b57cec5SDimitry Andric if (!HasVBPtr || SharedVBPtrBase)
30980b57cec5SDimitry Andric return;
30990b57cec5SDimitry Andric // Inject the VBPointer at the injection site.
31000b57cec5SDimitry Andric CharUnits InjectionSite = VBPtrOffset;
31010b57cec5SDimitry Andric // But before we do, make sure it's properly aligned.
31020b57cec5SDimitry Andric VBPtrOffset = VBPtrOffset.alignTo(PointerInfo.Alignment);
31030b57cec5SDimitry Andric // Determine where the first field should be laid out after the vbptr.
31040b57cec5SDimitry Andric CharUnits FieldStart = VBPtrOffset + PointerInfo.Size;
31050b57cec5SDimitry Andric // Shift everything after the vbptr down, unless we're using an external
31060b57cec5SDimitry Andric // layout.
31070b57cec5SDimitry Andric if (UseExternalLayout) {
31080b57cec5SDimitry Andric // It is possible that there were no fields or bases located after vbptr,
31090b57cec5SDimitry Andric // so the size was not adjusted before.
31100b57cec5SDimitry Andric if (Size < FieldStart)
31110b57cec5SDimitry Andric Size = FieldStart;
31120b57cec5SDimitry Andric return;
31130b57cec5SDimitry Andric }
31140b57cec5SDimitry Andric // Make sure that the amount we push the fields back by is a multiple of the
31150b57cec5SDimitry Andric // alignment.
31160b57cec5SDimitry Andric CharUnits Offset = (FieldStart - InjectionSite)
31170b57cec5SDimitry Andric .alignTo(std::max(RequiredAlignment, Alignment));
31180b57cec5SDimitry Andric Size += Offset;
31190b57cec5SDimitry Andric for (uint64_t &FieldOffset : FieldOffsets)
31200b57cec5SDimitry Andric FieldOffset += Context.toBits(Offset);
31210b57cec5SDimitry Andric for (BaseOffsetsMapTy::value_type &Base : Bases)
31220b57cec5SDimitry Andric if (Base.second >= InjectionSite)
31230b57cec5SDimitry Andric Base.second += Offset;
31240b57cec5SDimitry Andric }
31250b57cec5SDimitry Andric
injectVFPtr(const CXXRecordDecl * RD)31260b57cec5SDimitry Andric void MicrosoftRecordLayoutBuilder::injectVFPtr(const CXXRecordDecl *RD) {
31270b57cec5SDimitry Andric if (!HasOwnVFPtr)
31280b57cec5SDimitry Andric return;
31290b57cec5SDimitry Andric // Make sure that the amount we push the struct back by is a multiple of the
31300b57cec5SDimitry Andric // alignment.
31310b57cec5SDimitry Andric CharUnits Offset =
31320b57cec5SDimitry Andric PointerInfo.Size.alignTo(std::max(RequiredAlignment, Alignment));
31330b57cec5SDimitry Andric // Push back the vbptr, but increase the size of the object and push back
31340b57cec5SDimitry Andric // regular fields by the offset only if not using external record layout.
31350b57cec5SDimitry Andric if (HasVBPtr)
31360b57cec5SDimitry Andric VBPtrOffset += Offset;
31370b57cec5SDimitry Andric
31380b57cec5SDimitry Andric if (UseExternalLayout) {
3139bdd1243dSDimitry Andric // The class may have size 0 and a vfptr (e.g. it's an interface class). The
3140bdd1243dSDimitry Andric // size was not correctly set before in this case.
3141bdd1243dSDimitry Andric if (Size.isZero())
31420b57cec5SDimitry Andric Size += Offset;
31430b57cec5SDimitry Andric return;
31440b57cec5SDimitry Andric }
31450b57cec5SDimitry Andric
31460b57cec5SDimitry Andric Size += Offset;
31470b57cec5SDimitry Andric
31480b57cec5SDimitry Andric // If we're using an external layout, the fields offsets have already
31490b57cec5SDimitry Andric // accounted for this adjustment.
31500b57cec5SDimitry Andric for (uint64_t &FieldOffset : FieldOffsets)
31510b57cec5SDimitry Andric FieldOffset += Context.toBits(Offset);
31520b57cec5SDimitry Andric for (BaseOffsetsMapTy::value_type &Base : Bases)
31530b57cec5SDimitry Andric Base.second += Offset;
31540b57cec5SDimitry Andric }
31550b57cec5SDimitry Andric
layoutVirtualBases(const CXXRecordDecl * RD)31560b57cec5SDimitry Andric void MicrosoftRecordLayoutBuilder::layoutVirtualBases(const CXXRecordDecl *RD) {
31570b57cec5SDimitry Andric if (!HasVBPtr)
31580b57cec5SDimitry Andric return;
31590b57cec5SDimitry Andric // Vtordisps are always 4 bytes (even in 64-bit mode)
31600b57cec5SDimitry Andric CharUnits VtorDispSize = CharUnits::fromQuantity(4);
31610b57cec5SDimitry Andric CharUnits VtorDispAlignment = VtorDispSize;
31620b57cec5SDimitry Andric // vtordisps respect pragma pack.
31630b57cec5SDimitry Andric if (!MaxFieldAlignment.isZero())
31640b57cec5SDimitry Andric VtorDispAlignment = std::min(VtorDispAlignment, MaxFieldAlignment);
31650b57cec5SDimitry Andric // The alignment of the vtordisp is at least the required alignment of the
31660b57cec5SDimitry Andric // entire record. This requirement may be present to support vtordisp
31670b57cec5SDimitry Andric // injection.
31680b57cec5SDimitry Andric for (const CXXBaseSpecifier &VBase : RD->vbases()) {
31690b57cec5SDimitry Andric const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl();
31700b57cec5SDimitry Andric const ASTRecordLayout &BaseLayout = Context.getASTRecordLayout(BaseDecl);
31710b57cec5SDimitry Andric RequiredAlignment =
31720b57cec5SDimitry Andric std::max(RequiredAlignment, BaseLayout.getRequiredAlignment());
31730b57cec5SDimitry Andric }
31740b57cec5SDimitry Andric VtorDispAlignment = std::max(VtorDispAlignment, RequiredAlignment);
31750b57cec5SDimitry Andric // Compute the vtordisp set.
31760b57cec5SDimitry Andric llvm::SmallPtrSet<const CXXRecordDecl *, 2> HasVtorDispSet;
31770b57cec5SDimitry Andric computeVtorDispSet(HasVtorDispSet, RD);
31780b57cec5SDimitry Andric // Iterate through the virtual bases and lay them out.
31790b57cec5SDimitry Andric const ASTRecordLayout *PreviousBaseLayout = nullptr;
31800b57cec5SDimitry Andric for (const CXXBaseSpecifier &VBase : RD->vbases()) {
31810b57cec5SDimitry Andric const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl();
31820b57cec5SDimitry Andric const ASTRecordLayout &BaseLayout = Context.getASTRecordLayout(BaseDecl);
3183349cc55cSDimitry Andric bool HasVtordisp = HasVtorDispSet.contains(BaseDecl);
31840b57cec5SDimitry Andric // Insert padding between two bases if the left first one is zero sized or
31850b57cec5SDimitry Andric // contains a zero sized subobject and the right is zero sized or one leads
31860b57cec5SDimitry Andric // with a zero sized base. The padding between virtual bases is 4
31870b57cec5SDimitry Andric // bytes (in both 32 and 64 bits modes) and always involves rounding up to
31880b57cec5SDimitry Andric // the required alignment, we don't know why.
31890b57cec5SDimitry Andric if ((PreviousBaseLayout && PreviousBaseLayout->endsWithZeroSizedObject() &&
31900b57cec5SDimitry Andric BaseLayout.leadsWithZeroSizedBase() && !recordUsesEBO(RD)) ||
31910b57cec5SDimitry Andric HasVtordisp) {
31920b57cec5SDimitry Andric Size = Size.alignTo(VtorDispAlignment) + VtorDispSize;
31930b57cec5SDimitry Andric Alignment = std::max(VtorDispAlignment, Alignment);
31940b57cec5SDimitry Andric }
31950b57cec5SDimitry Andric // Insert the virtual base.
31960b57cec5SDimitry Andric ElementInfo Info = getAdjustedElementInfo(BaseLayout);
31970b57cec5SDimitry Andric CharUnits BaseOffset;
31980b57cec5SDimitry Andric
31990b57cec5SDimitry Andric // Respect the external AST source base offset, if present.
32000b57cec5SDimitry Andric if (UseExternalLayout) {
32010b57cec5SDimitry Andric if (!External.getExternalVBaseOffset(BaseDecl, BaseOffset))
32020b57cec5SDimitry Andric BaseOffset = Size;
32030b57cec5SDimitry Andric } else
32040b57cec5SDimitry Andric BaseOffset = Size.alignTo(Info.Alignment);
32050b57cec5SDimitry Andric
32060b57cec5SDimitry Andric assert(BaseOffset >= Size && "base offset already allocated");
32070b57cec5SDimitry Andric
32080b57cec5SDimitry Andric VBases.insert(std::make_pair(BaseDecl,
32090b57cec5SDimitry Andric ASTRecordLayout::VBaseInfo(BaseOffset, HasVtordisp)));
32100b57cec5SDimitry Andric Size = BaseOffset + BaseLayout.getNonVirtualSize();
32110b57cec5SDimitry Andric PreviousBaseLayout = &BaseLayout;
32120b57cec5SDimitry Andric }
32130b57cec5SDimitry Andric }
32140b57cec5SDimitry Andric
finalizeLayout(const RecordDecl * RD)32150b57cec5SDimitry Andric void MicrosoftRecordLayoutBuilder::finalizeLayout(const RecordDecl *RD) {
32160b57cec5SDimitry Andric // Respect required alignment. Note that in 32-bit mode Required alignment
32170b57cec5SDimitry Andric // may be 0 and cause size not to be updated.
32180b57cec5SDimitry Andric DataSize = Size;
32190b57cec5SDimitry Andric if (!RequiredAlignment.isZero()) {
32200b57cec5SDimitry Andric Alignment = std::max(Alignment, RequiredAlignment);
32210b57cec5SDimitry Andric auto RoundingAlignment = Alignment;
32220b57cec5SDimitry Andric if (!MaxFieldAlignment.isZero())
32230b57cec5SDimitry Andric RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment);
32240b57cec5SDimitry Andric RoundingAlignment = std::max(RoundingAlignment, RequiredAlignment);
32250b57cec5SDimitry Andric Size = Size.alignTo(RoundingAlignment);
32260b57cec5SDimitry Andric }
32270b57cec5SDimitry Andric if (Size.isZero()) {
32280b57cec5SDimitry Andric if (!recordUsesEBO(RD) || !cast<CXXRecordDecl>(RD)->isEmpty()) {
32290b57cec5SDimitry Andric EndsWithZeroSizedObject = true;
32300b57cec5SDimitry Andric LeadsWithZeroSizedBase = true;
32310b57cec5SDimitry Andric }
32320b57cec5SDimitry Andric // Zero-sized structures have size equal to their alignment if a
32330b57cec5SDimitry Andric // __declspec(align) came into play.
32340b57cec5SDimitry Andric if (RequiredAlignment >= MinEmptyStructSize)
32350b57cec5SDimitry Andric Size = Alignment;
32360b57cec5SDimitry Andric else
32370b57cec5SDimitry Andric Size = MinEmptyStructSize;
32380b57cec5SDimitry Andric }
32390b57cec5SDimitry Andric
32400b57cec5SDimitry Andric if (UseExternalLayout) {
32410b57cec5SDimitry Andric Size = Context.toCharUnitsFromBits(External.Size);
32420b57cec5SDimitry Andric if (External.Align)
32430b57cec5SDimitry Andric Alignment = Context.toCharUnitsFromBits(External.Align);
32440b57cec5SDimitry Andric }
32450b57cec5SDimitry Andric }
32460b57cec5SDimitry Andric
32470b57cec5SDimitry Andric // Recursively walks the non-virtual bases of a class and determines if any of
32480b57cec5SDimitry Andric // them are in the bases with overridden methods set.
32490b57cec5SDimitry Andric static bool
RequiresVtordisp(const llvm::SmallPtrSetImpl<const CXXRecordDecl * > & BasesWithOverriddenMethods,const CXXRecordDecl * RD)32500b57cec5SDimitry Andric RequiresVtordisp(const llvm::SmallPtrSetImpl<const CXXRecordDecl *> &
32510b57cec5SDimitry Andric BasesWithOverriddenMethods,
32520b57cec5SDimitry Andric const CXXRecordDecl *RD) {
32530b57cec5SDimitry Andric if (BasesWithOverriddenMethods.count(RD))
32540b57cec5SDimitry Andric return true;
32550b57cec5SDimitry Andric // If any of a virtual bases non-virtual bases (recursively) requires a
32560b57cec5SDimitry Andric // vtordisp than so does this virtual base.
32570b57cec5SDimitry Andric for (const CXXBaseSpecifier &Base : RD->bases())
32580b57cec5SDimitry Andric if (!Base.isVirtual() &&
32590b57cec5SDimitry Andric RequiresVtordisp(BasesWithOverriddenMethods,
32600b57cec5SDimitry Andric Base.getType()->getAsCXXRecordDecl()))
32610b57cec5SDimitry Andric return true;
32620b57cec5SDimitry Andric return false;
32630b57cec5SDimitry Andric }
32640b57cec5SDimitry Andric
computeVtorDispSet(llvm::SmallPtrSetImpl<const CXXRecordDecl * > & HasVtordispSet,const CXXRecordDecl * RD) const32650b57cec5SDimitry Andric void MicrosoftRecordLayoutBuilder::computeVtorDispSet(
32660b57cec5SDimitry Andric llvm::SmallPtrSetImpl<const CXXRecordDecl *> &HasVtordispSet,
32670b57cec5SDimitry Andric const CXXRecordDecl *RD) const {
32680b57cec5SDimitry Andric // /vd2 or #pragma vtordisp(2): Always use vtordisps for virtual bases with
32690b57cec5SDimitry Andric // vftables.
3270480093f4SDimitry Andric if (RD->getMSVtorDispMode() == MSVtorDispMode::ForVFTable) {
32710b57cec5SDimitry Andric for (const CXXBaseSpecifier &Base : RD->vbases()) {
32720b57cec5SDimitry Andric const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
32730b57cec5SDimitry Andric const ASTRecordLayout &Layout = Context.getASTRecordLayout(BaseDecl);
32740b57cec5SDimitry Andric if (Layout.hasExtendableVFPtr())
32750b57cec5SDimitry Andric HasVtordispSet.insert(BaseDecl);
32760b57cec5SDimitry Andric }
32770b57cec5SDimitry Andric return;
32780b57cec5SDimitry Andric }
32790b57cec5SDimitry Andric
32800b57cec5SDimitry Andric // If any of our bases need a vtordisp for this type, so do we. Check our
32810b57cec5SDimitry Andric // direct bases for vtordisp requirements.
32820b57cec5SDimitry Andric for (const CXXBaseSpecifier &Base : RD->bases()) {
32830b57cec5SDimitry Andric const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
32840b57cec5SDimitry Andric const ASTRecordLayout &Layout = Context.getASTRecordLayout(BaseDecl);
32850b57cec5SDimitry Andric for (const auto &bi : Layout.getVBaseOffsetsMap())
32860b57cec5SDimitry Andric if (bi.second.hasVtorDisp())
32870b57cec5SDimitry Andric HasVtordispSet.insert(bi.first);
32880b57cec5SDimitry Andric }
32890b57cec5SDimitry Andric // We don't introduce any additional vtordisps if either:
32900b57cec5SDimitry Andric // * A user declared constructor or destructor aren't declared.
32910b57cec5SDimitry Andric // * #pragma vtordisp(0) or the /vd0 flag are in use.
32920b57cec5SDimitry Andric if ((!RD->hasUserDeclaredConstructor() && !RD->hasUserDeclaredDestructor()) ||
3293480093f4SDimitry Andric RD->getMSVtorDispMode() == MSVtorDispMode::Never)
32940b57cec5SDimitry Andric return;
32950b57cec5SDimitry Andric // /vd1 or #pragma vtordisp(1): Try to guess based on whether we think it's
32960b57cec5SDimitry Andric // possible for a partially constructed object with virtual base overrides to
32970b57cec5SDimitry Andric // escape a non-trivial constructor.
3298480093f4SDimitry Andric assert(RD->getMSVtorDispMode() == MSVtorDispMode::ForVBaseOverride);
32990b57cec5SDimitry Andric // Compute a set of base classes which define methods we override. A virtual
33000b57cec5SDimitry Andric // base in this set will require a vtordisp. A virtual base that transitively
33010b57cec5SDimitry Andric // contains one of these bases as a non-virtual base will also require a
33020b57cec5SDimitry Andric // vtordisp.
33030b57cec5SDimitry Andric llvm::SmallPtrSet<const CXXMethodDecl *, 8> Work;
33040b57cec5SDimitry Andric llvm::SmallPtrSet<const CXXRecordDecl *, 2> BasesWithOverriddenMethods;
33050b57cec5SDimitry Andric // Seed the working set with our non-destructor, non-pure virtual methods.
33060b57cec5SDimitry Andric for (const CXXMethodDecl *MD : RD->methods())
33075ffd83dbSDimitry Andric if (MicrosoftVTableContext::hasVtableSlot(MD) &&
33087a6dacacSDimitry Andric !isa<CXXDestructorDecl>(MD) && !MD->isPureVirtual())
33090b57cec5SDimitry Andric Work.insert(MD);
33100b57cec5SDimitry Andric while (!Work.empty()) {
33110b57cec5SDimitry Andric const CXXMethodDecl *MD = *Work.begin();
33120b57cec5SDimitry Andric auto MethodRange = MD->overridden_methods();
33130b57cec5SDimitry Andric // If a virtual method has no-overrides it lives in its parent's vtable.
33140b57cec5SDimitry Andric if (MethodRange.begin() == MethodRange.end())
33150b57cec5SDimitry Andric BasesWithOverriddenMethods.insert(MD->getParent());
33160b57cec5SDimitry Andric else
33170b57cec5SDimitry Andric Work.insert(MethodRange.begin(), MethodRange.end());
33180b57cec5SDimitry Andric // We've finished processing this element, remove it from the working set.
33190b57cec5SDimitry Andric Work.erase(MD);
33200b57cec5SDimitry Andric }
33210b57cec5SDimitry Andric // For each of our virtual bases, check if it is in the set of overridden
33220b57cec5SDimitry Andric // bases or if it transitively contains a non-virtual base that is.
33230b57cec5SDimitry Andric for (const CXXBaseSpecifier &Base : RD->vbases()) {
33240b57cec5SDimitry Andric const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
33250b57cec5SDimitry Andric if (!HasVtordispSet.count(BaseDecl) &&
33260b57cec5SDimitry Andric RequiresVtordisp(BasesWithOverriddenMethods, BaseDecl))
33270b57cec5SDimitry Andric HasVtordispSet.insert(BaseDecl);
33280b57cec5SDimitry Andric }
33290b57cec5SDimitry Andric }
33300b57cec5SDimitry Andric
33310b57cec5SDimitry Andric /// getASTRecordLayout - Get or compute information about the layout of the
33320b57cec5SDimitry Andric /// specified record (struct/union/class), which indicates its size and field
33330b57cec5SDimitry Andric /// position information.
33340b57cec5SDimitry Andric const ASTRecordLayout &
getASTRecordLayout(const RecordDecl * D) const33350b57cec5SDimitry Andric ASTContext::getASTRecordLayout(const RecordDecl *D) const {
33360b57cec5SDimitry Andric // These asserts test different things. A record has a definition
33370b57cec5SDimitry Andric // as soon as we begin to parse the definition. That definition is
33380b57cec5SDimitry Andric // not a complete definition (which is what isDefinition() tests)
33390b57cec5SDimitry Andric // until we *finish* parsing the definition.
33400b57cec5SDimitry Andric
33410b57cec5SDimitry Andric if (D->hasExternalLexicalStorage() && !D->getDefinition())
33420b57cec5SDimitry Andric getExternalSource()->CompleteType(const_cast<RecordDecl*>(D));
3343bdd1243dSDimitry Andric // Complete the redecl chain (if necessary).
3344bdd1243dSDimitry Andric (void)D->getMostRecentDecl();
33450b57cec5SDimitry Andric
33460b57cec5SDimitry Andric D = D->getDefinition();
33470b57cec5SDimitry Andric assert(D && "Cannot get layout of forward declarations!");
33480b57cec5SDimitry Andric assert(!D->isInvalidDecl() && "Cannot get layout of invalid decl!");
33490b57cec5SDimitry Andric assert(D->isCompleteDefinition() && "Cannot layout type before complete!");
33500b57cec5SDimitry Andric
33510b57cec5SDimitry Andric // Look up this layout, if already laid out, return what we have.
33520b57cec5SDimitry Andric // Note that we can't save a reference to the entry because this function
33530b57cec5SDimitry Andric // is recursive.
33540b57cec5SDimitry Andric const ASTRecordLayout *Entry = ASTRecordLayouts[D];
33550b57cec5SDimitry Andric if (Entry) return *Entry;
33560b57cec5SDimitry Andric
33570b57cec5SDimitry Andric const ASTRecordLayout *NewEntry = nullptr;
33580b57cec5SDimitry Andric
33590b57cec5SDimitry Andric if (isMsLayout(*this)) {
33600b57cec5SDimitry Andric if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
33615f757f3fSDimitry Andric EmptySubobjectMap EmptySubobjects(*this, RD);
33625f757f3fSDimitry Andric MicrosoftRecordLayoutBuilder Builder(*this, &EmptySubobjects);
33630b57cec5SDimitry Andric Builder.cxxLayout(RD);
33640b57cec5SDimitry Andric NewEntry = new (*this) ASTRecordLayout(
33650b57cec5SDimitry Andric *this, Builder.Size, Builder.Alignment, Builder.Alignment,
3366e8d8bef9SDimitry Andric Builder.Alignment, Builder.RequiredAlignment, Builder.HasOwnVFPtr,
3367e8d8bef9SDimitry Andric Builder.HasOwnVFPtr || Builder.PrimaryBase, Builder.VBPtrOffset,
3368e8d8bef9SDimitry Andric Builder.DataSize, Builder.FieldOffsets, Builder.NonVirtualSize,
3369e8d8bef9SDimitry Andric Builder.Alignment, Builder.Alignment, CharUnits::Zero(),
33700b57cec5SDimitry Andric Builder.PrimaryBase, false, Builder.SharedVBPtrBase,
33710b57cec5SDimitry Andric Builder.EndsWithZeroSizedObject, Builder.LeadsWithZeroSizedBase,
33720b57cec5SDimitry Andric Builder.Bases, Builder.VBases);
33730b57cec5SDimitry Andric } else {
33745f757f3fSDimitry Andric MicrosoftRecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/nullptr);
33750b57cec5SDimitry Andric Builder.layout(D);
33760b57cec5SDimitry Andric NewEntry = new (*this) ASTRecordLayout(
33770b57cec5SDimitry Andric *this, Builder.Size, Builder.Alignment, Builder.Alignment,
3378e8d8bef9SDimitry Andric Builder.Alignment, Builder.RequiredAlignment, Builder.Size,
3379e8d8bef9SDimitry Andric Builder.FieldOffsets);
33800b57cec5SDimitry Andric }
33810b57cec5SDimitry Andric } else {
33820b57cec5SDimitry Andric if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
33830b57cec5SDimitry Andric EmptySubobjectMap EmptySubobjects(*this, RD);
33840b57cec5SDimitry Andric ItaniumRecordLayoutBuilder Builder(*this, &EmptySubobjects);
33850b57cec5SDimitry Andric Builder.Layout(RD);
33860b57cec5SDimitry Andric
33870b57cec5SDimitry Andric // In certain situations, we are allowed to lay out objects in the
33880b57cec5SDimitry Andric // tail-padding of base classes. This is ABI-dependent.
33890b57cec5SDimitry Andric // FIXME: this should be stored in the record layout.
33900b57cec5SDimitry Andric bool skipTailPadding =
33910b57cec5SDimitry Andric mustSkipTailPadding(getTargetInfo().getCXXABI(), RD);
33920b57cec5SDimitry Andric
33930b57cec5SDimitry Andric // FIXME: This should be done in FinalizeLayout.
33940b57cec5SDimitry Andric CharUnits DataSize =
33950b57cec5SDimitry Andric skipTailPadding ? Builder.getSize() : Builder.getDataSize();
33960b57cec5SDimitry Andric CharUnits NonVirtualSize =
33970b57cec5SDimitry Andric skipTailPadding ? DataSize : Builder.NonVirtualSize;
33980b57cec5SDimitry Andric NewEntry = new (*this) ASTRecordLayout(
3399e8d8bef9SDimitry Andric *this, Builder.getSize(), Builder.Alignment,
3400e8d8bef9SDimitry Andric Builder.PreferredAlignment, Builder.UnadjustedAlignment,
34010b57cec5SDimitry Andric /*RequiredAlignment : used by MS-ABI)*/
34020b57cec5SDimitry Andric Builder.Alignment, Builder.HasOwnVFPtr, RD->isDynamicClass(),
34030b57cec5SDimitry Andric CharUnits::fromQuantity(-1), DataSize, Builder.FieldOffsets,
34040b57cec5SDimitry Andric NonVirtualSize, Builder.NonVirtualAlignment,
3405e8d8bef9SDimitry Andric Builder.PreferredNVAlignment,
34060b57cec5SDimitry Andric EmptySubobjects.SizeOfLargestEmptySubobject, Builder.PrimaryBase,
34070b57cec5SDimitry Andric Builder.PrimaryBaseIsVirtual, nullptr, false, false, Builder.Bases,
34080b57cec5SDimitry Andric Builder.VBases);
34090b57cec5SDimitry Andric } else {
34100b57cec5SDimitry Andric ItaniumRecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/nullptr);
34110b57cec5SDimitry Andric Builder.Layout(D);
34120b57cec5SDimitry Andric
34130b57cec5SDimitry Andric NewEntry = new (*this) ASTRecordLayout(
3414e8d8bef9SDimitry Andric *this, Builder.getSize(), Builder.Alignment,
3415e8d8bef9SDimitry Andric Builder.PreferredAlignment, Builder.UnadjustedAlignment,
34160b57cec5SDimitry Andric /*RequiredAlignment : used by MS-ABI)*/
34170b57cec5SDimitry Andric Builder.Alignment, Builder.getSize(), Builder.FieldOffsets);
34180b57cec5SDimitry Andric }
34190b57cec5SDimitry Andric }
34200b57cec5SDimitry Andric
34210b57cec5SDimitry Andric ASTRecordLayouts[D] = NewEntry;
34220b57cec5SDimitry Andric
34230b57cec5SDimitry Andric if (getLangOpts().DumpRecordLayouts) {
34240b57cec5SDimitry Andric llvm::outs() << "\n*** Dumping AST Record Layout\n";
34250b57cec5SDimitry Andric DumpRecordLayout(D, llvm::outs(), getLangOpts().DumpRecordLayoutsSimple);
34260b57cec5SDimitry Andric }
34270b57cec5SDimitry Andric
34280b57cec5SDimitry Andric return *NewEntry;
34290b57cec5SDimitry Andric }
34300b57cec5SDimitry Andric
getCurrentKeyFunction(const CXXRecordDecl * RD)34310b57cec5SDimitry Andric const CXXMethodDecl *ASTContext::getCurrentKeyFunction(const CXXRecordDecl *RD) {
34320b57cec5SDimitry Andric if (!getTargetInfo().getCXXABI().hasKeyFunctions())
34330b57cec5SDimitry Andric return nullptr;
34340b57cec5SDimitry Andric
34350b57cec5SDimitry Andric assert(RD->getDefinition() && "Cannot get key function for forward decl!");
34360b57cec5SDimitry Andric RD = RD->getDefinition();
34370b57cec5SDimitry Andric
34380b57cec5SDimitry Andric // Beware:
34390b57cec5SDimitry Andric // 1) computing the key function might trigger deserialization, which might
34400b57cec5SDimitry Andric // invalidate iterators into KeyFunctions
34410b57cec5SDimitry Andric // 2) 'get' on the LazyDeclPtr might also trigger deserialization and
34420b57cec5SDimitry Andric // invalidate the LazyDeclPtr within the map itself
34430b57cec5SDimitry Andric LazyDeclPtr Entry = KeyFunctions[RD];
34440b57cec5SDimitry Andric const Decl *Result =
34450b57cec5SDimitry Andric Entry ? Entry.get(getExternalSource()) : computeKeyFunction(*this, RD);
34460b57cec5SDimitry Andric
34470b57cec5SDimitry Andric // Store it back if it changed.
34480b57cec5SDimitry Andric if (Entry.isOffset() || Entry.isValid() != bool(Result))
34490b57cec5SDimitry Andric KeyFunctions[RD] = const_cast<Decl*>(Result);
34500b57cec5SDimitry Andric
34510b57cec5SDimitry Andric return cast_or_null<CXXMethodDecl>(Result);
34520b57cec5SDimitry Andric }
34530b57cec5SDimitry Andric
setNonKeyFunction(const CXXMethodDecl * Method)34540b57cec5SDimitry Andric void ASTContext::setNonKeyFunction(const CXXMethodDecl *Method) {
34550b57cec5SDimitry Andric assert(Method == Method->getFirstDecl() &&
34560b57cec5SDimitry Andric "not working with method declaration from class definition");
34570b57cec5SDimitry Andric
34580b57cec5SDimitry Andric // Look up the cache entry. Since we're working with the first
34590b57cec5SDimitry Andric // declaration, its parent must be the class definition, which is
34600b57cec5SDimitry Andric // the correct key for the KeyFunctions hash.
34610b57cec5SDimitry Andric const auto &Map = KeyFunctions;
34620b57cec5SDimitry Andric auto I = Map.find(Method->getParent());
34630b57cec5SDimitry Andric
34640b57cec5SDimitry Andric // If it's not cached, there's nothing to do.
34650b57cec5SDimitry Andric if (I == Map.end()) return;
34660b57cec5SDimitry Andric
34670b57cec5SDimitry Andric // If it is cached, check whether it's the target method, and if so,
34680b57cec5SDimitry Andric // remove it from the cache. Note, the call to 'get' might invalidate
34690b57cec5SDimitry Andric // the iterator and the LazyDeclPtr object within the map.
34700b57cec5SDimitry Andric LazyDeclPtr Ptr = I->second;
34710b57cec5SDimitry Andric if (Ptr.get(getExternalSource()) == Method) {
34720b57cec5SDimitry Andric // FIXME: remember that we did this for module / chained PCH state?
34730b57cec5SDimitry Andric KeyFunctions.erase(Method->getParent());
34740b57cec5SDimitry Andric }
34750b57cec5SDimitry Andric }
34760b57cec5SDimitry Andric
getFieldOffset(const ASTContext & C,const FieldDecl * FD)34770b57cec5SDimitry Andric static uint64_t getFieldOffset(const ASTContext &C, const FieldDecl *FD) {
34780b57cec5SDimitry Andric const ASTRecordLayout &Layout = C.getASTRecordLayout(FD->getParent());
34790b57cec5SDimitry Andric return Layout.getFieldOffset(FD->getFieldIndex());
34800b57cec5SDimitry Andric }
34810b57cec5SDimitry Andric
getFieldOffset(const ValueDecl * VD) const34820b57cec5SDimitry Andric uint64_t ASTContext::getFieldOffset(const ValueDecl *VD) const {
34830b57cec5SDimitry Andric uint64_t OffsetInBits;
34840b57cec5SDimitry Andric if (const FieldDecl *FD = dyn_cast<FieldDecl>(VD)) {
34850b57cec5SDimitry Andric OffsetInBits = ::getFieldOffset(*this, FD);
34860b57cec5SDimitry Andric } else {
34870b57cec5SDimitry Andric const IndirectFieldDecl *IFD = cast<IndirectFieldDecl>(VD);
34880b57cec5SDimitry Andric
34890b57cec5SDimitry Andric OffsetInBits = 0;
34900b57cec5SDimitry Andric for (const NamedDecl *ND : IFD->chain())
34910b57cec5SDimitry Andric OffsetInBits += ::getFieldOffset(*this, cast<FieldDecl>(ND));
34920b57cec5SDimitry Andric }
34930b57cec5SDimitry Andric
34940b57cec5SDimitry Andric return OffsetInBits;
34950b57cec5SDimitry Andric }
34960b57cec5SDimitry Andric
lookupFieldBitOffset(const ObjCInterfaceDecl * OID,const ObjCImplementationDecl * ID,const ObjCIvarDecl * Ivar) const34970b57cec5SDimitry Andric uint64_t ASTContext::lookupFieldBitOffset(const ObjCInterfaceDecl *OID,
34980b57cec5SDimitry Andric const ObjCImplementationDecl *ID,
34990b57cec5SDimitry Andric const ObjCIvarDecl *Ivar) const {
3500349cc55cSDimitry Andric Ivar = Ivar->getCanonicalDecl();
35010b57cec5SDimitry Andric const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
35020b57cec5SDimitry Andric
35030b57cec5SDimitry Andric // FIXME: We should eliminate the need to have ObjCImplementationDecl passed
35040b57cec5SDimitry Andric // in here; it should never be necessary because that should be the lexical
35050b57cec5SDimitry Andric // decl context for the ivar.
35060b57cec5SDimitry Andric
35070b57cec5SDimitry Andric // If we know have an implementation (and the ivar is in it) then
35080b57cec5SDimitry Andric // look up in the implementation layout.
35090b57cec5SDimitry Andric const ASTRecordLayout *RL;
35100b57cec5SDimitry Andric if (ID && declaresSameEntity(ID->getClassInterface(), Container))
35110b57cec5SDimitry Andric RL = &getASTObjCImplementationLayout(ID);
35120b57cec5SDimitry Andric else
35130b57cec5SDimitry Andric RL = &getASTObjCInterfaceLayout(Container);
35140b57cec5SDimitry Andric
35150b57cec5SDimitry Andric // Compute field index.
35160b57cec5SDimitry Andric //
35170b57cec5SDimitry Andric // FIXME: The index here is closely tied to how ASTContext::getObjCLayout is
35180b57cec5SDimitry Andric // implemented. This should be fixed to get the information from the layout
35190b57cec5SDimitry Andric // directly.
35200b57cec5SDimitry Andric unsigned Index = 0;
35210b57cec5SDimitry Andric
35220b57cec5SDimitry Andric for (const ObjCIvarDecl *IVD = Container->all_declared_ivar_begin();
35230b57cec5SDimitry Andric IVD; IVD = IVD->getNextIvar()) {
35240b57cec5SDimitry Andric if (Ivar == IVD)
35250b57cec5SDimitry Andric break;
35260b57cec5SDimitry Andric ++Index;
35270b57cec5SDimitry Andric }
35280b57cec5SDimitry Andric assert(Index < RL->getFieldCount() && "Ivar is not inside record layout!");
35290b57cec5SDimitry Andric
35300b57cec5SDimitry Andric return RL->getFieldOffset(Index);
35310b57cec5SDimitry Andric }
35320b57cec5SDimitry Andric
35330b57cec5SDimitry Andric /// getObjCLayout - Get or compute information about the layout of the
35340b57cec5SDimitry Andric /// given interface.
35350b57cec5SDimitry Andric ///
35360b57cec5SDimitry Andric /// \param Impl - If given, also include the layout of the interface's
35370b57cec5SDimitry Andric /// implementation. This may differ by including synthesized ivars.
35380b57cec5SDimitry Andric const ASTRecordLayout &
getObjCLayout(const ObjCInterfaceDecl * D,const ObjCImplementationDecl * Impl) const35390b57cec5SDimitry Andric ASTContext::getObjCLayout(const ObjCInterfaceDecl *D,
35400b57cec5SDimitry Andric const ObjCImplementationDecl *Impl) const {
35410b57cec5SDimitry Andric // Retrieve the definition
35420b57cec5SDimitry Andric if (D->hasExternalLexicalStorage() && !D->getDefinition())
35430b57cec5SDimitry Andric getExternalSource()->CompleteType(const_cast<ObjCInterfaceDecl*>(D));
35440b57cec5SDimitry Andric D = D->getDefinition();
35455ffd83dbSDimitry Andric assert(D && !D->isInvalidDecl() && D->isThisDeclarationADefinition() &&
35465ffd83dbSDimitry Andric "Invalid interface decl!");
35470b57cec5SDimitry Andric
35480b57cec5SDimitry Andric // Look up this layout, if already laid out, return what we have.
35490b57cec5SDimitry Andric const ObjCContainerDecl *Key =
35500b57cec5SDimitry Andric Impl ? (const ObjCContainerDecl*) Impl : (const ObjCContainerDecl*) D;
35510b57cec5SDimitry Andric if (const ASTRecordLayout *Entry = ObjCLayouts[Key])
35520b57cec5SDimitry Andric return *Entry;
35530b57cec5SDimitry Andric
35540b57cec5SDimitry Andric // Add in synthesized ivar count if laying out an implementation.
35550b57cec5SDimitry Andric if (Impl) {
35560b57cec5SDimitry Andric unsigned SynthCount = CountNonClassIvars(D);
35570b57cec5SDimitry Andric // If there aren't any synthesized ivars then reuse the interface
35580b57cec5SDimitry Andric // entry. Note we can't cache this because we simply free all
35590b57cec5SDimitry Andric // entries later; however we shouldn't look up implementations
35600b57cec5SDimitry Andric // frequently.
35610b57cec5SDimitry Andric if (SynthCount == 0)
35620b57cec5SDimitry Andric return getObjCLayout(D, nullptr);
35630b57cec5SDimitry Andric }
35640b57cec5SDimitry Andric
35650b57cec5SDimitry Andric ItaniumRecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/nullptr);
35660b57cec5SDimitry Andric Builder.Layout(D);
35670b57cec5SDimitry Andric
3568e8d8bef9SDimitry Andric const ASTRecordLayout *NewEntry = new (*this) ASTRecordLayout(
3569e8d8bef9SDimitry Andric *this, Builder.getSize(), Builder.Alignment, Builder.PreferredAlignment,
35700b57cec5SDimitry Andric Builder.UnadjustedAlignment,
35710b57cec5SDimitry Andric /*RequiredAlignment : used by MS-ABI)*/
3572e8d8bef9SDimitry Andric Builder.Alignment, Builder.getDataSize(), Builder.FieldOffsets);
35730b57cec5SDimitry Andric
35740b57cec5SDimitry Andric ObjCLayouts[Key] = NewEntry;
35750b57cec5SDimitry Andric
35760b57cec5SDimitry Andric return *NewEntry;
35770b57cec5SDimitry Andric }
35780b57cec5SDimitry Andric
PrintOffset(raw_ostream & OS,CharUnits Offset,unsigned IndentLevel)35790b57cec5SDimitry Andric static void PrintOffset(raw_ostream &OS,
35800b57cec5SDimitry Andric CharUnits Offset, unsigned IndentLevel) {
35810b57cec5SDimitry Andric OS << llvm::format("%10" PRId64 " | ", (int64_t)Offset.getQuantity());
35820b57cec5SDimitry Andric OS.indent(IndentLevel * 2);
35830b57cec5SDimitry Andric }
35840b57cec5SDimitry Andric
PrintBitFieldOffset(raw_ostream & OS,CharUnits Offset,unsigned Begin,unsigned Width,unsigned IndentLevel)35850b57cec5SDimitry Andric static void PrintBitFieldOffset(raw_ostream &OS, CharUnits Offset,
35860b57cec5SDimitry Andric unsigned Begin, unsigned Width,
35870b57cec5SDimitry Andric unsigned IndentLevel) {
35880b57cec5SDimitry Andric llvm::SmallString<10> Buffer;
35890b57cec5SDimitry Andric {
35900b57cec5SDimitry Andric llvm::raw_svector_ostream BufferOS(Buffer);
35910b57cec5SDimitry Andric BufferOS << Offset.getQuantity() << ':';
35920b57cec5SDimitry Andric if (Width == 0) {
35930b57cec5SDimitry Andric BufferOS << '-';
35940b57cec5SDimitry Andric } else {
35950b57cec5SDimitry Andric BufferOS << Begin << '-' << (Begin + Width - 1);
35960b57cec5SDimitry Andric }
35970b57cec5SDimitry Andric }
35980b57cec5SDimitry Andric
35990b57cec5SDimitry Andric OS << llvm::right_justify(Buffer, 10) << " | ";
36000b57cec5SDimitry Andric OS.indent(IndentLevel * 2);
36010b57cec5SDimitry Andric }
36020b57cec5SDimitry Andric
PrintIndentNoOffset(raw_ostream & OS,unsigned IndentLevel)36030b57cec5SDimitry Andric static void PrintIndentNoOffset(raw_ostream &OS, unsigned IndentLevel) {
36040b57cec5SDimitry Andric OS << " | ";
36050b57cec5SDimitry Andric OS.indent(IndentLevel * 2);
36060b57cec5SDimitry Andric }
36070b57cec5SDimitry Andric
DumpRecordLayout(raw_ostream & OS,const RecordDecl * RD,const ASTContext & C,CharUnits Offset,unsigned IndentLevel,const char * Description,bool PrintSizeInfo,bool IncludeVirtualBases)36080b57cec5SDimitry Andric static void DumpRecordLayout(raw_ostream &OS, const RecordDecl *RD,
36090b57cec5SDimitry Andric const ASTContext &C,
36100b57cec5SDimitry Andric CharUnits Offset,
36110b57cec5SDimitry Andric unsigned IndentLevel,
36120b57cec5SDimitry Andric const char* Description,
36130b57cec5SDimitry Andric bool PrintSizeInfo,
36140b57cec5SDimitry Andric bool IncludeVirtualBases) {
36150b57cec5SDimitry Andric const ASTRecordLayout &Layout = C.getASTRecordLayout(RD);
36160b57cec5SDimitry Andric auto CXXRD = dyn_cast<CXXRecordDecl>(RD);
36170b57cec5SDimitry Andric
36180b57cec5SDimitry Andric PrintOffset(OS, Offset, IndentLevel);
361981ad6265SDimitry Andric OS << C.getTypeDeclType(const_cast<RecordDecl *>(RD));
36200b57cec5SDimitry Andric if (Description)
36210b57cec5SDimitry Andric OS << ' ' << Description;
36220b57cec5SDimitry Andric if (CXXRD && CXXRD->isEmpty())
36230b57cec5SDimitry Andric OS << " (empty)";
36240b57cec5SDimitry Andric OS << '\n';
36250b57cec5SDimitry Andric
36260b57cec5SDimitry Andric IndentLevel++;
36270b57cec5SDimitry Andric
36280b57cec5SDimitry Andric // Dump bases.
36290b57cec5SDimitry Andric if (CXXRD) {
36300b57cec5SDimitry Andric const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
36310b57cec5SDimitry Andric bool HasOwnVFPtr = Layout.hasOwnVFPtr();
36320b57cec5SDimitry Andric bool HasOwnVBPtr = Layout.hasOwnVBPtr();
36330b57cec5SDimitry Andric
36340b57cec5SDimitry Andric // Vtable pointer.
36350b57cec5SDimitry Andric if (CXXRD->isDynamicClass() && !PrimaryBase && !isMsLayout(C)) {
36360b57cec5SDimitry Andric PrintOffset(OS, Offset, IndentLevel);
36370b57cec5SDimitry Andric OS << '(' << *RD << " vtable pointer)\n";
36380b57cec5SDimitry Andric } else if (HasOwnVFPtr) {
36390b57cec5SDimitry Andric PrintOffset(OS, Offset, IndentLevel);
36400b57cec5SDimitry Andric // vfptr (for Microsoft C++ ABI)
36410b57cec5SDimitry Andric OS << '(' << *RD << " vftable pointer)\n";
36420b57cec5SDimitry Andric }
36430b57cec5SDimitry Andric
36440b57cec5SDimitry Andric // Collect nvbases.
36450b57cec5SDimitry Andric SmallVector<const CXXRecordDecl *, 4> Bases;
36460b57cec5SDimitry Andric for (const CXXBaseSpecifier &Base : CXXRD->bases()) {
36470b57cec5SDimitry Andric assert(!Base.getType()->isDependentType() &&
36480b57cec5SDimitry Andric "Cannot layout class with dependent bases.");
36490b57cec5SDimitry Andric if (!Base.isVirtual())
36500b57cec5SDimitry Andric Bases.push_back(Base.getType()->getAsCXXRecordDecl());
36510b57cec5SDimitry Andric }
36520b57cec5SDimitry Andric
36530b57cec5SDimitry Andric // Sort nvbases by offset.
36540b57cec5SDimitry Andric llvm::stable_sort(
36550b57cec5SDimitry Andric Bases, [&](const CXXRecordDecl *L, const CXXRecordDecl *R) {
36560b57cec5SDimitry Andric return Layout.getBaseClassOffset(L) < Layout.getBaseClassOffset(R);
36570b57cec5SDimitry Andric });
36580b57cec5SDimitry Andric
36590b57cec5SDimitry Andric // Dump (non-virtual) bases
36600b57cec5SDimitry Andric for (const CXXRecordDecl *Base : Bases) {
36610b57cec5SDimitry Andric CharUnits BaseOffset = Offset + Layout.getBaseClassOffset(Base);
36620b57cec5SDimitry Andric DumpRecordLayout(OS, Base, C, BaseOffset, IndentLevel,
36630b57cec5SDimitry Andric Base == PrimaryBase ? "(primary base)" : "(base)",
36640b57cec5SDimitry Andric /*PrintSizeInfo=*/false,
36650b57cec5SDimitry Andric /*IncludeVirtualBases=*/false);
36660b57cec5SDimitry Andric }
36670b57cec5SDimitry Andric
36680b57cec5SDimitry Andric // vbptr (for Microsoft C++ ABI)
36690b57cec5SDimitry Andric if (HasOwnVBPtr) {
36700b57cec5SDimitry Andric PrintOffset(OS, Offset + Layout.getVBPtrOffset(), IndentLevel);
36710b57cec5SDimitry Andric OS << '(' << *RD << " vbtable pointer)\n";
36720b57cec5SDimitry Andric }
36730b57cec5SDimitry Andric }
36740b57cec5SDimitry Andric
36750b57cec5SDimitry Andric // Dump fields.
36760b57cec5SDimitry Andric uint64_t FieldNo = 0;
36770b57cec5SDimitry Andric for (RecordDecl::field_iterator I = RD->field_begin(),
36780b57cec5SDimitry Andric E = RD->field_end(); I != E; ++I, ++FieldNo) {
36790b57cec5SDimitry Andric const FieldDecl &Field = **I;
36800b57cec5SDimitry Andric uint64_t LocalFieldOffsetInBits = Layout.getFieldOffset(FieldNo);
36810b57cec5SDimitry Andric CharUnits FieldOffset =
36820b57cec5SDimitry Andric Offset + C.toCharUnitsFromBits(LocalFieldOffsetInBits);
36830b57cec5SDimitry Andric
36840b57cec5SDimitry Andric // Recursively dump fields of record type.
36850b57cec5SDimitry Andric if (auto RT = Field.getType()->getAs<RecordType>()) {
36860b57cec5SDimitry Andric DumpRecordLayout(OS, RT->getDecl(), C, FieldOffset, IndentLevel,
36870b57cec5SDimitry Andric Field.getName().data(),
36880b57cec5SDimitry Andric /*PrintSizeInfo=*/false,
36890b57cec5SDimitry Andric /*IncludeVirtualBases=*/true);
36900b57cec5SDimitry Andric continue;
36910b57cec5SDimitry Andric }
36920b57cec5SDimitry Andric
36930b57cec5SDimitry Andric if (Field.isBitField()) {
36940b57cec5SDimitry Andric uint64_t LocalFieldByteOffsetInBits = C.toBits(FieldOffset - Offset);
36950b57cec5SDimitry Andric unsigned Begin = LocalFieldOffsetInBits - LocalFieldByteOffsetInBits;
36960b57cec5SDimitry Andric unsigned Width = Field.getBitWidthValue(C);
36970b57cec5SDimitry Andric PrintBitFieldOffset(OS, FieldOffset, Begin, Width, IndentLevel);
36980b57cec5SDimitry Andric } else {
36990b57cec5SDimitry Andric PrintOffset(OS, FieldOffset, IndentLevel);
37000b57cec5SDimitry Andric }
3701fe6060f1SDimitry Andric const QualType &FieldType = C.getLangOpts().DumpRecordLayoutsCanonical
3702fe6060f1SDimitry Andric ? Field.getType().getCanonicalType()
3703fe6060f1SDimitry Andric : Field.getType();
370481ad6265SDimitry Andric OS << FieldType << ' ' << Field << '\n';
37050b57cec5SDimitry Andric }
37060b57cec5SDimitry Andric
37070b57cec5SDimitry Andric // Dump virtual bases.
37080b57cec5SDimitry Andric if (CXXRD && IncludeVirtualBases) {
37090b57cec5SDimitry Andric const ASTRecordLayout::VBaseOffsetsMapTy &VtorDisps =
37100b57cec5SDimitry Andric Layout.getVBaseOffsetsMap();
37110b57cec5SDimitry Andric
37120b57cec5SDimitry Andric for (const CXXBaseSpecifier &Base : CXXRD->vbases()) {
37130b57cec5SDimitry Andric assert(Base.isVirtual() && "Found non-virtual class!");
37140b57cec5SDimitry Andric const CXXRecordDecl *VBase = Base.getType()->getAsCXXRecordDecl();
37150b57cec5SDimitry Andric
37160b57cec5SDimitry Andric CharUnits VBaseOffset = Offset + Layout.getVBaseClassOffset(VBase);
37170b57cec5SDimitry Andric
37180b57cec5SDimitry Andric if (VtorDisps.find(VBase)->second.hasVtorDisp()) {
37190b57cec5SDimitry Andric PrintOffset(OS, VBaseOffset - CharUnits::fromQuantity(4), IndentLevel);
37200b57cec5SDimitry Andric OS << "(vtordisp for vbase " << *VBase << ")\n";
37210b57cec5SDimitry Andric }
37220b57cec5SDimitry Andric
37230b57cec5SDimitry Andric DumpRecordLayout(OS, VBase, C, VBaseOffset, IndentLevel,
37240b57cec5SDimitry Andric VBase == Layout.getPrimaryBase() ?
37250b57cec5SDimitry Andric "(primary virtual base)" : "(virtual base)",
37260b57cec5SDimitry Andric /*PrintSizeInfo=*/false,
37270b57cec5SDimitry Andric /*IncludeVirtualBases=*/false);
37280b57cec5SDimitry Andric }
37290b57cec5SDimitry Andric }
37300b57cec5SDimitry Andric
37310b57cec5SDimitry Andric if (!PrintSizeInfo) return;
37320b57cec5SDimitry Andric
37330b57cec5SDimitry Andric PrintIndentNoOffset(OS, IndentLevel - 1);
37340b57cec5SDimitry Andric OS << "[sizeof=" << Layout.getSize().getQuantity();
37350b57cec5SDimitry Andric if (CXXRD && !isMsLayout(C))
37360b57cec5SDimitry Andric OS << ", dsize=" << Layout.getDataSize().getQuantity();
37370b57cec5SDimitry Andric OS << ", align=" << Layout.getAlignment().getQuantity();
3738e8d8bef9SDimitry Andric if (C.getTargetInfo().defaultsToAIXPowerAlignment())
3739e8d8bef9SDimitry Andric OS << ", preferredalign=" << Layout.getPreferredAlignment().getQuantity();
37400b57cec5SDimitry Andric
37410b57cec5SDimitry Andric if (CXXRD) {
37420b57cec5SDimitry Andric OS << ",\n";
37430b57cec5SDimitry Andric PrintIndentNoOffset(OS, IndentLevel - 1);
37440b57cec5SDimitry Andric OS << " nvsize=" << Layout.getNonVirtualSize().getQuantity();
37450b57cec5SDimitry Andric OS << ", nvalign=" << Layout.getNonVirtualAlignment().getQuantity();
3746e8d8bef9SDimitry Andric if (C.getTargetInfo().defaultsToAIXPowerAlignment())
3747e8d8bef9SDimitry Andric OS << ", preferrednvalign="
3748e8d8bef9SDimitry Andric << Layout.getPreferredNVAlignment().getQuantity();
37490b57cec5SDimitry Andric }
37500b57cec5SDimitry Andric OS << "]\n";
37510b57cec5SDimitry Andric }
37520b57cec5SDimitry Andric
DumpRecordLayout(const RecordDecl * RD,raw_ostream & OS,bool Simple) const3753e8d8bef9SDimitry Andric void ASTContext::DumpRecordLayout(const RecordDecl *RD, raw_ostream &OS,
37540b57cec5SDimitry Andric bool Simple) const {
37550b57cec5SDimitry Andric if (!Simple) {
37560b57cec5SDimitry Andric ::DumpRecordLayout(OS, RD, *this, CharUnits(), 0, nullptr,
37570b57cec5SDimitry Andric /*PrintSizeInfo*/ true,
37580b57cec5SDimitry Andric /*IncludeVirtualBases=*/true);
37590b57cec5SDimitry Andric return;
37600b57cec5SDimitry Andric }
37610b57cec5SDimitry Andric
37620b57cec5SDimitry Andric // The "simple" format is designed to be parsed by the
37630b57cec5SDimitry Andric // layout-override testing code. There shouldn't be any external
37640b57cec5SDimitry Andric // uses of this format --- when LLDB overrides a layout, it sets up
37650b57cec5SDimitry Andric // the data structures directly --- so feel free to adjust this as
37660b57cec5SDimitry Andric // you like as long as you also update the rudimentary parser for it
37670b57cec5SDimitry Andric // in libFrontend.
37680b57cec5SDimitry Andric
37690b57cec5SDimitry Andric const ASTRecordLayout &Info = getASTRecordLayout(RD);
377081ad6265SDimitry Andric OS << "Type: " << getTypeDeclType(RD) << "\n";
37710b57cec5SDimitry Andric OS << "\nLayout: ";
37720b57cec5SDimitry Andric OS << "<ASTRecordLayout\n";
37730b57cec5SDimitry Andric OS << " Size:" << toBits(Info.getSize()) << "\n";
37740b57cec5SDimitry Andric if (!isMsLayout(*this))
37750b57cec5SDimitry Andric OS << " DataSize:" << toBits(Info.getDataSize()) << "\n";
37760b57cec5SDimitry Andric OS << " Alignment:" << toBits(Info.getAlignment()) << "\n";
3777e8d8bef9SDimitry Andric if (Target->defaultsToAIXPowerAlignment())
3778e8d8bef9SDimitry Andric OS << " PreferredAlignment:" << toBits(Info.getPreferredAlignment())
3779e8d8bef9SDimitry Andric << "\n";
378006c3fb27SDimitry Andric if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
378106c3fb27SDimitry Andric OS << " BaseOffsets: [";
378206c3fb27SDimitry Andric const CXXRecordDecl *Base = nullptr;
378306c3fb27SDimitry Andric for (auto I : CXXRD->bases()) {
378406c3fb27SDimitry Andric if (I.isVirtual())
378506c3fb27SDimitry Andric continue;
378606c3fb27SDimitry Andric if (Base)
378706c3fb27SDimitry Andric OS << ", ";
378806c3fb27SDimitry Andric Base = I.getType()->getAsCXXRecordDecl();
378906c3fb27SDimitry Andric OS << Info.CXXInfo->BaseOffsets[Base].getQuantity();
379006c3fb27SDimitry Andric }
379106c3fb27SDimitry Andric OS << "]>\n";
379206c3fb27SDimitry Andric OS << " VBaseOffsets: [";
379306c3fb27SDimitry Andric const CXXRecordDecl *VBase = nullptr;
379406c3fb27SDimitry Andric for (auto I : CXXRD->vbases()) {
379506c3fb27SDimitry Andric if (VBase)
379606c3fb27SDimitry Andric OS << ", ";
379706c3fb27SDimitry Andric VBase = I.getType()->getAsCXXRecordDecl();
379806c3fb27SDimitry Andric OS << Info.CXXInfo->VBaseOffsets[VBase].VBaseOffset.getQuantity();
379906c3fb27SDimitry Andric }
380006c3fb27SDimitry Andric OS << "]>\n";
380106c3fb27SDimitry Andric }
38020b57cec5SDimitry Andric OS << " FieldOffsets: [";
38030b57cec5SDimitry Andric for (unsigned i = 0, e = Info.getFieldCount(); i != e; ++i) {
3804e8d8bef9SDimitry Andric if (i)
3805e8d8bef9SDimitry Andric OS << ", ";
38060b57cec5SDimitry Andric OS << Info.getFieldOffset(i);
38070b57cec5SDimitry Andric }
38080b57cec5SDimitry Andric OS << "]>\n";
38090b57cec5SDimitry Andric }
3810