clang 23.0.0git
Descriptor.cpp
Go to the documentation of this file.
1//===--- Descriptor.cpp - Types for the constexpr VM ------------*- C++ -*-===//
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#include "Descriptor.h"
10#include "Boolean.h"
11#include "Char.h"
12#include "FixedPoint.h"
13#include "Floating.h"
14#include "IntegralAP.h"
15#include "MemberPointer.h"
16#include "Pointer.h"
17#include "PrimType.h"
18#include "Record.h"
19#include "Source.h"
20#include "clang/AST/ExprCXX.h"
21
22using namespace clang;
23using namespace clang::interp;
24
25template <typename T> static constexpr bool needsCtor() {
26 if constexpr (std::is_same_v<T, Integral<8, true>> ||
27 std::is_same_v<T, Integral<8, false>> ||
28 std::is_same_v<T, Integral<16, true>> ||
29 std::is_same_v<T, Integral<16, false>> ||
30 std::is_same_v<T, Integral<32, true>> ||
31 std::is_same_v<T, Integral<32, false>> ||
32 std::is_same_v<T, Integral<64, true>> ||
33 std::is_same_v<T, Integral<64, false>> ||
34 std::is_same_v<T, Boolean>)
35 return false;
36
37 return true;
38}
39
40template <typename T>
41static void ctorTy(Block *, std::byte *Ptr, bool, bool, bool, bool, bool,
42 const Descriptor *) {
43 static_assert(needsCtor<T>());
44 new (Ptr) T();
45}
46
47template <typename T>
48static void dtorTy(Block *, std::byte *Ptr, const Descriptor *) {
49 static_assert(needsCtor<T>());
50 reinterpret_cast<T *>(Ptr)->~T();
51}
52
53template <typename T>
54static void ctorArrayTy(Block *, std::byte *Ptr, bool, bool, bool, bool, bool,
55 const Descriptor *D) {
56 new (Ptr) InitMapPtr();
57
58 if constexpr (needsCtor<T>()) {
59 Ptr += sizeof(InitMapPtr);
60 for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) {
61 new (&reinterpret_cast<T *>(Ptr)[I]) T();
62 }
63 }
64}
65
66template <typename T>
67static void dtorArrayTy(Block *, std::byte *Ptr, const Descriptor *D) {
68 InitMapPtr &IMP = *reinterpret_cast<InitMapPtr *>(Ptr);
69 IMP.deleteInitMap();
70
71 if constexpr (needsCtor<T>()) {
72 Ptr += sizeof(InitMapPtr);
73 for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) {
74 reinterpret_cast<T *>(Ptr)[I].~T();
75 }
76 }
77}
78
79static void ctorArrayDesc(Block *B, std::byte *Ptr, bool IsConst,
80 bool IsMutable, bool IsVolatile, bool IsActive,
81 bool InUnion, const Descriptor *D) {
82 const unsigned NumElems = D->getNumElems();
83 const unsigned ElemSize =
85
86 unsigned ElemOffset = 0;
87 for (unsigned I = 0; I != NumElems; ++I, ElemOffset += ElemSize) {
88 auto *ElemPtr = Ptr + ElemOffset;
89 auto *Desc = reinterpret_cast<InlineDescriptor *>(ElemPtr);
90 auto *SD = D->ElemDesc;
91
92 Desc->Offset = ElemOffset + sizeof(InlineDescriptor);
93 Desc->Desc = SD;
94 Desc->IsInitialized = true;
95 Desc->IsBase = false;
96 Desc->IsActive = IsActive;
97 Desc->IsConst = IsConst || D->IsConst;
98 Desc->IsFieldMutable = IsMutable || D->IsMutable;
99 Desc->InUnion = InUnion;
100 Desc->IsArrayElement = true;
101 Desc->IsVolatile = IsVolatile;
102
103 if (auto Fn = D->ElemDesc->CtorFn) {
104 auto *ElemLoc = reinterpret_cast<std::byte *>(Desc + 1);
105 Fn(B, ElemLoc, Desc->IsConst, Desc->IsFieldMutable, IsVolatile, IsActive,
106 Desc->InUnion || SD->isUnion(), D->ElemDesc);
107 }
108 }
109}
110
111static void dtorArrayDesc(Block *B, std::byte *Ptr, const Descriptor *D) {
112 const unsigned NumElems = D->getNumElems();
113 const unsigned ElemSize =
114 D->ElemDesc->getAllocSize() + sizeof(InlineDescriptor);
115
116 unsigned ElemOffset = 0;
117 auto Dtor = D->ElemDesc->DtorFn;
118 assert(Dtor &&
119 "a composite array without an elem dtor shouldn't have a dtor itself");
120 for (unsigned I = 0; I != NumElems; ++I, ElemOffset += ElemSize) {
121 auto *ElemPtr = Ptr + ElemOffset;
122 auto *Desc = reinterpret_cast<InlineDescriptor *>(ElemPtr);
123 auto *ElemLoc = reinterpret_cast<std::byte *>(Desc + 1);
124 Dtor(B, ElemLoc, D->ElemDesc);
125 }
126}
127
128static void initField(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable,
129 bool IsVolatile, bool IsActive, bool IsUnionField,
130 bool InUnion, const Descriptor *D, unsigned FieldOffset) {
131 auto *Desc = reinterpret_cast<InlineDescriptor *>(Ptr + FieldOffset) - 1;
132 Desc->Offset = FieldOffset;
133 Desc->Desc = D;
134 Desc->IsInitialized = D->IsArray;
135 Desc->IsBase = false;
136 Desc->IsActive = IsActive && !IsUnionField;
137 Desc->InUnion = InUnion;
138 Desc->IsConst = IsConst || D->IsConst;
139 Desc->IsFieldMutable = IsMutable || D->IsMutable;
140 Desc->IsVolatile = IsVolatile || D->IsVolatile;
141 // True if this field is const AND the parent is mutable.
142 Desc->IsConstInMutable = Desc->IsConst && IsMutable;
143 Desc->LifeState =
146 : (Desc->IsActive ? Lifetime::NotStarted : Lifetime::Started);
147
148 if (auto Fn = D->CtorFn)
149 Fn(B, Ptr + FieldOffset, Desc->IsConst, Desc->IsFieldMutable,
150 Desc->IsVolatile, Desc->IsActive, InUnion || D->isUnion(), D);
151}
152
153static void initBase(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable,
154 bool IsVolatile, bool IsActive, bool InUnion,
155 const Descriptor *D, unsigned FieldOffset,
156 bool IsVirtualBase) {
157 assert(D);
158 assert(D->ElemRecord);
159 assert(!D->ElemRecord->isUnion()); // Unions cannot be base classes.
160
161 auto *Desc = reinterpret_cast<InlineDescriptor *>(Ptr + FieldOffset) - 1;
162 Desc->Offset = FieldOffset;
163 Desc->Desc = D;
164 Desc->IsInitialized = D->IsArray;
165 Desc->IsBase = true;
166 Desc->IsVirtualBase = IsVirtualBase;
167 Desc->IsActive = IsActive && !InUnion;
168 Desc->IsConst = IsConst || D->IsConst;
169 Desc->IsFieldMutable = IsMutable || D->IsMutable;
170 Desc->InUnion = InUnion;
171 Desc->IsVolatile = false;
172
173 for (const auto &V : D->ElemRecord->bases())
174 initBase(B, Ptr + FieldOffset, IsConst, IsMutable, IsVolatile, IsActive,
175 InUnion, V.Desc, V.Offset, false);
176 for (const auto &F : D->ElemRecord->fields())
177 initField(B, Ptr + FieldOffset, IsConst, IsMutable, IsVolatile, IsActive,
178 InUnion, InUnion, F.Desc, F.Offset);
179}
180
181static void ctorRecord(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable,
182 bool IsVolatile, bool IsActive, bool InUnion,
183 const Descriptor *D) {
184 for (const auto &V : D->ElemRecord->bases())
185 initBase(B, Ptr, IsConst, IsMutable, IsVolatile, IsActive, InUnion, V.Desc,
186 V.Offset,
187 /*IsVirtualBase=*/false);
188 for (const auto &F : D->ElemRecord->fields()) {
189 bool IsUnionField = D->isUnion();
190 initField(B, Ptr, IsConst, IsMutable, IsVolatile, IsActive, IsUnionField,
191 InUnion || IsUnionField, F.Desc, F.Offset);
192 }
193 for (const auto &V : D->ElemRecord->virtual_bases())
194 initBase(B, Ptr, IsConst, IsMutable, IsVolatile, IsActive, InUnion, V.Desc,
195 V.Offset,
196 /*IsVirtualBase=*/true);
197}
198
199static void destroyField(Block *B, std::byte *Ptr, const Descriptor *D,
200 unsigned FieldOffset) {
201 if (auto Fn = D->DtorFn)
202 Fn(B, Ptr + FieldOffset, D);
203}
204
205static void destroyBase(Block *B, std::byte *Ptr, const Descriptor *D,
206 unsigned FieldOffset) {
207 assert(D);
208 assert(D->ElemRecord);
209
210 for (const auto &V : D->ElemRecord->bases())
211 destroyBase(B, Ptr + FieldOffset, V.Desc, V.Offset);
212 for (const auto &F : D->ElemRecord->fields())
213 destroyField(B, Ptr + FieldOffset, F.Desc, F.Offset);
214}
215
216static void dtorRecord(Block *B, std::byte *Ptr, const Descriptor *D) {
217 for (const auto &F : D->ElemRecord->bases())
218 destroyBase(B, Ptr, F.Desc, F.Offset);
219 for (const auto &F : D->ElemRecord->fields())
220 destroyField(B, Ptr, F.Desc, F.Offset);
221 for (const auto &F : D->ElemRecord->virtual_bases())
222 destroyBase(B, Ptr, F.Desc, F.Offset);
223}
224
225/// Whether a record needs its descriptor dtor function called.
226static bool needsRecordDtor(const Record *R) {
227 for (const auto &B : R->bases()) {
228 if (B.Desc->DtorFn)
229 return true;
230 }
231
232 for (const auto &F : R->fields()) {
233 if (F.Desc->DtorFn)
234 return true;
235 }
236
237 for (const auto &V : R->virtual_bases()) {
238 if (V.Desc->DtorFn)
239 return true;
240 }
241 return false;
242}
243
245 switch (T) {
246 case PT_Float:
248 case PT_IntAP:
250 case PT_IntAPS:
252 case PT_Ptr:
254 case PT_MemberPtr:
256 default:
257 return nullptr;
258 }
259 llvm_unreachable("Unhandled PrimType");
260}
261
263 switch (T) {
264 case PT_Float:
266 case PT_IntAP:
268 case PT_IntAPS:
270 case PT_Ptr:
272 case PT_MemberPtr:
274 default:
275 return nullptr;
276 }
277 llvm_unreachable("Unhandled PrimType");
278}
279
282 llvm_unreachable("unknown Expr");
283}
284
287 llvm_unreachable("unknown Expr");
288}
289
290/// Primitives.
291Descriptor::Descriptor(const DeclTy &D, const Type *SourceTy, PrimType Type,
292 MetadataSize MD, bool IsConst, bool IsTemporary,
293 bool IsMutable, bool IsVolatile)
294 : Source(D), SourceType(SourceTy), ElemSize(primSize(Type)), Size(ElemSize),
295 MDSize(MD.value_or(0)), AllocSize(align(Size + MDSize)), PrimT(Type),
299 assert(AllocSize >= Size);
300 assert(Source && "Missing source");
301}
302
303/// Primitive arrays.
305 size_t NumElems, bool IsConst, bool IsTemporary,
306 bool IsMutable)
307 : Source(D), ElemSize(primSize(Type)), Size(ElemSize * NumElems),
308 MDSize(MD.value_or(0)),
309 AllocSize(align(MDSize) + align(Size) + sizeof(InitMapPtr)), PrimT(Type),
313 assert(Source && "Missing source");
314 assert(NumElems <= (MaxArrayElemBytes / ElemSize));
315}
316
317/// Primitive unknown-size arrays.
319 bool IsTemporary, bool IsConst, UnknownSize)
320 : Source(D), ElemSize(primSize(Type)), Size(UnknownSizeMark),
321 MDSize(MD.value_or(0)),
322 AllocSize(MDSize + sizeof(InitMapPtr) + alignof(void *)), PrimT(Type),
326 assert(Source && "Missing source");
327}
328
329/// Arrays of composite elements.
330Descriptor::Descriptor(const DeclTy &D, const Type *SourceTy,
331 const Descriptor *Elem, MetadataSize MD,
332 unsigned NumElems, bool IsConst, bool IsTemporary,
333 bool IsMutable)
334 : Source(D), SourceType(SourceTy),
335 ElemSize(Elem->getAllocSize() + sizeof(InlineDescriptor)),
336 Size(ElemSize * NumElems), MDSize(MD.value_or(0)),
337 AllocSize(std::max<size_t>(alignof(void *), Size) + MDSize),
341 assert(Source && "Missing source");
342}
343
344/// Unknown-size arrays of composite elements.
347 : Source(D), ElemSize(Elem->getAllocSize() + sizeof(InlineDescriptor)),
348 Size(UnknownSizeMark), MDSize(MD.value_or(0)),
349 AllocSize(MDSize + alignof(void *)), ElemDesc(Elem), IsConst(true),
352 assert(Source && "Missing source");
353}
354
355/// Composite records.
357 bool IsConst, bool IsTemporary, bool IsMutable,
358 bool IsVolatile)
359 : Source(D), ElemSize(std::max<size_t>(alignof(void *), R->getFullSize())),
360 Size(ElemSize), MDSize(MD.value_or(0)), AllocSize(Size + MDSize),
364 assert(Source && "Missing source");
365}
366
367/// Dummy.
369 : Source(D), ElemSize(1), Size(1), MDSize(MD.value_or(0)),
370 AllocSize(MDSize), ElemRecord(nullptr), IsConst(true), IsMutable(false),
372 assert(Source && "Missing source");
373}
374
376 if (SourceType)
377 return QualType(SourceType, 0);
378 if (const auto *D = asValueDecl())
379 return D->getType();
380 if (const auto *T = dyn_cast_if_present<TypeDecl>(asDecl()))
381 return T->getASTContext().getTypeDeclType(T);
382
383 // The Source sometimes has a different type than the once
384 // we really save. Try to consult the Record first.
385 if (isRecord()) {
386 const RecordDecl *RD = ElemRecord->getDecl();
387 return RD->getASTContext().getCanonicalTagType(RD);
388 }
389 if (const auto *E = asExpr())
390 return E->getType();
391 llvm_unreachable("Invalid descriptor type");
392}
393
395 assert(isArray());
396 QualType T = getType();
397 if (const auto *AT = T->getAs<AtomicType>())
398 T = AT->getValueType();
399 if (T->isPointerOrReferenceType())
400 T = T->getPointeeType();
401
402 if (const auto *AT = T->getAsArrayTypeUnsafe()) {
403 // For primitive arrays, we don't save a QualType at all,
404 // just a PrimType. Try to figure out the QualType here.
405 if (isPrimitiveArray()) {
406 while (T->isArrayType())
407 T = T->getAsArrayTypeUnsafe()->getElementType();
408 return T;
409 }
410 return AT->getElementType();
411 }
412 if (const auto *CT = T->getAs<ComplexType>())
413 return CT->getElementType();
414 if (const auto *CT = T->getAs<VectorType>())
415 return CT->getElementType();
416
417 return T;
418}
419
421 auto MakeArrayType = [&](QualType ElemType) -> QualType {
422 if (IsArray)
423 return Ctx.getConstantArrayType(
424 ElemType, APInt(64, static_cast<uint64_t>(getNumElems()), false),
425 nullptr, ArraySizeModifier::Normal, 0);
426 return ElemType;
427 };
428
429 if (const auto *E = asExpr()) {
430 if (isa<CXXNewExpr>(E))
431 return MakeArrayType(E->getType()->getPointeeType());
432
433 // std::allocator.allocate() call.
434 if (const auto *ME = dyn_cast<CXXMemberCallExpr>(E);
435 ME && ME->getRecordDecl()->getName() == "allocator" &&
436 ME->getMethodDecl()->getName() == "allocate")
437 return MakeArrayType(E->getType()->getPointeeType());
438 return E->getType();
439 }
440
441 return getType();
442}
443
445 if (const auto *E = asExpr()) {
446 if (isa<CXXNewExpr>(E))
447 return E->getType()->getPointeeType();
448
449 // std::allocator.allocate() call.
450 if (const auto *ME = dyn_cast<CXXMemberCallExpr>(E);
451 ME && ME->getRecordDecl()->getName() == "allocator" &&
452 ME->getMethodDecl()->getName() == "allocate")
453 return E->getType()->getPointeeType();
454 return E->getType();
455 }
456
457 return getType();
458}
459
461 if (auto *D = dyn_cast<const Decl *>(Source))
462 return D->getLocation();
463 if (auto *E = dyn_cast<const Expr *>(Source))
464 return E->getExprLoc();
465 llvm_unreachable("Invalid descriptor type");
466}
467
469 if (const auto *D = dyn_cast<const Decl *>(Source))
470 return SourceInfo(D);
471 if (const auto *E = dyn_cast<const Expr *>(Source))
472 return SourceInfo(E);
473 llvm_unreachable("Invalid descriptor type");
474}
475
477 if (isPrimitive() || isPrimitiveArray())
478 return true;
479
480 if (isRecord()) {
481 assert(ElemRecord);
482 return ElemRecord->hasTrivialDtor();
483 }
484
485 if (!ElemDesc)
486 return true;
487 // Composite arrays.
488 return ElemDesc->hasTrivialDtor();
489}
490
491bool Descriptor::isUnion() const { return isRecord() && ElemRecord->isUnion(); }
492
494 if ((isPrimitive() || isPrimitiveArray()) &&
496 if (getPrimType() == PT_Bool)
497 return 1;
498 FIXED_SIZE_INT_TYPE_SWITCH(getPrimType(), { return T::bitWidth() / 8; });
499 }
500 return ElemSize;
501}
#define V(N, I)
static void ctorRecord(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, bool IsVolatile, bool IsActive, bool InUnion, const Descriptor *D)
static void dtorTy(Block *, std::byte *Ptr, const Descriptor *)
static BlockCtorFn getCtorArrayPrim(PrimType Type)
static void destroyField(Block *B, std::byte *Ptr, const Descriptor *D, unsigned FieldOffset)
static void initField(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, bool IsVolatile, bool IsActive, bool IsUnionField, bool InUnion, const Descriptor *D, unsigned FieldOffset)
static void dtorArrayTy(Block *, std::byte *Ptr, const Descriptor *D)
static void ctorTy(Block *, std::byte *Ptr, bool, bool, bool, bool, bool, const Descriptor *)
static void ctorArrayDesc(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, bool IsVolatile, bool IsActive, bool InUnion, const Descriptor *D)
static void destroyBase(Block *B, std::byte *Ptr, const Descriptor *D, unsigned FieldOffset)
static constexpr bool needsCtor()
static void dtorArrayDesc(Block *B, std::byte *Ptr, const Descriptor *D)
static BlockCtorFn getCtorPrim(PrimType T)
static bool needsRecordDtor(const Record *R)
Whether a record needs its descriptor dtor function called.
static BlockDtorFn getDtorArrayPrim(PrimType Type)
static void ctorArrayTy(Block *, std::byte *Ptr, bool, bool, bool, bool, bool, const Descriptor *D)
static BlockDtorFn getDtorPrim(PrimType T)
static void dtorRecord(Block *B, std::byte *Ptr, const Descriptor *D)
static void initBase(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, bool IsVolatile, bool IsActive, bool InUnion, const Descriptor *D, unsigned FieldOffset, bool IsVirtualBase)
Defines the clang::Expr interface and subclasses for C++ expressions.
#define FIXED_SIZE_INT_TYPE_SWITCH(Expr, B)
Definition PrimType.h:263
#define TYPE_SWITCH(Expr, B)
Definition PrimType.h:223
__DEVICE__ int max(int __a, int __b)
__SIZE_TYPE__ size_t
The unsigned integer type of the result of the sizeof operator.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:227
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type.
CanQualType getCanonicalTagType(const TagDecl *TD) const
Complex values, per C99 6.2.5p11.
Definition TypeBase.h:3330
ASTContext & getASTContext() const LLVM_READONLY
Definition DeclBase.cpp:547
A (possibly-)qualified type.
Definition TypeBase.h:937
Represents a struct/union/class.
Definition Decl.h:4343
Encodes a location in the source.
The base class of the type hierarchy.
Definition TypeBase.h:1871
Represents a GCC generic vector type.
Definition TypeBase.h:4230
A memory block, either on the stack or in the heap.
Definition InterpBlock.h:44
Structure/Class descriptor.
Definition Record.h:25
bool isUnion() const
Checks if the record is a union.
Definition Record.h:69
llvm::iterator_range< const_virtual_iter > virtual_bases() const
Definition Record.h:117
llvm::iterator_range< const_base_iter > bases() const
Definition Record.h:102
llvm::iterator_range< const_field_iter > fields() const
Definition Record.h:90
Describes the statement/declaration an opcode was generated from.
Definition Source.h:74
void(*)(Block *Storage, std::byte *FieldPtr, const Descriptor *FieldDesc) BlockDtorFn
Invoked when a block is destroyed.
Definition Descriptor.h:40
llvm::PointerUnion< const Decl *, const Expr * > DeclTy
Definition Descriptor.h:29
bool NE(InterpState &S, CodePtr OpPC)
Definition Interp.h:1442
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
Definition PrimType.h:201
constexpr bool isIntegerOrBoolType(PrimType T)
Definition PrimType.h:52
llvm::APInt APInt
Definition FixedPoint.h:19
PrimType
Enumeration of the primitive types of the VM.
Definition PrimType.h:34
size_t primSize(PrimType Type)
Returns the size of a primitive type in bytes.
Definition PrimType.cpp:24
void(*)(Block *Storage, std::byte *FieldPtr, bool IsConst, bool IsMutable, bool IsVolatile, bool IsActive, bool InUnion, const Descriptor *FieldDesc) BlockCtorFn
Invoked whenever a block is created.
Definition Descriptor.h:34
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
#define false
Definition stdbool.h:26
#define true
Definition stdbool.h:25
Token to denote structures of unknown size.
Definition Descriptor.h:142
Describes a memory block created by an allocation site.
Definition Descriptor.h:123
const bool IsConst
Flag indicating if the block is mutable.
Definition Descriptor.h:162
unsigned getAllocSize() const
Returns the allocated size, including metadata.
Definition Descriptor.h:248
unsigned getNumElems() const
Returns the number of elements stored in the block.
Definition Descriptor.h:260
bool isPrimitive() const
Checks if the descriptor is of a primitive.
Definition Descriptor.h:274
QualType getElemQualType() const
bool hasTrivialDtor() const
Whether variables of this descriptor need their destructor called or not.
const BlockDtorFn DtorFn
Definition Descriptor.h:174
const OptPrimType PrimT
The primitive type this descriptor was created for, or the primitive element type in case this is a p...
Definition Descriptor.h:160
const ValueDecl * asValueDecl() const
Definition Descriptor.h:216
const BlockCtorFn CtorFn
Storage management methods.
Definition Descriptor.h:173
static constexpr unsigned MaxArrayElemBytes
Maximum number of bytes to be used for array elements.
Definition Descriptor.h:149
QualType getType() const
const Decl * asDecl() const
Definition Descriptor.h:212
const Descriptor *const ElemDesc
Descriptor of the array element.
Definition Descriptor.h:156
SourceInfo getLoc() const
Descriptor(const DeclTy &D, const Type *SourceTy, PrimType Type, MetadataSize MD, bool IsConst, bool IsTemporary, bool IsMutable, bool IsVolatile)
Allocates a descriptor for a primitive.
SourceLocation getLocation() const
const bool IsMutable
Flag indicating if a field is mutable.
Definition Descriptor.h:164
QualType getDataType(const ASTContext &Ctx) const
std::optional< unsigned > MetadataSize
Definition Descriptor.h:144
const bool IsArray
Flag indicating if the block is an array.
Definition Descriptor.h:169
unsigned getElemDataSize() const
Returns the element data size, i.e.
bool isPrimitiveArray() const
Checks if the descriptor is of an array of primitives.
Definition Descriptor.h:265
QualType getDataElemType() const
PrimType getPrimType() const
Definition Descriptor.h:242
bool isRecord() const
Checks if the descriptor is of a record.
Definition Descriptor.h:279
const bool IsTemporary
Flag indicating if the block is a temporary.
Definition Descriptor.h:166
const Record *const ElemRecord
Pointer to the record, if block contains records.
Definition Descriptor.h:154
bool isUnion() const
Checks if the descriptor is of a union.
const Expr * asExpr() const
Definition Descriptor.h:213
bool isArray() const
Checks if the descriptor is of an array.
Definition Descriptor.h:277
A pointer-sized struct we use to allocate into data storage.
Definition InitMap.h:79
void deleteInitMap()
Delete the InitMap if one exists.
Definition InitMap.h:113
Inline descriptor embedded in structures and arrays.
Definition Descriptor.h:68
unsigned Offset
Offset inside the structure/array.
Definition Descriptor.h:70