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