36 unsigned TypeModifier = 0) {
54 CurType = Entry.FD->getType();
94 return Ptr.computeLayoutOffset(ASTCtx).value_or(0);
128 auto isFlexibleArrayMember = [&](
const Descriptor *FieldDesc) {
130 FAMKind StrictFlexArraysLevel =
133 if (StrictFlexArraysLevel == FAMKind::Default)
136 unsigned NumElems = FieldDesc->getNumElems();
137 if (NumElems == 0 && StrictFlexArraysLevel != FAMKind::IncompleteOnly)
140 if (NumElems == 1 && StrictFlexArraysLevel == FAMKind::OneZeroOrIncomplete)
145 const Descriptor *FieldDesc = Ptr.getFieldDesc();
150 isFlexibleArrayMember(FieldDesc);
159 for (
unsigned I = 0; I != OP.
PathLength; ++I) {
161 switch (Entry.
Kind) {
181 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT)) {
182 if (Index != CAT->getLimitedSize() - 1)
184 CurType = CAT->getElementType();
202 const auto *CAT = dyn_cast<ConstantArrayType>(CurType);
207 FAMKind StrictFlexArraysLevel =
210 if (StrictFlexArraysLevel == FAMKind::Default)
213 unsigned Size = CAT->getZExtSize();
214 if (Size == 0 && StrictFlexArraysLevel != FAMKind::IncompleteOnly)
217 if (Size == 1 && StrictFlexArraysLevel == FAMKind::OneZeroOrIncomplete)
225static std::optional<uint64_t>
227 bool UseClosestSurroundingVariable,
228 bool &OffsetIsNegative) {
232 std::optional<uint64_t> SurroundingArrayOffset;
235 switch (Entry.Kind) {
263 uint64_t Index = Entry.Index;
266 OffsetIsNegative =
true;
268 SurroundingArrayOffset = Offset;
290 if (UseClosestSurroundingVariable && SurroundingArrayOffset)
291 return Offset - *SurroundingArrayOffset;
295 if (UseClosestSurroundingVariable &&
307 if (UseClosestSurroundingVariable)
328static std::optional<unsigned>
330 bool UseClosestSurroundingVariable,
bool WritingOffTheEnd,
331 bool DetermineForCompleteObject) {
336 if (UseClosestSurroundingVariable) {
351 if (!WritingOffTheEnd && !DetermineForCompleteObject)
364 if (!
Base->getType()->isRecordType())
367 if (!
Base->hasInit())
369 CharUnits FlexibleArraySize =
Base->getFlexibleArrayInitChars(ASTCtx);
370 return (TypeSize + FlexibleArraySize).getQuantity();
385 const Expr *E,
bool IsDynamic) {
389 bool InvalidBase =
false;
390 if (Ptr.isOpaquePointer()) {
391 bool UseClosestSurroundingVariable = (Kind == 1) || (Kind == 3);
399 std::optional<unsigned> FullSize =
401 WritingOffTheEnd, DetermineForCompleteObject);
408 bool OffsetIsNegative =
false;
410 ASTCtx, Ptr, UseClosestSurroundingVariable, OffsetIsNegative);
415 if (OffsetIsNegative)
429 const auto *FD = ME ? dyn_cast<FieldDecl>(ME->getMemberDecl()) :
nullptr;
430 if (FD && FD->getType()->isCountAttributedType())
434 if (!UseClosestSurroundingVariable || DetermineForCompleteObject) {
436 if (Kind == 3 && !DetermineForCompleteObject)
448 *Offset += Ptr.getByteOffset();
450 if (*Offset > *FullSize)
453 if (Kind == 1 && InvalidBase && WritingOffTheEnd)
456 assert(*Offset <= *FullSize);
457 return static_cast<unsigned>(*FullSize - *Offset);
462 if (Ptr.isDummy() && Ptr.getType()->isPointerType())
465 if (!Ptr.isBlockPointer())
469 if (
const VarDecl *VD = Ptr.getRootVarDecl();
470 VD && VD->getType()->isPointerType())
474 bool UseFieldDesc = (Kind & 1u);
475 bool ReportMinimum = (Kind & 2u);
480 if (Ptr.isArrayElement())
483 bool DetermineForCompleteObject = Ptr.getFieldDesc() == Ptr.getDeclDesc();
484 const Descriptor *DeclDesc = Ptr.getDeclDesc();
487 if (!UseFieldDesc || DetermineForCompleteObject) {
506 if (UseFieldDesc && Ptr.isBaseClass())
507 Ptr = Ptr.stripBaseCasts();
509 const Descriptor *Desc = UseFieldDesc ? Ptr.getFieldDesc() : DeclDesc;
518 if (Ptr.isBaseClass()) {
534 assert(ByteOffset <= *FullSize);
535 return *FullSize - ByteOffset;
static bool pointsToCompleteObject(const ASTContext &ASTCtx, const Pointer &Ptr)
Check if the given pointer points to the complete object, i.e.
static bool pointsToLastObject(const Pointer &Ptr)
Does Ptr point to the last subobject?
static bool isUserWritingOffTheEnd(const ASTContext &Ctx, const Pointer &Ptr, bool InvalidBase)
Does Ptr point to the last object AND to a flexible array member?
static std::optional< unsigned > computeOpaqueSize(const ASTContext &ASTCtx, const Pointer &Ptr, bool UseClosestSurroundingVariable, bool WritingOffTheEnd, bool DetermineForCompleteObject)
static QualType computeFieldType(const ASTContext &ASTCtx, const OpaquePointer &OP, unsigned TypeModifier=0)
static std::optional< uint64_t > computeOpaquePtrOffset(const ASTContext &ASTCtx, const Pointer &Ptr, bool UseClosestSurroundingVariable, bool &OffsetIsNegative)
Determine the offset of the given pointer.
static unsigned computePointerOffset(const ASTContext &ASTCtx, const Pointer &Ptr)
Compute the byte offset of Ptr in the full declaration.
static std::optional< unsigned > computeFullDescSize(const ASTContext &ASTCtx, const Descriptor *Desc)
static bool hasLayout(const RecordDecl *D)
Whether layout (offset and size) information can be queried for D.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
const LangOptions & getLangOpts() const
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
CanQualType getCanonicalTagType(const TagDecl *TD) const
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
QualType getElementType() const
CharUnits - This is an opaque type for sizes expressed in character units.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
This represents one expression.
Represents a member of a struct/union/class.
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
StrictFlexArraysLevelKind
A (possibly-)qualified type.
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
Represents a struct/union/class.
unsigned getNumFields() const
Returns the number of fields (non-static data members) in this record.
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
bool isPointerType() const
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
bool isFunctionType() const
Represents a variable declaration or definition.
A pointer to a memory block, live or dead.
Pointer getArray() const
Returns the parent array.
bool isArrayElement() const
Checks if the pointer points to an array.
Pointer getBase() const
Returns a pointer to the object of which this pointer is a field.
bool isRoot() const
Pointer points directly to a block.
const FieldDecl * getField() const
Returns the field information.
Pointer expand() const
Expands a pointer to the containing array, undoing narrowing.
bool isBaseClass() const
Checks if a structure is a base class.
const Record * getRecord() const
Returns the record descriptor of a class.
Structure/Class descriptor.
const RecordDecl * getDecl() const
Returns the underlying declaration.
unsigned getNumFields() const
UnsignedOrNone evaluateBuiltinObjectSize(const ASTContext &ASTCtx, unsigned Kind, Pointer &Ptr, const Expr *E, bool IsDynamic)
Evaluate __builtin_object_size or __builtin_dynamic_object_size for the given pointer and Kind.
bool Add(InterpState &S, CodePtr OpPC)
static bool validType(QualType T)
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
const Expr * findStructFieldAccess(const Expr *E, const Expr **OutArrayIndex=nullptr, QualType *OutArrayElementTy=nullptr)
Walk E through parens, implicit casts, unary &/*, array subscripts and comma operators to find the he...
OptionalUnsigned< unsigned > UnsignedOrNone
const FunctionProtoType * T
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 uint8_t
Describes a memory block created by an allocation site.
bool isPrimitive() const
Checks if the descriptor is of a primitive.
QualType getDataType(const ASTContext &Ctx) const
bool isRecord() const
Checks if the descriptor is of a record.
const Record *const ElemRecord
Pointer to the record, if block contains records.
bool isArray() const
Checks if the descriptor is of an array.
QualType getObjectType() const
QualType getSurroundingArray() const
If this is pointing to an array element, return the array.
const PointerPathEntry * Path
ArrayRef< PointerPathEntry > path() const
bool isArrayElement() const
enum clang::interp::PointerPathEntry::@133156275124227243235357227301330162015140142322 Kind