1 //===--- APValue.h - Union class for APFloat/APSInt/Complex -----*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // This file defines the APValue class.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_CLANG_AST_APVALUE_H
14 #define LLVM_CLANG_AST_APVALUE_H
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"
26 namespace serialization {
27 template <typename T> class BasicReaderBase;
28 } // end namespace serialization
35 class DiagnosticBuilder;
38 struct PrintingPolicy;
43 /// Symbolic representation of typeid(T) for some type T.
44 class TypeInfoLValue {
48 TypeInfoLValue() : T() {}
49 explicit TypeInfoLValue(const Type *T);
51 const Type *getType() const { return T; }
52 explicit operator bool() const { return T; }
54 void *getOpaqueValue() { return const_cast<Type*>(T); }
55 static TypeInfoLValue getFromOpaqueValue(void *Value) {
57 V.T = reinterpret_cast<const Type*>(Value);
61 void print(llvm::raw_ostream &Out, const PrintingPolicy &Policy) const;
64 /// Symbolic representation of a dynamic allocation.
65 class DynamicAllocLValue {
69 DynamicAllocLValue() : Index(0) {}
70 explicit DynamicAllocLValue(unsigned Index) : Index(Index + 1) {}
71 unsigned getIndex() { return Index - 1; }
73 explicit operator bool() const { return Index != 0; }
75 void *getOpaqueValue() {
76 return reinterpret_cast<void *>(static_cast<uintptr_t>(Index)
77 << NumLowBitsAvailable);
79 static DynamicAllocLValue getFromOpaqueValue(void *Value) {
81 V.Index = reinterpret_cast<uintptr_t>(Value) >> NumLowBitsAvailable;
85 static unsigned getMaxIndex() {
86 return (std::numeric_limits<unsigned>::max() >> NumLowBitsAvailable) - 1;
89 static constexpr int NumLowBitsAvailable = 3;
94 template<> struct PointerLikeTypeTraits<clang::TypeInfoLValue> {
95 static void *getAsVoidPointer(clang::TypeInfoLValue V) {
96 return V.getOpaqueValue();
98 static clang::TypeInfoLValue getFromVoidPointer(void *P) {
99 return clang::TypeInfoLValue::getFromOpaqueValue(P);
101 // Validated by static_assert in APValue.cpp; hardcoded to avoid needing
102 // to include Type.h.
103 static constexpr int NumLowBitsAvailable = 3;
106 template<> struct PointerLikeTypeTraits<clang::DynamicAllocLValue> {
107 static void *getAsVoidPointer(clang::DynamicAllocLValue V) {
108 return V.getOpaqueValue();
110 static clang::DynamicAllocLValue getFromVoidPointer(void *P) {
111 return clang::DynamicAllocLValue::getFromOpaqueValue(P);
113 static constexpr int NumLowBitsAvailable =
114 clang::DynamicAllocLValue::NumLowBitsAvailable;
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]
123 typedef llvm::APFixedPoint APFixedPoint;
124 typedef llvm::APSInt APSInt;
125 typedef llvm::APFloat APFloat;
128 /// There is no such object (it's outside its lifetime).
130 /// This object has an indeterminate value (C++ [basic.indet]).
147 typedef llvm::PointerUnion<const ValueDecl *, const Expr *, TypeInfoLValue,
152 LValueBase() : Local{} {}
153 LValueBase(const ValueDecl *P, unsigned I = 0, unsigned V = 0);
154 LValueBase(const Expr *P, unsigned I = 0, unsigned V = 0);
155 static LValueBase getDynamicAlloc(DynamicAllocLValue LV, QualType Type);
156 static LValueBase getTypeInfo(TypeInfoLValue LV, QualType TypeInfo);
158 void Profile(llvm::FoldingSetNodeID &ID) const;
161 bool is() const { return Ptr.is<T>(); }
164 T get() const { return Ptr.get<T>(); }
167 T dyn_cast() const { return Ptr.dyn_cast<T>(); }
169 void *getOpaqueValue() const;
173 explicit operator bool() const;
175 unsigned getCallIndex() const;
176 unsigned getVersion() const;
177 QualType getTypeInfoType() const;
178 QualType getDynamicAllocType() const;
180 QualType getType() const;
182 friend bool operator==(const LValueBase &LHS, const LValueBase &RHS);
183 friend bool operator!=(const LValueBase &LHS, const LValueBase &RHS) {
184 return !(LHS == RHS);
186 friend llvm::hash_code hash_value(const LValueBase &Base);
187 friend struct llvm::DenseMapInfo<LValueBase>;
192 unsigned CallIndex, Version;
196 /// The type std::type_info, if this is a TypeInfoLValue.
198 /// The QualType, if this is a DynamicAllocLValue.
199 void *DynamicAllocType;
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;
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?");
214 LValuePathEntry() : Value() {}
215 LValuePathEntry(BaseOrMemberType BaseOrMember);
216 static LValuePathEntry ArrayIndex(uint64_t Index) {
217 LValuePathEntry Result;
218 Result.Value = Index;
222 BaseOrMemberType getAsBaseOrMember() const {
223 return BaseOrMemberType::getFromOpaqueValue(
224 reinterpret_cast<void *>(Value));
226 uint64_t getAsArrayIndex() const { return Value; }
228 void Profile(llvm::FoldingSetNodeID &ID) const;
230 friend bool operator==(LValuePathEntry A, LValuePathEntry B) {
231 return A.Value == B.Value;
233 friend bool operator!=(LValuePathEntry A, LValuePathEntry B) {
234 return A.Value != B.Value;
236 friend llvm::hash_code hash_value(LValuePathEntry A) {
237 return llvm::hash_value(A.Value);
240 class LValuePathSerializationHelper {
244 ArrayRef<LValuePathEntry> Path;
246 LValuePathSerializationHelper(ArrayRef<LValuePathEntry>, QualType);
249 struct NoLValuePath {};
250 struct UninitArray {};
251 struct UninitStruct {};
253 template <typename Impl> friend class clang::serialization::BasicReaderBase;
254 friend class ASTImporter;
255 friend class ASTNodeImporter;
260 struct ComplexAPSInt {
262 ComplexAPSInt() : Real(1), Imag(1) {}
264 struct ComplexAPFloat {
266 ComplexAPFloat() : Real(0.0), Imag(0.0) {}
272 Vec() : Elts(nullptr), NumElts(0) {}
273 ~Vec() { delete[] Elts; }
277 unsigned NumElts, ArrSize;
278 Arr(unsigned NumElts, unsigned ArrSize);
285 StructData(unsigned NumBases, unsigned NumFields);
289 const FieldDecl *Field;
294 struct AddrLabelDiffData {
295 const AddrLabelExpr* LHSExpr;
296 const AddrLabelExpr* RHSExpr;
298 struct MemberPointerData;
300 // We ensure elsewhere that Data is big enough for LV and MemberPointerData.
301 typedef llvm::AlignedCharArrayUnion<void *, APSInt, APFloat, ComplexAPSInt,
302 ComplexAPFloat, Vec, Arr, StructData,
303 UnionData, AddrLabelDiffData> DataType;
304 static const size_t DataSize = sizeof(DataType);
309 APValue() : Kind(None) {}
310 explicit APValue(APSInt I) : Kind(None) {
311 MakeInt(); setInt(std::move(I));
313 explicit APValue(APFloat F) : Kind(None) {
314 MakeFloat(); setFloat(std::move(F));
316 explicit APValue(APFixedPoint FX) : Kind(None) {
317 MakeFixedPoint(std::move(FX));
319 explicit APValue(const APValue *E, unsigned N) : Kind(None) {
320 MakeVector(); setVector(E, N);
322 APValue(APSInt R, APSInt I) : Kind(None) {
323 MakeComplexInt(); setComplexInt(std::move(R), std::move(I));
325 APValue(APFloat R, APFloat I) : Kind(None) {
326 MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I));
328 APValue(const APValue &RHS);
329 APValue(APValue &&RHS);
330 APValue(LValueBase B, const CharUnits &O, NoLValuePath N,
331 bool IsNullPtr = false)
333 MakeLValue(); setLValue(B, O, N, IsNullPtr);
335 APValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path,
336 bool OnePastTheEnd, bool IsNullPtr = false)
338 MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, IsNullPtr);
340 APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(None) {
341 MakeArray(InitElts, Size);
343 APValue(UninitStruct, unsigned B, unsigned M) : Kind(None) {
346 explicit APValue(const FieldDecl *D, const APValue &V = APValue())
348 MakeUnion(); setUnion(D, V);
350 APValue(const ValueDecl *Member, bool IsDerivedMember,
351 ArrayRef<const CXXRecordDecl*> Path) : Kind(None) {
352 MakeMemberPointer(Member, IsDerivedMember, Path);
354 APValue(const AddrLabelExpr* LHSExpr, const AddrLabelExpr* RHSExpr)
356 MakeAddrLabelDiff(); setAddrLabelDiff(LHSExpr, RHSExpr);
358 static APValue IndeterminateValue() {
360 Result.Kind = Indeterminate;
364 APValue &operator=(const APValue &RHS);
365 APValue &operator=(APValue &&RHS);
368 if (Kind != None && Kind != Indeterminate)
369 DestroyDataAndMakeUninit();
372 /// Returns whether the object performed allocations.
374 /// If APValues are constructed via placement new, \c needsCleanup()
375 /// indicates whether the destructor must be called in order to correctly
376 /// free all allocated memory.
377 bool needsCleanup() const;
379 /// Swaps the contents of this and the given APValue.
380 void swap(APValue &RHS);
382 /// profile this value. There is no guarantee that values of different
383 /// types will not produce the same profiled value, so the type should
384 /// typically also be profiled if it's not implied by the context.
385 void Profile(llvm::FoldingSetNodeID &ID) const;
387 ValueKind getKind() const { return Kind; }
389 bool isAbsent() const { return Kind == None; }
390 bool isIndeterminate() const { return Kind == Indeterminate; }
391 bool hasValue() const { return Kind != None && Kind != Indeterminate; }
393 bool isInt() const { return Kind == Int; }
394 bool isFloat() const { return Kind == Float; }
395 bool isFixedPoint() const { return Kind == FixedPoint; }
396 bool isComplexInt() const { return Kind == ComplexInt; }
397 bool isComplexFloat() const { return Kind == ComplexFloat; }
398 bool isLValue() const { return Kind == LValue; }
399 bool isVector() const { return Kind == Vector; }
400 bool isArray() const { return Kind == Array; }
401 bool isStruct() const { return Kind == Struct; }
402 bool isUnion() const { return Kind == Union; }
403 bool isMemberPointer() const { return Kind == MemberPointer; }
404 bool isAddrLabelDiff() const { return Kind == AddrLabelDiff; }
407 void dump(raw_ostream &OS, const ASTContext &Context) const;
409 void printPretty(raw_ostream &OS, const ASTContext &Ctx, QualType Ty) const;
410 void printPretty(raw_ostream &OS, const PrintingPolicy &Policy, QualType Ty,
411 const ASTContext *Ctx = nullptr) const;
413 std::string getAsString(const ASTContext &Ctx, QualType Ty) const;
416 assert(isInt() && "Invalid accessor");
417 return *(APSInt *)(char *)&Data;
419 const APSInt &getInt() const {
420 return const_cast<APValue*>(this)->getInt();
423 /// Try to convert this value to an integral constant. This works if it's an
424 /// integer, null pointer, or offset from a null pointer. Returns true on
426 bool toIntegralConstant(APSInt &Result, QualType SrcTy,
427 const ASTContext &Ctx) const;
429 APFloat &getFloat() {
430 assert(isFloat() && "Invalid accessor");
431 return *(APFloat *)(char *)&Data;
433 const APFloat &getFloat() const {
434 return const_cast<APValue*>(this)->getFloat();
437 APFixedPoint &getFixedPoint() {
438 assert(isFixedPoint() && "Invalid accessor");
439 return *(APFixedPoint *)(char *)&Data;
441 const APFixedPoint &getFixedPoint() const {
442 return const_cast<APValue *>(this)->getFixedPoint();
445 APSInt &getComplexIntReal() {
446 assert(isComplexInt() && "Invalid accessor");
447 return ((ComplexAPSInt *)(char *)&Data)->Real;
449 const APSInt &getComplexIntReal() const {
450 return const_cast<APValue*>(this)->getComplexIntReal();
453 APSInt &getComplexIntImag() {
454 assert(isComplexInt() && "Invalid accessor");
455 return ((ComplexAPSInt *)(char *)&Data)->Imag;
457 const APSInt &getComplexIntImag() const {
458 return const_cast<APValue*>(this)->getComplexIntImag();
461 APFloat &getComplexFloatReal() {
462 assert(isComplexFloat() && "Invalid accessor");
463 return ((ComplexAPFloat *)(char *)&Data)->Real;
465 const APFloat &getComplexFloatReal() const {
466 return const_cast<APValue*>(this)->getComplexFloatReal();
469 APFloat &getComplexFloatImag() {
470 assert(isComplexFloat() && "Invalid accessor");
471 return ((ComplexAPFloat *)(char *)&Data)->Imag;
473 const APFloat &getComplexFloatImag() const {
474 return const_cast<APValue*>(this)->getComplexFloatImag();
477 const LValueBase getLValueBase() const;
478 CharUnits &getLValueOffset();
479 const CharUnits &getLValueOffset() const {
480 return const_cast<APValue*>(this)->getLValueOffset();
482 bool isLValueOnePastTheEnd() const;
483 bool hasLValuePath() const;
484 ArrayRef<LValuePathEntry> getLValuePath() const;
485 unsigned getLValueCallIndex() const;
486 unsigned getLValueVersion() const;
487 bool isNullPointer() const;
489 APValue &getVectorElt(unsigned I) {
490 assert(isVector() && "Invalid accessor");
491 assert(I < getVectorLength() && "Index out of range");
492 return ((Vec *)(char *)&Data)->Elts[I];
494 const APValue &getVectorElt(unsigned I) const {
495 return const_cast<APValue*>(this)->getVectorElt(I);
497 unsigned getVectorLength() const {
498 assert(isVector() && "Invalid accessor");
499 return ((const Vec *)(const void *)&Data)->NumElts;
502 APValue &getArrayInitializedElt(unsigned I) {
503 assert(isArray() && "Invalid accessor");
504 assert(I < getArrayInitializedElts() && "Index out of range");
505 return ((Arr *)(char *)&Data)->Elts[I];
507 const APValue &getArrayInitializedElt(unsigned I) const {
508 return const_cast<APValue*>(this)->getArrayInitializedElt(I);
510 bool hasArrayFiller() const {
511 return getArrayInitializedElts() != getArraySize();
513 APValue &getArrayFiller() {
514 assert(isArray() && "Invalid accessor");
515 assert(hasArrayFiller() && "No array filler");
516 return ((Arr *)(char *)&Data)->Elts[getArrayInitializedElts()];
518 const APValue &getArrayFiller() const {
519 return const_cast<APValue*>(this)->getArrayFiller();
521 unsigned getArrayInitializedElts() const {
522 assert(isArray() && "Invalid accessor");
523 return ((const Arr *)(const void *)&Data)->NumElts;
525 unsigned getArraySize() const {
526 assert(isArray() && "Invalid accessor");
527 return ((const Arr *)(const void *)&Data)->ArrSize;
530 unsigned getStructNumBases() const {
531 assert(isStruct() && "Invalid accessor");
532 return ((const StructData *)(const char *)&Data)->NumBases;
534 unsigned getStructNumFields() const {
535 assert(isStruct() && "Invalid accessor");
536 return ((const StructData *)(const char *)&Data)->NumFields;
538 APValue &getStructBase(unsigned i) {
539 assert(isStruct() && "Invalid accessor");
540 assert(i < getStructNumBases() && "base class index OOB");
541 return ((StructData *)(char *)&Data)->Elts[i];
543 APValue &getStructField(unsigned i) {
544 assert(isStruct() && "Invalid accessor");
545 assert(i < getStructNumFields() && "field index OOB");
546 return ((StructData *)(char *)&Data)->Elts[getStructNumBases() + i];
548 const APValue &getStructBase(unsigned i) const {
549 return const_cast<APValue*>(this)->getStructBase(i);
551 const APValue &getStructField(unsigned i) const {
552 return const_cast<APValue*>(this)->getStructField(i);
555 const FieldDecl *getUnionField() const {
556 assert(isUnion() && "Invalid accessor");
557 return ((const UnionData *)(const char *)&Data)->Field;
559 APValue &getUnionValue() {
560 assert(isUnion() && "Invalid accessor");
561 return *((UnionData *)(char *)&Data)->Value;
563 const APValue &getUnionValue() const {
564 return const_cast<APValue*>(this)->getUnionValue();
567 const ValueDecl *getMemberPointerDecl() const;
568 bool isMemberPointerToDerivedMember() const;
569 ArrayRef<const CXXRecordDecl*> getMemberPointerPath() const;
571 const AddrLabelExpr* getAddrLabelDiffLHS() const {
572 assert(isAddrLabelDiff() && "Invalid accessor");
573 return ((const AddrLabelDiffData *)(const char *)&Data)->LHSExpr;
575 const AddrLabelExpr* getAddrLabelDiffRHS() const {
576 assert(isAddrLabelDiff() && "Invalid accessor");
577 return ((const AddrLabelDiffData *)(const char *)&Data)->RHSExpr;
580 void setInt(APSInt I) {
581 assert(isInt() && "Invalid accessor");
582 *(APSInt *)(char *)&Data = std::move(I);
584 void setFloat(APFloat F) {
585 assert(isFloat() && "Invalid accessor");
586 *(APFloat *)(char *)&Data = std::move(F);
588 void setFixedPoint(APFixedPoint FX) {
589 assert(isFixedPoint() && "Invalid accessor");
590 *(APFixedPoint *)(char *)&Data = std::move(FX);
592 void setVector(const APValue *E, unsigned N) {
593 MutableArrayRef<APValue> InternalElts = setVectorUninit(N);
594 for (unsigned i = 0; i != N; ++i)
595 InternalElts[i] = E[i];
597 void setComplexInt(APSInt R, APSInt I) {
598 assert(R.getBitWidth() == I.getBitWidth() &&
599 "Invalid complex int (type mismatch).");
600 assert(isComplexInt() && "Invalid accessor");
601 ((ComplexAPSInt *)(char *)&Data)->Real = std::move(R);
602 ((ComplexAPSInt *)(char *)&Data)->Imag = std::move(I);
604 void setComplexFloat(APFloat R, APFloat I) {
605 assert(&R.getSemantics() == &I.getSemantics() &&
606 "Invalid complex float (type mismatch).");
607 assert(isComplexFloat() && "Invalid accessor");
608 ((ComplexAPFloat *)(char *)&Data)->Real = std::move(R);
609 ((ComplexAPFloat *)(char *)&Data)->Imag = std::move(I);
611 void setLValue(LValueBase B, const CharUnits &O, NoLValuePath,
613 void setLValue(LValueBase B, const CharUnits &O,
614 ArrayRef<LValuePathEntry> Path, bool OnePastTheEnd,
616 void setUnion(const FieldDecl *Field, const APValue &Value);
617 void setAddrLabelDiff(const AddrLabelExpr* LHSExpr,
618 const AddrLabelExpr* RHSExpr) {
619 ((AddrLabelDiffData *)(char *)&Data)->LHSExpr = LHSExpr;
620 ((AddrLabelDiffData *)(char *)&Data)->RHSExpr = RHSExpr;
624 void DestroyDataAndMakeUninit();
626 assert(isAbsent() && "Bad state change");
627 new ((void *)&Data) APSInt(1);
631 assert(isAbsent() && "Bad state change");
632 new ((void *)(char *)&Data) APFloat(0.0);
635 void MakeFixedPoint(APFixedPoint &&FX) {
636 assert(isAbsent() && "Bad state change");
637 new ((void *)(char *)&Data) APFixedPoint(std::move(FX));
641 assert(isAbsent() && "Bad state change");
642 new ((void *)(char *)&Data) Vec();
645 void MakeComplexInt() {
646 assert(isAbsent() && "Bad state change");
647 new ((void *)(char *)&Data) ComplexAPSInt();
650 void MakeComplexFloat() {
651 assert(isAbsent() && "Bad state change");
652 new ((void *)(char *)&Data) ComplexAPFloat();
656 void MakeArray(unsigned InitElts, unsigned Size);
657 void MakeStruct(unsigned B, unsigned M) {
658 assert(isAbsent() && "Bad state change");
659 new ((void *)(char *)&Data) StructData(B, M);
663 assert(isAbsent() && "Bad state change");
664 new ((void *)(char *)&Data) UnionData();
667 void MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
668 ArrayRef<const CXXRecordDecl*> Path);
669 void MakeAddrLabelDiff() {
670 assert(isAbsent() && "Bad state change");
671 new ((void *)(char *)&Data) AddrLabelDiffData();
672 Kind = AddrLabelDiff;
676 /// The following functions are used as part of initialization, during
677 /// deserialization and importing. Reserve the space so that it can be
678 /// filled in by those steps.
679 MutableArrayRef<APValue> setVectorUninit(unsigned N) {
680 assert(isVector() && "Invalid accessor");
681 Vec *V = ((Vec *)(char *)&Data);
682 V->Elts = new APValue[N];
684 return {V->Elts, V->NumElts};
686 MutableArrayRef<LValuePathEntry>
687 setLValueUninit(LValueBase B, const CharUnits &O, unsigned Size,
688 bool OnePastTheEnd, bool IsNullPtr);
689 MutableArrayRef<const CXXRecordDecl *>
690 setMemberPointerUninit(const ValueDecl *Member, bool IsDerivedMember,
694 } // end namespace clang.
697 template<> struct DenseMapInfo<clang::APValue::LValueBase> {
698 static clang::APValue::LValueBase getEmptyKey();
699 static clang::APValue::LValueBase getTombstoneKey();
700 static unsigned getHashValue(const clang::APValue::LValueBase &Base);
701 static bool isEqual(const clang::APValue::LValueBase &LHS,
702 const clang::APValue::LValueBase &RHS);