26 :
Pointer(Pointee, Pointee->getDescriptor()->getMetadataSize(),
27 Pointee->getDescriptor()->getMetadataSize()) {}
30 :
Pointer(Pointee, BaseAndOffset, BaseAndOffset) {}
33 : Offset(
P.Offset), PointeeStorage(
P.PointeeStorage),
34 StorageKind(
P.StorageKind) {
37 PointeeStorage.BS.Pointee->addPointer(
this);
42 assert((
Base == RootPtrMark ||
Base %
alignof(
void *) == 0) &&
"wrong base");
44 PointeeStorage.BS = {Pointee,
Base};
47 Pointee->addPointer(
this);
51 : Offset(
P.Offset), PointeeStorage(
P.PointeeStorage),
52 StorageKind(
P.StorageKind) {
55 PointeeStorage.BS.Pointee->replacePointer(&
P,
this);
62 if (
Block *Pointee = PointeeStorage.BS.Pointee) {
63 Pointee->removePointer(
this);
64 PointeeStorage.BS.Pointee =
nullptr;
73 if (
P.isBlockPointer() && this->block() ==
P.block()) {
75 PointeeStorage.BS.Base =
P.PointeeStorage.BS.Base;
79 if (
Block *Pointee = PointeeStorage.BS.Pointee) {
80 Pointee->removePointer(
this);
81 PointeeStorage.BS.Pointee =
nullptr;
86 StorageKind =
P.StorageKind;
89 if (
P.isBlockPointer()) {
90 PointeeStorage.BS =
P.PointeeStorage.BS;
91 PointeeStorage.BS.Pointee =
P.PointeeStorage.BS.Pointee;
93 if (PointeeStorage.BS.Pointee)
94 PointeeStorage.BS.Pointee->addPointer(
this);
95 }
else if (
P.isIntegralPointer()) {
96 PointeeStorage.Int =
P.PointeeStorage.Int;
97 }
else if (
P.isFunctionPointer()) {
98 PointeeStorage.Fn =
P.PointeeStorage.Fn;
100 assert(
false &&
"Unhandled storage kind");
108 if (
P.isBlockPointer() && this->block() ==
P.block()) {
110 PointeeStorage.BS.Base =
P.PointeeStorage.BS.Base;
114 if (
Block *Pointee = PointeeStorage.BS.Pointee) {
115 assert(
P.block() != this->block());
116 Pointee->removePointer(
this);
117 PointeeStorage.BS.Pointee =
nullptr;
122 StorageKind =
P.StorageKind;
125 if (
P.isBlockPointer()) {
126 PointeeStorage.BS =
P.PointeeStorage.BS;
127 PointeeStorage.BS.Pointee =
P.PointeeStorage.BS.Pointee;
129 if (PointeeStorage.BS.Pointee)
130 PointeeStorage.BS.Pointee->addPointer(
this);
131 }
else if (
P.isIntegralPointer()) {
132 PointeeStorage.Int =
P.PointeeStorage.Int;
133 }
else if (
P.isFunctionPointer()) {
134 PointeeStorage.Fn =
P.PointeeStorage.Fn;
136 assert(
false &&
"Unhandled storage kind");
159 else if (
const auto *
E = Desc->
asExpr()) {
161 if (
const auto *NewExpr = dyn_cast<CXXNewExpr>(
E)) {
163 if (NewExpr->isArray()) {
171 AllocatedType = NewExpr->getAllocatedType();
175 static int ReportedDynamicAllocs = 0;
182 llvm_unreachable(
"Invalid allocation type");
193 if (FD->getParent()->isInvalidDecl())
196 unsigned FieldIndex = FD->getFieldIndex();
222 bool IsVirtual =
false;
226 if (
const auto *BaseOrMember = Desc->
asDecl()) {
227 if (
const auto *FD = dyn_cast<FieldDecl>(BaseOrMember)) {
230 }
else if (
const auto *RD = dyn_cast<CXXRecordDecl>(BaseOrMember)) {
236 cast<CXXRecordDecl>(BaseRecord->
getDecl()));
248 llvm_unreachable(
"Invalid field type");
261 std::reverse(
Path.begin(),
Path.end());
268 switch (StorageKind) {
270 const Block *B = PointeeStorage.BS.Pointee;
271 OS <<
"(Block) " << B <<
" {";
274 OS <<
"rootptr(" << PointeeStorage.BS.Base <<
"), ";
276 OS << PointeeStorage.BS.Base <<
", ";
281 OS << Offset <<
", ";
291 OS << PointeeStorage.Int.Value <<
" + " << Offset <<
", "
292 << PointeeStorage.Int.Desc;
321 assert(PointeeStorage.BS.Pointee &&
322 "Cannot check if null pointer was initialized");
326 if (
isStatic() && PointeeStorage.BS.Base == 0)
337 return IM->second->isElementInitialized(
getIndex());
351 assert(PointeeStorage.BS.Pointee &&
"Cannot initialize null pointer");
364 if (
isStatic() && PointeeStorage.BS.Base == 0)
374 std::make_pair(
false, std::make_shared<InitMap>(Desc->
getNumElems()));
382 if (IM->second->initializeElement(
getIndex())) {
390 assert(PointeeStorage.BS.Base != 0 &&
391 "Only composite fields can be initialised");
397 assert(PointeeStorage.BS.Base != 0 &&
398 "Only composite fields can be activated");
402 if (!getInlineDesc()->InUnion)
413 for (
const Record::Field &F : UnionRecord->
fields()) {
415 if (FieldPtr == *
this) {
417 FieldPtr.getInlineDesc()->
IsActive =
false;
448 if (A.StorageKind != B.StorageKind)
469 assert(!ResultType.
isNull());
472 Composite = [&Composite, &Ctx, &ASTCtx](
QualType Ty,
const Pointer &Ptr,
475 Ty = AT->getValueType();
478 if (Ptr.isDummy() || !Ptr.isLive() || !Ptr.isBlockPointer() ||
483 if (std::optional<PrimType>
T = Ctx.
classify(Ty)) {
488 if (
const auto *RT = Ty->getAs<
RecordType>()) {
489 const auto *
Record = Ptr.getRecord();
490 assert(
Record &&
"Missing record descriptor");
493 if (RT->getDecl()->isUnion()) {
498 QualType FieldTy = F.Decl->getType();
500 if (std::optional<PrimType>
T = Ctx.
classify(FieldTy)) {
503 Ok &= Composite(FieldTy, FP,
Value);
517 for (
unsigned I = 0; I < NF; ++I) {
519 QualType FieldTy = FD->Decl->getType();
523 if (std::optional<PrimType>
T = Ctx.
classify(FieldTy)) {
526 Ok &= Composite(FieldTy, FP,
Value);
530 for (
unsigned I = 0; I < NB; ++I) {
534 Ok &= Composite(BaseTy, BP, R.getStructBase(I));
537 for (
unsigned I = 0; I < NV; ++I) {
541 Ok &= Composite(VirtBaseTy, VP, R.getStructBase(NB + I));
547 if (Ty->isIncompleteArrayType()) {
552 if (
const auto *AT = Ty->getAsArrayTypeUnsafe()) {
553 const size_t NumElems = Ptr.getNumElems();
554 QualType ElemTy = AT->getElementType();
558 for (
unsigned I = 0; I < NumElems; ++I) {
561 if (std::optional<PrimType>
T = Ctx.
classify(ElemTy)) {
564 Ok &= Composite(ElemTy, EP.
narrow(), Slot);
572 QualType ElemTy = CT->getElementType();
575 std::optional<PrimType> ElemT = Ctx.
classify(ElemTy);
578 auto V1 = Ptr.atIndex(0).deref<T>();
579 auto V2 = Ptr.atIndex(1).deref<T>();
580 R =
APValue(V1.toAPSInt(), V2.toAPSInt());
592 if (
const auto *VT = Ty->getAs<
VectorType>()) {
593 assert(Ptr.getFieldDesc()->isPrimitiveArray());
594 QualType ElemTy = VT->getElementType();
598 Values.reserve(VT->getNumElements());
599 for (
unsigned I = 0; I != VT->getNumElements(); ++I) {
601 Values.push_back(Ptr.atIndex(I).deref<
T>().toAPValue(ASTCtx));
605 assert(Values.size() == VT->getNumElements());
606 R =
APValue(Values.data(), Values.size());
610 llvm_unreachable(
"invalid value to return");
622 if (std::optional<PrimType>
T = Ctx.
classify(ResultType)) {
634 unsigned Offset)
const {
641 const Record::Field *F =
nullptr;
642 for (
auto &It : R->
fields()) {
643 if (It.Offset == Offset) {
654 uint64_t FieldOffset =
Defines the clang::Expr interface and subclasses for C++ expressions.
#define INT_TYPE_SWITCH(Expr, B)
#define TYPE_SWITCH(Expr, B)
static uint64_t getFieldOffset(const ASTContext &C, const FieldDecl *FD)
static LValueBase getDynamicAlloc(DynamicAllocLValue LV, QualType Type)
A non-discriminated union of a base, field, or array index.
static LValuePathEntry ArrayIndex(uint64_t Index)
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
APValue & getArrayInitializedElt(unsigned I)
std::string getAsString(const ASTContext &Ctx, QualType Ty) const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
QualType getRecordType(const RecordDecl *Decl) const
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
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.
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.
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.
CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const
getVBaseClassOffset - Get the offset, in chars, for the given base class.
CharUnits - This is an opaque type for sizes expressed in character units.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
Complex values, per C99 6.2.5p11.
Symbolic representation of a dynamic allocation.
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.
A (possibly-)qualified type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
bool isFloatingType() const
Represents a GCC generic vector type.
A memory block, either on the stack or in the heap.
unsigned getSize() const
Returns the size of the block.
std::byte * rawData()
Returns a pointer to the raw data, including metadata.
Holds all information required to evaluate constexpr code in a module.
ASTContext & getASTContext() const
Returns the AST context.
std::optional< PrimType > classify(QualType T) const
Classifies a type.
const APFloat & getAPFloat() const
const Function * getFunction() const
APValue toAPValue(const ASTContext &) const
A pointer to a memory block, live or dead.
static bool hasSameBase(const Pointer &A, const Pointer &B)
Checks if two pointers are comparable.
Pointer narrow() const
Restricts the scope of an array element pointer.
void deactivate() const
Deactivates an entire strurcutre.
bool isInitialized() const
Checks if an object was initialized.
bool isStatic() const
Checks if the storage is static.
Pointer atIndex(uint64_t Idx) const
Offsets a pointer inside an array.
bool isDummy() const
Checks if the pointer points to a dummy value.
void print(llvm::raw_ostream &OS) const
Prints the pointer.
int64_t getIndex() const
Returns the index into an array.
bool isActive() const
Checks if the object is active.
Pointer atField(unsigned Off) const
Creates a pointer to a field.
T & deref() const
Dereferences the pointer, if it's live.
DeclTy getSource() const
Returns the expression or declaration the pointer has been created for.
unsigned getNumElems() const
Returns the number of elements.
Pointer getArray() const
Returns the parent array.
bool isUnknownSizeArray() const
Checks if the structure is an array of unknown size.
void activate() const
Activats a field.
void operator=(const Pointer &P)
bool isIntegralPointer() const
QualType getType() const
Returns the type of the innermost field.
bool isArrayElement() const
Checks if the pointer points to an array.
bool isArrayRoot() const
Whether this array refers to an array, but not to the first element.
bool isLive() const
Checks if the pointer is live.
Pointer getBase() const
Returns a pointer to the object of which this pointer is a field.
std::string toDiagnosticString(const ASTContext &Ctx) const
Converts the pointer to a string usable in diagnostics.
bool isZero() const
Checks if the pointer is null.
const IntPointer & asIntPointer() const
bool isRoot() const
Pointer points directly to a block.
const Descriptor * getDeclDesc() const
Accessor for information about the declaration site.
static bool pointToSameBlock(const Pointer &A, const Pointer &B)
Checks if both given pointers point to the same block.
APValue toAPValue(const ASTContext &ASTCtx) const
Converts the pointer to an APValue.
bool isOnePastEnd() const
Checks if the index is one past end.
static bool hasSameArray(const Pointer &A, const Pointer &B)
Checks if two pointers can be subtracted.
bool isPastEnd() const
Checks if the pointer points past the end of the object.
bool isElementPastEnd() const
Checks if the pointer is an out-of-bounds element pointer.
bool isBlockPointer() const
std::optional< APValue > toRValue(const Context &Ctx, QualType ResultType) const
Converts the pointer to an APValue that is an rvalue.
const FunctionPointer & asFunctionPointer() const
const Block * block() const
bool isFunctionPointer() const
const Descriptor * getFieldDesc() const
Accessors for information about the innermost field.
bool isVirtualBaseClass() const
const BlockPointer & asBlockPointer() const
void initialize() const
Initializes a field.
bool isField() const
Checks if the item is a field in an object.
const Record * getRecord() const
Returns the record descriptor of a class.
Structure/Class descriptor.
const RecordDecl * getDecl() const
Returns the underlying declaration.
unsigned getNumBases() const
const Field * getField(const FieldDecl *FD) const
Returns a field.
const Base * getVirtualBase(const RecordDecl *RD) const
Returns a virtual base descriptor.
unsigned getNumFields() const
unsigned getNumVirtualBases() const
llvm::iterator_range< const_field_iter > fields() const
const Base * getBase(const RecordDecl *FD) const
Returns a base descriptor.
std::optional< std::pair< bool, std::shared_ptr< InitMap > > > InitMapPtr
PrimType
Enumeration of the primitive types of the VM.
The JSON file list parser is used to communicate input to InstallAPI.
@ Result
The result type of a method or function.
const FunctionProtoType * T
unsigned Base
Start of the current subfield.
Block * Pointee
The block the pointer is pointing to.
Describes a memory block created by an allocation site.
unsigned getNumElems() const
Returns the number of elements stored in the block.
const ValueDecl * asValueDecl() const
const Decl * asDecl() const
const bool IsArray
Flag indicating if the block is an array.
bool isPrimitiveArray() const
Checks if the descriptor is of an array of primitives.
const FieldDecl * asFieldDecl() const
const Record *const ElemRecord
Pointer to the record, if block contains records.
bool isUnion() const
Checks if the descriptor is of a union.
const Expr * asExpr() const
bool isArray() const
Checks if the descriptor is of an array.
Descriptor used for global variables.
GlobalInitState InitState
unsigned IsActive
Flag indicating if the field is the active member of a union.
unsigned IsInitialized
For primitive fields, it indicates if the field was initialized.
IntPointer atOffset(const ASTContext &ASTCtx, unsigned Offset) const