clang 24.0.0git
Pointer.h
Go to the documentation of this file.
1//===--- Pointer.h - Types for the constexpr VM -----------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Defines the classes responsible for pointer tracking.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_CLANG_AST_INTERP_POINTER_H
14#define LLVM_CLANG_AST_INTERP_POINTER_H
15
16#include "Descriptor.h"
17#include "Function.h"
18#include "InitMap.h"
19#include "InterpBlock.h"
21#include "clang/AST/Decl.h"
22#include "clang/AST/DeclCXX.h"
23#include "clang/AST/Expr.h"
24#include "llvm/Support/raw_ostream.h"
25
26namespace clang {
27namespace interp {
28class Block;
29class DeadBlock;
30class Pointer;
31class Context;
32
33class Pointer;
34inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Pointer &P);
35
36struct PtrView {
37 static constexpr unsigned PastEndMark = ~0u;
38
40 unsigned Base;
41 uint64_t Offset;
42
43 bool isZero() const { return !Pointee; }
44 bool isLive() const { return Pointee && !Pointee->isDead(); }
45 bool isDummy() const { return Pointee && Pointee->isDummy(); }
46 bool isActive() const { return isRoot() || getInlineDesc()->IsActive; }
47 bool isArrayRoot() const { return inArray() && Offset == Base; }
48 bool isElementPastEnd() const { return Offset == PastEndMark; }
49 bool isZeroSizeArray() const { return getFieldDesc()->isZeroSizeArray(); }
50 bool isMutable() const {
51 return !isRoot() && getInlineDesc()->IsFieldMutable;
52 }
53 bool inUnion() const { return getInlineDesc()->InUnion; };
54 bool inArray() const { return getFieldDesc()->IsArray; }
55 bool inPrimitiveArray() const { return getFieldDesc()->isPrimitiveArray(); }
56 const Block *block() const { return Pointee; }
57
58 unsigned getEvalID() { return Pointee->getEvalID(); }
59
60 bool isRoot() const { return Base == Pointee->getMetadataSize(); }
61
62 bool isConst() const {
64 }
65
67 assert(Base != sizeof(GlobalInlineDescriptor));
69 assert(Base >= sizeof(InlineDescriptor));
70 return getDescriptor(Base);
71 }
72
74 assert(Offset != 0 && "Not a nested pointer");
75 return reinterpret_cast<InlineDescriptor *>(Pointee->rawData() + Offset) -
76 1;
77 }
78
79 const Descriptor *getFieldDesc() const {
80 if (isRoot())
81 return Pointee->getDescriptor();
82 return getInlineDesc()->Desc;
83 }
84
85 const Descriptor *getDeclDesc() const { return Pointee->getDescriptor(); }
86
87 size_t elemSize() const { return getFieldDesc()->getElemSize(); }
88
89 [[nodiscard]] PtrView narrow() const {
90 // Null pointers cannot be narrowed.
91 if (isZero() || isUnknownSizeArray())
92 return *this;
93
94 if (inArray()) {
95 // Pointer is one past end - magic offset marks that.
96 if (isOnePastEnd())
98
99 if (Offset != Base) {
100 // If we're pointing to a primitive array element, there's nothing to
101 // do.
102 if (inPrimitiveArray())
103 return *this;
104 // Pointer is to a composite array element - enter it.
105 return PtrView{Pointee, static_cast<unsigned>(Offset), Offset};
106 }
107 }
108 // Otherwise, we're pointing to a non-array element or
109 // are already narrowed to a composite array element. Nothing to do.
110 return *this;
111 }
112
113 [[nodiscard]] PtrView expand() const {
114 if (isElementPastEnd()) {
115 // Revert to an outer one-past-end pointer.
116 unsigned Adjust;
117 if (inPrimitiveArray())
118 Adjust = sizeof(InitMapPtr);
119 else
120 Adjust = sizeof(InlineDescriptor);
121 return PtrView{Pointee, Base, Base + getSize() + Adjust};
122 }
123
124 // Do not step out of array elements.
125 if (Base != Offset)
126 return *this;
127
128 if (isRoot())
129 return PtrView{Pointee, Base, Base};
130
131 // Step into the containing array, if inside one.
132 unsigned Next = Base - getInlineDesc()->Offset;
133 const Descriptor *Desc = (Next == Pointee->getMetadataSize())
134 ? getDeclDesc()
136 if (!Desc->IsArray)
137 return *this;
138 return PtrView{Pointee, Next, Offset};
139 }
140
141 [[nodiscard]] PtrView stripBaseCasts() const {
142 PtrView V = *this;
143 while (V.isBaseClass())
144 V = V.getBase();
145 return V;
146 }
147
148 [[nodiscard]] PtrView getArray() const {
149 assert(Offset != Base && "not an array element");
150 return PtrView{Pointee, Base, Base};
151 }
152
153 const Record *getRecord() const { return getFieldDesc()->ElemRecord; }
154 const Record *getElemRecord() const {
155 const Descriptor *ElemDesc = getFieldDesc()->ElemDesc;
156 return ElemDesc ? ElemDesc->ElemRecord : nullptr;
157 }
158 const FieldDecl *getField() const { return getFieldDesc()->asFieldDecl(); }
159
160 bool isField() const {
161 return !isZero() && !isRoot() && getFieldDesc()->asDecl();
162 }
163
164 bool isBaseClass() const { return isField() && getInlineDesc()->IsBase; }
165 bool isVirtualBaseClass() const {
166 return isField() && getInlineDesc()->IsVirtualBase;
167 }
168 bool isUnknownSizeArray() const {
170 }
171
172 bool isPastEnd() const { return Offset > Pointee->getSize(); }
173
174 unsigned getOffset() const {
175 assert(Offset != PastEndMark);
176
177 unsigned Adjust = 0;
178 if (Offset != Base) {
179 if (getFieldDesc()->ElemDesc)
180 Adjust = sizeof(InlineDescriptor);
181 else
182 Adjust = sizeof(InitMapPtr);
183 }
184 return Offset - Base - Adjust;
185 }
186 size_t getSize() const { return getFieldDesc()->getSize(); }
187
188 bool isOnePastEnd() const {
189 if (!Pointee)
190 return false;
191
192 if (isUnknownSizeArray())
193 return false;
194 return isPastEnd() || (getSize() == getOffset());
195 }
196
197 PtrView atIndex(unsigned Idx) const {
198 unsigned Off = Idx * elemSize();
199 if (getFieldDesc()->ElemDesc)
200 Off += sizeof(InlineDescriptor);
201 else
202 Off += sizeof(InitMapPtr);
203 return PtrView{Pointee, Base, Base + Off};
204 }
205
206 int64_t getIndex() const {
207 if (isZero())
208 return 0;
209 // narrow()ed element in a composite array.
210 if (Base > sizeof(InlineDescriptor) && Base == Offset)
211 return 0;
212
213 if (auto ElemSize = elemSize())
214 return getOffset() / ElemSize;
215 return 0;
216 }
217
218 unsigned getNumElems() const { return getSize() / elemSize(); }
219
220 bool isArrayElement() const {
221 if (inArray() && Base != Offset)
222 return true;
223
224 // Might be a narrow()'ed element in a composite array.
225 // Check the inline descriptor.
226 if (Base >= sizeof(InlineDescriptor) && getInlineDesc()->IsArrayElement)
227 return true;
228
229 return false;
230 }
231
232 template <typename T> T &deref() const {
233 assert(isLive() && "Invalid pointer");
234 assert(Pointee);
235
236 if (isArrayRoot())
237 return *reinterpret_cast<T *>(Pointee->rawData() + Base +
238 sizeof(InitMapPtr));
239
240 return *reinterpret_cast<T *>(Pointee->rawData() + Offset);
241 }
242
243 template <typename T> T &elem(unsigned I) const {
244 assert(isLive() && "Invalid pointer");
245 assert(Pointee);
246 assert(getFieldDesc()->isPrimitiveArray());
247 assert(I < getFieldDesc()->getNumElems());
248
249 unsigned ElemByteOffset = I * getFieldDesc()->getElemSize();
250 unsigned ReadOffset = Base + sizeof(InitMapPtr) + ElemByteOffset;
251 assert(ReadOffset + sizeof(T) <= Pointee->getSize());
252
253 return *reinterpret_cast<T *>(Pointee->rawData() + ReadOffset);
254 }
255
256 [[nodiscard]] PtrView getBase() const {
257 unsigned NewBase = Base - getInlineDesc()->Offset;
258 return PtrView{Pointee, NewBase, NewBase};
259 }
260
261 [[nodiscard]] PtrView atField(unsigned Offset) const {
262 unsigned F = this->Offset + Offset;
263 return PtrView{Pointee, F, F};
264 }
265
267 if (isRoot() && Base == Offset) {
268 // If this pointer points to the root of a declaration, try to consult
269 // the ValueDecl directly, since that has a type with more information,
270 // e.g. the correct ElaboratedTypeKeyword.
271 if (const ValueDecl *VD = getDeclDesc()->asValueDecl())
272 return VD->getType();
273 return getDeclDesc()->getType();
274 }
275 if (inPrimitiveArray() && Offset != Base) {
276 // Unfortunately, complex and vector types are not array types in clang,
277 // but they are for us.
278 if (const auto *AT = getFieldDesc()->getType()->getAsArrayTypeUnsafe())
279 return AT->getElementType();
280 if (const auto *CT = getFieldDesc()->getType()->getAs<ComplexType>())
281 return CT->getElementType();
282 if (const auto *CT = getFieldDesc()->getType()->getAs<VectorType>())
283 return CT->getElementType();
284 }
285
286 return getFieldDesc()->getType();
287 }
288
289 bool isInitialized() const {
290 if (isRoot() && Base == sizeof(GlobalInlineDescriptor) && Offset == Base) {
291 const auto &GD = Pointee->getBlockDesc<GlobalInlineDescriptor>();
293 }
294
295 assert(Pointee && "Cannot check if null pointer was initialized");
296 const Descriptor *Desc = getFieldDesc();
297 assert(Desc);
298 if (Desc->isPrimitiveArray())
300
301 if (Base == 0)
302 return true;
303 // Field has its bit in an inline descriptor.
305 }
306
307 void initializeElement(unsigned Index) const;
308 bool allElementsInitialized() const;
309 bool isElementInitialized(unsigned Index) const;
311 return *reinterpret_cast<InitMapPtr *>(Pointee->rawData() + Base);
312 }
313 void initialize() const;
314 void activate() const;
315
316 void setLifeState(Lifetime L) const;
317 Lifetime getLifetime() const;
320
321 bool operator==(const PtrView &Other) const {
322 return Other.Pointee == Pointee && Base == Other.Base &&
323 Offset == Other.Offset;
324 }
325
326 bool operator!=(const PtrView &Other) const { return !(Other == *this); }
327};
328
330 /// The block the pointer is pointing to.
332 /// Start of the current subfield.
333 unsigned Base;
334 /// Previous link in the pointer chain.
336 /// Next link in the pointer chain.
338};
339
341 const Type *Ty;
342 uint64_t Value;
343
344 std::optional<IntPointer> atOffset(const Context &Ctx, unsigned Offset) const;
345 IntPointer baseCast(const Context &Ctx, unsigned BaseOffset) const;
346
348 if (!Ty)
349 return QualType();
350
351 QualType QT(Ty, 0);
352 if (QT->isPointerOrReferenceType())
353 QT = QT->getPointeeType();
354 else if (QT->isArrayType())
356
357 return QT.IgnoreParens();
358 }
359};
360
363};
364
366 const Type *TypePtr;
368};
369
370enum class Storage { Int, Block, Fn, Typeid };
371
372/// A pointer to a memory block, live or dead.
373///
374/// This object can be allocated into interpreter stack frames. If pointing to
375/// a live block, it is a link in the chain of pointers pointing to the block.
376///
377/// In the simplest form, a Pointer has a Block* (the pointee) and both Base
378/// and Offset are 0, which means it will point to raw data.
379///
380/// The Base field is used to access metadata about the data. For primitive
381/// arrays, the Base is followed by an InitMap. In a variety of cases, the
382/// Base is preceded by an InlineDescriptor, which is used to track the
383/// initialization state, among other things.
384///
385/// The Offset field is used to access the actual data. In other words, the
386/// data the pointer decribes can be found at
387/// Pointee->rawData() + Pointer.Offset.
388///
389/// \verbatim
390/// Pointee Offset
391/// │ │
392/// │ │
393/// ▼ ▼
394/// ┌───────┬────────────┬─────────┬────────────────────────────┐
395/// │ Block │ InlineDesc │ InitMap │ Actual Data │
396/// └───────┴────────────┴─────────┴────────────────────────────┘
397/// ▲
398/// │
399/// │
400/// Base
401/// \endverbatim
402class Pointer {
403public:
404 Pointer() : StorageKind(Storage::Int), Int{nullptr, 0} {}
406 : StorageKind(Storage::Int), Int(std::move(IntPtr)) {}
407 Pointer(Block *B);
408 Pointer(Block *B, uint64_t BaseAndOffset);
409 Pointer(const Pointer &P);
410 Pointer(Pointer &&P);
411 Pointer(uint64_t Address, const Type *Ty, uint64_t Offset = 0)
412 : Offset(Offset), StorageKind(Storage::Int), Int{Ty, Address} {}
413 Pointer(const Function *F, uint64_t Offset = 0)
414 : Offset(Offset), StorageKind(Storage::Fn), Fn{F} {}
415 Pointer(const Type *TypePtr, const Type *TypeInfoType, uint64_t Offset = 0)
416 : Offset(Offset), StorageKind(Storage::Typeid) {
417 Typeid.TypePtr = TypePtr;
418 Typeid.TypeInfoType = TypeInfoType;
419 }
420
421 Pointer(Block *Pointee, unsigned Base, uint64_t Offset);
422 explicit Pointer(PtrView V) : Pointer(V.Pointee, V.Base, V.Offset) {}
423 ~Pointer();
424
425 Pointer &operator=(const Pointer &P);
427
428 /// Equality operators are just for tests.
429 bool operator==(const Pointer &P) const {
430 if (P.StorageKind != StorageKind)
431 return false;
432 if (isIntegralPointer())
433 return P.Int.Value == Int.Value && P.Int.Ty == Int.Ty &&
434 P.Offset == Offset;
435
436 if (isFunctionPointer())
437 return P.Fn.Func == Fn.Func && P.Offset == Offset;
438
439 return P.view() == view();
440 }
441
442 bool operator!=(const Pointer &P) const { return !(P == *this); }
443
444 /// Converts the pointer to an APValue.
445 APValue toAPValue(const ASTContext &ASTCtx) const;
446
447 /// Converts the pointer to a string usable in diagnostics.
448 std::string toDiagnosticString(const ASTContext &Ctx) const;
449
450 uint64_t getIntegerRepresentation() const {
451 if (isIntegralPointer())
452 return Int.Value + (Offset * elemSize());
453 if (isFunctionPointer())
454 return reinterpret_cast<uint64_t>(Fn.Func) + Offset;
455 return reinterpret_cast<uint64_t>(BS.Pointee) + Offset;
456 }
457
458 PtrView view() const {
459 assert(isBlockPointer());
460 return PtrView{BS.Pointee, BS.Base, Offset};
461 }
462
463 /// Converts the pointer to an APValue that is an rvalue.
464 std::optional<APValue> toRValue(const Context &Ctx,
465 QualType ResultType) const;
466
467 /// Offsets a pointer inside an array.
468 [[nodiscard]] Pointer atIndex(uint64_t Idx) const {
469 if (isIntegralPointer())
470 return Pointer(Int.Value, Int.Ty, Idx);
471 if (isFunctionPointer())
472 return Pointer(Fn.Func, Idx);
473
474 return Pointer(view().atIndex(Idx));
475 }
476
477 /// Creates a pointer to a field.
478 [[nodiscard]] Pointer atField(unsigned Off) const {
479 return Pointer(view().atField(Off));
480 }
481
482 /// Subtract the given offset from the current Base and Offset
483 /// of the pointer.
484 [[nodiscard]] Pointer atFieldSub(unsigned Off) const {
485 assert(Offset >= Off);
486 unsigned O = Offset - Off;
487 return Pointer(BS.Pointee, O, O);
488 }
489
490 /// Restricts the scope of an array element pointer.
491 [[nodiscard]] Pointer narrow() const {
492 if (!isBlockPointer())
493 return *this;
494 return Pointer(view().narrow());
495 }
496
497 /// Expands a pointer to the containing array, undoing narrowing.
498 [[nodiscard]] Pointer expand() const {
499 if (!isBlockPointer())
500 return *this;
501 return Pointer(view().expand());
502 }
503
504 /// Checks if the pointer is null.
505 bool isZero() const {
506 switch (StorageKind) {
507 case Storage::Int:
508 return Int.Value == 0 && Offset == 0;
509 case Storage::Block:
510 return BS.Pointee == nullptr;
511 case Storage::Fn:
512 return !Fn.Func;
513 case Storage::Typeid:
514 return false;
515 }
516 llvm_unreachable("Unknown clang::interp::Storage enum");
517 }
518 /// Checks if the pointer is live.
519 bool isLive() const {
520 if (!isBlockPointer())
521 return true;
522 return view().isLive();
523 }
524 /// Checks if the item is a field in an object.
525 bool isField() const {
526 if (!isBlockPointer())
527 return false;
528
529 return view().isField();
530 }
531
532 /// Accessor for information about the declaration site.
533 const Descriptor *getDeclDesc() const {
534 if (!isBlockPointer())
535 return nullptr;
536
537 assert(isBlockPointer());
538 assert(BS.Pointee);
539 return BS.Pointee->Desc;
540 }
542
543 /// Returns the expression or declaration the pointer has been created for.
545 if (isBlockPointer())
546 return getDeclDesc()->getSource();
547 if (isFunctionPointer()) {
548 const Function *F = Fn.Func;
549 return F ? F->getDecl() : DeclOrExpr();
550 }
551 llvm_unreachable("Unsupported pointer type in getSource()");
552 return DeclOrExpr();
553 }
554
555 /// Returns a pointer to the object of which this pointer is a field.
556 [[nodiscard]] Pointer getBase() const { return Pointer(view().getBase()); }
557 /// Returns the parent array.
558 [[nodiscard]] Pointer getArray() const { return Pointer(view().getArray()); }
559
560 /// Accessors for information about the innermost field.
561 const Descriptor *getFieldDesc() const {
562 if (isIntegralPointer())
563 return nullptr;
564
565 if (isRoot())
566 return getDeclDesc();
567 return getInlineDesc()->Desc;
568 }
569
570 /// Returns the type of the innermost field.
572 switch (StorageKind) {
573 case Storage::Int:
574 return Int.getPointeeType();
575 case Storage::Block:
576 return view().getType();
577 case Storage::Fn:
578 return Fn.Func->getDecl()->getType();
579 case Storage::Typeid:
580 return QualType(Typeid.TypeInfoType, 0);
581 }
582 llvm_unreachable("Unhandled StorageKind");
583 }
584
585 const VarDecl *getRootVarDecl() const;
586 const Expr *getRootExpr() const;
587
588 [[nodiscard]] Pointer getDeclPtr() const { return Pointer(BS.Pointee); }
589
590 /// Returns the element size of the innermost field.
591 size_t elemSize() const {
592 if (isIntegralPointer()) {
593 // FIXME: Remove this and handle int ptrs specially?
594 return 1;
595 }
596
597 return view().elemSize();
598 }
599 /// Returns the total size of the innermost field.
600 size_t getSize() const {
601 assert(isBlockPointer());
602 return getFieldDesc()->getSize();
603 }
604
605 /// Returns the offset into an array.
606 unsigned getOffset() const {
607 assert(Offset != PtrView::PastEndMark && "invalid offset");
608 return view().getOffset();
609 }
610
611 /// Whether this array refers to an array, but not
612 /// to the first element.
613 bool isArrayRoot() const { return view().isArrayRoot(); }
614
615 /// Checks if the innermost field is an array.
616 bool inArray() const {
617 if (isBlockPointer())
618 return view().inArray();
619 return false;
620 }
621 bool inUnion() const {
622 if (isBlockPointer() && BS.Base >= sizeof(InlineDescriptor))
623 return view().inUnion();
624 return false;
625 };
626
627 /// Checks if the structure is a primitive array.
628 bool inPrimitiveArray() const {
629 if (isBlockPointer())
630 return view().inPrimitiveArray();
631 return false;
632 }
633 /// Checks if the structure is an array of unknown size.
634 bool isUnknownSizeArray() const {
635 if (!isBlockPointer())
636 return false;
638 }
639 /// Checks if the pointer points to an array.
640 bool isArrayElement() const {
641 if (!isBlockPointer())
642 return false;
643
644 return view().isArrayElement();
645 }
646 /// Pointer points directly to a block.
647 bool isRoot() const {
648 if (isZero() || !isBlockPointer())
649 return true;
650 return view().isRoot();
651 }
652 /// If this pointer has an InlineDescriptor we can use to initialize.
653 bool canBeInitialized() const {
654 if (!isBlockPointer())
655 return false;
656
657 return BS.Pointee && BS.Base > 0;
658 }
659
660 [[nodiscard]] const BlockPointer &asBlockPointer() const {
661 assert(isBlockPointer());
662 return BS;
663 }
664 [[nodiscard]] const IntPointer &asIntPointer() const {
665 assert(isIntegralPointer());
666 return Int;
667 }
668 [[nodiscard]] const FunctionPointer &asFunctionPointer() const {
669 assert(isFunctionPointer());
670 return Fn;
671 }
672 [[nodiscard]] const TypeidPointer &asTypeidPointer() const {
673 assert(isTypeidPointer());
674 return Typeid;
675 }
676
677 bool isBlockPointer() const { return StorageKind == Storage::Block; }
678 bool isIntegralPointer() const { return StorageKind == Storage::Int; }
679 bool isFunctionPointer() const { return StorageKind == Storage::Fn; }
680 bool isTypeidPointer() const { return StorageKind == Storage::Typeid; }
681
682 /// Returns the record descriptor of a class.
683 const Record *getRecord() const {
684 if (!isBlockPointer())
685 return nullptr;
686 return view().getRecord();
687 }
688 /// Returns the element record type, if this is a non-primive array.
689 const Record *getElemRecord() const { return view().getElemRecord(); }
690 /// Returns the field information.
691 const FieldDecl *getField() const {
692 if (const Descriptor *FD = getFieldDesc())
693 return FD->asFieldDecl();
694 return nullptr;
695 }
696
697 /// Checks if the storage is extern.
698 bool isExtern() const {
699 if (isBlockPointer())
700 return BS.Pointee && BS.Pointee->isExtern();
701 return false;
702 }
703 /// Checks if the storage is static.
704 bool isStatic() const {
705 if (!isBlockPointer())
706 return true;
707 assert(BS.Pointee);
708 return BS.Pointee->isStatic();
709 }
710 /// Checks if the storage is temporary.
711 bool isTemporary() const {
712 if (isBlockPointer()) {
713 assert(BS.Pointee);
714 return BS.Pointee->isTemporary();
715 }
716 return false;
717 }
718 /// Checks if the storage has been dynamically allocated.
719 bool isDynamic() const {
720 if (isBlockPointer()) {
721 assert(BS.Pointee);
722 return BS.Pointee->isDynamic();
723 }
724 return false;
725 }
726 /// Checks if the storage is a static temporary.
727 bool isStaticTemporary() const { return isStatic() && isTemporary(); }
728
729 /// Checks if the field is mutable.
730 bool isMutable() const {
731 if (!isBlockPointer())
732 return false;
733 return view().isMutable();
734 }
735
736 bool isWeak() const {
737 if (isFunctionPointer()) {
738 if (!Fn.Func || !Fn.Func->getDecl())
739 return false;
740
741 return Fn.Func->getDecl()->isWeak();
742 }
743 if (!isBlockPointer())
744 return false;
745
746 assert(isBlockPointer());
747 return BS.Pointee->isWeak();
748 }
749 /// Checks if the object is active.
750 bool isActive() const {
751 if (!isBlockPointer())
752 return true;
753 return view().isActive();
754 }
755 /// Checks if a structure is a base class.
756 bool isBaseClass() const { return view().isBaseClass(); }
757 bool isVirtualBaseClass() const { return view().isVirtualBaseClass(); }
758
759 /// Checks if the pointer points to a dummy value.
760 bool isDummy() const {
761 if (!isBlockPointer())
762 return false;
763 return view().isDummy();
764 }
765
766 /// Checks if an object or a subfield is mutable.
767 bool isConst() const {
768 if (isIntegralPointer())
769 return true;
770 return view().isConst();
771 }
772 bool isConstInMutable() const {
773 if (!isBlockPointer())
774 return false;
775 return isRoot() ? false : getInlineDesc()->IsConstInMutable;
776 }
777
778 /// Checks if an object or a subfield is volatile.
779 bool isVolatile() const {
780 if (!isBlockPointer())
781 return false;
782 return isRoot() ? getDeclDesc()->IsVolatile : getInlineDesc()->IsVolatile;
783 }
784
785 /// Returns the declaration ID.
787 if (isBlockPointer()) {
788 assert(BS.Pointee);
789 return BS.Pointee->getDeclID();
790 }
791 return std::nullopt;
792 }
793
794 /// Returns the byte offset from the start.
795 uint64_t getByteOffset() const {
796 if (isIntegralPointer())
797 return Int.Value + Offset;
798 if (isTypeidPointer())
799 return reinterpret_cast<uintptr_t>(Typeid.TypePtr) + Offset;
800 if (isOnePastEnd())
802 return Offset;
803 }
804
805 /// Returns the number of elements.
806 unsigned getNumElems() const {
807 if (!isBlockPointer())
808 return ~0u;
809 return view().getNumElems();
810 }
811
812 const Block *block() const { return BS.Pointee; }
813
814 /// If backed by actual data (i.e. a block pointer), return
815 /// an address to that data.
816 const std::byte *getRawAddress() const {
817 assert(isBlockPointer());
818 return BS.Pointee->rawData() + Offset;
819 }
820
821 /// Returns the index into an array.
822 int64_t getIndex() const {
823 if (!isBlockPointer())
825
826 return view().getIndex();
827 }
828
829 /// Checks if the index is one past end.
830 bool isOnePastEnd() const {
831 if (!isBlockPointer())
832 return false;
833
834 if (!BS.Pointee)
835 return false;
836
837 if (isUnknownSizeArray())
838 return false;
839
840 return isPastEnd() || (getSize() == getOffset());
841 }
842
843 /// Checks if the pointer points past the end of the object.
844 bool isPastEnd() const {
845 if (isIntegralPointer())
846 return false;
847
848 return !isZero() && Offset > BS.Pointee->getSize();
849 }
850
851 /// Checks if the pointer is an out-of-bounds element pointer.
852 bool isElementPastEnd() const { return Offset == PtrView::PastEndMark; }
853
854 /// Checks if the pointer is pointing to a zero-size array.
855 bool isZeroSizeArray() const {
856 if (isFunctionPointer())
857 return false;
858 if (const auto *Desc = getFieldDesc())
859 return Desc->isZeroSizeArray();
860 return false;
861 }
862
863 /// Checks whether the pointer can be dereferenced to the given PrimType.
864 bool canDeref(PrimType T) const {
865 if (const Descriptor *FieldDesc = getFieldDesc()) {
866 return (FieldDesc->isPrimitive() || FieldDesc->isPrimitiveArray()) &&
867 FieldDesc->getPrimType() == T;
868 }
869 return false;
870 }
871
872 /// Dereferences the pointer, if it's live.
873 template <typename T> T &deref() const {
874 assert(isLive() && "Invalid pointer");
875 assert(isBlockPointer());
876 assert(BS.Pointee);
877 assert(isDereferencable());
878 assert(Offset + sizeof(T) <= BS.Pointee->getSize());
879
880 return view().deref<T>();
881 }
882
883 /// Dereferences the element at index \p I.
884 /// This is equivalent to atIndex(I).deref<T>().
885 template <typename T> T &elem(unsigned I) const {
886 assert(isLive() && "Invalid pointer");
887 assert(isBlockPointer());
888 assert(BS.Pointee);
889 assert(isDereferencable());
890 assert(getFieldDesc()->isPrimitiveArray());
891 assert(I < getFieldDesc()->getNumElems());
892
893 return view().elem<T>(I);
894 }
895
896 bool isConstexprUnknown() const {
897 if (!isBlockPointer())
898 return false;
900 }
901
902 /// Whether this block can be read from at all. This is only true for
903 /// block pointers that point to a valid location inside that block.
904 bool isDereferencable() const {
905 if (!isBlockPointer())
906 return false;
907 if (isDummy())
908 return false;
909 if (isConstexprUnknown())
910 return false;
911 if (isPastEnd())
912 return false;
913
914 return true;
915 }
916
917 /// Initializes a field.
918 void initialize() const {
919 if (!isBlockPointer())
920 return;
921 view().initialize();
922 }
923 /// Initialized the given element of a primitive array.
924 void initializeElement(unsigned Index) const {
925 view().initializeElement(Index);
926 }
927 /// Initialize all elements of a primitive array at once. This can be
928 /// used in situations where we *know* we have initialized *all* elements
929 /// of a primtive array.
930 void initializeAllElements() const;
931 /// Checks if an object was initialized.
932 bool isInitialized() const;
933 /// Like isInitialized(), but for primitive arrays.
934 bool isElementInitialized(unsigned Index) const {
935 if (!isBlockPointer())
936 return true;
937
938 return view().isElementInitialized(Index);
939 }
941 assert(getFieldDesc()->isPrimitiveArray());
942 assert(isArrayRoot());
943 return view().allElementsInitialized();
944 }
945 bool allElementsAlive() const;
946 bool isElementAlive(unsigned Index) const;
947
948 /// Activates a field.
949 void activate() const { view().activate(); }
950 /// Deactivates an entire strurcutre.
951 void deactivate() const {
952 // TODO: this only appears in constructors, so nothing to deactivate.
953 }
954
956 if (!isBlockPointer())
957 return Lifetime::Started;
958 return view().getLifetime();
959 }
960
961 /// Start the lifetime of this pointer. This works for pointer with an
962 /// InlineDescriptor as well as primitive array elements. Pointers are usually
963 /// alive by default, unless the underlying object has been allocated with
964 /// std::allocator. This function is used by std::construct_at.
966 /// Ends the lifetime of the pointer. This works for pointer with an
967 /// InlineDescriptor as well as primitive array elements. This function is
968 /// used by std::destroy_at.
970
971 void setLifeState(Lifetime L) const {
972 if (!isBlockPointer())
973 return;
974 view().setLifeState(L);
975 };
976
977 /// Strip base casts from this Pointer.
978 /// The result is either a root pointer or something
979 /// that isn't a base class anymore.
980 [[nodiscard]] Pointer stripBaseCasts() const {
981 return Pointer(view().stripBaseCasts());
982 }
983
984 /// Compare two pointers.
986 if (!hasSameBase(*this, Other))
988
989 if (Offset < Other.Offset)
991 if (Offset > Other.Offset)
993
995 }
996
997 /// Checks if two pointers are comparable.
998 static bool hasSameBase(const Pointer &A, const Pointer &B);
999 /// Checks if two pointers can be subtracted.
1000 static bool elemsOfSameArray(const Pointer &A, const Pointer &B);
1001 /// Checks if both given pointers point to the same block.
1002 static bool pointToSameBlock(const Pointer &A, const Pointer &B);
1003
1004 static std::optional<std::pair<PtrView, PtrView>>
1005 computeSplitPoint(const Pointer &A, const Pointer &B);
1006
1007 /// Whether this points to a block that's been created for a "literal lvalue",
1008 /// i.e. a non-MaterializeTemporaryExpr Expr.
1009 bool pointsToLiteral() const;
1010 bool pointsToStringLiteral() const;
1011 /// Whether this points to a block created for an AddrLabelExpr.
1012 bool pointsToLabel() const;
1013 /// Returns the AddrLabelExpr the Pointer points to, if any.
1015 if (const Descriptor *Desc = getDeclDesc())
1016 return dyn_cast_if_present<AddrLabelExpr>(Desc->asExpr());
1017 return nullptr;
1018 }
1019
1020 /// Prints the pointer.
1021 void print(llvm::raw_ostream &OS) const;
1022
1023 /// Compute an integer that can be used to compare this pointer to
1024 /// another one. This is usually NOT the same as the pointer offset
1025 /// regarding the AST record layout.
1026 std::optional<size_t>
1027 computeOffsetForComparison(const ASTContext &ASTCtx) const;
1028 /// Compute the pointer offset as given by the ASTRecordLayout.
1029 /// Returns the result in bytes.
1030 std::optional<size_t> computeLayoutOffset(const ASTContext &ASTCtx) const;
1031
1032private:
1033 friend class Block;
1034 friend class DeadBlock;
1035 friend class MemberPointer;
1036 friend class InterpState;
1037 friend class DynamicAllocator;
1038 friend class Program;
1039
1040 /// Returns the embedded descriptor preceding a field.
1041 InlineDescriptor *getInlineDesc() const {
1042 assert(isBlockPointer());
1043 assert(BS.Base != sizeof(GlobalInlineDescriptor));
1044 assert(BS.Base <= BS.Pointee->getSize());
1045 assert(BS.Base >= sizeof(InlineDescriptor));
1046 return getDescriptor(BS.Base);
1047 }
1048
1049 /// Returns a descriptor at a given offset.
1050 InlineDescriptor *getDescriptor(unsigned Offset) const {
1051 assert(Offset != 0 && "Not a nested pointer");
1052 assert(isBlockPointer());
1053 assert(!isZero());
1054 return view().getDescriptor(Offset);
1055 }
1056
1057 /// Returns a reference to the InitMapPtr which stores the initialization map.
1058 InitMapPtr &getInitMap() const {
1059 assert(isBlockPointer());
1060 assert(!isZero());
1061 return view().getInitMap();
1062 }
1063
1064 /// Offset into the storage.
1065 uint64_t Offset = 0;
1066
1067 Storage StorageKind = Storage::Int;
1068 union {
1073 };
1074};
1075
1076inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Pointer &P) {
1077 P.print(OS);
1078 OS << ' ';
1079 if (P.isZero())
1080 return OS;
1081
1082 if (const Descriptor *D = P.getFieldDesc())
1083 D->dump(OS);
1084 if (P.isArrayElement()) {
1085 if (P.isOnePastEnd())
1086 OS << " one-past-the-end";
1087 else {
1088 OS << ' ';
1089 std::string Indices;
1090 llvm::raw_string_ostream SS(Indices);
1091 Pointer K = P;
1092 while (K.isArrayElement()) {
1093 SS << ']' << K.expand().getIndex() << '[';
1094 K = K.expand().getArray();
1095 }
1096 std::reverse(Indices.begin(), Indices.end());
1097 OS << Indices;
1098 }
1099 } else if (P.isBlockPointer() && P.isArrayRoot())
1100 OS << " arrayroot";
1101
1102 if (P.isBlockPointer() && P.block() && P.block()->isDummy())
1103 OS << " dummy";
1104 if (!P.isLive())
1105 OS << " dead";
1106 if (P.isBlockPointer() && P.isBaseClass())
1107 OS << " base-class";
1108 return OS;
1109}
1110
1111} // namespace interp
1112} // namespace clang
1113
1114#endif
#define V(N, I)
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
FormatToken * Next
The next token in the unwrapped line.
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Definition APValue.h:122
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:223
AddrLabelExpr - The GNU address of label extension, representing &&label.
Definition Expr.h:4570
QualType getElementType() const
Definition TypeBase.h:3848
This represents one expression.
Definition Expr.h:113
Represents a member of a struct/union/class.
Definition Decl.h:3294
A (possibly-)qualified type.
Definition TypeBase.h:938
QualType IgnoreParens() const
Returns the specified type after dropping any outer-level parentheses.
Definition TypeBase.h:1331
Encodes a location in the source.
The base class of the type hierarchy.
Definition TypeBase.h:1879
bool isArrayType() const
Definition TypeBase.h:8838
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:789
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
Definition TypeBase.h:9391
bool isPointerOrReferenceType() const
Definition TypeBase.h:8743
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition Decl.h:712
Represents a variable declaration or definition.
Definition Decl.h:932
A memory block, either on the stack or in the heap.
Definition InterpBlock.h:43
bool isDummy() const
Definition InterpBlock.h:88
Holds all information required to evaluate constexpr code in a module.
Definition Context.h:47
Descriptor for a dead block.
Bytecode function.
Definition Function.h:99
const FunctionDecl * getDecl() const
Returns the original FunctionDecl.
Definition Function.h:134
A pointer to a memory block, live or dead.
Definition Pointer.h:402
static bool hasSameBase(const Pointer &A, const Pointer &B)
Checks if two pointers are comparable.
Definition Pointer.cpp:819
Pointer narrow() const
Restricts the scope of an array element pointer.
Definition Pointer.h:491
friend class Program
Definition Pointer.h:1038
UnsignedOrNone getDeclID() const
Returns the declaration ID.
Definition Pointer.h:786
Pointer stripBaseCasts() const
Strip base casts from this Pointer.
Definition Pointer.h:980
const Expr * getRootExpr() const
Definition Pointer.cpp:1167
bool isVolatile() const
Checks if an object or a subfield is volatile.
Definition Pointer.h:779
bool isInitialized() const
Checks if an object was initialized.
Definition Pointer.cpp:576
bool pointsToLabel() const
Whether this points to a block created for an AddrLabelExpr.
Definition Pointer.cpp:906
bool isStatic() const
Checks if the storage is static.
Definition Pointer.h:704
bool isDynamic() const
Checks if the storage has been dynamically allocated.
Definition Pointer.h:719
bool inUnion() const
Definition Pointer.h:621
const VarDecl * getRootVarDecl() const
Definition Pointer.cpp:1161
bool isZeroSizeArray() const
Checks if the pointer is pointing to a zero-size array.
Definition Pointer.h:855
FunctionPointer Fn
Definition Pointer.h:1071
bool allElementsInitialized() const
Definition Pointer.h:940
Pointer atIndex(uint64_t Idx) const
Offsets a pointer inside an array.
Definition Pointer.h:468
bool isDummy() const
Checks if the pointer points to a dummy value.
Definition Pointer.h:760
const AddrLabelExpr * getPointedToLabel() const
Returns the AddrLabelExpr the Pointer points to, if any.
Definition Pointer.h:1014
Pointer atFieldSub(unsigned Off) const
Subtract the given offset from the current Base and Offset of the pointer.
Definition Pointer.h:484
bool inPrimitiveArray() const
Checks if the structure is a primitive array.
Definition Pointer.h:628
void print(llvm::raw_ostream &OS) const
Prints the pointer.
Definition Pointer.cpp:337
bool isExtern() const
Checks if the storage is extern.
Definition Pointer.h:698
int64_t getIndex() const
Returns the index into an array.
Definition Pointer.h:822
friend class MemberPointer
Definition Pointer.h:1035
bool isActive() const
Checks if the object is active.
Definition Pointer.h:750
bool canDeref(PrimType T) const
Checks whether the pointer can be dereferenced to the given PrimType.
Definition Pointer.h:864
bool isConst() const
Checks if an object or a subfield is mutable.
Definition Pointer.h:767
Pointer(uint64_t Address, const Type *Ty, uint64_t Offset=0)
Definition Pointer.h:411
DeclOrExpr getSource() const
Returns the expression or declaration the pointer has been created for.
Definition Pointer.h:544
Pointer atField(unsigned Off) const
Creates a pointer to a field.
Definition Pointer.h:478
bool isWeak() const
Definition Pointer.h:736
T & deref() const
Dereferences the pointer, if it's live.
Definition Pointer.h:873
Pointer(IntPointer &&IntPtr)
Definition Pointer.h:405
bool isMutable() const
Checks if the field is mutable.
Definition Pointer.h:730
bool isConstInMutable() const
Definition Pointer.h:772
unsigned getNumElems() const
Returns the number of elements.
Definition Pointer.h:806
Pointer getArray() const
Returns the parent array.
Definition Pointer.h:558
bool isUnknownSizeArray() const
Checks if the structure is an array of unknown size.
Definition Pointer.h:634
const TypeidPointer & asTypeidPointer() const
Definition Pointer.h:672
bool isIntegralPointer() const
Definition Pointer.h:678
QualType getType() const
Returns the type of the innermost field.
Definition Pointer.h:571
bool operator==(const Pointer &P) const
Equality operators are just for tests.
Definition Pointer.h:429
bool isArrayElement() const
Checks if the pointer points to an array.
Definition Pointer.h:640
void initializeAllElements() const
Initialize all elements of a primitive array at once.
Definition Pointer.cpp:719
bool pointsToStringLiteral() const
Definition Pointer.cpp:895
void initialize() const
Initializes a field.
Definition Pointer.h:918
std::optional< size_t > computeOffsetForComparison(const ASTContext &ASTCtx) const
Compute an integer that can be used to compare this pointer to another one.
Definition Pointer.cpp:382
bool isArrayRoot() const
Whether this array refers to an array, but not to the first element.
Definition Pointer.h:613
bool isLive() const
Checks if the pointer is live.
Definition Pointer.h:519
static bool elemsOfSameArray(const Pointer &A, const Pointer &B)
Checks if two pointers can be subtracted.
Definition Pointer.cpp:843
bool inArray() const
Checks if the innermost field is an array.
Definition Pointer.h:616
bool isElementAlive(unsigned Index) const
Definition Pointer.cpp:623
bool isStaticTemporary() const
Checks if the storage is a static temporary.
Definition Pointer.h:727
Pointer(const Type *TypePtr, const Type *TypeInfoType, uint64_t Offset=0)
Definition Pointer.h:415
T & elem(unsigned I) const
Dereferences the element at index I.
Definition Pointer.h:885
bool pointsToLiteral() const
Whether this points to a block that's been created for a "literal lvalue", i.e.
Definition Pointer.cpp:884
std::optional< size_t > computeLayoutOffset(const ASTContext &ASTCtx) const
Compute the pointer offset as given by the ASTRecordLayout.
Definition Pointer.cpp:462
bool allElementsAlive() const
Definition Pointer.cpp:742
Pointer getBase() const
Returns a pointer to the object of which this pointer is a field.
Definition Pointer.h:556
uint64_t getByteOffset() const
Returns the byte offset from the start.
Definition Pointer.h:795
bool isTypeidPointer() const
Definition Pointer.h:680
std::string toDiagnosticString(const ASTContext &Ctx) const
Converts the pointer to a string usable in diagnostics.
Definition Pointer.cpp:563
bool isZero() const
Checks if the pointer is null.
Definition Pointer.h:505
Pointer & operator=(const Pointer &P)
Definition Pointer.cpp:95
ComparisonCategoryResult compare(const Pointer &Other) const
Compare two pointers.
Definition Pointer.h:985
bool isConstexprUnknown() const
Definition Pointer.h:896
const IntPointer & asIntPointer() const
Definition Pointer.h:664
bool isRoot() const
Pointer points directly to a block.
Definition Pointer.h:647
const Descriptor * getDeclDesc() const
Accessor for information about the declaration site.
Definition Pointer.h:533
void activate() const
Activates a field.
Definition Pointer.h:949
const Record * getElemRecord() const
Returns the element record type, if this is a non-primive array.
Definition Pointer.h:689
static bool pointToSameBlock(const Pointer &A, const Pointer &B)
Checks if both given pointers point to the same block.
Definition Pointer.cpp:837
APValue toAPValue(const ASTContext &ASTCtx) const
Converts the pointer to an APValue.
Definition Pointer.cpp:178
unsigned getOffset() const
Returns the offset into an array.
Definition Pointer.h:606
friend class DynamicAllocator
Definition Pointer.h:1037
void endLifetime() const
Ends the lifetime of the pointer.
Definition Pointer.h:969
void setLifeState(Lifetime L) const
Definition Pointer.h:971
bool isOnePastEnd() const
Checks if the index is one past end.
Definition Pointer.h:830
friend class InterpState
Definition Pointer.h:1036
uint64_t getIntegerRepresentation() const
Definition Pointer.h:450
bool isPastEnd() const
Checks if the pointer points past the end of the object.
Definition Pointer.h:844
Pointer(const Function *F, uint64_t Offset=0)
Definition Pointer.h:413
const FieldDecl * getField() const
Returns the field information.
Definition Pointer.h:691
Pointer expand() const
Expands a pointer to the containing array, undoing narrowing.
Definition Pointer.h:498
friend class Block
Definition Pointer.h:1033
bool isElementPastEnd() const
Checks if the pointer is an out-of-bounds element pointer.
Definition Pointer.h:852
bool isDereferencable() const
Whether this block can be read from at all.
Definition Pointer.h:904
void startLifetime() const
Start the lifetime of this pointer.
Definition Pointer.h:965
bool isBlockPointer() const
Definition Pointer.h:677
bool operator!=(const Pointer &P) const
Definition Pointer.h:442
void deactivate() const
Deactivates an entire strurcutre.
Definition Pointer.h:951
friend class DeadBlock
Definition Pointer.h:1034
TypeidPointer Typeid
Definition Pointer.h:1072
std::optional< APValue > toRValue(const Context &Ctx, QualType ResultType) const
Converts the pointer to an APValue that is an rvalue.
Definition Pointer.cpp:962
size_t getSize() const
Returns the total size of the innermost field.
Definition Pointer.h:600
bool isTemporary() const
Checks if the storage is temporary.
Definition Pointer.h:711
const FunctionPointer & asFunctionPointer() const
Definition Pointer.h:668
SourceLocation getDeclLoc() const
Definition Pointer.h:541
const Block * block() const
Definition Pointer.h:812
void initializeElement(unsigned Index) const
Initialized the given element of a primitive array.
Definition Pointer.h:924
bool isFunctionPointer() const
Definition Pointer.h:679
Pointer getDeclPtr() const
Definition Pointer.h:588
const Descriptor * getFieldDesc() const
Accessors for information about the innermost field.
Definition Pointer.h:561
PtrView view() const
Definition Pointer.h:458
bool isVirtualBaseClass() const
Definition Pointer.h:757
bool isBaseClass() const
Checks if a structure is a base class.
Definition Pointer.h:756
size_t elemSize() const
Returns the element size of the innermost field.
Definition Pointer.h:591
bool canBeInitialized() const
If this pointer has an InlineDescriptor we can use to initialize.
Definition Pointer.h:653
Lifetime getLifetime() const
Definition Pointer.h:955
const BlockPointer & asBlockPointer() const
Definition Pointer.h:660
const std::byte * getRawAddress() const
If backed by actual data (i.e.
Definition Pointer.h:816
bool isField() const
Checks if the item is a field in an object.
Definition Pointer.h:525
static std::optional< std::pair< PtrView, PtrView > > computeSplitPoint(const Pointer &A, const Pointer &B)
Definition Pointer.cpp:916
bool isElementInitialized(unsigned Index) const
Like isInitialized(), but for primitive arrays.
Definition Pointer.h:934
const Record * getRecord() const
Returns the record descriptor of a class.
Definition Pointer.h:683
Structure/Class descriptor.
Definition Record.h:25
@ Address
A pointer to a ValueDecl.
Definition Primitives.h:28
llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, const Boolean &B)
Definition Boolean.h:153
PrimType
Enumeration of the primitive types of the VM.
Definition PrimType.h:34
Top level wrappers for InstallAPI frontend operations.
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
ComparisonCategoryResult
An enumeration representing the possible results of a three-way comparison.
OptionalUnsigned< unsigned > UnsignedOrNone
const FunctionProtoType * T
@ Off
Never emit colors regardless of the output stream.
@ Other
Other implicit parameter.
Definition Decl.h:1774
__UINTPTR_TYPE__ uintptr_t
An unsigned integer type with the property that any valid pointer to void can be converted to this ty...
#define false
Definition stdbool.h:26
Pointer * Prev
Previous link in the pointer chain.
Definition Pointer.h:335
Pointer * Next
Next link in the pointer chain.
Definition Pointer.h:337
unsigned Base
Start of the current subfield.
Definition Pointer.h:333
Block * Pointee
The block the pointer is pointing to.
Definition Pointer.h:331
Describes a memory block created by an allocation site.
Definition Descriptor.h:122
const bool IsConst
Flag indicating if the block is mutable.
Definition Descriptor.h:154
unsigned getSize() const
Returns the size of the object without metadata.
Definition Descriptor.h:226
QualType getType() const
const Decl * asDecl() const
Definition Descriptor.h:201
const Descriptor *const ElemDesc
Descriptor of the array element.
Definition Descriptor.h:148
SourceLocation getLocation() const
bool isUnknownSizeArray() const
Checks if the descriptor is of an array of unknown size.
Definition Descriptor.h:257
unsigned getElemSize() const
returns the size of an element when the structure is viewed as an array.
Definition Descriptor.h:239
const bool IsArray
Flag indicating if the block is an array.
Definition Descriptor.h:161
bool isPrimitiveArray() const
Checks if the descriptor is of an array of primitives.
Definition Descriptor.h:251
DeclOrExpr getSource() const
Definition Descriptor.h:203
bool isZeroSizeArray() const
Checks if the descriptor is of an array of zero size.
Definition Descriptor.h:255
const FieldDecl * asFieldDecl() const
Definition Descriptor.h:213
const Record *const ElemRecord
Pointer to the record, if block contains records.
Definition Descriptor.h:146
Descriptor used for global variables.
Definition Descriptor.h:49
A pointer-sized struct we use to allocate into data storage.
Definition InitMap.h:79
Inline descriptor embedded in structures and arrays.
Definition Descriptor.h:67
unsigned IsActive
Flag indicating if the field is the active member of a union.
Definition Descriptor.h:89
unsigned IsBase
Flag indicating if the field is an embedded base class.
Definition Descriptor.h:83
unsigned IsVirtualBase
Flag inidcating if the field is a virtual base class.
Definition Descriptor.h:86
unsigned InUnion
Flag indicating if this field is in a union (even if nested).
Definition Descriptor.h:92
unsigned Offset
Offset inside the structure/array.
Definition Descriptor.h:69
unsigned IsInitialized
For primitive fields, it indicates if the field was initialized.
Definition Descriptor.h:80
unsigned IsConst
Flag indicating if the storage is constant or not.
Definition Descriptor.h:74
unsigned IsFieldMutable
Flag indicating if the field is mutable (if in a record).
Definition Descriptor.h:95
QualType getPointeeType() const
Definition Pointer.h:347
IntPointer baseCast(const Context &Ctx, unsigned BaseOffset) const
Definition Pointer.cpp:1201
std::optional< IntPointer > atOffset(const Context &Ctx, unsigned Offset) const
Definition Pointer.cpp:1173
bool isUnknownSizeArray() const
Definition Pointer.h:168
const Descriptor * getDeclDesc() const
Definition Pointer.h:85
bool allElementsInitialized() const
Definition Pointer.cpp:726
PtrView atField(unsigned Offset) const
Definition Pointer.h:261
bool isField() const
Definition Pointer.h:160
size_t elemSize() const
Definition Pointer.h:87
const Record * getRecord() const
Definition Pointer.h:153
const Descriptor * getFieldDesc() const
Definition Pointer.h:79
const FieldDecl * getField() const
Definition Pointer.h:158
bool isElementInitialized(unsigned Index) const
Definition Pointer.cpp:598
static constexpr unsigned PastEndMark
Definition Pointer.h:37
unsigned getEvalID()
Definition Pointer.h:58
PtrView atIndex(unsigned Idx) const
Definition Pointer.h:197
bool isBaseClass() const
Definition Pointer.h:164
bool inPrimitiveArray() const
Definition Pointer.h:55
void activate() const
Definition Pointer.cpp:759
InlineDescriptor * getDescriptor(unsigned Offset) const
Definition Pointer.h:73
bool inArray() const
Definition Pointer.h:54
void startLifetime() const
Definition Pointer.h:318
PtrView narrow() const
Definition Pointer.h:89
T & elem(unsigned I) const
Definition Pointer.h:243
bool isElementPastEnd() const
Definition Pointer.h:48
const Block * block() const
Definition Pointer.h:56
bool isInitialized() const
Definition Pointer.h:289
bool isArrayElement() const
Definition Pointer.h:220
bool isPastEnd() const
Definition Pointer.h:172
PtrView getArray() const
Definition Pointer.h:148
bool isZero() const
Definition Pointer.h:43
const Record * getElemRecord() const
Definition Pointer.h:154
unsigned getNumElems() const
Definition Pointer.h:218
InitMapPtr & getInitMap() const
Definition Pointer.h:310
InlineDescriptor * getInlineDesc() const
Definition Pointer.h:66
bool inUnion() const
Definition Pointer.h:53
bool isMutable() const
Definition Pointer.h:50
void endLifetime() const
Definition Pointer.h:319
void initializeElement(unsigned Index) const
Definition Pointer.cpp:698
bool operator==(const PtrView &Other) const
Definition Pointer.h:321
void initialize() const
Definition Pointer.cpp:677
QualType getType() const
Definition Pointer.h:266
bool isOnePastEnd() const
Definition Pointer.h:188
bool isConst() const
Definition Pointer.h:62
bool isRoot() const
Definition Pointer.h:60
void setLifeState(Lifetime L) const
Definition Pointer.cpp:655
Lifetime getLifetime() const
Definition Pointer.cpp:636
PtrView getBase() const
Definition Pointer.h:256
unsigned getOffset() const
Definition Pointer.h:174
bool isActive() const
Definition Pointer.h:46
bool isDummy() const
Definition Pointer.h:45
PtrView expand() const
Definition Pointer.h:113
bool isVirtualBaseClass() const
Definition Pointer.h:165
bool isZeroSizeArray() const
Definition Pointer.h:49
bool isLive() const
Definition Pointer.h:44
bool isArrayRoot() const
Definition Pointer.h:47
T & deref() const
Definition Pointer.h:232
bool operator!=(const PtrView &Other) const
Definition Pointer.h:326
PtrView stripBaseCasts() const
Definition Pointer.h:141
size_t getSize() const
Definition Pointer.h:186
int64_t getIndex() const
Definition Pointer.h:206