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/FixedPoint.h"
17 #include "clang/Basic/LLVM.h"
18 #include "llvm/ADT/APFloat.h"
19 #include "llvm/ADT/APSInt.h"
20 #include "llvm/ADT/PointerIntPair.h"
21 #include "llvm/ADT/PointerUnion.h"
29 class DiagnosticBuilder;
32 struct PrintingPolicy;
36 /// Symbolic representation of typeid(T) for some type T.
37 class TypeInfoLValue {
41 TypeInfoLValue() : T() {}
42 explicit TypeInfoLValue(const Type *T);
44 const Type *getType() const { return T; }
45 explicit operator bool() const { return T; }
47 void *getOpaqueValue() { return const_cast<Type*>(T); }
48 static TypeInfoLValue getFromOpaqueValue(void *Value) {
50 V.T = reinterpret_cast<const Type*>(Value);
54 void print(llvm::raw_ostream &Out, const PrintingPolicy &Policy) const;
57 /// Symbolic representation of a dynamic allocation.
58 class DynamicAllocLValue {
62 DynamicAllocLValue() : Index(0) {}
63 explicit DynamicAllocLValue(unsigned Index) : Index(Index + 1) {}
64 unsigned getIndex() { return Index - 1; }
66 explicit operator bool() const { return Index != 0; }
68 void *getOpaqueValue() {
69 return reinterpret_cast<void *>(static_cast<uintptr_t>(Index)
70 << NumLowBitsAvailable);
72 static DynamicAllocLValue getFromOpaqueValue(void *Value) {
74 V.Index = reinterpret_cast<uintptr_t>(Value) >> NumLowBitsAvailable;
78 static unsigned getMaxIndex() {
79 return (std::numeric_limits<unsigned>::max() >> NumLowBitsAvailable) - 1;
82 static constexpr int NumLowBitsAvailable = 3;
87 template<> struct PointerLikeTypeTraits<clang::TypeInfoLValue> {
88 static void *getAsVoidPointer(clang::TypeInfoLValue V) {
89 return V.getOpaqueValue();
91 static clang::TypeInfoLValue getFromVoidPointer(void *P) {
92 return clang::TypeInfoLValue::getFromOpaqueValue(P);
94 // Validated by static_assert in APValue.cpp; hardcoded to avoid needing
96 static constexpr int NumLowBitsAvailable = 3;
99 template<> struct PointerLikeTypeTraits<clang::DynamicAllocLValue> {
100 static void *getAsVoidPointer(clang::DynamicAllocLValue V) {
101 return V.getOpaqueValue();
103 static clang::DynamicAllocLValue getFromVoidPointer(void *P) {
104 return clang::DynamicAllocLValue::getFromOpaqueValue(P);
106 static constexpr int NumLowBitsAvailable =
107 clang::DynamicAllocLValue::NumLowBitsAvailable;
112 /// APValue - This class implements a discriminated union of [uninitialized]
113 /// [APSInt] [APFloat], [Complex APSInt] [Complex APFloat], [Expr + Offset],
114 /// [Vector: N * APValue], [Array: N * APValue]
116 typedef llvm::APSInt APSInt;
117 typedef llvm::APFloat APFloat;
120 /// There is no such object (it's outside its lifetime).
122 /// This object has an indeterminate value (C++ [basic.indet]).
139 typedef llvm::PointerUnion<const ValueDecl *, const Expr *, TypeInfoLValue,
144 LValueBase() : Local{} {}
145 LValueBase(const ValueDecl *P, unsigned I = 0, unsigned V = 0);
146 LValueBase(const Expr *P, unsigned I = 0, unsigned V = 0);
147 static LValueBase getDynamicAlloc(DynamicAllocLValue LV, QualType Type);
148 static LValueBase getTypeInfo(TypeInfoLValue LV, QualType TypeInfo);
151 bool is() const { return Ptr.is<T>(); }
154 T get() const { return Ptr.get<T>(); }
157 T dyn_cast() const { return Ptr.dyn_cast<T>(); }
159 void *getOpaqueValue() const;
163 explicit operator bool() const;
165 unsigned getCallIndex() const;
166 unsigned getVersion() const;
167 QualType getTypeInfoType() const;
168 QualType getDynamicAllocType() const;
170 friend bool operator==(const LValueBase &LHS, const LValueBase &RHS);
171 friend bool operator!=(const LValueBase &LHS, const LValueBase &RHS) {
172 return !(LHS == RHS);
174 friend llvm::hash_code hash_value(const LValueBase &Base);
179 unsigned CallIndex, Version;
183 /// The type std::type_info, if this is a TypeInfoLValue.
185 /// The QualType, if this is a DynamicAllocLValue.
186 void *DynamicAllocType;
190 /// A FieldDecl or CXXRecordDecl, along with a flag indicating whether we
191 /// mean a virtual or non-virtual base class subobject.
192 typedef llvm::PointerIntPair<const Decl *, 1, bool> BaseOrMemberType;
194 /// A non-discriminated union of a base, field, or array index.
195 class LValuePathEntry {
196 static_assert(sizeof(uintptr_t) <= sizeof(uint64_t),
197 "pointer doesn't fit in 64 bits?");
201 LValuePathEntry() : Value() {}
202 LValuePathEntry(BaseOrMemberType BaseOrMember)
203 : Value{reinterpret_cast<uintptr_t>(BaseOrMember.getOpaqueValue())} {}
204 static LValuePathEntry ArrayIndex(uint64_t Index) {
205 LValuePathEntry Result;
206 Result.Value = Index;
210 BaseOrMemberType getAsBaseOrMember() const {
211 return BaseOrMemberType::getFromOpaqueValue(
212 reinterpret_cast<void *>(Value));
214 uint64_t getAsArrayIndex() const { return Value; }
216 friend bool operator==(LValuePathEntry A, LValuePathEntry B) {
217 return A.Value == B.Value;
219 friend bool operator!=(LValuePathEntry A, LValuePathEntry B) {
220 return A.Value != B.Value;
222 friend llvm::hash_code hash_value(LValuePathEntry A) {
223 return llvm::hash_value(A.Value);
226 struct NoLValuePath {};
227 struct UninitArray {};
228 struct UninitStruct {};
230 friend class ASTReader;
231 friend class ASTWriter;
236 struct ComplexAPSInt {
238 ComplexAPSInt() : Real(1), Imag(1) {}
240 struct ComplexAPFloat {
242 ComplexAPFloat() : Real(0.0), Imag(0.0) {}
248 Vec() : Elts(nullptr), NumElts(0) {}
249 ~Vec() { delete[] Elts; }
253 unsigned NumElts, ArrSize;
254 Arr(unsigned NumElts, unsigned ArrSize);
261 StructData(unsigned NumBases, unsigned NumFields);
265 const FieldDecl *Field;
270 struct AddrLabelDiffData {
271 const AddrLabelExpr* LHSExpr;
272 const AddrLabelExpr* RHSExpr;
274 struct MemberPointerData;
276 // We ensure elsewhere that Data is big enough for LV and MemberPointerData.
277 typedef llvm::AlignedCharArrayUnion<void *, APSInt, APFloat, ComplexAPSInt,
278 ComplexAPFloat, Vec, Arr, StructData,
279 UnionData, AddrLabelDiffData> DataType;
280 static const size_t DataSize = sizeof(DataType);
285 APValue() : Kind(None) {}
286 explicit APValue(APSInt I) : Kind(None) {
287 MakeInt(); setInt(std::move(I));
289 explicit APValue(APFloat F) : Kind(None) {
290 MakeFloat(); setFloat(std::move(F));
292 explicit APValue(APFixedPoint FX) : Kind(None) {
293 MakeFixedPoint(std::move(FX));
295 explicit APValue(const APValue *E, unsigned N) : Kind(None) {
296 MakeVector(); setVector(E, N);
298 APValue(APSInt R, APSInt I) : Kind(None) {
299 MakeComplexInt(); setComplexInt(std::move(R), std::move(I));
301 APValue(APFloat R, APFloat I) : Kind(None) {
302 MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I));
304 APValue(const APValue &RHS);
305 APValue(APValue &&RHS) : Kind(None) { swap(RHS); }
306 APValue(LValueBase B, const CharUnits &O, NoLValuePath N,
307 bool IsNullPtr = false)
309 MakeLValue(); setLValue(B, O, N, IsNullPtr);
311 APValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path,
312 bool OnePastTheEnd, bool IsNullPtr = false)
314 MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, IsNullPtr);
316 APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(None) {
317 MakeArray(InitElts, Size);
319 APValue(UninitStruct, unsigned B, unsigned M) : Kind(None) {
322 explicit APValue(const FieldDecl *D, const APValue &V = APValue())
324 MakeUnion(); setUnion(D, V);
326 APValue(const ValueDecl *Member, bool IsDerivedMember,
327 ArrayRef<const CXXRecordDecl*> Path) : Kind(None) {
328 MakeMemberPointer(Member, IsDerivedMember, Path);
330 APValue(const AddrLabelExpr* LHSExpr, const AddrLabelExpr* RHSExpr)
332 MakeAddrLabelDiff(); setAddrLabelDiff(LHSExpr, RHSExpr);
334 static APValue IndeterminateValue() {
336 Result.Kind = Indeterminate;
341 if (Kind != None && Kind != Indeterminate)
342 DestroyDataAndMakeUninit();
345 /// Returns whether the object performed allocations.
347 /// If APValues are constructed via placement new, \c needsCleanup()
348 /// indicates whether the destructor must be called in order to correctly
349 /// free all allocated memory.
350 bool needsCleanup() const;
352 /// Swaps the contents of this and the given APValue.
353 void swap(APValue &RHS);
355 ValueKind getKind() const { return Kind; }
357 bool isAbsent() const { return Kind == None; }
358 bool isIndeterminate() const { return Kind == Indeterminate; }
359 bool hasValue() const { return Kind != None && Kind != Indeterminate; }
361 bool isInt() const { return Kind == Int; }
362 bool isFloat() const { return Kind == Float; }
363 bool isFixedPoint() const { return Kind == FixedPoint; }
364 bool isComplexInt() const { return Kind == ComplexInt; }
365 bool isComplexFloat() const { return Kind == ComplexFloat; }
366 bool isLValue() const { return Kind == LValue; }
367 bool isVector() const { return Kind == Vector; }
368 bool isArray() const { return Kind == Array; }
369 bool isStruct() const { return Kind == Struct; }
370 bool isUnion() const { return Kind == Union; }
371 bool isMemberPointer() const { return Kind == MemberPointer; }
372 bool isAddrLabelDiff() const { return Kind == AddrLabelDiff; }
375 void dump(raw_ostream &OS) const;
377 void printPretty(raw_ostream &OS, const ASTContext &Ctx, QualType Ty) const;
378 std::string getAsString(const ASTContext &Ctx, QualType Ty) const;
381 assert(isInt() && "Invalid accessor");
382 return *(APSInt*)(char*)Data.buffer;
384 const APSInt &getInt() const {
385 return const_cast<APValue*>(this)->getInt();
388 /// Try to convert this value to an integral constant. This works if it's an
389 /// integer, null pointer, or offset from a null pointer. Returns true on
391 bool toIntegralConstant(APSInt &Result, QualType SrcTy,
392 const ASTContext &Ctx) const;
394 APFloat &getFloat() {
395 assert(isFloat() && "Invalid accessor");
396 return *(APFloat*)(char*)Data.buffer;
398 const APFloat &getFloat() const {
399 return const_cast<APValue*>(this)->getFloat();
402 APFixedPoint &getFixedPoint() {
403 assert(isFixedPoint() && "Invalid accessor");
404 return *(APFixedPoint *)(char *)Data.buffer;
406 const APFixedPoint &getFixedPoint() const {
407 return const_cast<APValue *>(this)->getFixedPoint();
410 APSInt &getComplexIntReal() {
411 assert(isComplexInt() && "Invalid accessor");
412 return ((ComplexAPSInt*)(char*)Data.buffer)->Real;
414 const APSInt &getComplexIntReal() const {
415 return const_cast<APValue*>(this)->getComplexIntReal();
418 APSInt &getComplexIntImag() {
419 assert(isComplexInt() && "Invalid accessor");
420 return ((ComplexAPSInt*)(char*)Data.buffer)->Imag;
422 const APSInt &getComplexIntImag() const {
423 return const_cast<APValue*>(this)->getComplexIntImag();
426 APFloat &getComplexFloatReal() {
427 assert(isComplexFloat() && "Invalid accessor");
428 return ((ComplexAPFloat*)(char*)Data.buffer)->Real;
430 const APFloat &getComplexFloatReal() const {
431 return const_cast<APValue*>(this)->getComplexFloatReal();
434 APFloat &getComplexFloatImag() {
435 assert(isComplexFloat() && "Invalid accessor");
436 return ((ComplexAPFloat*)(char*)Data.buffer)->Imag;
438 const APFloat &getComplexFloatImag() const {
439 return const_cast<APValue*>(this)->getComplexFloatImag();
442 const LValueBase getLValueBase() const;
443 CharUnits &getLValueOffset();
444 const CharUnits &getLValueOffset() const {
445 return const_cast<APValue*>(this)->getLValueOffset();
447 bool isLValueOnePastTheEnd() const;
448 bool hasLValuePath() const;
449 ArrayRef<LValuePathEntry> getLValuePath() const;
450 unsigned getLValueCallIndex() const;
451 unsigned getLValueVersion() const;
452 bool isNullPointer() const;
454 APValue &getVectorElt(unsigned I) {
455 assert(isVector() && "Invalid accessor");
456 assert(I < getVectorLength() && "Index out of range");
457 return ((Vec*)(char*)Data.buffer)->Elts[I];
459 const APValue &getVectorElt(unsigned I) const {
460 return const_cast<APValue*>(this)->getVectorElt(I);
462 unsigned getVectorLength() const {
463 assert(isVector() && "Invalid accessor");
464 return ((const Vec*)(const void *)Data.buffer)->NumElts;
467 APValue &getArrayInitializedElt(unsigned I) {
468 assert(isArray() && "Invalid accessor");
469 assert(I < getArrayInitializedElts() && "Index out of range");
470 return ((Arr*)(char*)Data.buffer)->Elts[I];
472 const APValue &getArrayInitializedElt(unsigned I) const {
473 return const_cast<APValue*>(this)->getArrayInitializedElt(I);
475 bool hasArrayFiller() const {
476 return getArrayInitializedElts() != getArraySize();
478 APValue &getArrayFiller() {
479 assert(isArray() && "Invalid accessor");
480 assert(hasArrayFiller() && "No array filler");
481 return ((Arr*)(char*)Data.buffer)->Elts[getArrayInitializedElts()];
483 const APValue &getArrayFiller() const {
484 return const_cast<APValue*>(this)->getArrayFiller();
486 unsigned getArrayInitializedElts() const {
487 assert(isArray() && "Invalid accessor");
488 return ((const Arr*)(const void *)Data.buffer)->NumElts;
490 unsigned getArraySize() const {
491 assert(isArray() && "Invalid accessor");
492 return ((const Arr*)(const void *)Data.buffer)->ArrSize;
495 unsigned getStructNumBases() const {
496 assert(isStruct() && "Invalid accessor");
497 return ((const StructData*)(const char*)Data.buffer)->NumBases;
499 unsigned getStructNumFields() const {
500 assert(isStruct() && "Invalid accessor");
501 return ((const StructData*)(const char*)Data.buffer)->NumFields;
503 APValue &getStructBase(unsigned i) {
504 assert(isStruct() && "Invalid accessor");
505 return ((StructData*)(char*)Data.buffer)->Elts[i];
507 APValue &getStructField(unsigned i) {
508 assert(isStruct() && "Invalid accessor");
509 return ((StructData*)(char*)Data.buffer)->Elts[getStructNumBases() + i];
511 const APValue &getStructBase(unsigned i) const {
512 return const_cast<APValue*>(this)->getStructBase(i);
514 const APValue &getStructField(unsigned i) const {
515 return const_cast<APValue*>(this)->getStructField(i);
518 const FieldDecl *getUnionField() const {
519 assert(isUnion() && "Invalid accessor");
520 return ((const UnionData*)(const char*)Data.buffer)->Field;
522 APValue &getUnionValue() {
523 assert(isUnion() && "Invalid accessor");
524 return *((UnionData*)(char*)Data.buffer)->Value;
526 const APValue &getUnionValue() const {
527 return const_cast<APValue*>(this)->getUnionValue();
530 const ValueDecl *getMemberPointerDecl() const;
531 bool isMemberPointerToDerivedMember() const;
532 ArrayRef<const CXXRecordDecl*> getMemberPointerPath() const;
534 const AddrLabelExpr* getAddrLabelDiffLHS() const {
535 assert(isAddrLabelDiff() && "Invalid accessor");
536 return ((const AddrLabelDiffData*)(const char*)Data.buffer)->LHSExpr;
538 const AddrLabelExpr* getAddrLabelDiffRHS() const {
539 assert(isAddrLabelDiff() && "Invalid accessor");
540 return ((const AddrLabelDiffData*)(const char*)Data.buffer)->RHSExpr;
543 void setInt(APSInt I) {
544 assert(isInt() && "Invalid accessor");
545 *(APSInt *)(char *)Data.buffer = std::move(I);
547 void setFloat(APFloat F) {
548 assert(isFloat() && "Invalid accessor");
549 *(APFloat *)(char *)Data.buffer = std::move(F);
551 void setFixedPoint(APFixedPoint FX) {
552 assert(isFixedPoint() && "Invalid accessor");
553 *(APFixedPoint *)(char *)Data.buffer = std::move(FX);
555 void setVector(const APValue *E, unsigned N) {
556 assert(isVector() && "Invalid accessor");
557 ((Vec*)(char*)Data.buffer)->Elts = new APValue[N];
558 ((Vec*)(char*)Data.buffer)->NumElts = N;
559 for (unsigned i = 0; i != N; ++i)
560 ((Vec*)(char*)Data.buffer)->Elts[i] = E[i];
562 void setComplexInt(APSInt R, APSInt I) {
563 assert(R.getBitWidth() == I.getBitWidth() &&
564 "Invalid complex int (type mismatch).");
565 assert(isComplexInt() && "Invalid accessor");
566 ((ComplexAPSInt *)(char *)Data.buffer)->Real = std::move(R);
567 ((ComplexAPSInt *)(char *)Data.buffer)->Imag = std::move(I);
569 void setComplexFloat(APFloat R, APFloat I) {
570 assert(&R.getSemantics() == &I.getSemantics() &&
571 "Invalid complex float (type mismatch).");
572 assert(isComplexFloat() && "Invalid accessor");
573 ((ComplexAPFloat *)(char *)Data.buffer)->Real = std::move(R);
574 ((ComplexAPFloat *)(char *)Data.buffer)->Imag = std::move(I);
576 void setLValue(LValueBase B, const CharUnits &O, NoLValuePath,
578 void setLValue(LValueBase B, const CharUnits &O,
579 ArrayRef<LValuePathEntry> Path, bool OnePastTheEnd,
581 void setUnion(const FieldDecl *Field, const APValue &Value) {
582 assert(isUnion() && "Invalid accessor");
583 ((UnionData*)(char*)Data.buffer)->Field = Field;
584 *((UnionData*)(char*)Data.buffer)->Value = Value;
586 void setAddrLabelDiff(const AddrLabelExpr* LHSExpr,
587 const AddrLabelExpr* RHSExpr) {
588 ((AddrLabelDiffData*)(char*)Data.buffer)->LHSExpr = LHSExpr;
589 ((AddrLabelDiffData*)(char*)Data.buffer)->RHSExpr = RHSExpr;
592 /// Assign by swapping from a copy of the RHS.
593 APValue &operator=(APValue RHS) {
599 void DestroyDataAndMakeUninit();
601 assert(isAbsent() && "Bad state change");
602 new ((void*)Data.buffer) APSInt(1);
606 assert(isAbsent() && "Bad state change");
607 new ((void*)(char*)Data.buffer) APFloat(0.0);
610 void MakeFixedPoint(APFixedPoint &&FX) {
611 assert(isAbsent() && "Bad state change");
612 new ((void *)(char *)Data.buffer) APFixedPoint(std::move(FX));
616 assert(isAbsent() && "Bad state change");
617 new ((void*)(char*)Data.buffer) Vec();
620 void MakeComplexInt() {
621 assert(isAbsent() && "Bad state change");
622 new ((void*)(char*)Data.buffer) ComplexAPSInt();
625 void MakeComplexFloat() {
626 assert(isAbsent() && "Bad state change");
627 new ((void*)(char*)Data.buffer) ComplexAPFloat();
631 void MakeArray(unsigned InitElts, unsigned Size);
632 void MakeStruct(unsigned B, unsigned M) {
633 assert(isAbsent() && "Bad state change");
634 new ((void*)(char*)Data.buffer) StructData(B, M);
638 assert(isAbsent() && "Bad state change");
639 new ((void*)(char*)Data.buffer) UnionData();
642 void MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
643 ArrayRef<const CXXRecordDecl*> Path);
644 void MakeAddrLabelDiff() {
645 assert(isAbsent() && "Bad state change");
646 new ((void*)(char*)Data.buffer) AddrLabelDiffData();
647 Kind = AddrLabelDiff;
651 } // end namespace clang.
654 template<> struct DenseMapInfo<clang::APValue::LValueBase> {
655 static clang::APValue::LValueBase getEmptyKey();
656 static clang::APValue::LValueBase getTombstoneKey();
657 static unsigned getHashValue(const clang::APValue::LValueBase &Base);
658 static bool isEqual(const clang::APValue::LValueBase &LHS,
659 const clang::APValue::LValueBase &RHS);