1//===--- APValue.h - Union class for APFloat/APSInt/Complex -----*- 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// This file defines the APValue class.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_CLANG_AST_APVALUE_H
14#define LLVM_CLANG_AST_APVALUE_H
15
16#include "clang/Basic/LLVM.h"
17#include "llvm/ADT/APFixedPoint.h"
18#include "llvm/ADT/APFloat.h"
19#include "llvm/ADT/APSInt.h"
20#include "llvm/ADT/FoldingSet.h"
21#include "llvm/ADT/PointerIntPair.h"
22#include "llvm/ADT/PointerUnion.h"
23#include "llvm/Support/AlignOf.h"
24
25namespace clang {
26namespace serialization {
27template <typename T> class BasicReaderBase;
28} // end namespace serialization
29
30 class AddrLabelExpr;
31 class ASTContext;
32 class CharUnits;
33 class CXXRecordDecl;
34 class Decl;
35 class DiagnosticBuilder;
36 class Expr;
37 class FieldDecl;
38 struct PrintingPolicy;
39 class Type;
40 class ValueDecl;
41 class QualType;
42
43/// Symbolic representation of typeid(T) for some type T.
44class TypeInfoLValue {
45 const Type *T;
46
47public:
48 TypeInfoLValue() : T() {}
49 explicit TypeInfoLValue(const Type *T);
50
51 const Type *getType() const { return T; }
52 explicit operator bool() const { return T; }
53
54 const void *getOpaqueValue() const { return T; }
55 static TypeInfoLValue getFromOpaqueValue(const void *Value) {
56 TypeInfoLValue V;
57 V.T = reinterpret_cast<const Type*>(Value);
58 return V;
59 }
60
61 void print(llvm::raw_ostream &Out, const PrintingPolicy &Policy) const;
62};
63
64/// Symbolic representation of a dynamic allocation.
65class DynamicAllocLValue {
66 unsigned Index;
67
68public:
69 DynamicAllocLValue() : Index(0) {}
70 explicit DynamicAllocLValue(unsigned Index) : Index(Index + 1) {}
71 unsigned getIndex() { return Index - 1; }
72
73 explicit operator bool() const { return Index != 0; }
74
75 const void *getOpaqueValue() const {
76 return reinterpret_cast<const void *>(static_cast<uintptr_t>(Index)
77 << NumLowBitsAvailable);
78 }
79 static DynamicAllocLValue getFromOpaqueValue(const void *Value) {
80 DynamicAllocLValue V;
81 V.Index = reinterpret_cast<uintptr_t>(Value) >> NumLowBitsAvailable;
82 return V;
83 }
84
85 static unsigned getMaxIndex() {
86 return (std::numeric_limits<unsigned>::max() >> NumLowBitsAvailable) - 1;
87 }
88
89 static constexpr int NumLowBitsAvailable = 3;
90};
91}
92
93namespace llvm {
94template<> struct PointerLikeTypeTraits<clang::TypeInfoLValue> {
95 static const void *getAsVoidPointer(clang::TypeInfoLValue V) {
96 return V.getOpaqueValue();
97 }
98 static clang::TypeInfoLValue getFromVoidPointer(const void *P) {
99 return clang::TypeInfoLValue::getFromOpaqueValue(Value: P);
100 }
101 // Validated by static_assert in APValue.cpp; hardcoded to avoid needing
102 // to include Type.h.
103 static constexpr int NumLowBitsAvailable = 3;
104};
105
106template<> struct PointerLikeTypeTraits<clang::DynamicAllocLValue> {
107 static const void *getAsVoidPointer(clang::DynamicAllocLValue V) {
108 return V.getOpaqueValue();
109 }
110 static clang::DynamicAllocLValue getFromVoidPointer(const void *P) {
111 return clang::DynamicAllocLValue::getFromOpaqueValue(Value: P);
112 }
113 static constexpr int NumLowBitsAvailable =
114 clang::DynamicAllocLValue::NumLowBitsAvailable;
115};
116}
117
118namespace clang {
119/// APValue - This class implements a discriminated union of [uninitialized]
120/// [APSInt] [APFloat], [Complex APSInt] [Complex APFloat], [Expr + Offset],
121/// [Vector: N * APValue], [Array: N * APValue]
122class APValue {
123 typedef llvm::APFixedPoint APFixedPoint;
124 typedef llvm::APSInt APSInt;
125 typedef llvm::APFloat APFloat;
126public:
127 enum ValueKind {
128 /// There is no such object (it's outside its lifetime).
129 None,
130 /// This object has an indeterminate value (C++ [basic.indet]).
131 Indeterminate,
132 Int,
133 Float,
134 FixedPoint,
135 ComplexInt,
136 ComplexFloat,
137 LValue,
138 Vector,
139 Matrix,
140 Array,
141 Struct,
142 Union,
143 MemberPointer,
144 AddrLabelDiff
145 };
146
147 class alignas(uint64_t) LValueBase {
148 typedef llvm::PointerUnion<const ValueDecl *, const Expr *, TypeInfoLValue,
149 DynamicAllocLValue>
150 PtrTy;
151
152 public:
153 LValueBase() : Local{} {}
154 LValueBase(const ValueDecl *P, unsigned I = 0, unsigned V = 0);
155 LValueBase(const Expr *P, unsigned I = 0, unsigned V = 0);
156 static LValueBase getDynamicAlloc(DynamicAllocLValue LV, QualType Type);
157 static LValueBase getTypeInfo(TypeInfoLValue LV, QualType TypeInfo);
158
159 void Profile(llvm::FoldingSetNodeID &ID) const;
160
161 template <class T> bool is() const { return isa<T>(Ptr); }
162
163 template <class T> T get() const { return cast<T>(Ptr); }
164
165 template <class T> T dyn_cast() const {
166 return dyn_cast_if_present<T>(Ptr);
167 }
168
169 void *getOpaqueValue() const;
170
171 bool isNull() const;
172
173 explicit operator bool() const;
174
175 unsigned getCallIndex() const;
176 unsigned getVersion() const;
177 QualType getTypeInfoType() const;
178 QualType getDynamicAllocType() const;
179
180 QualType getType() const;
181
182 friend bool operator==(const LValueBase &LHS, const LValueBase &RHS);
183 friend bool operator!=(const LValueBase &LHS, const LValueBase &RHS) {
184 return !(LHS == RHS);
185 }
186 friend llvm::hash_code hash_value(const LValueBase &Base);
187 friend struct llvm::DenseMapInfo<LValueBase>;
188
189 private:
190 PtrTy Ptr;
191 struct LocalState {
192 unsigned CallIndex, Version;
193 };
194 union {
195 LocalState Local;
196 /// The type std::type_info, if this is a TypeInfoLValue.
197 void *TypeInfoType;
198 /// The QualType, if this is a DynamicAllocLValue.
199 void *DynamicAllocType;
200 };
201 };
202
203 /// A FieldDecl or CXXRecordDecl, along with a flag indicating whether we
204 /// mean a virtual or non-virtual base class subobject.
205 typedef llvm::PointerIntPair<const Decl *, 1, bool> BaseOrMemberType;
206
207 /// A non-discriminated union of a base, field, or array index.
208 class LValuePathEntry {
209 static_assert(sizeof(uintptr_t) <= sizeof(uint64_t),
210 "pointer doesn't fit in 64 bits?");
211 uint64_t Value;
212
213 public:
214 LValuePathEntry() : Value() {}
215 LValuePathEntry(BaseOrMemberType BaseOrMember);
216 static LValuePathEntry ArrayIndex(uint64_t Index) {
217 LValuePathEntry Result;
218 Result.Value = Index;
219 return Result;
220 }
221
222 BaseOrMemberType getAsBaseOrMember() const {
223 return BaseOrMemberType::getFromOpaqueValue(
224 V: reinterpret_cast<void *>(Value));
225 }
226 uint64_t getAsArrayIndex() const { return Value; }
227
228 void Profile(llvm::FoldingSetNodeID &ID) const;
229
230 friend bool operator==(LValuePathEntry A, LValuePathEntry B) {
231 return A.Value == B.Value;
232 }
233 friend bool operator!=(LValuePathEntry A, LValuePathEntry B) {
234 return A.Value != B.Value;
235 }
236 friend llvm::hash_code hash_value(LValuePathEntry A) {
237 return llvm::hash_value(value: A.Value);
238 }
239 };
240 class LValuePathSerializationHelper {
241 const void *Ty;
242
243 public:
244 ArrayRef<LValuePathEntry> Path;
245
246 LValuePathSerializationHelper(ArrayRef<LValuePathEntry>, QualType);
247 QualType getType();
248 };
249 struct NoLValuePath {};
250 struct UninitArray {};
251 struct UninitStruct {};
252 struct ConstexprUnknown {};
253
254 template <typename Impl> friend class clang::serialization::BasicReaderBase;
255 friend class ASTImporter;
256 friend class ASTNodeImporter;
257
258private:
259 ValueKind Kind;
260 bool AllowConstexprUnknown : 1;
261
262 struct ComplexAPSInt {
263 APSInt Real, Imag;
264 ComplexAPSInt() : Real(1), Imag(1) {}
265 };
266 struct ComplexAPFloat {
267 APFloat Real, Imag;
268 ComplexAPFloat() : Real(0.0), Imag(0.0) {}
269 };
270 struct LV;
271 struct Vec {
272 APValue *Elts = nullptr;
273 unsigned NumElts = 0;
274 Vec() = default;
275 Vec(const Vec &) = delete;
276 Vec &operator=(const Vec &) = delete;
277 ~Vec() { delete[] Elts; }
278 };
279 struct Mat {
280 APValue *Elts = nullptr;
281 unsigned NumRows = 0;
282 unsigned NumCols = 0;
283 Mat() = default;
284 Mat(const Mat &) = delete;
285 Mat &operator=(const Mat &) = delete;
286 ~Mat() { delete[] Elts; }
287 };
288 struct Arr {
289 APValue *Elts;
290 unsigned NumElts, ArrSize;
291 Arr(unsigned NumElts, unsigned ArrSize);
292 Arr(const Arr &) = delete;
293 Arr &operator=(const Arr &) = delete;
294 ~Arr();
295 };
296 struct StructData {
297 APValue *Elts;
298 unsigned NumBases;
299 unsigned NumFields;
300 StructData(unsigned NumBases, unsigned NumFields);
301 StructData(const StructData &) = delete;
302 StructData &operator=(const StructData &) = delete;
303 ~StructData();
304 };
305 struct UnionData {
306 const FieldDecl *Field;
307 APValue *Value;
308 UnionData();
309 UnionData(const UnionData &) = delete;
310 UnionData &operator=(const UnionData &) = delete;
311 ~UnionData();
312 };
313 struct AddrLabelDiffData {
314 const AddrLabelExpr* LHSExpr;
315 const AddrLabelExpr* RHSExpr;
316 };
317 struct MemberPointerData;
318
319 // We ensure elsewhere that Data is big enough for LV and MemberPointerData.
320 typedef llvm::AlignedCharArrayUnion<void *, APSInt, APFloat, ComplexAPSInt,
321 ComplexAPFloat, Vec, Mat, Arr, StructData,
322 UnionData, AddrLabelDiffData>
323 DataType;
324 static const size_t DataSize = sizeof(DataType);
325
326 DataType Data;
327
328public:
329 bool allowConstexprUnknown() const { return AllowConstexprUnknown; }
330
331 void setConstexprUnknown(bool IsConstexprUnknown = true) {
332 AllowConstexprUnknown = IsConstexprUnknown;
333 }
334
335 /// Creates an empty APValue of type None.
336 APValue() : Kind(None), AllowConstexprUnknown(false) {}
337 /// Creates an integer APValue holding the given value.
338 explicit APValue(APSInt I) : Kind(None), AllowConstexprUnknown(false) {
339 MakeInt(); setInt(std::move(I));
340 }
341 /// Creates a float APValue holding the given value.
342 explicit APValue(APFloat F) : Kind(None), AllowConstexprUnknown(false) {
343 MakeFloat(); setFloat(std::move(F));
344 }
345 /// Creates a fixed-point APValue holding the given value.
346 explicit APValue(APFixedPoint FX) : Kind(None), AllowConstexprUnknown(false) {
347 MakeFixedPoint(FX: std::move(FX));
348 }
349 /// Creates a vector APValue with \p N elements. The elements
350 /// are read from \p E.
351 explicit APValue(const APValue *E, unsigned N)
352 : Kind(None), AllowConstexprUnknown(false) {
353 MakeVector(); setVector(E, N);
354 }
355 /// Creates a matrix APValue with given dimensions. The elements
356 /// are read from \p E and assumed to be in row-major order.
357 explicit APValue(const APValue *E, unsigned NumRows, unsigned NumCols)
358 : Kind(None), AllowConstexprUnknown(false) {
359 MakeMatrix();
360 setMatrix(E, NumRows, NumCols);
361 }
362 /// Creates an integer complex APValue with the given real and imaginary
363 /// values.
364 APValue(APSInt R, APSInt I) : Kind(None), AllowConstexprUnknown(false) {
365 MakeComplexInt(); setComplexInt(R: std::move(R), I: std::move(I));
366 }
367 /// Creates a float complex APValue with the given real and imaginary values.
368 APValue(APFloat R, APFloat I) : Kind(None), AllowConstexprUnknown(false) {
369 MakeComplexFloat(); setComplexFloat(R: std::move(R), I: std::move(I));
370 }
371 APValue(const APValue &RHS);
372 APValue(APValue &&RHS);
373 /// Creates an lvalue APValue without an lvalue path.
374 /// \param Base The base of the lvalue.
375 /// \param Offset The offset of the lvalue.
376 /// \param IsNullPtr Whether this lvalue is a null pointer.
377 APValue(LValueBase Base, const CharUnits &Offset, NoLValuePath,
378 bool IsNullPtr = false)
379 : Kind(None), AllowConstexprUnknown(false) {
380 MakeLValue();
381 setLValue(B: Base, O: Offset, NoLValuePath{}, IsNullPtr);
382 }
383 /// Creates an lvalue APValue with an lvalue path.
384 /// \param Base The base of the lvalue.
385 /// \param Offset The offset of the lvalue.
386 /// \param Path The lvalue path.
387 /// \param OnePastTheEnd Whether this lvalue is one-past-the-end of the
388 /// subobject it points to.
389 /// \param IsNullPtr Whether this lvalue is a null pointer.
390 APValue(LValueBase Base, const CharUnits &Offset,
391 ArrayRef<LValuePathEntry> Path, bool OnePastTheEnd,
392 bool IsNullPtr = false)
393 : Kind(None), AllowConstexprUnknown(false) {
394 MakeLValue();
395 setLValue(B: Base, O: Offset, Path, OnePastTheEnd, IsNullPtr);
396 }
397 /// Creates a constexpr unknown lvalue APValue.
398 /// \param Base The base of the lvalue.
399 /// \param Offset The offset of the lvalue.
400 /// \param IsNullPtr Whether this lvalue is a null pointer.
401 APValue(LValueBase Base, const CharUnits &Offset, ConstexprUnknown,
402 bool IsNullPtr = false)
403 : Kind(None), AllowConstexprUnknown(true) {
404 MakeLValue();
405 setLValue(B: Base, O: Offset, NoLValuePath{}, IsNullPtr);
406 }
407
408 /// Creates a new array APValue.
409 /// \param UninitArray Marker. Pass an empty UninitArray.
410 /// \param InitElts Number of elements you're going to initialize in the
411 /// array.
412 /// \param Size Full size of the array.
413 APValue(UninitArray, unsigned InitElts, unsigned Size)
414 : Kind(None), AllowConstexprUnknown(false) {
415 MakeArray(InitElts, Size);
416 }
417 /// Creates a new struct APValue.
418 /// \param UninitStruct Marker. Pass an empty UninitStruct.
419 /// \param NumBases Number of bases.
420 /// \param NumMembers Number of members.
421 APValue(UninitStruct, unsigned NumBases, unsigned NumMembers)
422 : Kind(None), AllowConstexprUnknown(false) {
423 MakeStruct(B: NumBases, M: NumMembers);
424 }
425 /// Creates a new union APValue.
426 /// \param ActiveDecl The FieldDecl of the active union member.
427 /// \param ActiveValue The value of the active union member.
428 explicit APValue(const FieldDecl *ActiveDecl,
429 const APValue &ActiveValue = APValue())
430 : Kind(None), AllowConstexprUnknown(false) {
431 MakeUnion();
432 setUnion(Field: ActiveDecl, Value: ActiveValue);
433 }
434 /// Creates a new member pointer APValue.
435 /// \param Member Declaration of the member
436 /// \param IsDerivedMember Whether member is a derived one.
437 /// \param Path The path of the member.
438 APValue(const ValueDecl *Member, bool IsDerivedMember,
439 ArrayRef<const CXXRecordDecl *> Path)
440 : Kind(None), AllowConstexprUnknown(false) {
441 MakeMemberPointer(Member, IsDerivedMember, Path);
442 }
443 /// Creates a new address label diff APValue.
444 /// \param LHSExpr The left-hand side of the difference.
445 /// \param RHSExpr The right-hand side of the difference.
446 APValue(const AddrLabelExpr *LHSExpr, const AddrLabelExpr *RHSExpr)
447 : Kind(None), AllowConstexprUnknown(false) {
448 MakeAddrLabelDiff(); setAddrLabelDiff(LHSExpr, RHSExpr);
449 }
450 static APValue IndeterminateValue() {
451 APValue Result;
452 Result.Kind = Indeterminate;
453 return Result;
454 }
455
456 APValue &operator=(const APValue &RHS);
457 APValue &operator=(APValue &&RHS);
458
459 ~APValue() {
460 if (Kind != None && Kind != Indeterminate)
461 DestroyDataAndMakeUninit();
462 }
463
464 /// Returns whether the object performed allocations.
465 ///
466 /// If APValues are constructed via placement new, \c needsCleanup()
467 /// indicates whether the destructor must be called in order to correctly
468 /// free all allocated memory.
469 bool needsCleanup() const;
470
471 /// Swaps the contents of this and the given APValue.
472 void swap(APValue &RHS);
473
474 /// profile this value. There is no guarantee that values of different
475 /// types will not produce the same profiled value, so the type should
476 /// typically also be profiled if it's not implied by the context.
477 void Profile(llvm::FoldingSetNodeID &ID) const;
478
479 ValueKind getKind() const { return Kind; }
480
481 bool isAbsent() const { return Kind == None; }
482 bool isIndeterminate() const { return Kind == Indeterminate; }
483 bool hasValue() const { return Kind != None && Kind != Indeterminate; }
484
485 bool isInt() const { return Kind == Int; }
486 bool isFloat() const { return Kind == Float; }
487 bool isFixedPoint() const { return Kind == FixedPoint; }
488 bool isComplexInt() const { return Kind == ComplexInt; }
489 bool isComplexFloat() const { return Kind == ComplexFloat; }
490 bool isLValue() const { return Kind == LValue; }
491 bool isVector() const { return Kind == Vector; }
492 bool isMatrix() const { return Kind == Matrix; }
493 bool isArray() const { return Kind == Array; }
494 bool isStruct() const { return Kind == Struct; }
495 bool isUnion() const { return Kind == Union; }
496 bool isMemberPointer() const { return Kind == MemberPointer; }
497 bool isAddrLabelDiff() const { return Kind == AddrLabelDiff; }
498
499 void dump() const;
500 void dump(raw_ostream &OS, const ASTContext &Context) const;
501
502 void printPretty(raw_ostream &OS, const ASTContext &Ctx, QualType Ty) const;
503 void printPretty(raw_ostream &OS, const PrintingPolicy &Policy, QualType Ty,
504 const ASTContext *Ctx = nullptr) const;
505
506 std::string getAsString(const ASTContext &Ctx, QualType Ty) const;
507
508 APSInt &getInt() {
509 assert(isInt() && "Invalid accessor");
510 return *(APSInt *)(char *)&Data;
511 }
512 const APSInt &getInt() const {
513 return const_cast<APValue*>(this)->getInt();
514 }
515
516 /// Try to convert this value to an integral constant. This works if it's an
517 /// integer, null pointer, or offset from a null pointer. Returns true on
518 /// success.
519 bool toIntegralConstant(APSInt &Result, QualType SrcTy,
520 const ASTContext &Ctx) const;
521
522 APFloat &getFloat() {
523 assert(isFloat() && "Invalid accessor");
524 return *(APFloat *)(char *)&Data;
525 }
526 const APFloat &getFloat() const {
527 return const_cast<APValue*>(this)->getFloat();
528 }
529
530 APFixedPoint &getFixedPoint() {
531 assert(isFixedPoint() && "Invalid accessor");
532 return *(APFixedPoint *)(char *)&Data;
533 }
534 const APFixedPoint &getFixedPoint() const {
535 return const_cast<APValue *>(this)->getFixedPoint();
536 }
537
538 APSInt &getComplexIntReal() {
539 assert(isComplexInt() && "Invalid accessor");
540 return ((ComplexAPSInt *)(char *)&Data)->Real;
541 }
542 const APSInt &getComplexIntReal() const {
543 return const_cast<APValue*>(this)->getComplexIntReal();
544 }
545
546 APSInt &getComplexIntImag() {
547 assert(isComplexInt() && "Invalid accessor");
548 return ((ComplexAPSInt *)(char *)&Data)->Imag;
549 }
550 const APSInt &getComplexIntImag() const {
551 return const_cast<APValue*>(this)->getComplexIntImag();
552 }
553
554 APFloat &getComplexFloatReal() {
555 assert(isComplexFloat() && "Invalid accessor");
556 return ((ComplexAPFloat *)(char *)&Data)->Real;
557 }
558 const APFloat &getComplexFloatReal() const {
559 return const_cast<APValue*>(this)->getComplexFloatReal();
560 }
561
562 APFloat &getComplexFloatImag() {
563 assert(isComplexFloat() && "Invalid accessor");
564 return ((ComplexAPFloat *)(char *)&Data)->Imag;
565 }
566 const APFloat &getComplexFloatImag() const {
567 return const_cast<APValue*>(this)->getComplexFloatImag();
568 }
569
570 const LValueBase getLValueBase() const;
571 CharUnits &getLValueOffset();
572 const CharUnits &getLValueOffset() const {
573 return const_cast<APValue*>(this)->getLValueOffset();
574 }
575 bool isLValueOnePastTheEnd() const;
576 bool hasLValuePath() const;
577 ArrayRef<LValuePathEntry> getLValuePath() const;
578 unsigned getLValueCallIndex() const;
579 unsigned getLValueVersion() const;
580 bool isNullPointer() const;
581
582 APValue &getVectorElt(unsigned I) {
583 assert(isVector() && "Invalid accessor");
584 assert(I < getVectorLength() && "Index out of range");
585 return ((Vec *)(char *)&Data)->Elts[I];
586 }
587 const APValue &getVectorElt(unsigned I) const {
588 return const_cast<APValue*>(this)->getVectorElt(I);
589 }
590 unsigned getVectorLength() const {
591 assert(isVector() && "Invalid accessor");
592 return ((const Vec *)(const void *)&Data)->NumElts;
593 }
594
595 unsigned getMatrixNumRows() const {
596 assert(isMatrix() && "Invalid accessor");
597 return ((const Mat *)(const void *)&Data)->NumRows;
598 }
599 unsigned getMatrixNumColumns() const {
600 assert(isMatrix() && "Invalid accessor");
601 return ((const Mat *)(const void *)&Data)->NumCols;
602 }
603 unsigned getMatrixNumElements() const {
604 return getMatrixNumRows() * getMatrixNumColumns();
605 }
606 APValue &getMatrixElt(unsigned Idx) {
607 assert(isMatrix() && "Invalid accessor");
608 assert(Idx < getMatrixNumElements() && "Index out of range");
609 return ((Mat *)(char *)&Data)->Elts[Idx];
610 }
611 const APValue &getMatrixElt(unsigned Idx) const {
612 return const_cast<APValue *>(this)->getMatrixElt(Idx);
613 }
614 APValue &getMatrixElt(unsigned Row, unsigned Col) {
615 assert(isMatrix() && "Invalid accessor");
616 assert(Row < getMatrixNumRows() && "Row index out of range");
617 assert(Col < getMatrixNumColumns() && "Column index out of range");
618 // Matrix elements are stored in row-major order.
619 unsigned I = Row * getMatrixNumColumns() + Col;
620 return getMatrixElt(Idx: I);
621 }
622 const APValue &getMatrixElt(unsigned Row, unsigned Col) const {
623 return const_cast<APValue *>(this)->getMatrixElt(Row, Col);
624 }
625
626 APValue &getArrayInitializedElt(unsigned I) {
627 assert(isArray() && "Invalid accessor");
628 assert(I < getArrayInitializedElts() && "Index out of range");
629 return ((Arr *)(char *)&Data)->Elts[I];
630 }
631 const APValue &getArrayInitializedElt(unsigned I) const {
632 return const_cast<APValue*>(this)->getArrayInitializedElt(I);
633 }
634 bool hasArrayFiller() const {
635 return getArrayInitializedElts() != getArraySize();
636 }
637 APValue &getArrayFiller() {
638 assert(isArray() && "Invalid accessor");
639 assert(hasArrayFiller() && "No array filler");
640 return ((Arr *)(char *)&Data)->Elts[getArrayInitializedElts()];
641 }
642 const APValue &getArrayFiller() const {
643 return const_cast<APValue*>(this)->getArrayFiller();
644 }
645 unsigned getArrayInitializedElts() const {
646 assert(isArray() && "Invalid accessor");
647 return ((const Arr *)(const void *)&Data)->NumElts;
648 }
649 unsigned getArraySize() const {
650 assert(isArray() && "Invalid accessor");
651 return ((const Arr *)(const void *)&Data)->ArrSize;
652 }
653
654 unsigned getStructNumBases() const {
655 assert(isStruct() && "Invalid accessor");
656 return ((const StructData *)(const char *)&Data)->NumBases;
657 }
658 unsigned getStructNumFields() const {
659 assert(isStruct() && "Invalid accessor");
660 return ((const StructData *)(const char *)&Data)->NumFields;
661 }
662 APValue &getStructBase(unsigned i) {
663 assert(isStruct() && "Invalid accessor");
664 assert(i < getStructNumBases() && "base class index OOB");
665 return ((StructData *)(char *)&Data)->Elts[i];
666 }
667 APValue &getStructField(unsigned i) {
668 assert(isStruct() && "Invalid accessor");
669 assert(i < getStructNumFields() && "field index OOB");
670 return ((StructData *)(char *)&Data)->Elts[getStructNumBases() + i];
671 }
672 const APValue &getStructBase(unsigned i) const {
673 return const_cast<APValue*>(this)->getStructBase(i);
674 }
675 const APValue &getStructField(unsigned i) const {
676 return const_cast<APValue*>(this)->getStructField(i);
677 }
678
679 const FieldDecl *getUnionField() const {
680 assert(isUnion() && "Invalid accessor");
681 return ((const UnionData *)(const char *)&Data)->Field;
682 }
683 APValue &getUnionValue() {
684 assert(isUnion() && "Invalid accessor");
685 return *((UnionData *)(char *)&Data)->Value;
686 }
687 const APValue &getUnionValue() const {
688 return const_cast<APValue*>(this)->getUnionValue();
689 }
690
691 const ValueDecl *getMemberPointerDecl() const;
692 bool isMemberPointerToDerivedMember() const;
693 ArrayRef<const CXXRecordDecl*> getMemberPointerPath() const;
694
695 const AddrLabelExpr* getAddrLabelDiffLHS() const {
696 assert(isAddrLabelDiff() && "Invalid accessor");
697 return ((const AddrLabelDiffData *)(const char *)&Data)->LHSExpr;
698 }
699 const AddrLabelExpr* getAddrLabelDiffRHS() const {
700 assert(isAddrLabelDiff() && "Invalid accessor");
701 return ((const AddrLabelDiffData *)(const char *)&Data)->RHSExpr;
702 }
703
704 void setInt(APSInt I) {
705 assert(isInt() && "Invalid accessor");
706 *(APSInt *)(char *)&Data = std::move(I);
707 }
708 void setFloat(APFloat F) {
709 assert(isFloat() && "Invalid accessor");
710 *(APFloat *)(char *)&Data = std::move(F);
711 }
712 void setFixedPoint(APFixedPoint FX) {
713 assert(isFixedPoint() && "Invalid accessor");
714 *(APFixedPoint *)(char *)&Data = std::move(FX);
715 }
716 void setVector(const APValue *E, unsigned N) {
717 MutableArrayRef<APValue> InternalElts = setVectorUninit(N);
718 for (unsigned i = 0; i != N; ++i)
719 InternalElts[i] = E[i];
720 }
721 void setMatrix(const APValue *E, unsigned NumRows, unsigned NumCols) {
722 MutableArrayRef<APValue> InternalElts = setMatrixUninit(NumRows, NumCols);
723 for (unsigned i = 0; i != NumRows * NumCols; ++i)
724 InternalElts[i] = E[i];
725 }
726 void setComplexInt(APSInt R, APSInt I) {
727 assert(R.getBitWidth() == I.getBitWidth() &&
728 "Invalid complex int (type mismatch).");
729 assert(isComplexInt() && "Invalid accessor");
730 ((ComplexAPSInt *)(char *)&Data)->Real = std::move(R);
731 ((ComplexAPSInt *)(char *)&Data)->Imag = std::move(I);
732 }
733 void setComplexFloat(APFloat R, APFloat I) {
734 assert(&R.getSemantics() == &I.getSemantics() &&
735 "Invalid complex float (type mismatch).");
736 assert(isComplexFloat() && "Invalid accessor");
737 ((ComplexAPFloat *)(char *)&Data)->Real = std::move(R);
738 ((ComplexAPFloat *)(char *)&Data)->Imag = std::move(I);
739 }
740 void setLValue(LValueBase B, const CharUnits &O, NoLValuePath,
741 bool IsNullPtr);
742 void setLValue(LValueBase B, const CharUnits &O,
743 ArrayRef<LValuePathEntry> Path, bool OnePastTheEnd,
744 bool IsNullPtr);
745 void setUnion(const FieldDecl *Field, const APValue &Value);
746 void setAddrLabelDiff(const AddrLabelExpr* LHSExpr,
747 const AddrLabelExpr* RHSExpr) {
748 ((AddrLabelDiffData *)(char *)&Data)->LHSExpr = LHSExpr;
749 ((AddrLabelDiffData *)(char *)&Data)->RHSExpr = RHSExpr;
750 }
751
752private:
753 void DestroyDataAndMakeUninit();
754 void MakeInt() {
755 assert(isAbsent() && "Bad state change");
756 new ((void *)&Data) APSInt(1);
757 Kind = Int;
758 }
759 void MakeFloat() {
760 assert(isAbsent() && "Bad state change");
761 new ((void *)(char *)&Data) APFloat(0.0);
762 Kind = Float;
763 }
764 void MakeFixedPoint(APFixedPoint &&FX) {
765 assert(isAbsent() && "Bad state change");
766 new ((void *)(char *)&Data) APFixedPoint(std::move(FX));
767 Kind = FixedPoint;
768 }
769 void MakeVector() {
770 assert(isAbsent() && "Bad state change");
771 new ((void *)(char *)&Data) Vec();
772 Kind = Vector;
773 }
774 void MakeMatrix() {
775 assert(isAbsent() && "Bad state change");
776 new ((void *)(char *)&Data) Mat();
777 Kind = Matrix;
778 }
779 void MakeComplexInt() {
780 assert(isAbsent() && "Bad state change");
781 new ((void *)(char *)&Data) ComplexAPSInt();
782 Kind = ComplexInt;
783 }
784 void MakeComplexFloat() {
785 assert(isAbsent() && "Bad state change");
786 new ((void *)(char *)&Data) ComplexAPFloat();
787 Kind = ComplexFloat;
788 }
789 void MakeLValue();
790 void MakeArray(unsigned InitElts, unsigned Size);
791 void MakeStruct(unsigned B, unsigned M) {
792 assert(isAbsent() && "Bad state change");
793 new ((void *)(char *)&Data) StructData(B, M);
794 Kind = Struct;
795 }
796 void MakeUnion() {
797 assert(isAbsent() && "Bad state change");
798 new ((void *)(char *)&Data) UnionData();
799 Kind = Union;
800 }
801 void MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
802 ArrayRef<const CXXRecordDecl*> Path);
803 void MakeAddrLabelDiff() {
804 assert(isAbsent() && "Bad state change");
805 new ((void *)(char *)&Data) AddrLabelDiffData();
806 Kind = AddrLabelDiff;
807 }
808
809private:
810 /// The following functions are used as part of initialization, during
811 /// deserialization and importing. Reserve the space so that it can be
812 /// filled in by those steps.
813 MutableArrayRef<APValue> setVectorUninit(unsigned N) {
814 assert(isVector() && "Invalid accessor");
815 Vec *V = ((Vec *)(char *)&Data);
816 V->Elts = new APValue[N];
817 V->NumElts = N;
818 return {V->Elts, V->NumElts};
819 }
820 MutableArrayRef<APValue> setMatrixUninit(unsigned NumRows, unsigned NumCols) {
821 assert(isMatrix() && "Invalid accessor");
822 Mat *M = ((Mat *)(char *)&Data);
823 unsigned NumElts = NumRows * NumCols;
824 M->Elts = new APValue[NumElts];
825 M->NumRows = NumRows;
826 M->NumCols = NumCols;
827 return {M->Elts, NumElts};
828 }
829 MutableArrayRef<LValuePathEntry>
830 setLValueUninit(LValueBase B, const CharUnits &O, unsigned Size,
831 bool OnePastTheEnd, bool IsNullPtr);
832 MutableArrayRef<const CXXRecordDecl *>
833 setMemberPointerUninit(const ValueDecl *Member, bool IsDerivedMember,
834 unsigned Size);
835};
836
837} // end namespace clang.
838
839namespace llvm {
840template<> struct DenseMapInfo<clang::APValue::LValueBase> {
841 static clang::APValue::LValueBase getEmptyKey();
842 static clang::APValue::LValueBase getTombstoneKey();
843 static unsigned getHashValue(const clang::APValue::LValueBase &Base);
844 static bool isEqual(const clang::APValue::LValueBase &LHS,
845 const clang::APValue::LValueBase &RHS);
846};
847}
848
849#endif
850