27 :
Pointer(Pointee, Pointee->getDescriptor()->getMetadataSize(),
28 Pointee->getDescriptor()->getMetadataSize()) {}
31 :
Pointer(Pointee, BaseAndOffset, BaseAndOffset) {}
35 assert((
Base == RootPtrMark ||
Base %
alignof(
void *) == 0) &&
"wrong base");
37 BS = {Pointee,
Base,
nullptr,
nullptr};
40 Pointee->addPointer(
this);
44 : Offset(
P.Offset), StorageKind(
P.StorageKind) {
45 switch (StorageKind) {
64 switch (StorageKind) {
87 Pointee->removePointer(
this);
97 if (
P.isBlockPointer() && this->block() ==
P.block()) {
104 Pointee->removePointer(
this);
110 StorageKind =
P.StorageKind;
113 if (
P.isBlockPointer()) {
118 }
else if (
P.isIntegralPointer()) {
120 }
else if (
P.isFunctionPointer()) {
122 }
else if (
P.isTypeidPointer()) {
125 assert(
false &&
"Unhandled storage kind");
134 if (
P.isBlockPointer() && this->block() ==
P.block()) {
141 Pointee->removePointer(
this);
147 StorageKind =
P.StorageKind;
150 if (
P.isBlockPointer()) {
155 }
else if (
P.isIntegralPointer()) {
157 }
else if (
P.isFunctionPointer()) {
159 }
else if (
P.isTypeidPointer()) {
162 assert(
false &&
"Unhandled storage kind");
201 else if (
const auto *
E = Desc->
asExpr()) {
210 llvm_unreachable(
"Invalid allocation type");
221 if (FD->getParent()->isInvalidDecl())
224 unsigned FieldIndex = FD->getFieldIndex();
251 const auto *Dcl = Desc->
asDecl();
254 if (
const auto *FD = dyn_cast_if_present<FieldDecl>(Dcl))
283 if (
const auto *BaseOrMember = Desc->
asDecl()) {
284 bool IsVirtual =
false;
285 if (
const auto *FD = dyn_cast<FieldDecl>(BaseOrMember)) {
288 }
else if (
const auto *RD = dyn_cast<CXXRecordDecl>(BaseOrMember)) {
294 cast<CXXRecordDecl>(BaseRecord->
getDecl()));
306 llvm_unreachable(
"Invalid field type");
314 std::reverse(
Path.begin(),
Path.end());
323 switch (StorageKind) {
326 OS <<
"(Block) " << B <<
" {";
329 OS <<
"rootptr(" <<
BS.
Base <<
"), ";
336 OS << Offset <<
", ";
373 if (
P.isVirtualBaseClass()) {
379 if (
P.isBaseClass()) {
380 if (
P.getRecord()->getNumVirtualBases() > 0)
381 Result +=
P.getInlineDesc()->Offset;
385 if (
P.isArrayElement()) {
387 Result += (
P.getIndex() *
P.elemSize());
393 if (
P.isOnePastEnd())
398 if (
const Record *R =
P.getBase().getRecord(); R && R->isUnion()) {
399 if (
P.isOnePastEnd())
407 Result +=
P.getInlineDesc()->Offset;
408 if (
P.isOnePastEnd())
442 assert(
BS.
Pointee &&
"Cannot check if null pointer was initialized");
478 return IM->second->isElementInitialized(Index);
487 assert(
BS.
Pointee &&
"Cannot initialize null pointer");
510 std::make_pair(
false, std::make_shared<InitMap>(Desc->
getNumElems()));
518 if (IM->second->initializeElement(
getIndex())) {
526 assert(
BS.
Base != 0 &&
"Only composite fields can be initialised");
536 IM = std::make_pair(
true,
nullptr);
557 return IM && IM->first;
562 assert(
BS.
Base != 0 &&
"Only composite fields can be activated");
566 if (!getInlineDesc()->InUnion)
571 P.getInlineDesc()->IsActive =
true;
572 if (
const Record *R =
P.getRecord(); R && !R->isUnion()) {
573 for (
const Record::Field &F : R->fields()) {
574 Pointer FieldPtr =
P.atField(F.Offset);
575 if (!FieldPtr.getInlineDesc()->
IsActive)
584 P.getInlineDesc()->IsActive =
false;
586 if (
const Record *R =
P.getRecord()) {
587 for (
const Record::Field &F : R->fields()) {
588 Pointer FieldPtr =
P.atField(F.Offset);
589 if (FieldPtr.getInlineDesc()->
IsActive)
605 for (
const Record::Field &F : BR->fields()) {
630 if (A.StorageKind != B.StorageKind)
655 return E && !isa<MaterializeTemporaryExpr, StringLiteral>(
E);
666 return isa_and_nonnull<StringLiteral>(
E);
669std::optional<std::pair<Pointer, Pointer>>
680 return std::make_pair(A, B);
683 if (
P.isArrayElement())
684 return P.expand().getArray();
702 return std::make_pair(CurA, CurB);
708 llvm_unreachable(
"The loop above should've returned.");
713 const ASTContext &ASTCtx = Ctx.getASTContext();
714 assert(!ResultType.
isNull());
717 Composite = [&Composite, &Ctx, &ASTCtx](
QualType Ty,
const Pointer &Ptr,
720 Ty = AT->getValueType();
723 if (Ptr.isDummy() || !Ptr.isLive() || !Ptr.isBlockPointer() ||
733 if (
const auto *RT = Ty->getAsCanonical<
RecordType>()) {
734 const auto *
Record = Ptr.getRecord();
735 assert(
Record &&
"Missing record descriptor");
738 if (RT->getOriginalDecl()->isUnion()) {
743 QualType FieldTy = F.Decl->getType();
748 Ok &= Composite(FieldTy, FP,
Value);
762 for (
unsigned I = 0; I < NF; ++I) {
764 QualType FieldTy = FD->Decl->getType();
771 Ok &= Composite(FieldTy, FP,
Value);
775 for (
unsigned I = 0; I < NB; ++I) {
779 Ok &= Composite(BaseTy, BP, R.getStructBase(I));
782 for (
unsigned I = 0; I < NV; ++I) {
787 Ok &= Composite(VirtBaseTy, VP, R.getStructBase(NB + I));
793 if (Ty->isIncompleteArrayType()) {
798 if (
const auto *AT = Ty->getAsArrayTypeUnsafe()) {
799 const size_t NumElems = Ptr.getNumElems();
800 QualType ElemTy = AT->getElementType();
805 for (
unsigned I = 0; I != NumElems; ++I) {
808 TYPE_SWITCH(*ElemT, Slot = Ptr.elem<
T>(I).toAPValue(ASTCtx));
810 Ok &= Composite(ElemTy, Ptr.atIndex(I).narrow(), Slot);
819 if (!Ptr.getFieldDesc()->isPrimitiveArray())
822 QualType ElemTy = CT->getElementType();
827 auto V1 = Ptr.elem<
T>(0);
828 auto V2 = Ptr.elem<
T>(1);
829 R =
APValue(V1.toAPSInt(), V2.toAPSInt());
841 if (
const auto *VT = Ty->getAs<
VectorType>()) {
842 assert(Ptr.getFieldDesc()->isPrimitiveArray());
843 QualType ElemTy = VT->getElementType();
844 PrimType ElemT = *Ctx.classify(ElemTy);
847 Values.reserve(VT->getNumElements());
848 for (
unsigned I = 0; I != VT->getNumElements(); ++I) {
850 { Values.push_back(Ptr.elem<
T>(I).toAPValue(ASTCtx)); });
853 assert(Values.size() == VT->getNumElements());
854 R =
APValue(Values.data(), Values.size());
858 llvm_unreachable(
"invalid value to return");
876 if (!Composite(ResultType, *
this,
Result))
882 unsigned Offset)
const {
889 const Record::Field *F =
nullptr;
890 for (
auto &It : R->
fields()) {
891 if (It.Offset == Offset) {
902 uint64_t FieldOffset =
909 unsigned BaseOffset)
const {
919 for (
const Record::Base &B : R->
bases()) {
920 if (B.Offset == BaseOffset) {
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 getTypeInfo(TypeInfoLValue LV, QualType TypeInfo)
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 ...
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
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.
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.
Represents a function declaration or definition.
A (possibly-)qualified type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
RecordDecl * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Symbolic representation of typeid(T) for some type T.
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
bool isReferenceType() const
bool isFloatingType() const
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
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.
const Descriptor * getDescriptor() const
Returns the block's descriptor.
std::byte * rawData()
Returns a pointer to the raw data, including metadata.
Holds all information required to evaluate constexpr code in a module.
If a Floating is constructed from Memory, it DOES NOT OWN THAT MEMORY.
APFloat getAPFloat() const
const Function * getFunction() const
std::string toDiagnosticString(const ASTContext &Ctx) const
const BlockExpr * getExpr() const
const FunctionDecl * getDecl() const
Returns the original FunctionDecl.
A pointer to a memory block, live or dead.
static bool hasSameBase(const Pointer &A, const Pointer &B)
Checks if two pointers are comparable.
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.
bool isDynamic() const
Checks if the storage has been dynamically allocated.
bool isZeroSizeArray() const
Checks if the pointer is pointing to a zero-size array.
bool isElementInitialized(unsigned Index) const
Like isInitialized(), but for primitive arrays.
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.
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.
static std::optional< std::pair< Pointer, Pointer > > computeSplitPoint(const Pointer &A, const Pointer &B)
const TypeidPointer & asTypeidPointer() const
bool isIntegralPointer() const
QualType getType() const
Returns the type of the innermost field.
bool isArrayElement() const
Checks if the pointer points to an array.
void initializeAllElements() const
Initialize all elements of a primitive array at once.
bool pointsToStringLiteral() const
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.
bool pointsToLiteral() const
Whether this points to a block that's been created for a "literal lvalue", i.e.
Pointer getBase() const
Returns a pointer to the object of which this pointer is a field.
bool isTypeidPointer() const
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.
Pointer & operator=(const Pointer &P)
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.
Pointer expand() const
Expands a pointer to the containing array, undoing narrowing.
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
bool allElementsInitialized() const
const Block * block() const
bool isFunctionPointer() const
Pointer getDeclPtr() const
const Descriptor * getFieldDesc() const
Accessors for information about the innermost field.
bool isVirtualBaseClass() const
size_t computeOffsetForComparison() const
Compute an integer that can be used to compare this pointer to another one.
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.
bool isUnion() const
Checks if the record is a union.
unsigned getNumBases() const
const Field * getField(const FieldDecl *FD) const
Returns a field.
llvm::iterator_range< const_base_iter > bases() const
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
int const char * function
__UINTPTR_TYPE__ uintptr_t
An unsigned integer type with the property that any valid pointer to void can be converted to this ty...
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.
QualType getElemQualType() const
const ValueDecl * asValueDecl() const
const Decl * asDecl() const
QualType getDataType(const ASTContext &Ctx) 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.
const Expr * asExpr() const
Descriptor used for global variables.
GlobalInitState InitState
unsigned IsActive
Flag indicating if the field is the active member of a union.
unsigned Offset
Offset inside the structure/array.
unsigned IsInitialized
For primitive fields, it indicates if the field was initialized.
IntPointer baseCast(const ASTContext &ASTCtx, unsigned BaseOffset) const
IntPointer atOffset(const ASTContext &ASTCtx, unsigned Offset) const
const Type * TypeInfoType