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