1 //===- RecordLayout.cpp - Layout information for a struct/union -----------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file defines the RecordLayout interface. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "clang/AST/RecordLayout.h" 14 #include "clang/AST/ASTContext.h" 15 #include "clang/Basic/TargetCXXABI.h" 16 #include "clang/Basic/TargetInfo.h" 17 #include <cassert> 18 19 using namespace clang; 20 21 void ASTRecordLayout::Destroy(ASTContext &Ctx) { 22 if (CXXInfo) { 23 CXXInfo->~CXXRecordLayoutInfo(); 24 Ctx.Deallocate(CXXInfo); 25 } 26 this->~ASTRecordLayout(); 27 Ctx.Deallocate(this); 28 } 29 30 ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx, CharUnits size, 31 CharUnits alignment, 32 CharUnits preferredAlignment, 33 CharUnits unadjustedAlignment, 34 CharUnits requiredAlignment, 35 CharUnits datasize, 36 ArrayRef<uint64_t> fieldoffsets) 37 : Size(size), DataSize(datasize), Alignment(alignment), 38 PreferredAlignment(preferredAlignment), 39 UnadjustedAlignment(unadjustedAlignment), 40 RequiredAlignment(requiredAlignment) { 41 FieldOffsets.append(Ctx, fieldoffsets.begin(), fieldoffsets.end()); 42 } 43 44 // Constructor for C++ records. 45 ASTRecordLayout::ASTRecordLayout( 46 const ASTContext &Ctx, CharUnits size, CharUnits alignment, 47 CharUnits preferredAlignment, CharUnits unadjustedAlignment, 48 CharUnits requiredAlignment, bool hasOwnVFPtr, bool hasExtendableVFPtr, 49 CharUnits vbptroffset, CharUnits datasize, ArrayRef<uint64_t> fieldoffsets, 50 CharUnits nonvirtualsize, CharUnits nonvirtualalignment, 51 CharUnits preferrednvalignment, CharUnits SizeOfLargestEmptySubobject, 52 const CXXRecordDecl *PrimaryBase, bool IsPrimaryBaseVirtual, 53 const CXXRecordDecl *BaseSharingVBPtr, bool EndsWithZeroSizedObject, 54 bool LeadsWithZeroSizedBase, const BaseOffsetsMapTy &BaseOffsets, 55 const VBaseOffsetsMapTy &VBaseOffsets) 56 : Size(size), DataSize(datasize), Alignment(alignment), 57 PreferredAlignment(preferredAlignment), 58 UnadjustedAlignment(unadjustedAlignment), 59 RequiredAlignment(requiredAlignment), 60 CXXInfo(new (Ctx) CXXRecordLayoutInfo) { 61 FieldOffsets.append(Ctx, fieldoffsets.begin(), fieldoffsets.end()); 62 63 CXXInfo->PrimaryBase.setPointer(PrimaryBase); 64 CXXInfo->PrimaryBase.setInt(IsPrimaryBaseVirtual); 65 CXXInfo->NonVirtualSize = nonvirtualsize; 66 CXXInfo->NonVirtualAlignment = nonvirtualalignment; 67 CXXInfo->PreferredNVAlignment = preferrednvalignment; 68 CXXInfo->SizeOfLargestEmptySubobject = SizeOfLargestEmptySubobject; 69 CXXInfo->BaseOffsets = BaseOffsets; 70 CXXInfo->VBaseOffsets = VBaseOffsets; 71 CXXInfo->HasOwnVFPtr = hasOwnVFPtr; 72 CXXInfo->VBPtrOffset = vbptroffset; 73 CXXInfo->HasExtendableVFPtr = hasExtendableVFPtr; 74 CXXInfo->BaseSharingVBPtr = BaseSharingVBPtr; 75 CXXInfo->EndsWithZeroSizedObject = EndsWithZeroSizedObject; 76 CXXInfo->LeadsWithZeroSizedBase = LeadsWithZeroSizedBase; 77 78 #ifndef NDEBUG 79 if (const CXXRecordDecl *PrimaryBase = getPrimaryBase()) { 80 if (isPrimaryBaseVirtual()) { 81 if (Ctx.getTargetInfo().getCXXABI().hasPrimaryVBases()) { 82 assert(getVBaseClassOffset(PrimaryBase).isZero() && 83 "Primary virtual base must be at offset 0!"); 84 } 85 } else { 86 assert(getBaseClassOffset(PrimaryBase).isZero() && 87 "Primary base must be at offset 0!"); 88 } 89 } 90 #endif 91 } 92