File indexing completed on 2026-05-10 08:36:40
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef LLVM_CLANG_AST_RECORDLAYOUT_H
0014 #define LLVM_CLANG_AST_RECORDLAYOUT_H
0015
0016 #include "clang/AST/ASTVector.h"
0017 #include "clang/AST/CharUnits.h"
0018 #include "clang/AST/DeclCXX.h"
0019 #include "clang/Basic/LLVM.h"
0020 #include "llvm/ADT/ArrayRef.h"
0021 #include "llvm/ADT/DenseMap.h"
0022 #include "llvm/ADT/PointerIntPair.h"
0023 #include <cassert>
0024 #include <cstdint>
0025
0026 namespace clang {
0027
0028 class ASTContext;
0029 class CXXRecordDecl;
0030
0031
0032
0033
0034
0035
0036
0037
0038 class ASTRecordLayout {
0039 public:
0040 struct VBaseInfo {
0041
0042
0043 CharUnits VBaseOffset;
0044
0045 private:
0046
0047
0048
0049 bool HasVtorDisp = false;
0050
0051 public:
0052 VBaseInfo() = default;
0053 VBaseInfo(CharUnits VBaseOffset, bool hasVtorDisp)
0054 : VBaseOffset(VBaseOffset), HasVtorDisp(hasVtorDisp) {}
0055
0056 bool hasVtorDisp() const { return HasVtorDisp; }
0057 };
0058
0059 using VBaseOffsetsMapTy = llvm::DenseMap<const CXXRecordDecl *, VBaseInfo>;
0060
0061 private:
0062 friend class ASTContext;
0063
0064
0065 CharUnits Size;
0066
0067
0068 CharUnits DataSize;
0069
0070
0071 CharUnits Alignment;
0072
0073
0074
0075
0076 CharUnits PreferredAlignment;
0077
0078
0079
0080 CharUnits UnadjustedAlignment;
0081
0082
0083
0084 CharUnits RequiredAlignment;
0085
0086
0087 ASTVector<uint64_t> FieldOffsets;
0088
0089
0090 struct CXXRecordLayoutInfo {
0091
0092
0093 CharUnits NonVirtualSize;
0094
0095
0096
0097 CharUnits NonVirtualAlignment;
0098
0099
0100
0101
0102 CharUnits PreferredNVAlignment;
0103
0104
0105
0106
0107 CharUnits SizeOfLargestEmptySubobject;
0108
0109
0110 CharUnits VBPtrOffset;
0111
0112
0113
0114
0115 bool HasOwnVFPtr : 1;
0116
0117
0118
0119
0120 bool HasExtendableVFPtr : 1;
0121
0122
0123
0124
0125 bool EndsWithZeroSizedObject : 1;
0126
0127
0128
0129 bool LeadsWithZeroSizedBase : 1;
0130
0131
0132 llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> PrimaryBase;
0133
0134
0135 const CXXRecordDecl *BaseSharingVBPtr;
0136
0137
0138 using BaseOffsetsMapTy = llvm::DenseMap<const CXXRecordDecl *, CharUnits>;
0139
0140
0141 BaseOffsetsMapTy BaseOffsets;
0142
0143
0144 VBaseOffsetsMapTy VBaseOffsets;
0145 };
0146
0147
0148
0149 CXXRecordLayoutInfo *CXXInfo = nullptr;
0150
0151 ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment,
0152 CharUnits preferredAlignment, CharUnits unadjustedAlignment,
0153 CharUnits requiredAlignment, CharUnits datasize,
0154 ArrayRef<uint64_t> fieldoffsets);
0155
0156 using BaseOffsetsMapTy = CXXRecordLayoutInfo::BaseOffsetsMapTy;
0157
0158
0159 ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment,
0160 CharUnits preferredAlignment, CharUnits unadjustedAlignment,
0161 CharUnits requiredAlignment, bool hasOwnVFPtr,
0162 bool hasExtendableVFPtr, CharUnits vbptroffset,
0163 CharUnits datasize, ArrayRef<uint64_t> fieldoffsets,
0164 CharUnits nonvirtualsize, CharUnits nonvirtualalignment,
0165 CharUnits preferrednvalignment,
0166 CharUnits SizeOfLargestEmptySubobject,
0167 const CXXRecordDecl *PrimaryBase, bool IsPrimaryBaseVirtual,
0168 const CXXRecordDecl *BaseSharingVBPtr,
0169 bool EndsWithZeroSizedObject, bool LeadsWithZeroSizedBase,
0170 const BaseOffsetsMapTy &BaseOffsets,
0171 const VBaseOffsetsMapTy &VBaseOffsets);
0172
0173 ~ASTRecordLayout() = default;
0174
0175 void Destroy(ASTContext &Ctx);
0176
0177 public:
0178 ASTRecordLayout(const ASTRecordLayout &) = delete;
0179 ASTRecordLayout &operator=(const ASTRecordLayout &) = delete;
0180
0181
0182 CharUnits getAlignment() const { return Alignment; }
0183
0184
0185
0186 CharUnits getPreferredAlignment() const { return PreferredAlignment; }
0187
0188
0189
0190 CharUnits getUnadjustedAlignment() const { return UnadjustedAlignment; }
0191
0192
0193 CharUnits getSize() const { return Size; }
0194
0195
0196 unsigned getFieldCount() const { return FieldOffsets.size(); }
0197
0198
0199
0200 uint64_t getFieldOffset(unsigned FieldNo) const {
0201 return FieldOffsets[FieldNo];
0202 }
0203
0204
0205
0206 CharUnits getDataSize() const { return DataSize; }
0207
0208
0209
0210 CharUnits getNonVirtualSize() const {
0211 assert(CXXInfo && "Record layout does not have C++ specific info!");
0212
0213 return CXXInfo->NonVirtualSize;
0214 }
0215
0216
0217
0218 CharUnits getNonVirtualAlignment() const {
0219 assert(CXXInfo && "Record layout does not have C++ specific info!");
0220
0221 return CXXInfo->NonVirtualAlignment;
0222 }
0223
0224
0225
0226
0227 CharUnits getPreferredNVAlignment() const {
0228 assert(CXXInfo && "Record layout does not have C++ specific info!");
0229
0230 return CXXInfo->PreferredNVAlignment;
0231 }
0232
0233
0234 const CXXRecordDecl *getPrimaryBase() const {
0235 assert(CXXInfo && "Record layout does not have C++ specific info!");
0236
0237 return CXXInfo->PrimaryBase.getPointer();
0238 }
0239
0240
0241
0242 bool isPrimaryBaseVirtual() const {
0243 assert(CXXInfo && "Record layout does not have C++ specific info!");
0244
0245 return CXXInfo->PrimaryBase.getInt();
0246 }
0247
0248
0249 CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const {
0250 assert(CXXInfo && "Record layout does not have C++ specific info!");
0251
0252 Base = Base->getDefinition();
0253 assert(CXXInfo->BaseOffsets.count(Base) && "Did not find base!");
0254
0255 return CXXInfo->BaseOffsets[Base];
0256 }
0257
0258
0259 CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const {
0260 assert(CXXInfo && "Record layout does not have C++ specific info!");
0261
0262 VBase = VBase->getDefinition();
0263 assert(CXXInfo->VBaseOffsets.count(VBase) && "Did not find base!");
0264
0265 return CXXInfo->VBaseOffsets[VBase].VBaseOffset;
0266 }
0267
0268 CharUnits getSizeOfLargestEmptySubobject() const {
0269 assert(CXXInfo && "Record layout does not have C++ specific info!");
0270 return CXXInfo->SizeOfLargestEmptySubobject;
0271 }
0272
0273
0274
0275
0276
0277
0278
0279
0280 bool hasOwnVFPtr() const {
0281 assert(CXXInfo && "Record layout does not have C++ specific info!");
0282 return CXXInfo->HasOwnVFPtr;
0283 }
0284
0285
0286
0287
0288 bool hasExtendableVFPtr() const {
0289 assert(CXXInfo && "Record layout does not have C++ specific info!");
0290 return CXXInfo->HasExtendableVFPtr;
0291 }
0292
0293
0294
0295
0296
0297
0298
0299
0300 bool hasOwnVBPtr() const {
0301 assert(CXXInfo && "Record layout does not have C++ specific info!");
0302 return hasVBPtr() && !CXXInfo->BaseSharingVBPtr;
0303 }
0304
0305
0306 bool hasVBPtr() const {
0307 assert(CXXInfo && "Record layout does not have C++ specific info!");
0308 return !CXXInfo->VBPtrOffset.isNegative();
0309 }
0310
0311 CharUnits getRequiredAlignment() const { return RequiredAlignment; }
0312
0313 bool endsWithZeroSizedObject() const {
0314 return CXXInfo && CXXInfo->EndsWithZeroSizedObject;
0315 }
0316
0317 bool leadsWithZeroSizedBase() const {
0318 assert(CXXInfo && "Record layout does not have C++ specific info!");
0319 return CXXInfo->LeadsWithZeroSizedBase;
0320 }
0321
0322
0323
0324 CharUnits getVBPtrOffset() const {
0325 assert(CXXInfo && "Record layout does not have C++ specific info!");
0326 return CXXInfo->VBPtrOffset;
0327 }
0328
0329 const CXXRecordDecl *getBaseSharingVBPtr() const {
0330 assert(CXXInfo && "Record layout does not have C++ specific info!");
0331 return CXXInfo->BaseSharingVBPtr;
0332 }
0333
0334 const VBaseOffsetsMapTy &getVBaseOffsetsMap() const {
0335 assert(CXXInfo && "Record layout does not have C++ specific info!");
0336 return CXXInfo->VBaseOffsets;
0337 }
0338 };
0339
0340 }
0341
0342 #endif