clang: lib/AST/ByteCode/Pointer.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
22
23using namespace clang;
25
27 : Pointer(Pointee, Pointee->getDescriptor()->getMetadataSize(),
28 Pointee->getDescriptor()->getMetadataSize()) {}
29
31 : Pointer(Pointee, BaseAndOffset, BaseAndOffset) {}
32
34 : Offset(Offset), StorageKind(Storage::Block) {
35 assert((Base == RootPtrMark || Base % alignof(void *) == 0) && "wrong base");
37
38 BS = {Pointee, Base, nullptr, nullptr};
39
40 if (Pointee)
41 Pointee->addPointer(this);
42}
43
45 : Offset(P.Offset), StorageKind(P.StorageKind) {
46 switch (StorageKind) {
49 break;
52 if (BS.Pointee)
53 BS.Pointee->addPointer(this);
54 break;
57 break;
60 break;
61 }
62}
63
65 switch (StorageKind) {
67 Int = P.Int;
68 break;
70 BS = P.BS;
71 if (BS.Pointee)
72 BS.Pointee->replacePointer(&P, this);
73 break;
75 Fn = P.Fn;
76 break;
79 break;
80 }
81}
82
85 return;
86
87 if (Block *Pointee = BS.Pointee) {
88 Pointee->removePointer(this);
89 BS.Pointee = nullptr;
90 Pointee->cleanup();
91 }
92}
93
95
96
99 Offset = P.Offset;
101 return *this;
102 }
103
104 if (Block *Pointee = BS.Pointee) {
105 Pointee->removePointer(this);
106 BS.Pointee = nullptr;
107 Pointee->cleanup();
108 }
109 }
110
111 StorageKind = P.StorageKind;
112 Offset = P.Offset;
113
114 switch (StorageKind) {
117 break;
120
121 if (BS.Pointee)
122 BS.Pointee->addPointer(this);
123 break;
126 break;
129 }
130 return *this;
131}
132
134
135
137 if (P.isBlockPointer() && this->block() == P.block()) {
138 Offset = P.Offset;
139 BS.Base = P.BS.Base;
140 return *this;
141 }
142
143 if (Block *Pointee = BS.Pointee) {
144 Pointee->removePointer(this);
145 BS.Pointee = nullptr;
146 Pointee->cleanup();
147 }
148 }
149
150 StorageKind = P.StorageKind;
151 Offset = P.Offset;
152
153 switch (StorageKind) {
155 Int = P.Int;
156 break;
158 BS = P.BS;
159
160 if (BS.Pointee)
161 BS.Pointee->addPointer(this);
162 break;
164 Fn = P.Fn;
165 break;
168 }
169 return *this;
170}
171
174
177 false, true);
179 return APValue(static_cast<const Expr *>(nullptr),
181 Path,
182 false, false);
187 false, false);
189 {},
190 false, false);
191 }
192
198 false, false);
199 }
200
201
204 if (const auto *VD = Desc->asValueDecl())
206 else if (const auto *E = Desc->asExpr()) {
211 } else {
213 }
214 } else
215 llvm_unreachable("Invalid allocation type");
216
219 isOnePastEnd(), false);
220
222
224
225
226 if (FD->getParent()->isInvalidDecl())
229 unsigned FieldIndex = FD->getFieldIndex();
231 };
232
233 bool UsePath = true;
235 VD && VD->getType()->isReferenceType())
236 UsePath = false;
237
238
242
244
248 unsigned Index = Ptr.getIndex();
254 } else {
256 const auto *Dcl = Desc->asDecl();
258
259 if (const auto *FD = dyn_cast_if_present(Dcl))
261
263 }
267 unsigned Index;
270 OnePastEnd = false;
271 } else
273
277
278 } else {
280 }
284 } else {
286
287
288 if (const auto *BaseOrMember = Desc->asDecl()) {
289 bool IsVirtual = false;
290 if (const auto *FD = dyn_cast(BaseOrMember)) {
293 } else if (const auto *RD = dyn_cast(BaseOrMember)) {
297
300 if (IsVirtual)
302 else
304
305 } else {
307 }
309 continue;
310 }
311 llvm_unreachable("Invalid field type");
312 }
313 }
314
315
316
317
318
319 std::reverse(Path.begin(), Path.end());
320
321 if (UsePath)
322 return APValue(Base, Offset, Path, OnePastEnd);
323
325}
326
328 switch (StorageKind) {
330 const Block *B = BS.Pointee;
331 OS << "(Block) " << B << " {";
332
334 OS << "rootptr(" << BS.Base << "), ";
335 else
336 OS << BS.Base << ", ";
337
339 OS << "pastend, ";
340 else
341 OS << Offset << ", ";
342
343 if (B)
345 else
346 OS << "nullptr";
347 OS << "}";
348 } break;
350 OS << "(Int) {";
351 OS << Int.Value << " + " << Offset << ", " << Int.Desc;
352 OS << "}";
353 break;
356 << " }";
357 break;
361 << "}";
362 }
363}
364
366 switch (StorageKind) {
368 return Int.Value + Offset;
370
371 break;
373 return Fn.getIntegerRepresentation() + Offset;
376 }
377
380 while (true) {
381
383 Result += getInlineDesc()->Offset;
385 continue;
386 }
387
392 continue;
393 }
398 continue;
399 }
400
404 break;
405 }
406
410
412 continue;
413 }
414
415
419
422 break;
423 }
424
426}
427
430 return "nullptr";
431
433 return (Twine("&(") + Twine(asIntPointer().Value + Offset) + ")").str();
434
437
439}
440
443 return true;
444
446 Offset == BS.Base) {
449 }
450
451 assert(BS.Pointee && "Cannot check if null pointer was initialized");
453 assert(Desc);
456
458 return true;
459
460 return getInlineDesc()->IsInitialized;
461}
462
465 return true;
466
468 assert(Desc);
469
471 return true;
472
474 Offset == BS.Base) {
477 }
478
481 if (!IM)
482 return false;
483
484 if (IM->first)
485 return true;
486
487 return IM->second->isElementInitialized(Index);
488 }
490}
491
494 return;
495
496 assert(BS.Pointee && "Cannot initialize null pointer");
497
499 Offset == BS.Base) {
502 return;
503 }
504
506 assert(Desc);
510 return;
511 }
512
513
514 assert(BS.Base != 0 && "Only composite fields can be initialised");
515 getInlineDesc()->IsInitialized = true;
516}
517
519
521 return;
522
524
526 if (!IM) {
528 IM = std::make_pair(false, std::make_shared(Desc->getNumElems()));
529 }
530
531 assert(IM);
532
533
534 if (IM->first)
535 return;
536
537 if (IM->second->initializeElement(Index)) {
538 IM->first = true;
539 IM->second.reset();
540 }
541}
542
546
548 if (!IM) {
549 IM = std::make_pair(true, nullptr);
550 } else {
551 IM->first = true;
552 IM->second.reset();
553 }
554}
555
559
561 return true;
562
564 Offset == BS.Base) {
567 }
568
570 return IM && IM->first;
571}
572
574
575 assert(BS.Base != 0 && "Only composite fields can be activated");
576
578 return;
579 if (!getInlineDesc()->InUnion)
580 return;
581
584 P.getInlineDesc()->IsActive = true;
585 if (const Record *R = P.getRecord(); R && !R->isUnion()) {
586 for (const Record::Field &F : R->fields()) {
587 Pointer FieldPtr = P.atField(F.Offset);
588 if (!FieldPtr.getInlineDesc()->IsActive)
590 }
591
592 }
593 };
594
597 P.getInlineDesc()->IsActive = false;
598
599 if (const Record *R = P.getRecord()) {
600 for (const Record::Field &F : R->fields()) {
601 Pointer FieldPtr = P.atField(F.Offset);
602 if (FieldPtr.getInlineDesc()->IsActive)
604 }
605
606 }
607 };
608
612
613
614
618 for (const Record::Field &F : BR->fields()) {
620 if (FieldPtr != Cur)
622 }
623 }
624 }
625}
626
630
632
634 return true;
635
637 return true;
639 return true;
641 return true;
642
643 if (A.StorageKind != B.StorageKind)
644 return false;
645
647}
648
654
659
662 return false;
663
665 return false;
666
669}
670
673 return false;
674
676 return false;
677
679 return isa_and_nonnull(E);
680}
681
682std::optional<std::pair<Pointer, Pointer>>
685 return std::nullopt;
686
688 return std::nullopt;
690 return std::nullopt;
691
692 if (A == B)
693 return std::make_pair(A, B);
694
696 if (P.isArrayElement())
697 return P.expand().getArray();
698 return P.getBase();
699 };
700
705 for (;;) {
707 CurA = IterA;
709 } else {
710 CurB = IterB;
712 }
713
714 if (IterA == IterB)
715 return std::make_pair(CurA, CurB);
716
718 return std::nullopt;
719 }
720
721 llvm_unreachable("The loop above should've returned.");
722}
723
727 assert(!ResultType.isNull());
728
730 Composite = [&Composite, &Ctx, &ASTCtx](QualType Ty, const Pointer &Ptr,
732 if (const auto *AT = Ty->getAs<AtomicType>())
733 Ty = AT->getValueType();
734
735
736 if (Ptr.isDummy() || !Ptr.isLive() || !Ptr.isBlockPointer() ||
737 Ptr.isPastEnd())
738 return false;
739
740
742 TYPE_SWITCH(*T, R = Ptr.deref<T>().toAPValue(ASTCtx));
743 return true;
744 }
745
746 if (const auto *RT = Ty->getAsCanonical()) {
747 const auto *Record = Ptr.getRecord();
748 assert(Record && "Missing record descriptor");
749
750 bool Ok = true;
751 if (RT->getDecl()->isUnion()) {
752 const FieldDecl *ActiveField = nullptr;
755 const Pointer &FP = Ptr.atField(F.Offset);
756 QualType FieldTy = F.Decl->getType();
760 } else {
761 Ok &= Composite(FieldTy, FP, Value);
762 }
764 break;
765 }
766 }
768 } else {
772
774
775 for (unsigned I = 0; I < NF; ++I) {
777 QualType FieldTy = FD->Decl->getType();
778 const Pointer &FP = Ptr.atField(FD->Offset);
780
783 } else {
784 Ok &= Composite(FieldTy, FP, Value);
785 }
786 }
787
788 for (unsigned I = 0; I < NB; ++I) {
791 const Pointer &BP = Ptr.atField(BD->Offset);
792 Ok &= Composite(BaseTy, BP, R.getStructBase(I));
793 }
794
795 for (unsigned I = 0; I < NV; ++I) {
799 const Pointer &VP = Ptr.atField(VD->Offset);
800 Ok &= Composite(VirtBaseTy, VP, R.getStructBase(NB + I));
801 }
802 }
803 return Ok;
804 }
805
806 if (Ty->isIncompleteArrayType()) {
808 return true;
809 }
810
811 if (const auto *AT = Ty->getAsArrayTypeUnsafe()) {
812 const size_t NumElems = Ptr.getNumElems();
813 QualType ElemTy = AT->getElementType();
815
816 bool Ok = true;
818 for (unsigned I = 0; I != NumElems; ++I) {
820 if (ElemT) {
821 TYPE_SWITCH(*ElemT, Slot = Ptr.elem<T>(I).toAPValue(ASTCtx));
822 } else {
823 Ok &= Composite(ElemTy, Ptr.atIndex(I).narrow(), Slot);
824 }
825 }
826 return Ok;
827 }
828
829
830 if (const auto *CT = Ty->getAs<ComplexType>()) {
831
832 if (!Ptr.getFieldDesc()->isPrimitiveArray())
833 return false;
834
835 QualType ElemTy = CT->getElementType();
838 assert(ElemT);
840 auto V1 = Ptr.elem<T>(0);
841 auto V2 = Ptr.elem<T>(1);
842 R = APValue(V1.toAPSInt(), V2.toAPSInt());
843 return true;
844 });
848 return true;
849 }
850 return false;
851 }
852
853
854 if (const auto *VT = Ty->getAs<VectorType>()) {
855 assert(Ptr.getFieldDesc()->isPrimitiveArray());
856 QualType ElemTy = VT->getElementType();
858
860 Values.reserve(VT->getNumElements());
861 for (unsigned I = 0; I != VT->getNumElements(); ++I) {
863 { Values.push_back(Ptr.elem<T>(I).toAPValue(ASTCtx)); });
864 }
865
866 assert(Values.size() == VT->getNumElements());
867 R = APValue(Values.data(), Values.size());
868 return true;
869 }
870
871 llvm_unreachable("invalid value to return");
872 };
873
874
876 return std::nullopt;
877
878
881
882
885 }
886
887
889 if (!Composite(ResultType, *this, Result))
890 return std::nullopt;
892}
893
895 unsigned Offset) const {
896 if (!this->Desc)
897 return *this;
898 const Record *R = this->Desc->ElemRecord;
899 if (!R)
900 return *this;
901
902 const Record::Field *F = nullptr;
903 for (auto &It : R->fields()) {
904 if (It.Offset == Offset) {
905 F = &It;
906 break;
907 }
908 }
909 if (!F)
910 return *this;
911
914 return std::nullopt;
915
918 uint64_t FieldOffset =
922}
923
925 unsigned BaseOffset) const {
927 assert(Value == 0);
928 return *this;
929 }
931 const Descriptor *BaseDesc = nullptr;
932
933
934
935 for (const Record::Base &B : R->bases()) {
936 if (B.Offset == BaseOffset) {
937 BaseDesc = B.Desc;
938 break;
939 }
940 }
941 assert(BaseDesc);
942
943
947
949}
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.
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 isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
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.
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.
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.
static bool hasSameBase(const Pointer &A, const Pointer &B)
Checks if two pointers are comparable.
Definition Pointer.cpp:631
void deactivate() const
Deactivates an entire strurcutre.
Definition Pointer.cpp:627
bool isInitialized() const
Checks if an object was initialized.
Definition Pointer.cpp:441
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.
Definition Pointer.cpp:463
bool isDummy() const
Checks if the pointer points to a dummy value.
void print(llvm::raw_ostream &OS) const
Prints the pointer.
Definition Pointer.cpp:327
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.
Definition Pointer.cpp:573
static std::optional< std::pair< Pointer, Pointer > > computeSplitPoint(const Pointer &A, const Pointer &B)
Definition Pointer.cpp:683
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.
Definition Pointer.cpp:543
bool pointsToStringLiteral() const
Definition Pointer.cpp:671
bool isArrayRoot() const
Whether this array refers to an array, but not to the first element.
~Pointer()
Definition Pointer.cpp:83
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.
Definition Pointer.cpp:660
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.
Definition Pointer.cpp:428
bool isZero() const
Checks if the pointer is null.
Pointer & operator=(const Pointer &P)
Definition Pointer.cpp:94
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.
Definition Pointer.cpp:649
APValue toAPValue(const ASTContext &ASTCtx) const
Converts the pointer to an APValue.
Definition Pointer.cpp:172
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.
Definition Pointer.cpp:655
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.
Definition Pointer.cpp:724
const FunctionPointer & asFunctionPointer() const
bool allElementsInitialized() const
Definition Pointer.cpp:556
const Block * block() const
bool isFunctionPointer() const
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.
size_t computeOffsetForComparison() const
Compute an integer that can be used to compare this pointer to another one.
Definition Pointer.cpp:365
const BlockPointer & asBlockPointer() const
void initialize() const
Initializes a field.
Definition Pointer.cpp:492
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.
Definition Pointer.cpp:518
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.
PrimType
Enumeration of the primitive types of the VM.
std::optional< std::pair< bool, std::shared_ptr< InitMap > > > InitMapPtr
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.
const FunctionProtoType * T
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.
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 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.
std::optional< IntPointer > atOffset(const ASTContext &ASTCtx, unsigned Offset) const
Definition Pointer.cpp:894
IntPointer baseCast(const ASTContext &ASTCtx, unsigned BaseOffset) const
Definition Pointer.cpp:924
const Type * TypeInfoType