clang 19.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 "InterpBlock.h"
19#include "clang/AST/Decl.h"
20#include "clang/AST/DeclCXX.h"
21#include "clang/AST/Expr.h"
22#include "llvm/ADT/PointerUnion.h"
23#include "llvm/Support/raw_ostream.h"
24
25namespace clang {
26namespace interp {
27class Block;
28class DeadBlock;
29class Pointer;
30class Context;
31template <unsigned A, bool B> class Integral;
32enum PrimType : unsigned;
33
34class Pointer;
35inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Pointer &P);
36
38 /// The block the pointer is pointing to.
40 /// Start of the current subfield.
41 unsigned Base;
42};
43
44struct IntPointer {
46 uint64_t Value;
47};
48
49enum class Storage { Block, Int };
50
51/// A pointer to a memory block, live or dead.
52///
53/// This object can be allocated into interpreter stack frames. If pointing to
54/// a live block, it is a link in the chain of pointers pointing to the block.
55///
56/// In the simplest form, a Pointer has a Block* (the pointee) and both Base
57/// and Offset are 0, which means it will point to raw data.
58///
59/// The Base field is used to access metadata about the data. For primitive
60/// arrays, the Base is followed by an InitMap. In a variety of cases, the
61/// Base is preceded by an InlineDescriptor, which is used to track the
62/// initialization state, among other things.
63///
64/// The Offset field is used to access the actual data. In other words, the
65/// data the pointer decribes can be found at
66/// Pointee->rawData() + Pointer.Offset.
67///
68///
69/// Pointee Offset
70/// │ │
71/// │ │
72/// ▼ ▼
73/// ┌───────┬────────────┬─────────┬────────────────────────────┐
74/// │ Block │ InlineDesc │ InitMap │ Actual Data │
75/// └───────┴────────────┴─────────┴────────────────────────────┘
76/// ▲
77/// │
78/// │
79/// Base
80class Pointer {
81private:
82 static constexpr unsigned PastEndMark = ~0u;
83 static constexpr unsigned RootPtrMark = ~0u;
84
85public:
87 StorageKind = Storage::Int;
88 PointeeStorage.Int.Value = 0;
89 PointeeStorage.Int.Desc = nullptr;
90 }
91 Pointer(Block *B);
92 Pointer(Block *B, uint64_t BaseAndOffset);
93 Pointer(const Pointer &P);
94 Pointer(Pointer &&P);
95 Pointer(uint64_t Address, const Descriptor *Desc, uint64_t Offset = 0)
96 : Offset(Offset), StorageKind(Storage::Int) {
97 PointeeStorage.Int.Value = Address;
98 PointeeStorage.Int.Desc = Desc;
99 }
100 ~Pointer();
101
102 void operator=(const Pointer &P);
103 void operator=(Pointer &&P);
104
105 /// Equality operators are just for tests.
106 bool operator==(const Pointer &P) const {
107 if (P.StorageKind != StorageKind)
108 return false;
109 if (isIntegralPointer())
110 return P.asIntPointer().Value == asIntPointer().Value &&
111 Offset == P.Offset;
112
113 assert(isBlockPointer());
114 return P.asBlockPointer().Pointee == asBlockPointer().Pointee &&
115 P.asBlockPointer().Base == asBlockPointer().Base &&
116 Offset == P.Offset;
117 }
118
119 bool operator!=(const Pointer &P) const { return !(P == *this); }
120
121 /// Converts the pointer to an APValue.
122 APValue toAPValue() const;
123
124 /// Converts the pointer to a string usable in diagnostics.
125 std::string toDiagnosticString(const ASTContext &Ctx) const;
126
127 uint64_t getIntegerRepresentation() const {
128 if (isIntegralPointer())
129 return asIntPointer().Value + (Offset * elemSize());
130 return reinterpret_cast<uint64_t>(asBlockPointer().Pointee) + Offset;
131 }
132
133 /// Converts the pointer to an APValue that is an rvalue.
134 std::optional<APValue> toRValue(const Context &Ctx) const;
135
136 /// Offsets a pointer inside an array.
137 [[nodiscard]] Pointer atIndex(uint64_t Idx) const {
138 if (isIntegralPointer())
139 return Pointer(asIntPointer().Value, asIntPointer().Desc, Idx);
140
141 if (asBlockPointer().Base == RootPtrMark)
142 return Pointer(asBlockPointer().Pointee, RootPtrMark,
143 getDeclDesc()->getSize());
144 uint64_t Off = Idx * elemSize();
145 if (getFieldDesc()->ElemDesc)
146 Off += sizeof(InlineDescriptor);
147 else
148 Off += sizeof(InitMapPtr);
149 return Pointer(asBlockPointer().Pointee, asBlockPointer().Base,
150 asBlockPointer().Base + Off);
151 }
152
153 /// Creates a pointer to a field.
154 [[nodiscard]] Pointer atField(unsigned Off) const {
155 unsigned Field = Offset + Off;
156 if (isIntegralPointer())
157 return Pointer(asIntPointer().Value + Field, asIntPointer().Desc);
158 return Pointer(asBlockPointer().Pointee, Field, Field);
159 }
160
161 /// Subtract the given offset from the current Base and Offset
162 /// of the pointer.
163 [[nodiscard]] Pointer atFieldSub(unsigned Off) const {
164 assert(Offset >= Off);
165 unsigned O = Offset - Off;
166 return Pointer(asBlockPointer().Pointee, O, O);
167 }
168
169 /// Restricts the scope of an array element pointer.
170 [[nodiscard]] Pointer narrow() const {
171 if (!isBlockPointer())
172 return *this;
173 assert(isBlockPointer());
174 // Null pointers cannot be narrowed.
175 if (isZero() || isUnknownSizeArray())
176 return *this;
177
178 // Pointer to an array of base types - enter block.
179 if (asBlockPointer().Base == RootPtrMark)
180 return Pointer(asBlockPointer().Pointee, sizeof(InlineDescriptor),
181 Offset == 0 ? Offset : PastEndMark);
182
183 // Pointer is one past end - magic offset marks that.
184 if (isOnePastEnd())
185 return Pointer(asBlockPointer().Pointee, asBlockPointer().Base,
186 PastEndMark);
187
188 // Primitive arrays are a bit special since they do not have inline
189 // descriptors. If Offset != Base, then the pointer already points to
190 // an element and there is nothing to do. Otherwise, the pointer is
191 // adjusted to the first element of the array.
192 if (inPrimitiveArray()) {
193 if (Offset != asBlockPointer().Base)
194 return *this;
195 return Pointer(asBlockPointer().Pointee, asBlockPointer().Base,
196 Offset + sizeof(InitMapPtr));
197 }
198
199 // Pointer is to a field or array element - enter it.
200 if (Offset != asBlockPointer().Base)
201 return Pointer(asBlockPointer().Pointee, Offset, Offset);
202
203 // Enter the first element of an array.
204 if (!getFieldDesc()->isArray())
205 return *this;
206
207 const unsigned NewBase = asBlockPointer().Base + sizeof(InlineDescriptor);
208 return Pointer(asBlockPointer().Pointee, NewBase, NewBase);
209 }
210
211 /// Expands a pointer to the containing array, undoing narrowing.
212 [[nodiscard]] Pointer expand() const {
213 if (isElementPastEnd()) {
214 // Revert to an outer one-past-end pointer.
215 unsigned Adjust;
216 if (inPrimitiveArray())
217 Adjust = sizeof(InitMapPtr);
218 else
219 Adjust = sizeof(InlineDescriptor);
220 return Pointer(asBlockPointer().Pointee, asBlockPointer().Base,
221 asBlockPointer().Base + getSize() + Adjust);
222 }
223
224 // Do not step out of array elements.
225 if (asBlockPointer().Base != Offset)
226 return *this;
227
228 // If at base, point to an array of base types.
229 if (isRoot())
230 return Pointer(asBlockPointer().Pointee, RootPtrMark, 0);
231
232 // Step into the containing array, if inside one.
233 unsigned Next = asBlockPointer().Base - getInlineDesc()->Offset;
234 const Descriptor *Desc =
235 Next == 0 ? getDeclDesc() : getDescriptor(Next)->Desc;
236 if (!Desc->IsArray)
237 return *this;
238 return Pointer(asBlockPointer().Pointee, Next, Offset);
239 }
240
241 /// Checks if the pointer is null.
242 bool isZero() const {
243 if (isBlockPointer())
244 return asBlockPointer().Pointee == nullptr;
245 assert(isIntegralPointer());
246 return asIntPointer().Value == 0 && Offset == 0;
247 }
248 /// Checks if the pointer is live.
249 bool isLive() const {
250 if (isIntegralPointer())
251 return true;
253 }
254 /// Checks if the item is a field in an object.
255 bool isField() const {
256 if (isIntegralPointer())
257 return false;
258
259 unsigned Base = asBlockPointer().Base;
260 return Base != 0 && Base != sizeof(InlineDescriptor) &&
261 Base != RootPtrMark && getFieldDesc()->asDecl();
262 }
263
264 /// Accessor for information about the declaration site.
265 const Descriptor *getDeclDesc() const {
266 if (isIntegralPointer())
267 return asIntPointer().Desc;
268
269 assert(isBlockPointer());
270 assert(asBlockPointer().Pointee);
271 return asBlockPointer().Pointee->Desc;
272 }
274
275 /// Returns the expression or declaration the pointer has been created for.
277 if (isBlockPointer())
278 return getDeclDesc()->getSource();
279
280 assert(isIntegralPointer());
282 }
283
284 /// Returns a pointer to the object of which this pointer is a field.
285 [[nodiscard]] Pointer getBase() const {
286 if (asBlockPointer().Base == RootPtrMark) {
287 assert(Offset == PastEndMark && "cannot get base of a block");
288 return Pointer(asBlockPointer().Pointee, asBlockPointer().Base, 0);
289 }
290 unsigned NewBase = asBlockPointer().Base - getInlineDesc()->Offset;
291 return Pointer(asBlockPointer().Pointee, NewBase, NewBase);
292 }
293 /// Returns the parent array.
294 [[nodiscard]] Pointer getArray() const {
295 if (asBlockPointer().Base == RootPtrMark) {
296 assert(Offset != 0 && Offset != PastEndMark && "not an array element");
297 return Pointer(asBlockPointer().Pointee, asBlockPointer().Base, 0);
298 }
299 assert(Offset != asBlockPointer().Base && "not an array element");
300 return Pointer(asBlockPointer().Pointee, asBlockPointer().Base,
302 }
303
304 /// Accessors for information about the innermost field.
305 const Descriptor *getFieldDesc() const {
306 if (isIntegralPointer())
307 return asIntPointer().Desc;
308
309 if (isRoot())
310 return getDeclDesc();
311 return getInlineDesc()->Desc;
312 }
313
314 /// Returns the type of the innermost field.
316 if (inPrimitiveArray() && Offset != asBlockPointer().Base) {
317 // Unfortunately, complex types are not array types in clang, but they are
318 // for us.
319 if (const auto *AT = getFieldDesc()->getType()->getAsArrayTypeUnsafe())
320 return AT->getElementType();
321 if (const auto *CT = getFieldDesc()->getType()->getAs<ComplexType>())
322 return CT->getElementType();
323 }
324 return getFieldDesc()->getType();
325 }
326
327 [[nodiscard]] Pointer getDeclPtr() const {
328 return Pointer(asBlockPointer().Pointee);
329 }
330
331 /// Returns the element size of the innermost field.
332 size_t elemSize() const {
333 if (isIntegralPointer()) {
334 if (!asIntPointer().Desc)
335 return 1;
336 return asIntPointer().Desc->getElemSize();
337 }
338
339 if (asBlockPointer().Base == RootPtrMark)
340 return getDeclDesc()->getSize();
341 return getFieldDesc()->getElemSize();
342 }
343 /// Returns the total size of the innermost field.
344 size_t getSize() const {
345 assert(isBlockPointer());
346 return getFieldDesc()->getSize();
347 }
348
349 /// Returns the offset into an array.
350 unsigned getOffset() const {
351 assert(Offset != PastEndMark && "invalid offset");
352 if (asBlockPointer().Base == RootPtrMark)
353 return Offset;
354
355 unsigned Adjust = 0;
356 if (Offset != asBlockPointer().Base) {
357 if (getFieldDesc()->ElemDesc)
358 Adjust = sizeof(InlineDescriptor);
359 else
360 Adjust = sizeof(InitMapPtr);
361 }
362 return Offset - asBlockPointer().Base - Adjust;
363 }
364
365 /// Whether this array refers to an array, but not
366 /// to the first element.
367 bool isArrayRoot() const {
368 return inArray() && Offset == asBlockPointer().Base;
369 }
370
371 /// Checks if the innermost field is an array.
372 bool inArray() const {
373 if (isBlockPointer())
374 return getFieldDesc()->IsArray;
375 return false;
376 }
377 /// Checks if the structure is a primitive array.
378 bool inPrimitiveArray() const {
379 if (isBlockPointer())
380 return getFieldDesc()->isPrimitiveArray();
381 return false;
382 }
383 /// Checks if the structure is an array of unknown size.
384 bool isUnknownSizeArray() const {
385 if (!isBlockPointer())
386 return false;
388 }
389 /// Checks if the pointer points to an array.
390 bool isArrayElement() const {
391 if (isBlockPointer())
392 return inArray() && asBlockPointer().Base != Offset;
393 return false;
394 }
395 /// Pointer points directly to a block.
396 bool isRoot() const {
397 if (isZero() || isIntegralPointer())
398 return true;
399 return (asBlockPointer().Base ==
400 asBlockPointer().Pointee->getDescriptor()->getMetadataSize() ||
401 asBlockPointer().Base == 0);
402 }
403 /// If this pointer has an InlineDescriptor we can use to initialize.
404 bool canBeInitialized() const {
405 if (!isBlockPointer())
406 return false;
407
408 return asBlockPointer().Pointee && asBlockPointer().Base > 0;
409 }
410
411 [[nodiscard]] const BlockPointer &asBlockPointer() const {
412 assert(isBlockPointer());
413 return PointeeStorage.BS;
414 }
415 [[nodiscard]] const IntPointer &asIntPointer() const {
416 assert(isIntegralPointer());
417 return PointeeStorage.Int;
418 }
419 bool isBlockPointer() const { return StorageKind == Storage::Block; }
420 bool isIntegralPointer() const { return StorageKind == Storage::Int; }
421
422 /// Returns the record descriptor of a class.
423 const Record *getRecord() const { return getFieldDesc()->ElemRecord; }
424 /// Returns the element record type, if this is a non-primive array.
425 const Record *getElemRecord() const {
426 const Descriptor *ElemDesc = getFieldDesc()->ElemDesc;
427 return ElemDesc ? ElemDesc->ElemRecord : nullptr;
428 }
429 /// Returns the field information.
430 const FieldDecl *getField() const { return getFieldDesc()->asFieldDecl(); }
431
432 /// Checks if the object is a union.
433 bool isUnion() const;
434
435 /// Checks if the storage is extern.
436 bool isExtern() const {
437 if (isBlockPointer())
439 return false;
440 }
441 /// Checks if the storage is static.
442 bool isStatic() const {
443 if (isIntegralPointer())
444 return true;
445 assert(asBlockPointer().Pointee);
446 return asBlockPointer().Pointee->isStatic();
447 }
448 /// Checks if the storage is temporary.
449 bool isTemporary() const {
450 if (isBlockPointer()) {
451 assert(asBlockPointer().Pointee);
453 }
454 return false;
455 }
456 /// Checks if the storage is a static temporary.
457 bool isStaticTemporary() const { return isStatic() && isTemporary(); }
458
459 /// Checks if the field is mutable.
460 bool isMutable() const {
461 if (!isBlockPointer())
462 return false;
463 return asBlockPointer().Base != 0 &&
464 asBlockPointer().Base != sizeof(InlineDescriptor) &&
465 getInlineDesc()->IsFieldMutable;
466 }
467
468 bool isWeak() const {
469 if (isIntegralPointer())
470 return false;
471
472 assert(isBlockPointer());
473 if (const ValueDecl *VD = getDeclDesc()->asValueDecl())
474 return VD->isWeak();
475 return false;
476 }
477 /// Checks if an object was initialized.
478 bool isInitialized() const;
479 /// Checks if the object is active.
480 bool isActive() const {
481 if (!isBlockPointer())
482 return true;
483 return isRoot() || getInlineDesc()->IsActive;
484 }
485 /// Checks if a structure is a base class.
486 bool isBaseClass() const { return isField() && getInlineDesc()->IsBase; }
487 /// Checks if the pointer points to a dummy value.
488 bool isDummy() const {
489 if (!isBlockPointer())
490 return false;
491
492 if (!asBlockPointer().Pointee)
493 return false;
494
495 return getDeclDesc()->isDummy();
496 }
497
498 /// Checks if an object or a subfield is mutable.
499 bool isConst() const {
500 if (isIntegralPointer())
501 return true;
502 return isRoot() ? getDeclDesc()->IsConst : getInlineDesc()->IsConst;
503 }
504
505 /// Returns the declaration ID.
506 std::optional<unsigned> getDeclID() const {
507 if (isBlockPointer()) {
508 assert(asBlockPointer().Pointee);
509 return asBlockPointer().Pointee->getDeclID();
510 }
511 return std::nullopt;
512 }
513
514 /// Returns the byte offset from the start.
515 unsigned getByteOffset() const {
516 if (isIntegralPointer())
517 return asIntPointer().Value + Offset;
518 return Offset;
519 }
520
521 /// Returns the number of elements.
522 unsigned getNumElems() const {
523 if (isIntegralPointer())
524 return ~unsigned(0);
525 return getSize() / elemSize();
526 }
527
528 const Block *block() const { return asBlockPointer().Pointee; }
529
530 /// Returns the index into an array.
531 int64_t getIndex() const {
532 if (!isBlockPointer())
533 return 0;
534
535 if (isZero())
536 return 0;
537
538 if (isElementPastEnd())
539 return 1;
540
541 // narrow()ed element in a composite array.
542 if (asBlockPointer().Base > sizeof(InlineDescriptor) &&
543 asBlockPointer().Base == Offset)
544 return 0;
545
546 if (auto ElemSize = elemSize())
547 return getOffset() / ElemSize;
548 return 0;
549 }
550
551 /// Checks if the index is one past end.
552 bool isOnePastEnd() const {
553 if (isIntegralPointer())
554 return false;
555
556 if (!asBlockPointer().Pointee)
557 return false;
558
559 return isElementPastEnd() || getSize() == getOffset();
560 }
561
562 /// Checks if the pointer is an out-of-bounds element pointer.
563 bool isElementPastEnd() const { return Offset == PastEndMark; }
564
565 /// Dereferences the pointer, if it's live.
566 template <typename T> T &deref() const {
567 assert(isLive() && "Invalid pointer");
568 assert(isBlockPointer());
569 assert(asBlockPointer().Pointee);
570 assert(Offset + sizeof(T) <=
571 asBlockPointer().Pointee->getDescriptor()->getAllocSize());
572
573 if (isArrayRoot())
574 return *reinterpret_cast<T *>(asBlockPointer().Pointee->rawData() +
575 asBlockPointer().Base + sizeof(InitMapPtr));
576
577 return *reinterpret_cast<T *>(asBlockPointer().Pointee->rawData() + Offset);
578 }
579
580 /// Dereferences a primitive element.
581 template <typename T> T &elem(unsigned I) const {
582 assert(I < getNumElems());
583 assert(isBlockPointer());
584 assert(asBlockPointer().Pointee);
585 return reinterpret_cast<T *>(asBlockPointer().Pointee->data() +
586 sizeof(InitMapPtr))[I];
587 }
588
589 /// Initializes a field.
590 void initialize() const;
591 /// Activats a field.
592 void activate() const;
593 /// Deactivates an entire strurcutre.
594 void deactivate() const;
595
596 /// Compare two pointers.
598 if (!hasSameBase(*this, Other))
600
601 if (Offset < Other.Offset)
603 else if (Offset > Other.Offset)
605
607 }
608
609 /// Checks if two pointers are comparable.
610 static bool hasSameBase(const Pointer &A, const Pointer &B);
611 /// Checks if two pointers can be subtracted.
612 static bool hasSameArray(const Pointer &A, const Pointer &B);
613
614 /// Prints the pointer.
615 void print(llvm::raw_ostream &OS) const;
616
617private:
618 friend class Block;
619 friend class DeadBlock;
620 friend struct InitMap;
621
622 Pointer(Block *Pointee, unsigned Base, uint64_t Offset);
623
624 /// Returns the embedded descriptor preceding a field.
625 InlineDescriptor *getInlineDesc() const {
626 return getDescriptor(asBlockPointer().Base);
627 }
628
629 /// Returns a descriptor at a given offset.
630 InlineDescriptor *getDescriptor(unsigned Offset) const {
631 assert(Offset != 0 && "Not a nested pointer");
632 assert(isBlockPointer());
633 assert(!isZero());
634 return reinterpret_cast<InlineDescriptor *>(
635 asBlockPointer().Pointee->rawData() + Offset) -
636 1;
637 }
638
639 /// Returns a reference to the InitMapPtr which stores the initialization map.
640 InitMapPtr &getInitMap() const {
641 assert(isBlockPointer());
642 assert(!isZero());
643 return *reinterpret_cast<InitMapPtr *>(asBlockPointer().Pointee->rawData() +
645 }
646
647 /// Offset into the storage.
648 uint64_t Offset = 0;
649
650 /// Previous link in the pointer chain.
651 Pointer *Prev = nullptr;
652 /// Next link in the pointer chain.
653 Pointer *Next = nullptr;
654
655 union {
658 } PointeeStorage;
659 Storage StorageKind = Storage::Int;
660};
661
662inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Pointer &P) {
663 P.print(OS);
664 return OS;
665}
666
667} // namespace interp
668} // namespace clang
669
670#endif
StringRef P
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
const CFGBlock * Block
Definition: HTMLLogger.cpp:153
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:182
Represents a member of a struct/union/class.
Definition: Decl.h:3057
A (possibly-)qualified type.
Definition: Type.h:940
Encodes a location in the source.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition: Decl.h:706
A memory block, either on the stack or in the heap.
Definition: InterpBlock.h:49
const Descriptor * Desc
Pointer to the stack slot descriptor.
Definition: InterpBlock.h:162
bool isExtern() const
Checks if the block is extern.
Definition: InterpBlock.h:69
std::byte * data()
Returns a pointer to the stored data.
Definition: InterpBlock.h:82
bool isStatic() const
Checks if the block has static storage duration.
Definition: InterpBlock.h:71
bool isTemporary() const
Checks if the block is temporary.
Definition: InterpBlock.h:73
std::byte * rawData()
Returns a pointer to the raw data, including metadata.
Definition: InterpBlock.h:95
bool IsDead
Flag indicating if the pointer is dead.
Definition: InterpBlock.h:157
std::optional< unsigned > getDeclID() const
Returns the declaration ID.
Definition: InterpBlock.h:77
Holds all information required to evaluate constexpr code in a module.
Definition: Context.h:40
Descriptor for a dead block.
Definition: InterpBlock.h:169
A pointer to a memory block, live or dead.
Definition: Pointer.h:80
static bool hasSameBase(const Pointer &A, const Pointer &B)
Checks if two pointers are comparable.
Definition: Pointer.cpp:294
Pointer narrow() const
Restricts the scope of an array element pointer.
Definition: Pointer.h:170
void deactivate() const
Deactivates an entire strurcutre.
Definition: Pointer.cpp:290
bool isInitialized() const
Checks if an object was initialized.
Definition: Pointer.cpp:215
bool isStatic() const
Checks if the storage is static.
Definition: Pointer.h:442
Pointer atIndex(uint64_t Idx) const
Offsets a pointer inside an array.
Definition: Pointer.h:137
bool isDummy() const
Checks if the pointer points to a dummy value.
Definition: Pointer.h:488
Pointer atFieldSub(unsigned Off) const
Subtract the given offset from the current Base and Offset of the pointer.
Definition: Pointer.h:163
bool inPrimitiveArray() const
Checks if the structure is a primitive array.
Definition: Pointer.h:378
void print(llvm::raw_ostream &OS) const
Prints the pointer.
Definition: Pointer.cpp:179
bool isExtern() const
Checks if the storage is extern.
Definition: Pointer.h:436
int64_t getIndex() const
Returns the index into an array.
Definition: Pointer.h:531
bool isActive() const
Checks if the object is active.
Definition: Pointer.h:480
bool isConst() const
Checks if an object or a subfield is mutable.
Definition: Pointer.h:499
Pointer atField(unsigned Off) const
Creates a pointer to a field.
Definition: Pointer.h:154
bool isUnion() const
Checks if the object is a union.
bool isWeak() const
Definition: Pointer.h:468
T & deref() const
Dereferences the pointer, if it's live.
Definition: Pointer.h:566
bool isMutable() const
Checks if the field is mutable.
Definition: Pointer.h:460
DeclTy getSource() const
Returns the expression or declaration the pointer has been created for.
Definition: Pointer.h:276
unsigned getNumElems() const
Returns the number of elements.
Definition: Pointer.h:522
Pointer getArray() const
Returns the parent array.
Definition: Pointer.h:294
bool isUnknownSizeArray() const
Checks if the structure is an array of unknown size.
Definition: Pointer.h:384
void activate() const
Activats a field.
Definition: Pointer.cpp:283
void operator=(const Pointer &P)
Definition: Pointer.cpp:65
bool isIntegralPointer() const
Definition: Pointer.h:420
QualType getType() const
Returns the type of the innermost field.
Definition: Pointer.h:315
bool operator==(const Pointer &P) const
Equality operators are just for tests.
Definition: Pointer.h:106
bool isArrayElement() const
Checks if the pointer points to an array.
Definition: Pointer.h:390
bool isArrayRoot() const
Whether this array refers to an array, but not to the first element.
Definition: Pointer.h:367
bool isLive() const
Checks if the pointer is live.
Definition: Pointer.h:249
bool inArray() const
Checks if the innermost field is an array.
Definition: Pointer.h:372
bool isStaticTemporary() const
Checks if the storage is a static temporary.
Definition: Pointer.h:457
T & elem(unsigned I) const
Dereferences a primitive element.
Definition: Pointer.h:581
Pointer(uint64_t Address, const Descriptor *Desc, uint64_t Offset=0)
Definition: Pointer.h:95
Pointer getBase() const
Returns a pointer to the object of which this pointer is a field.
Definition: Pointer.h:285
std::string toDiagnosticString(const ASTContext &Ctx) const
Converts the pointer to a string usable in diagnostics.
Definition: Pointer.cpp:205
bool isZero() const
Checks if the pointer is null.
Definition: Pointer.h:242
ComparisonCategoryResult compare(const Pointer &Other) const
Compare two pointers.
Definition: Pointer.h:597
const IntPointer & asIntPointer() const
Definition: Pointer.h:415
bool isRoot() const
Pointer points directly to a block.
Definition: Pointer.h:396
const Descriptor * getDeclDesc() const
Accessor for information about the declaration site.
Definition: Pointer.h:265
const Record * getElemRecord() const
Returns the element record type, if this is a non-primive array.
Definition: Pointer.h:425
unsigned getOffset() const
Returns the offset into an array.
Definition: Pointer.h:350
bool isOnePastEnd() const
Checks if the index is one past end.
Definition: Pointer.h:552
static bool hasSameArray(const Pointer &A, const Pointer &B)
Checks if two pointers can be subtracted.
Definition: Pointer.cpp:308
uint64_t getIntegerRepresentation() const
Definition: Pointer.h:127
const FieldDecl * getField() const
Returns the field information.
Definition: Pointer.h:430
Pointer expand() const
Expands a pointer to the containing array, undoing narrowing.
Definition: Pointer.h:212
bool isElementPastEnd() const
Checks if the pointer is an out-of-bounds element pointer.
Definition: Pointer.h:563
std::optional< APValue > toRValue(const Context &Ctx) const
Converts the pointer to an APValue that is an rvalue.
Definition: Pointer.cpp:314
bool isBlockPointer() const
Definition: Pointer.h:419
bool operator!=(const Pointer &P) const
Definition: Pointer.h:119
BlockPointer BS
Definition: Pointer.h:656
size_t getSize() const
Returns the total size of the innermost field.
Definition: Pointer.h:344
bool isTemporary() const
Checks if the storage is temporary.
Definition: Pointer.h:449
SourceLocation getDeclLoc() const
Definition: Pointer.h:273
const Block * block() const
Definition: Pointer.h:528
APValue toAPValue() const
Converts the pointer to an APValue.
Definition: Pointer.cpp:119
Pointer getDeclPtr() const
Definition: Pointer.h:327
const Descriptor * getFieldDesc() const
Accessors for information about the innermost field.
Definition: Pointer.h:305
std::optional< unsigned > getDeclID() const
Returns the declaration ID.
Definition: Pointer.h:506
bool isBaseClass() const
Checks if a structure is a base class.
Definition: Pointer.h:486
size_t elemSize() const
Returns the element size of the innermost field.
Definition: Pointer.h:332
bool canBeInitialized() const
If this pointer has an InlineDescriptor we can use to initialize.
Definition: Pointer.h:404
const BlockPointer & asBlockPointer() const
Definition: Pointer.h:411
void initialize() const
Initializes a field.
Definition: Pointer.cpp:242
bool isField() const
Checks if the item is a field in an object.
Definition: Pointer.h:255
unsigned getByteOffset() const
Returns the byte offset from the start.
Definition: Pointer.h:515
const Record * getRecord() const
Returns the record descriptor of a class.
Definition: Pointer.h:423
Structure/Class descriptor.
Definition: Record.h:25
std::optional< std::pair< bool, std::shared_ptr< InitMap > > > InitMapPtr
Definition: Descriptor.h:28
PrimType
Enumeration of the primitive types of the VM.
Definition: PrimType.h:32
llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, const Boolean &B)
Definition: Boolean.h:156
llvm::PointerUnion< const Decl *, const Expr * > DeclTy
Definition: Descriptor.h:27
The JSON file list parser is used to communicate input to InstallAPI.
ComparisonCategoryResult
An enumeration representing the possible results of a three-way comparison.
const FunctionProtoType * T
@ Other
Other implicit parameter.
unsigned Base
Start of the current subfield.
Definition: Pointer.h:41
Block * Pointee
The block the pointer is pointing to.
Definition: Pointer.h:39
Describes a memory block created by an allocation site.
Definition: Descriptor.h:91
const bool IsConst
Flag indicating if the block is mutable.
Definition: Descriptor.h:123
unsigned getSize() const
Returns the size of the object without metadata.
Definition: Descriptor.h:193
QualType getType() const
Definition: Descriptor.cpp:350
const DeclTy & getSource() const
Definition: Descriptor.h:174
const Decl * asDecl() const
Definition: Descriptor.h:172
const Descriptor *const ElemDesc
Descriptor of the array element.
Definition: Descriptor.h:117
bool isDummy() const
Checks if this is a dummy descriptor.
Definition: Descriptor.h:232
SourceLocation getLocation() const
Definition: Descriptor.cpp:366
bool isUnknownSizeArray() const
Checks if the descriptor is of an array of unknown size.
Definition: Descriptor.h:222
unsigned getElemSize() const
returns the size of an element when the structure is viewed as an array.
Definition: Descriptor.h:206
const bool IsArray
Flag indicating if the block is an array.
Definition: Descriptor.h:129
bool isPrimitiveArray() const
Checks if the descriptor is of an array of primitives.
Definition: Descriptor.h:216
const FieldDecl * asFieldDecl() const
Definition: Descriptor.h:184
const Record *const ElemRecord
Pointer to the record, if block contains records.
Definition: Descriptor.h:115
Bitfield tracking the initialisation status of elements of primitive arrays.
Definition: Descriptor.h:239
Inline descriptor embedded in structures and arrays.
Definition: Descriptor.h:56
unsigned IsActive
Flag indicating if the field is the active member of a union.
Definition: Descriptor.h:75
unsigned IsBase
Flag indicating if the field is an embedded base class.
Definition: Descriptor.h:72
const Descriptor * Desc
Definition: Descriptor.h:80
unsigned Offset
Offset inside the structure/array.
Definition: Descriptor.h:58
unsigned IsConst
Flag indicating if the storage is constant or not.
Definition: Descriptor.h:63
unsigned IsFieldMutable
Flag indicating if the field is mutable (if in a record).
Definition: Descriptor.h:78
const Descriptor * Desc
Definition: Pointer.h:45