29 :
Pointer(Pointee, Pointee->getDescriptor()->getMetadataSize(),
30 Pointee->getDescriptor()->getMetadataSize()) {}
33 :
Pointer(Pointee, BaseAndOffset, BaseAndOffset) {}
38 assert(
Base %
alignof(
void *) == 0 &&
"wrong base");
41 BS = {Pointee,
Base,
nullptr,
nullptr};
42 Pointee->addPointer(
this);
46 : Offset(P.Offset), StorageKind(P.StorageKind) {
47 switch (StorageKind) {
54 BS.Pointee->addPointer(
this);
66 switch (StorageKind) {
73 BS.Pointee->replacePointer(&P,
this);
88 if (
Block *Pointee =
BS.Pointee) {
89 Pointee->removePointer(
this);
105 if (
Block *Pointee =
BS.Pointee) {
106 Pointee->removePointer(
this);
107 BS.Pointee =
nullptr;
112 StorageKind = P.StorageKind;
115 switch (StorageKind) {
123 BS.Pointee->addPointer(
this);
138 if (P.isBlockPointer() && this->block() == P.block()) {
144 if (
Block *Pointee =
BS.Pointee) {
145 Pointee->removePointer(
this);
146 BS.Pointee =
nullptr;
151 StorageKind = P.StorageKind;
154 switch (StorageKind) {
162 BS.Pointee->addPointer(
this);
180 switch (StorageKind) {
212 else if (
const auto *E = Desc->
asExpr()) {
221 llvm_unreachable(
"Invalid allocation type");
228 if (FD->getParent()->isInvalidDecl())
231 unsigned FieldIndex = FD->getFieldIndex();
254 const auto *Dcl = Desc->
asDecl();
257 if (
const auto *FD = dyn_cast_if_present<FieldDecl>(Dcl))
286 if (
const auto *BaseOrMember = Desc->
asDecl()) {
287 bool IsVirtual =
false;
288 if (
const auto *FD = dyn_cast<FieldDecl>(BaseOrMember)) {
291 }
else if (
const auto *RD = dyn_cast<CXXRecordDecl>(BaseOrMember)) {
309 llvm_unreachable(
"Invalid field type");
317 std::reverse(Path.begin(), Path.end());
325 switch (StorageKind) {
328 OS <<
"(Block) " << B <<
" {";
331 OS <<
"rootptr(" <<
BS.Base <<
"), ";
333 OS <<
BS.Base <<
", ";
338 OS << Offset <<
", ";
347 OS <<
"(Int) {" <<
Int.Value <<
" + " << Offset <<
", " <<
Int.Ty <<
"}";
350 OS <<
"(Fn) { " <<
Fn.Func <<
" + " << Offset <<
" }";
370 switch (StorageKind) {
372 return Int.Value + Offset;
382 auto getTypeSize = [&](
QualType T) -> std::optional<size_t> {
383 if (
const RecordType *RT =
T->getAs<RecordType>()) {
385 if (!RT->getDecl()->getDefinition())
395 Result += getInlineDesc()->Offset;
448 switch (StorageKind) {
450 return Int.Value + Offset;
460 auto getTypeSize = [&](
QualType T) -> std::optional<size_t> {
461 if (
const RecordType *RT =
T->getAs<RecordType>()) {
463 if (!RT->getDecl()->getDefinition())
470 if (
const Record *R = P.getRecord())
475 auto getRecordSize = [&](
const RecordDecl *RD) ->
unsigned {
493 Result += getRecordSize(RD);
502 if (std::optional<size_t> ElemSize =
514 if (std::optional<size_t> Size =
531 if (std::optional<size_t> Size = getTypeSize(F->
getType()))
567 assert(
BS.Pointee &&
"Cannot check if null pointer was initialized");
576 return getInlineDesc()->IsInitialized;
674 assert(
Base != 0 &&
"Only composite fields can be initialised");
704 getInitMap().noteAllInitialized();
742 assert(
Base != 0 &&
"Only composite fields can be activated");
754 for (
const Record::Field &F : R->fields()) {
764 deactivate = [&deactivate](
PtrView &P) ->
void {
768 for (
const Record::Field &F : R->fields()) {
771 deactivate(FieldPtr);
791 for (
const Record::Field &F : BR->fields()) {
794 deactivate(FieldPtr);
812 if (A.StorageKind != B.StorageKind)
843 if (
V.isArrayElement() ||
V.isOnePastEnd())
844 V =
V.expand().getArray();
849 while (!
V.isRoot() && !
V.getFieldDesc()->IsArray) {
850 if (
V.isArrayElement()) {
851 V =
V.expand().getArray();
859 if (closestArray(A) != closestArray(B))
884 return isa_and_nonnull<StringLiteral>(E);
891 if (
const Expr *E =
BS.Pointee->getDescriptor()->asExpr())
896std::optional<std::pair<PtrView, PtrView>>
907 return std::make_pair(A.
view(), B.
view());
910 if (P.isArrayElement())
911 return P.expand().getArray();
928 if (IterA == IterB) {
933 return std::make_pair(CurA, CurB);
940 llvm_unreachable(
"The loop above should've returned.");
946 assert(!ResultType.
isNull());
952 Ty = AT->getValueType();
955 if (Ptr.isDummy() || !Ptr.isLive() || Ptr.isPastEnd())
960 const Descriptor *FieldDesc = Ptr.getFieldDesc();
963 if (
const auto *RT = Ty->getAsCanonical<RecordType>()) {
966 const auto *
Record = Ptr.getRecord();
967 assert(
Record &&
"Missing record descriptor");
970 if (RT->getDecl()->isUnion()) {
981 QualType FieldTy = F.Decl->getType();
982 Ok &= Composite(FieldTy, FP,
Value);
996 for (
unsigned I = 0; I != NF; ++I) {
1005 QualType FieldTy = FD->Decl->getType();
1006 Ok &= Composite(FieldTy, FP,
Value);
1010 for (
unsigned I = 0; I != NB; ++I) {
1014 Ok &= Composite(BaseTy, BP, R.getStructBase(I));
1017 for (
unsigned I = 0; I != NV; ++I) {
1023 Ok &= Composite(VirtBaseTy, VP, R.getStructVirtualBase(I));
1029 if (Ty->isIncompleteArrayType()) {
1034 if (
const auto *AT = Ty->getAsArrayTypeUnsafe()) {
1037 const size_t NumElems = Ptr.getNumElems();
1038 QualType ElemTy = AT->getElementType();
1043 for (
unsigned I = 0; I != NumElems; ++I) {
1044 APValue &Slot = R.getArrayInitializedElt(I);
1046 TYPE_SWITCH(*ElemT, Slot = Ptr.elem<
T>(I).toAPValue(ASTCtx));
1048 Ok &= Composite(ElemTy, Ptr.atIndex(I).narrow(), Slot);
1055 if (Ty->isAnyComplexType()) {
1063 auto V1 = Ptr.elem<
T>(0);
1064 auto V2 = Ptr.elem<
T>(1);
1065 R =
APValue(V1.toAPSInt(), V2.toAPSInt());
1077 if (
const auto *VT = Ty->getAs<
VectorType>()) {
1083 Values.reserve(VT->getNumElements());
1084 for (
unsigned I = 0; I != VT->getNumElements(); ++I) {
1086 { Values.push_back(Ptr.elem<
T>(I).toAPValue(ASTCtx)); });
1089 assert(Values.size() == VT->getNumElements());
1090 R =
APValue(Values.data(), Values.size());
1099 unsigned NumElems = MT->getNumElementsFlattened();
1102 Values.reserve(NumElems);
1103 for (
unsigned I = 0; I != NumElems; ++I) {
1105 { Values.push_back(Ptr.elem<
T>(I).toAPValue(ASTCtx)); });
1108 R =
APValue(Values.data(), MT->getNumRows(), MT->getNumColumns());
1112 llvm_unreachable(
"invalid value to return");
1117 return std::nullopt;
1122 return std::nullopt;
1131 return std::nullopt;
1138 return std::nullopt;
1149 unsigned Offset)
const {
1152 return std::nullopt;
1158 const Record::Field *F = R->findField(Offset);
1164 return std::nullopt;
1169 uint64_t FieldOffset =
1177 unsigned BaseOffset)
const {
1189 const Record::Base *B = R->findBase(BaseOffset);
1202 std::nullopt, RD,
false);
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 const RecordDecl * getRecordDecl(QualType QT)
Checks that the passed in QualType either is of RecordType or points to RecordType.
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.
QualType getTagType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier Qualifier, const TagDecl *TD, bool OwnsTag) const
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.
Represents a C++ struct/union/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.
ASTContext & getASTContext() const LLVM_READONLY
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.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Represents a struct/union/class.
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.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isLValueReferenceType() const
bool isAnyComplexType() const
bool isFunctionType() const
bool isRecordType() const
Represents a variable declaration or definition.
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.
const Record * getRecord(const RecordDecl *D) const
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.
bool isInitialized() const
Checks if an object was initialized.
bool pointsToLabel() const
Whether this points to a block created for an AddrLabelExpr.
bool isStatic() const
Checks if the storage is static.
bool isDynamic() const
Checks if the storage has been dynamically allocated.
const VarDecl * getRootVarDecl() const
bool isZeroSizeArray() const
Checks if the pointer is pointing to a zero-size 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 canDeref(PrimType T) const
Checks whether the pointer can be dereferenced to the given PrimType.
T & deref() const
Dereferences the pointer, if it's live.
const TypeidPointer & asTypeidPointer() const
bool isIntegralPointer() const
QualType getType() const
Returns the type of the innermost field.
void initializeAllElements() const
Initialize all elements of a primitive array at once.
bool pointsToStringLiteral() const
std::optional< size_t > computeOffsetForComparison(const ASTContext &ASTCtx) const
Compute an integer that can be used to compare this pointer to another one.
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.
static bool elemsOfSameArray(const Pointer &A, const Pointer &B)
Checks if two pointers can be subtracted.
bool isElementAlive(unsigned Index) const
bool pointsToLiteral() const
Whether this points to a block that's been created for a "literal lvalue", i.e.
std::optional< size_t > computeLayoutOffset(const ASTContext &ASTCtx) const
Compute the pointer offset as given by the ASTRecordLayout.
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)
bool isConstexprUnknown() const
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.
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.
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
Pointer getDeclPtr() const
const Descriptor * getFieldDesc() const
Accessors for information about the innermost field.
bool isBaseClass() const
Checks if a structure is a base class.
const BlockPointer & asBlockPointer() const
static std::optional< std::pair< PtrView, PtrView > > computeSplitPoint(const Pointer &A, const Pointer &B)
bool isElementInitialized(unsigned Index) const
Like isInitialized(), but for primitive arrays.
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.
Top level wrappers for InstallAPI frontend operations.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool isa(CodeGen::Address addr)
@ Result
The result type of a method or function.
const FunctionProtoType * T
U cast(CodeGen::Address addr)
@ None
No keyword precedes the qualified type name.
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
const VarDecl * asVarDecl() const
PrimType getPrimType() const
bool isRecord() const
Checks if the descriptor is of a record.
const Record *const ElemRecord
Pointer to the record, if block contains records.
const Expr * asExpr() const
bool isArray() const
Checks if the descriptor is of an array.
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.
unsigned IsInitialized
For primitive fields, it indicates if the field was initialized.
QualType getPointeeType() const
IntPointer baseCast(const Context &Ctx, unsigned BaseOffset) const
std::optional< IntPointer > atOffset(const Context &Ctx, unsigned Offset) const
const Descriptor * getDeclDesc() const
bool allElementsInitialized() const
PtrView atField(unsigned Offset) const
const Record * getRecord() const
const Descriptor * getFieldDesc() const
const FieldDecl * getField() const
bool isElementInitialized(unsigned Index) const
void startLifetime() const
bool isInitialized() const
bool isArrayElement() const
unsigned getNumElems() const
InitMapPtr & getInitMap() const
InlineDescriptor * getInlineDesc() const
void initializeElement(unsigned Index) const
bool isOnePastEnd() const
void setLifeState(Lifetime L) const
Lifetime getLifetime() const
bool isVirtualBaseClass() const
const Type * TypeInfoType