28 :
Pointer(Pointee, Pointee->getDescriptor()->getMetadataSize(),
29 Pointee->getDescriptor()->getMetadataSize()) {}
32 :
Pointer(Pointee, BaseAndOffset, BaseAndOffset) {}
37 assert((
Base == RootPtrMark ||
Base %
alignof(
void *) == 0) &&
"wrong base");
40 BS = {Pointee,
Base,
nullptr,
nullptr};
41 Pointee->addPointer(
this);
45 : Offset(P.Offset), StorageKind(P.StorageKind) {
46 switch (StorageKind) {
53 BS.Pointee->addPointer(
this);
65 switch (StorageKind) {
72 BS.Pointee->replacePointer(&P,
this);
87 if (
Block *Pointee =
BS.Pointee) {
88 Pointee->removePointer(
this);
104 if (
Block *Pointee =
BS.Pointee) {
105 Pointee->removePointer(
this);
106 BS.Pointee =
nullptr;
111 StorageKind = P.StorageKind;
114 switch (StorageKind) {
122 BS.Pointee->addPointer(
this);
137 if (P.isBlockPointer() && this->block() == P.block()) {
143 if (
Block *Pointee =
BS.Pointee) {
144 Pointee->removePointer(
this);
145 BS.Pointee =
nullptr;
150 StorageKind = P.StorageKind;
153 switch (StorageKind) {
161 BS.Pointee->addPointer(
this);
205 else if (
const auto *E = Desc->
asExpr()) {
214 llvm_unreachable(
"Invalid allocation type");
225 if (FD->getParent()->isInvalidDecl())
228 unsigned FieldIndex = FD->getFieldIndex();
234 VD && VD->
getType()->isReferenceType())
255 const auto *Dcl = Desc->
asDecl();
258 if (
const auto *FD = dyn_cast_if_present<FieldDecl>(Dcl))
287 if (
const auto *BaseOrMember = Desc->
asDecl()) {
288 bool IsVirtual =
false;
289 if (
const auto *FD = dyn_cast<FieldDecl>(BaseOrMember)) {
292 }
else if (
const auto *RD = dyn_cast<CXXRecordDecl>(BaseOrMember)) {
310 llvm_unreachable(
"Invalid field type");
318 std::reverse(Path.begin(), Path.end());
327 switch (StorageKind) {
330 OS <<
"(Block) " << B <<
" {";
333 OS <<
"rootptr(" <<
BS.Base <<
"), ";
335 OS <<
BS.Base <<
", ";
340 OS << Offset <<
", ";
350 OS <<
Int.Value <<
" + " << Offset <<
", " <<
Int.Desc;
354 OS <<
"(Fn) { " <<
Fn.Func <<
" + " << Offset <<
" }";
370 switch (StorageKind) {
372 return Int.Value + Offset;
386 Result += getInlineDesc()->Offset;
452 assert(
BS.Pointee &&
"Cannot check if null pointer was initialized");
461 return getInlineDesc()->IsInitialized;
550 assert(
BS.Pointee &&
"Cannot initialize null pointer");
568 assert(
BS.Base != 0 &&
"Only composite fields can be initialised");
569 getInlineDesc()->IsInitialized =
true;
597 getInitMap().noteAllInitialized();
636 assert(
BS.Base != 0 &&
"Only composite fields can be activated");
640 if (!getInlineDesc()->InUnion)
645 P.getInlineDesc()->IsActive =
true;
646 if (
const Record *R = P.getRecord(); R && !R->isUnion()) {
647 for (
const Record::Field &F : R->fields()) {
648 Pointer FieldPtr = P.atField(F.Offset);
649 if (!FieldPtr.getInlineDesc()->
IsActive)
658 P.getInlineDesc()->IsActive =
false;
660 if (
const Record *R = P.getRecord()) {
661 for (
const Record::Field &F : R->fields()) {
662 Pointer FieldPtr = P.atField(F.Offset);
663 if (FieldPtr.getInlineDesc()->
IsActive)
679 for (
const Record::Field &F : BR->fields()) {
704 if (A.StorageKind != B.StorageKind)
740 return isa_and_nonnull<StringLiteral>(E);
743std::optional<std::pair<Pointer, Pointer>>
754 return std::make_pair(A, B);
757 if (P.isArrayElement())
758 return P.expand().getArray();
776 return std::make_pair(CurA, CurB);
782 llvm_unreachable(
"The loop above should've returned.");
788 assert(!ResultType.
isNull());
791 Composite = [&Composite, &Ctx, &ASTCtx](
QualType Ty,
const Pointer &Ptr,
794 Ty = AT->getValueType();
797 if (Ptr.isDummy() || !Ptr.isLive() || !Ptr.isBlockPointer() ||
804 if (
const auto *RT = Ty->getAsCanonical<RecordType>()) {
805 const auto *
Record = Ptr.getRecord();
806 assert(
Record &&
"Missing record descriptor");
809 if (RT->getDecl()->isUnion()) {
813 const Pointer &FP = Ptr.atField(F.Offset);
820 QualType FieldTy = F.Decl->getType();
821 Ok &= Composite(FieldTy, FP,
Value);
835 for (
unsigned I = 0; I != NF; ++I) {
838 const Pointer &FP = Ptr.atField(FD->Offset);
844 QualType FieldTy = FD->Decl->getType();
845 Ok &= Composite(FieldTy, FP,
Value);
849 for (
unsigned I = 0; I != NB; ++I) {
852 const Pointer &BP = Ptr.atField(BD->Offset);
853 Ok &= Composite(BaseTy, BP, R.getStructBase(I));
856 for (
unsigned I = 0; I != NV; ++I) {
860 const Pointer &VP = Ptr.atField(VD->Offset);
861 Ok &= Composite(VirtBaseTy, VP, R.getStructBase(NB + I));
867 if (Ty->isIncompleteArrayType()) {
872 if (
const auto *AT = Ty->getAsArrayTypeUnsafe()) {
873 const size_t NumElems = Ptr.getNumElems();
874 QualType ElemTy = AT->getElementType();
879 for (
unsigned I = 0; I != NumElems; ++I) {
880 APValue &Slot = R.getArrayInitializedElt(I);
882 TYPE_SWITCH(*ElemT, Slot = Ptr.elem<T>(I).toAPValue(ASTCtx));
884 Ok &= Composite(ElemTy, Ptr.atIndex(I).narrow(), Slot);
891 if (Ty->isAnyComplexType()) {
901 auto V1 = Ptr.elem<T>(0);
902 auto V2 = Ptr.elem<T>(1);
903 R =
APValue(V1.toAPSInt(), V2.toAPSInt());
915 if (
const auto *VT = Ty->getAs<
VectorType>()) {
917 assert(Ptr.getFieldDesc()->isPrimitiveArray());
921 Values.reserve(VT->getNumElements());
922 for (
unsigned I = 0; I != VT->getNumElements(); ++I) {
924 { Values.push_back(Ptr.elem<T>(I).toAPValue(ASTCtx)); });
927 assert(Values.size() == VT->getNumElements());
928 R =
APValue(Values.data(), Values.size());
934 assert(Ptr.getFieldDesc()->isPrimitiveArray());
937 unsigned NumElems = MT->getNumElementsFlattened();
940 Values.reserve(NumElems);
941 for (
unsigned I = 0; I != NumElems; ++I) {
943 { Values.push_back(Ptr.elem<T>(I).toAPValue(ASTCtx)); });
946 R =
APValue(Values.data(), MT->getNumRows(), MT->getNumColumns());
950 llvm_unreachable(
"invalid value to return");
974 if (!Composite(ResultType, *
this,
Result))
980 unsigned Offset)
const {
987 const Record::Field *F =
nullptr;
988 for (
auto &It : R->fields()) {
989 if (It.Offset == Offset) {
1003 uint64_t FieldOffset =
1010 unsigned BaseOffset)
const {
1020 for (
const Record::Base &B : R->bases()) {
1021 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],...
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.
Represents a concrete matrix type with constant number of rows and columns.
bool isInvalidDecl() const
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.
Symbolic representation of typeid(T) for some type T.
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
bool isFunctionType() 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.
unsigned getSize() const
Returns the size of the block.
const Descriptor * getDescriptor() const
Returns the block's descriptor.
Holds all information required to evaluate constexpr code in a module.
ASTContext & getASTContext() const
Returns the AST context.
OptPrimType classify(QualType T) const
Classifies a type.
bool canClassify(QualType T) const
If a Floating is constructed from Memory, it DOES NOT OWN THAT MEMORY.
APFloat getAPFloat() const
const BlockExpr * getExpr() const
const FunctionDecl * getDecl() const
Returns the original FunctionDecl.
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.
void startLifetime() const
Start the lifetime of this pointer.
bool canDeref(PrimType T) const
Checks whether the pointer can be dereferenced to the given PrimType.
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.
size_t computeOffsetForComparison(const ASTContext &ASTCtx) const
Compute an integer that can be used to compare this pointer to another one.
bool isLive() const
Checks if the pointer is live.
bool inArray() const
Checks if the innermost field is an array.
bool isElementAlive(unsigned Index) const
bool pointsToLiteral() const
Whether this points to a block that's been created for a "literal lvalue", i.e.
bool allElementsAlive() const
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.
uint64_t getIntegerRepresentation() const
bool isPastEnd() const
Checks if the pointer points past the end of the object.
const FieldDecl * getField() const
Returns the field information.
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
void endLifetime() const
Ends the lifetime of the pointer.
Pointer getDeclPtr() const
const Descriptor * getFieldDesc() const
Accessors for information about the innermost field.
bool isVirtualBaseClass() const
bool isBaseClass() const
Checks if a structure is a base class.
size_t elemSize() const
Returns the element size of the innermost field.
Lifetime getLifetime() const
const BlockPointer & asBlockPointer() const
void initialize() const
Initializes a field.
bool isField() const
Checks if the item is a field in an object.
void initializeElement(unsigned Index) const
Initialized the given element of a primitive array.
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.
const Field * getField(unsigned I) const
unsigned getNumBases() const
const Base * getBase(unsigned I) const
const Base * getVirtualBase(unsigned I) const
unsigned getNumFields() const
unsigned getNumVirtualBases() const
llvm::iterator_range< const_field_iter > fields() const
constexpr bool isIntegerOrBoolType(PrimType T)
PrimType
Enumeration of the primitive types of the VM.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
@ Result
The result type of a method or function.
U cast(CodeGen::Address addr)
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.
bool isPrimitive() const
Checks if the descriptor is of a primitive.
QualType getElemQualType() const
const ValueDecl * asValueDecl() const
const Decl * asDecl() const
unsigned getMetadataSize() const
Returns the size of the metadata.
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
PrimType getPrimType() const
const Expr * asExpr() const
Descriptor used for global variables.
GlobalInitState InitState
A pointer-sized struct we use to allocate into data storage.
void noteAllInitialized()
bool allInitialized() const
Are all elements in the array already initialized?
void setInitMap(const InitMap *IM)
Bitfield tracking the initialisation status of elements of primitive arrays.
void startElementLifetime(unsigned I)
void endElementLifetime(unsigned I)
bool allElementsAlive() const
bool isElementInitialized(unsigned I) const
Checks if an element was initialized.
bool initializeElement(unsigned I)
Initializes an element. Returns true when object if fully initialized.
bool isElementAlive(unsigned I) const
Inline descriptor embedded in structures and arrays.
unsigned IsActive
Flag indicating if the field is the active member of a union.
unsigned Offset
Offset inside the structure/array.
std::optional< IntPointer > atOffset(const ASTContext &ASTCtx, unsigned Offset) const
IntPointer baseCast(const ASTContext &ASTCtx, unsigned BaseOffset) const
const Type * TypeInfoType