23 :
Pointer(Pointee, Pointee->getDescriptor()->getMetadataSize(),
24 Pointee->getDescriptor()->getMetadataSize()) {}
27 :
Pointer(Pointee, BaseAndOffset, BaseAndOffset) {}
30 : Offset(
P.Offset), PointeeStorage(
P.PointeeStorage),
31 StorageKind(
P.StorageKind) {
34 PointeeStorage.BS.Pointee->addPointer(
this);
39 assert((
Base == RootPtrMark ||
Base %
alignof(
void *) == 0) &&
"wrong base");
41 PointeeStorage.BS = {Pointee,
Base};
48 : Offset(
P.Offset), PointeeStorage(
P.PointeeStorage),
49 StorageKind(
P.StorageKind) {
52 PointeeStorage.BS.Pointee->replacePointer(&
P,
this);
59 if (PointeeStorage.BS.Pointee) {
60 PointeeStorage.BS.Pointee->removePointer(
this);
61 PointeeStorage.BS.Pointee->cleanup();
67 assert(
P.StorageKind == StorageKind || (this->isZero() &&
P.isZero()));
70 StorageKind =
P.StorageKind;
72 Block *Old = PointeeStorage.BS.Pointee;
73 if (WasBlockPointer && PointeeStorage.BS.Pointee)
74 PointeeStorage.BS.Pointee->removePointer(
this);
77 PointeeStorage.BS =
P.PointeeStorage.BS;
79 if (PointeeStorage.BS.Pointee)
80 PointeeStorage.BS.Pointee->addPointer(
this);
82 if (WasBlockPointer && Old)
86 PointeeStorage.Int =
P.PointeeStorage.Int;
88 assert(
false &&
"Unhandled storage kind");
94 assert(
P.StorageKind == StorageKind || (this->isZero() &&
P.isZero()));
97 StorageKind =
P.StorageKind;
99 Block *Old = PointeeStorage.BS.Pointee;
100 if (WasBlockPointer && PointeeStorage.BS.Pointee)
101 PointeeStorage.BS.Pointee->removePointer(
this);
104 PointeeStorage.BS =
P.PointeeStorage.BS;
106 if (PointeeStorage.BS.Pointee)
107 PointeeStorage.BS.Pointee->addPointer(
this);
109 if (WasBlockPointer && Old)
113 PointeeStorage.Int =
P.PointeeStorage.Int;
115 assert(
false &&
"Unhandled storage kind");
136 else if (
const auto *E = Desc->
asExpr())
139 llvm_unreachable(
"Invalid allocation type");
157 bool IsVirtual =
false;
161 if (
const auto *BaseOrMember = Desc->
asDecl()) {
166 llvm_unreachable(
"Invalid field type");
174 std::reverse(Path.begin(), Path.end());
176 return APValue(
Base, Offset, Path, IsOnePastEnd,
false);
180 OS << PointeeStorage.BS.Pointee <<
" (";
185 OS <<
"rootptr(" << PointeeStorage.BS.Base <<
"), ";
187 OS << PointeeStorage.BS.Base <<
", ";
192 OS << Offset <<
", ";
194 if (PointeeStorage.BS.Pointee)
195 OS << PointeeStorage.BS.Pointee->getSize();
200 OS << PointeeStorage.Int.Value <<
", " << PointeeStorage.Int.Desc;
219 assert(PointeeStorage.BS.Pointee &&
220 "Cannot check if null pointer was initialized");
224 if (
isStatic() && PointeeStorage.BS.Base == 0)
235 return IM->second->isElementInitialized(
getIndex());
239 return PointeeStorage.BS.Base == 0 || getInlineDesc()->
IsInitialized;
246 assert(PointeeStorage.BS.Pointee &&
"Cannot initialize null pointer");
252 if (
isStatic() && PointeeStorage.BS.Base == 0)
262 std::make_pair(
false, std::make_shared<InitMap>(Desc->
getNumElems()));
270 if (IM->second->initializeElement(
getIndex())) {
278 assert(PointeeStorage.BS.Base != 0 &&
279 "Only composite fields can be initialised");
285 assert(PointeeStorage.BS.Base != 0 &&
286 "Only composite fields can be initialised");
319 Ty = AT->getValueType();
322 if (Ptr.isDummy() || !Ptr.isLive() ||
323 (!Ptr.isUnknownSizeArray() && Ptr.isOnePastEnd()))
327 if (std::optional<PrimType>
T = Ctx.
classify(Ty)) {
332 if (
const auto *RT = Ty->getAs<
RecordType>()) {
333 const auto *
Record = Ptr.getRecord();
334 assert(
Record &&
"Missing record descriptor");
337 if (RT->getDecl()->isUnion()) {
342 QualType FieldTy = F.Decl->getType();
344 if (std::optional<PrimType>
T = Ctx.
classify(FieldTy)) {
347 Ok &= Composite(FieldTy, FP,
Value);
360 for (
unsigned I = 0; I < NF; ++I) {
362 QualType FieldTy = FD->Decl->getType();
366 if (std::optional<PrimType>
T = Ctx.
classify(FieldTy)) {
369 Ok &= Composite(FieldTy, FP,
Value);
373 for (
unsigned I = 0; I < NB; ++I) {
377 Ok &= Composite(BaseTy, BP, R.getStructBase(I));
380 for (
unsigned I = 0; I < NV; ++I) {
384 Ok &= Composite(VirtBaseTy, VP, R.getStructBase(NB + I));
390 if (Ty->isIncompleteArrayType()) {
395 if (
const auto *AT = Ty->getAsArrayTypeUnsafe()) {
396 const size_t NumElems = Ptr.getNumElems();
397 QualType ElemTy = AT->getElementType();
401 for (
unsigned I = 0; I < NumElems; ++I) {
404 if (std::optional<PrimType>
T = Ctx.
classify(ElemTy)) {
407 Ok &= Composite(ElemTy, EP.
narrow(), Slot);
415 QualType ElemTy = CT->getElementType();
418 std::optional<PrimType> ElemT = Ctx.
classify(ElemTy);
421 auto V1 = Ptr.atIndex(0).deref<T>();
422 auto V2 = Ptr.atIndex(1).deref<T>();
423 R =
APValue(V1.toAPSInt(), V2.toAPSInt());
435 if (
const auto *VT = Ty->getAs<
VectorType>()) {
436 assert(Ptr.getFieldDesc()->isPrimitiveArray());
437 QualType ElemTy = VT->getElementType();
441 Values.reserve(VT->getNumElements());
442 for (
unsigned I = 0; I != VT->getNumElements(); ++I) {
444 Values.push_back(Ptr.atIndex(I).deref<
T>().toAPValue());
448 assert(Values.size() == VT->getNumElements());
449 R =
APValue(Values.data(), Values.size());
453 llvm_unreachable(
"invalid value to return");
#define INT_TYPE_SWITCH(Expr, B)
#define TYPE_SWITCH(Expr, B)
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
CharUnits - This is an opaque type for sizes expressed in character units.
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.
This represents one expression.
Represents a member of a struct/union/class.
A (possibly-)qualified type.
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.
void addPointer(Pointer *P)
Pointer chain management.
void cleanup()
Deletes a dead block at the end of its lifetime.
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
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.
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 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.
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 isElementPastEnd() const
Checks if the pointer is an out-of-bounds element pointer.
std::optional< APValue > toRValue(const Context &Ctx) const
Converts the pointer to an APValue that is an rvalue.
bool isBlockPointer() const
APValue toAPValue() const
Converts the pointer to an APValue.
const Descriptor * getFieldDesc() const
Accessors for information about the innermost field.
const BlockPointer & asBlockPointer() const
void initialize() const
Initializes a field.
bool isField() const
Checks if the item is a field in an object.
Structure/Class descriptor.
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 Expr * asExpr() const
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.