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;
252 return asBlockPointer().Pointee && !asBlockPointer().Pointee->IsDead;
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 and vector types are not array types in clang,
318 // but they are 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 if (const auto *CT = getFieldDesc()->getType()->getAs<VectorType>())
324 return CT->getElementType();
325 }
326 return getFieldDesc()->getType();
327 }
328
329 [[nodiscard]] Pointer getDeclPtr() const {
330 return Pointer(asBlockPointer().Pointee);
331 }
332
333 /// Returns the element size of the innermost field.
334 size_t elemSize() const {
335 if (isIntegralPointer()) {
336 if (!asIntPointer().Desc)
337 return 1;
338 return asIntPointer().Desc->getElemSize();
339 }
340
341 if (asBlockPointer().Base == RootPtrMark)
342 return getDeclDesc()->getSize();
343 return getFieldDesc()->getElemSize();
344 }
345 /// Returns the total size of the innermost field.
346 size_t getSize() const {
347 assert(isBlockPointer());
348 return getFieldDesc()->getSize();
349 }
350
351 /// Returns the offset into an array.
352 unsigned getOffset() const {
353 assert(Offset != PastEndMark && "invalid offset");
354 if (asBlockPointer().Base == RootPtrMark)
355 return Offset;
356
357 unsigned Adjust = 0;
358 if (Offset != asBlockPointer().Base) {
359 if (getFieldDesc()->ElemDesc)
360 Adjust = sizeof(InlineDescriptor);
361 else
362 Adjust = sizeof(InitMapPtr);
363 }
364 return Offset - asBlockPointer().Base - Adjust;
365 }
366
367 /// Whether this array refers to an array, but not
368 /// to the first element.
369 bool isArrayRoot() const {
370 return inArray() && Offset == asBlockPointer().Base;
371 }
372
373 /// Checks if the innermost field is an array.
374 bool inArray() const {
375 if (isBlockPointer())
376 return getFieldDesc()->IsArray;
377 return false;
378 }
379 /// Checks if the structure is a primitive array.
380 bool inPrimitiveArray() const {
381 if (isBlockPointer())
382 return getFieldDesc()->isPrimitiveArray();
383 return false;
384 }
385 /// Checks if the structure is an array of unknown size.
386 bool isUnknownSizeArray() const {
387 if (!isBlockPointer())
388 return false;
390 }
391 /// Checks if the pointer points to an array.
392 bool isArrayElement() const {
393 if (isBlockPointer())
394 return inArray() && asBlockPointer().Base != Offset;
395 return false;
396 }
397 /// Pointer points directly to a block.
398 bool isRoot() const {
399 if (isZero() || isIntegralPointer())
400 return true;
401 return (asBlockPointer().Base ==
402 asBlockPointer().Pointee->getDescriptor()->getMetadataSize() ||
403 asBlockPointer().Base == 0);
404 }
405 /// If this pointer has an InlineDescriptor we can use to initialize.
406 bool canBeInitialized() const {
407 if (!isBlockPointer())
408 return false;
409
410 return asBlockPointer().Pointee && asBlockPointer().Base > 0;
411 }
412
413 [[nodiscard]] const BlockPointer &asBlockPointer() const {
414 assert(isBlockPointer());
415 return PointeeStorage.BS;
416 }
417 [[nodiscard]] const IntPointer &asIntPointer() const {
418 assert(isIntegralPointer());
419 return PointeeStorage.Int;
420 }
421 bool isBlockPointer() const { return StorageKind == Storage::Block; }
422 bool isIntegralPointer() const { return StorageKind == Storage::Int; }
423
424 /// Returns the record descriptor of a class.
425 const Record *getRecord() const { return getFieldDesc()->ElemRecord; }
426 /// Returns the element record type, if this is a non-primive array.
427 const Record *getElemRecord() const {
428 const Descriptor *ElemDesc = getFieldDesc()->ElemDesc;
429 return ElemDesc ? ElemDesc->ElemRecord : nullptr;
430 }
431 /// Returns the field information.
432 const FieldDecl *getField() const { return getFieldDesc()->asFieldDecl(); }
433
434 /// Checks if the object is a union.
435 bool isUnion() const;
436
437 /// Checks if the storage is extern.
438 bool isExtern() const {
439 if (isBlockPointer())
441 return false;
442 }
443 /// Checks if the storage is static.
444 bool isStatic() const {
445 if (isIntegralPointer())
446 return true;
447 assert(asBlockPointer().Pointee);
448 return asBlockPointer().Pointee->isStatic();
449 }
450 /// Checks if the storage is temporary.
451 bool isTemporary() const {
452 if (isBlockPointer()) {
453 assert(asBlockPointer().Pointee);
455 }
456 return false;
457 }
458 /// Checks if the storage is a static temporary.
459 bool isStaticTemporary() const { return isStatic() && isTemporary(); }
460
461 /// Checks if the field is mutable.
462 bool isMutable() const {
463 if (!isBlockPointer())
464 return false;
465 return asBlockPointer().Base != 0 &&
466 asBlockPointer().Base != sizeof(InlineDescriptor) &&
467 getInlineDesc()->IsFieldMutable;
468 }
469
470 bool isWeak() const {
471 if (isIntegralPointer())
472 return false;
473
474 assert(isBlockPointer());
475 if (const ValueDecl *VD = getDeclDesc()->asValueDecl())
476 return VD->isWeak();
477 return false;
478 }
479 /// Checks if an object was initialized.
480 bool isInitialized() const;
481 /// Checks if the object is active.
482 bool isActive() const {
483 if (!isBlockPointer())
484 return true;
485 return isRoot() || getInlineDesc()->IsActive;
486 }
487 /// Checks if a structure is a base class.
488 bool isBaseClass() const { return isField() && getInlineDesc()->IsBase; }
489 /// Checks if the pointer points to a dummy value.
490 bool isDummy() const {
491 if (!isBlockPointer())
492 return false;
493
494 if (!asBlockPointer().Pointee)
495 return false;
496
497 return getDeclDesc()->isDummy();
498 }
499
500 /// Checks if an object or a subfield is mutable.
501 bool isConst() const {
502 if (isIntegralPointer())
503 return true;
504 return isRoot() ? getDeclDesc()->IsConst : getInlineDesc()->IsConst;
505 }
506
507 /// Returns the declaration ID.
508 std::optional<unsigned> getDeclID() const {
509 if (isBlockPointer()) {
510 assert(asBlockPointer().Pointee);
511 return asBlockPointer().Pointee->getDeclID();
512 }
513 return std::nullopt;
514 }
515
516 /// Returns the byte offset from the start.
517 unsigned getByteOffset() const {
518 if (isIntegralPointer())
519 return asIntPointer().Value + Offset;
520 return Offset;
521 }
522
523 /// Returns the number of elements.
524 unsigned getNumElems() const {
525 if (isIntegralPointer())
526 return ~unsigned(0);
527 return getSize() / elemSize();
528 }
529
530 const Block *block() const { return asBlockPointer().Pointee; }
531
532 /// Returns the index into an array.
533 int64_t getIndex() const {
534 if (!isBlockPointer())
535 return 0;
536
537 if (isZero())
538 return 0;
539
540 // narrow()ed element in a composite array.
541 if (asBlockPointer().Base > sizeof(InlineDescriptor) &&
542 asBlockPointer().Base == Offset)
543 return 0;
544
545 if (auto ElemSize = elemSize())
546 return getOffset() / ElemSize;
547 return 0;
548 }
549
550 /// Checks if the index is one past end.
551 bool isOnePastEnd() const {
552 if (isIntegralPointer())
553 return false;
554
555 if (!asBlockPointer().Pointee)
556 return false;
557
558 return isElementPastEnd() ||
559 (getSize() == getOffset() && !isZeroSizeArray());
560 }
561
562 /// Checks if the pointer is an out-of-bounds element pointer.
563 bool isElementPastEnd() const { return Offset == PastEndMark; }
564
565 /// Checks if the pointer is pointing to a zero-size array.
566 bool isZeroSizeArray() const { return getFieldDesc()->isZeroSizeArray(); }
567
568 /// Dereferences the pointer, if it's live.
569 template <typename T> T &deref() const {
570 assert(isLive() && "Invalid pointer");
571 assert(isBlockPointer());
572 assert(asBlockPointer().Pointee);
573 assert(Offset + sizeof(T) <=
574 asBlockPointer().Pointee->getDescriptor()->getAllocSize());
575
576 if (isArrayRoot())
577 return *reinterpret_cast<T *>(asBlockPointer().Pointee->rawData() +
578 asBlockPointer().Base + sizeof(InitMapPtr));
579
580 return *reinterpret_cast<T *>(asBlockPointer().Pointee->rawData() + Offset);
581 }
582
583 /// Dereferences a primitive element.
584 template <typename T> T &elem(unsigned I) const {
585 assert(I < getNumElems());
586 assert(isBlockPointer());
587 assert(asBlockPointer().Pointee);
588 return reinterpret_cast<T *>(asBlockPointer().Pointee->data() +
589 sizeof(InitMapPtr))[I];
590 }
591
592 /// Initializes a field.
593 void initialize() const;
594 /// Activats a field.
595 void activate() const;
596 /// Deactivates an entire strurcutre.
597 void deactivate() const;
598
599 /// Compare two pointers.
601 if (!hasSameBase(*this, Other))
603
604 if (Offset < Other.Offset)
606 else if (Offset > Other.Offset)
608
610 }
611
612 /// Checks if two pointers are comparable.
613 static bool hasSameBase(const Pointer &A, const Pointer &B);
614 /// Checks if two pointers can be subtracted.
615 static bool hasSameArray(const Pointer &A, const Pointer &B);
616
617 /// Prints the pointer.
618 void print(llvm::raw_ostream &OS) const;
619
620private:
621 friend class Block;
622 friend class DeadBlock;
623 friend class MemberPointer;
624 friend struct InitMap;
625
626 Pointer(Block *Pointee, unsigned Base, uint64_t Offset);
627
628 /// Returns the embedded descriptor preceding a field.
629 InlineDescriptor *getInlineDesc() const {
630 return getDescriptor(asBlockPointer().Base);
631 }
632
633 /// Returns a descriptor at a given offset.
634 InlineDescriptor *getDescriptor(unsigned Offset) const {
635 assert(Offset != 0 && "Not a nested pointer");
636 assert(isBlockPointer());
637 assert(!isZero());
638 return reinterpret_cast<InlineDescriptor *>(
639 asBlockPointer().Pointee->rawData() + Offset) -
640 1;
641 }
642
643 /// Returns a reference to the InitMapPtr which stores the initialization map.
644 InitMapPtr &getInitMap() const {
645 assert(isBlockPointer());
646 assert(!isZero());
647 return *reinterpret_cast<InitMapPtr *>(asBlockPointer().Pointee->rawData() +
649 }
650
651 /// Offset into the storage.
652 uint64_t Offset = 0;
653
654 /// Previous link in the pointer chain.
655 Pointer *Prev = nullptr;
656 /// Next link in the pointer chain.
657 Pointer *Next = nullptr;
658
659 union {
662 } PointeeStorage;
663 Storage StorageKind = Storage::Int;
664};
665
666inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Pointer &P) {
667 P.print(OS);
668 return OS;
669}
670
671} // namespace interp
672} // namespace clang
673
674#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:185
Represents a member of a struct/union/class.
Definition: Decl.h:3059
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
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
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:171
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:302
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:298
bool isInitialized() const
Checks if an object was initialized.
Definition: Pointer.cpp:223
bool isStatic() const
Checks if the storage is static.
Definition: Pointer.h:444
bool isZeroSizeArray() const
Checks if the pointer is pointing to a zero-size array.
Definition: Pointer.h:566
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:490
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:380
void print(llvm::raw_ostream &OS) const
Prints the pointer.
Definition: Pointer.cpp:187
bool isExtern() const
Checks if the storage is extern.
Definition: Pointer.h:438
int64_t getIndex() const
Returns the index into an array.
Definition: Pointer.h:533
bool isActive() const
Checks if the object is active.
Definition: Pointer.h:482
bool isConst() const
Checks if an object or a subfield is mutable.
Definition: Pointer.h:501
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:470
T & deref() const
Dereferences the pointer, if it's live.
Definition: Pointer.h:569
bool isMutable() const
Checks if the field is mutable.
Definition: Pointer.h:462
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:524
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:386
void activate() const
Activats a field.
Definition: Pointer.cpp:291
void operator=(const Pointer &P)
Definition: Pointer.cpp:66
bool isIntegralPointer() const
Definition: Pointer.h:422
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:392
bool isArrayRoot() const
Whether this array refers to an array, but not to the first element.
Definition: Pointer.h:369
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:374
bool isStaticTemporary() const
Checks if the storage is a static temporary.
Definition: Pointer.h:459
T & elem(unsigned I) const
Dereferences a primitive element.
Definition: Pointer.h:584
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:213
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:600
const IntPointer & asIntPointer() const
Definition: Pointer.h:417
bool isRoot() const
Pointer points directly to a block.
Definition: Pointer.h:398
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:427
unsigned getOffset() const
Returns the offset into an array.
Definition: Pointer.h:352
bool isOnePastEnd() const
Checks if the index is one past end.
Definition: Pointer.h:551
static bool hasSameArray(const Pointer &A, const Pointer &B)
Checks if two pointers can be subtracted.
Definition: Pointer.cpp:316
uint64_t getIntegerRepresentation() const
Definition: Pointer.h:127
const FieldDecl * getField() const
Returns the field information.
Definition: Pointer.h:432
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:322
bool isBlockPointer() const
Definition: Pointer.h:421
bool operator!=(const Pointer &P) const
Definition: Pointer.h:119
BlockPointer BS
Definition: Pointer.h:660
size_t getSize() const
Returns the total size of the innermost field.
Definition: Pointer.h:346
bool isTemporary() const
Checks if the storage is temporary.
Definition: Pointer.h:451
SourceLocation getDeclLoc() const
Definition: Pointer.h:273
const Block * block() const
Definition: Pointer.h:530
APValue toAPValue() const
Converts the pointer to an APValue.
Definition: Pointer.cpp:122
Pointer getDeclPtr() const
Definition: Pointer.h:329
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:508
bool isBaseClass() const
Checks if a structure is a base class.
Definition: Pointer.h:488
size_t elemSize() const
Returns the element size of the innermost field.
Definition: Pointer.h:334
bool canBeInitialized() const
If this pointer has an InlineDescriptor we can use to initialize.
Definition: Pointer.h:406
const BlockPointer & asBlockPointer() const
Definition: Pointer.h:413
void initialize() const
Initializes a field.
Definition: Pointer.cpp:250
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:517
const Record * getRecord() const
Returns the record descriptor of a class.
Definition: Pointer.h:425
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:33
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
bool isZeroSizeArray() const
Checks if the descriptor is of an array of zero size.
Definition: Descriptor.h:220
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