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;
59 template<> struct PointerLikeTypeTraits<clang::TypeInfoLValue> {
60 static void *getAsVoidPointer(clang::TypeInfoLValue V) {
61 return V.getOpaqueValue();
63 static clang::TypeInfoLValue getFromVoidPointer(void *P) {
64 return clang::TypeInfoLValue::getFromOpaqueValue(P);
66 // Validated by static_assert in APValue.cpp; hardcoded to avoid needing
68 static constexpr int NumLowBitsAvailable = 3;
73 /// APValue - This class implements a discriminated union of [uninitialized]
74 /// [APSInt] [APFloat], [Complex APSInt] [Complex APFloat], [Expr + Offset],
75 /// [Vector: N * APValue], [Array: N * APValue]
77 typedef llvm::APSInt APSInt;
78 typedef llvm::APFloat APFloat;
81 /// There is no such object (it's outside its lifetime).
83 /// This object has an indeterminate value (C++ [basic.indet]).
100 typedef llvm::PointerUnion<const ValueDecl *, const Expr *, TypeInfoLValue>
104 LValueBase() : Local{} {}
105 LValueBase(const ValueDecl *P, unsigned I = 0, unsigned V = 0);
106 LValueBase(const Expr *P, unsigned I = 0, unsigned V = 0);
107 static LValueBase getTypeInfo(TypeInfoLValue LV, QualType TypeInfo);
110 bool is() const { return Ptr.is<T>(); }
113 T get() const { return Ptr.get<T>(); }
116 T dyn_cast() const { return Ptr.dyn_cast<T>(); }
118 void *getOpaqueValue() const;
122 explicit operator bool() const;
124 unsigned getCallIndex() const;
125 unsigned getVersion() const;
126 QualType getTypeInfoType() const;
128 friend bool operator==(const LValueBase &LHS, const LValueBase &RHS);
129 friend bool operator!=(const LValueBase &LHS, const LValueBase &RHS) {
130 return !(LHS == RHS);
132 friend llvm::hash_code hash_value(const LValueBase &Base);
137 unsigned CallIndex, Version;
141 /// The type std::type_info, if this is a TypeInfoLValue.
146 /// A FieldDecl or CXXRecordDecl, along with a flag indicating whether we
147 /// mean a virtual or non-virtual base class subobject.
148 typedef llvm::PointerIntPair<const Decl *, 1, bool> BaseOrMemberType;
150 /// A non-discriminated union of a base, field, or array index.
151 class LValuePathEntry {
152 static_assert(sizeof(uintptr_t) <= sizeof(uint64_t),
153 "pointer doesn't fit in 64 bits?");
157 LValuePathEntry() : Value() {}
158 LValuePathEntry(BaseOrMemberType BaseOrMember)
159 : Value{reinterpret_cast<uintptr_t>(BaseOrMember.getOpaqueValue())} {}
160 static LValuePathEntry ArrayIndex(uint64_t Index) {
161 LValuePathEntry Result;
162 Result.Value = Index;
166 BaseOrMemberType getAsBaseOrMember() const {
167 return BaseOrMemberType::getFromOpaqueValue(
168 reinterpret_cast<void *>(Value));
170 uint64_t getAsArrayIndex() const { return Value; }
172 friend bool operator==(LValuePathEntry A, LValuePathEntry B) {
173 return A.Value == B.Value;
175 friend bool operator!=(LValuePathEntry A, LValuePathEntry B) {
176 return A.Value != B.Value;
178 friend llvm::hash_code hash_value(LValuePathEntry A) {
179 return llvm::hash_value(A.Value);
182 struct NoLValuePath {};
183 struct UninitArray {};
184 struct UninitStruct {};
186 friend class ASTReader;
187 friend class ASTWriter;
192 struct ComplexAPSInt {
194 ComplexAPSInt() : Real(1), Imag(1) {}
196 struct ComplexAPFloat {
198 ComplexAPFloat() : Real(0.0), Imag(0.0) {}
204 Vec() : Elts(nullptr), NumElts(0) {}
205 ~Vec() { delete[] Elts; }
209 unsigned NumElts, ArrSize;
210 Arr(unsigned NumElts, unsigned ArrSize);
217 StructData(unsigned NumBases, unsigned NumFields);
221 const FieldDecl *Field;
226 struct AddrLabelDiffData {
227 const AddrLabelExpr* LHSExpr;
228 const AddrLabelExpr* RHSExpr;
230 struct MemberPointerData;
232 // We ensure elsewhere that Data is big enough for LV and MemberPointerData.
233 typedef llvm::AlignedCharArrayUnion<void *, APSInt, APFloat, ComplexAPSInt,
234 ComplexAPFloat, Vec, Arr, StructData,
235 UnionData, AddrLabelDiffData> DataType;
236 static const size_t DataSize = sizeof(DataType);
241 APValue() : Kind(None) {}
242 explicit APValue(APSInt I) : Kind(None) {
243 MakeInt(); setInt(std::move(I));
245 explicit APValue(APFloat F) : Kind(None) {
246 MakeFloat(); setFloat(std::move(F));
248 explicit APValue(APFixedPoint FX) : Kind(None) {
249 MakeFixedPoint(std::move(FX));
251 explicit APValue(const APValue *E, unsigned N) : Kind(None) {
252 MakeVector(); setVector(E, N);
254 APValue(APSInt R, APSInt I) : Kind(None) {
255 MakeComplexInt(); setComplexInt(std::move(R), std::move(I));
257 APValue(APFloat R, APFloat I) : Kind(None) {
258 MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I));
260 APValue(const APValue &RHS);
261 APValue(APValue &&RHS) : Kind(None) { swap(RHS); }
262 APValue(LValueBase B, const CharUnits &O, NoLValuePath N,
263 bool IsNullPtr = false)
265 MakeLValue(); setLValue(B, O, N, IsNullPtr);
267 APValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path,
268 bool OnePastTheEnd, bool IsNullPtr = false)
270 MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, IsNullPtr);
272 APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(None) {
273 MakeArray(InitElts, Size);
275 APValue(UninitStruct, unsigned B, unsigned M) : Kind(None) {
278 explicit APValue(const FieldDecl *D, const APValue &V = APValue())
280 MakeUnion(); setUnion(D, V);
282 APValue(const ValueDecl *Member, bool IsDerivedMember,
283 ArrayRef<const CXXRecordDecl*> Path) : Kind(None) {
284 MakeMemberPointer(Member, IsDerivedMember, Path);
286 APValue(const AddrLabelExpr* LHSExpr, const AddrLabelExpr* RHSExpr)
288 MakeAddrLabelDiff(); setAddrLabelDiff(LHSExpr, RHSExpr);
290 static APValue IndeterminateValue() {
292 Result.Kind = Indeterminate;
297 if (Kind != None && Kind != Indeterminate)
298 DestroyDataAndMakeUninit();
301 /// Returns whether the object performed allocations.
303 /// If APValues are constructed via placement new, \c needsCleanup()
304 /// indicates whether the destructor must be called in order to correctly
305 /// free all allocated memory.
306 bool needsCleanup() const;
308 /// Swaps the contents of this and the given APValue.
309 void swap(APValue &RHS);
311 ValueKind getKind() const { return Kind; }
313 bool isAbsent() const { return Kind == None; }
314 bool isIndeterminate() const { return Kind == Indeterminate; }
315 bool hasValue() const { return Kind != None && Kind != Indeterminate; }
317 bool isInt() const { return Kind == Int; }
318 bool isFloat() const { return Kind == Float; }
319 bool isFixedPoint() const { return Kind == FixedPoint; }
320 bool isComplexInt() const { return Kind == ComplexInt; }
321 bool isComplexFloat() const { return Kind == ComplexFloat; }
322 bool isLValue() const { return Kind == LValue; }
323 bool isVector() const { return Kind == Vector; }
324 bool isArray() const { return Kind == Array; }
325 bool isStruct() const { return Kind == Struct; }
326 bool isUnion() const { return Kind == Union; }
327 bool isMemberPointer() const { return Kind == MemberPointer; }
328 bool isAddrLabelDiff() const { return Kind == AddrLabelDiff; }
331 void dump(raw_ostream &OS) const;
333 void printPretty(raw_ostream &OS, const ASTContext &Ctx, QualType Ty) const;
334 std::string getAsString(const ASTContext &Ctx, QualType Ty) const;
337 assert(isInt() && "Invalid accessor");
338 return *(APSInt*)(char*)Data.buffer;
340 const APSInt &getInt() const {
341 return const_cast<APValue*>(this)->getInt();
344 /// Try to convert this value to an integral constant. This works if it's an
345 /// integer, null pointer, or offset from a null pointer. Returns true on
347 bool toIntegralConstant(APSInt &Result, QualType SrcTy,
348 const ASTContext &Ctx) const;
350 APFloat &getFloat() {
351 assert(isFloat() && "Invalid accessor");
352 return *(APFloat*)(char*)Data.buffer;
354 const APFloat &getFloat() const {
355 return const_cast<APValue*>(this)->getFloat();
358 APFixedPoint &getFixedPoint() {
359 assert(isFixedPoint() && "Invalid accessor");
360 return *(APFixedPoint *)(char *)Data.buffer;
362 const APFixedPoint &getFixedPoint() const {
363 return const_cast<APValue *>(this)->getFixedPoint();
366 APSInt &getComplexIntReal() {
367 assert(isComplexInt() && "Invalid accessor");
368 return ((ComplexAPSInt*)(char*)Data.buffer)->Real;
370 const APSInt &getComplexIntReal() const {
371 return const_cast<APValue*>(this)->getComplexIntReal();
374 APSInt &getComplexIntImag() {
375 assert(isComplexInt() && "Invalid accessor");
376 return ((ComplexAPSInt*)(char*)Data.buffer)->Imag;
378 const APSInt &getComplexIntImag() const {
379 return const_cast<APValue*>(this)->getComplexIntImag();
382 APFloat &getComplexFloatReal() {
383 assert(isComplexFloat() && "Invalid accessor");
384 return ((ComplexAPFloat*)(char*)Data.buffer)->Real;
386 const APFloat &getComplexFloatReal() const {
387 return const_cast<APValue*>(this)->getComplexFloatReal();
390 APFloat &getComplexFloatImag() {
391 assert(isComplexFloat() && "Invalid accessor");
392 return ((ComplexAPFloat*)(char*)Data.buffer)->Imag;
394 const APFloat &getComplexFloatImag() const {
395 return const_cast<APValue*>(this)->getComplexFloatImag();
398 const LValueBase getLValueBase() const;
399 CharUnits &getLValueOffset();
400 const CharUnits &getLValueOffset() const {
401 return const_cast<APValue*>(this)->getLValueOffset();
403 bool isLValueOnePastTheEnd() const;
404 bool hasLValuePath() const;
405 ArrayRef<LValuePathEntry> getLValuePath() const;
406 unsigned getLValueCallIndex() const;
407 unsigned getLValueVersion() const;
408 bool isNullPointer() const;
410 APValue &getVectorElt(unsigned I) {
411 assert(isVector() && "Invalid accessor");
412 assert(I < getVectorLength() && "Index out of range");
413 return ((Vec*)(char*)Data.buffer)->Elts[I];
415 const APValue &getVectorElt(unsigned I) const {
416 return const_cast<APValue*>(this)->getVectorElt(I);
418 unsigned getVectorLength() const {
419 assert(isVector() && "Invalid accessor");
420 return ((const Vec*)(const void *)Data.buffer)->NumElts;
423 APValue &getArrayInitializedElt(unsigned I) {
424 assert(isArray() && "Invalid accessor");
425 assert(I < getArrayInitializedElts() && "Index out of range");
426 return ((Arr*)(char*)Data.buffer)->Elts[I];
428 const APValue &getArrayInitializedElt(unsigned I) const {
429 return const_cast<APValue*>(this)->getArrayInitializedElt(I);
431 bool hasArrayFiller() const {
432 return getArrayInitializedElts() != getArraySize();
434 APValue &getArrayFiller() {
435 assert(isArray() && "Invalid accessor");
436 assert(hasArrayFiller() && "No array filler");
437 return ((Arr*)(char*)Data.buffer)->Elts[getArrayInitializedElts()];
439 const APValue &getArrayFiller() const {
440 return const_cast<APValue*>(this)->getArrayFiller();
442 unsigned getArrayInitializedElts() const {
443 assert(isArray() && "Invalid accessor");
444 return ((const Arr*)(const void *)Data.buffer)->NumElts;
446 unsigned getArraySize() const {
447 assert(isArray() && "Invalid accessor");
448 return ((const Arr*)(const void *)Data.buffer)->ArrSize;
451 unsigned getStructNumBases() const {
452 assert(isStruct() && "Invalid accessor");
453 return ((const StructData*)(const char*)Data.buffer)->NumBases;
455 unsigned getStructNumFields() const {
456 assert(isStruct() && "Invalid accessor");
457 return ((const StructData*)(const char*)Data.buffer)->NumFields;
459 APValue &getStructBase(unsigned i) {
460 assert(isStruct() && "Invalid accessor");
461 return ((StructData*)(char*)Data.buffer)->Elts[i];
463 APValue &getStructField(unsigned i) {
464 assert(isStruct() && "Invalid accessor");
465 return ((StructData*)(char*)Data.buffer)->Elts[getStructNumBases() + i];
467 const APValue &getStructBase(unsigned i) const {
468 return const_cast<APValue*>(this)->getStructBase(i);
470 const APValue &getStructField(unsigned i) const {
471 return const_cast<APValue*>(this)->getStructField(i);
474 const FieldDecl *getUnionField() const {
475 assert(isUnion() && "Invalid accessor");
476 return ((const UnionData*)(const char*)Data.buffer)->Field;
478 APValue &getUnionValue() {
479 assert(isUnion() && "Invalid accessor");
480 return *((UnionData*)(char*)Data.buffer)->Value;
482 const APValue &getUnionValue() const {
483 return const_cast<APValue*>(this)->getUnionValue();
486 const ValueDecl *getMemberPointerDecl() const;
487 bool isMemberPointerToDerivedMember() const;
488 ArrayRef<const CXXRecordDecl*> getMemberPointerPath() const;
490 const AddrLabelExpr* getAddrLabelDiffLHS() const {
491 assert(isAddrLabelDiff() && "Invalid accessor");
492 return ((const AddrLabelDiffData*)(const char*)Data.buffer)->LHSExpr;
494 const AddrLabelExpr* getAddrLabelDiffRHS() const {
495 assert(isAddrLabelDiff() && "Invalid accessor");
496 return ((const AddrLabelDiffData*)(const char*)Data.buffer)->RHSExpr;
499 void setInt(APSInt I) {
500 assert(isInt() && "Invalid accessor");
501 *(APSInt *)(char *)Data.buffer = std::move(I);
503 void setFloat(APFloat F) {
504 assert(isFloat() && "Invalid accessor");
505 *(APFloat *)(char *)Data.buffer = std::move(F);
507 void setFixedPoint(APFixedPoint FX) {
508 assert(isFixedPoint() && "Invalid accessor");
509 *(APFixedPoint *)(char *)Data.buffer = std::move(FX);
511 void setVector(const APValue *E, unsigned N) {
512 assert(isVector() && "Invalid accessor");
513 ((Vec*)(char*)Data.buffer)->Elts = new APValue[N];
514 ((Vec*)(char*)Data.buffer)->NumElts = N;
515 for (unsigned i = 0; i != N; ++i)
516 ((Vec*)(char*)Data.buffer)->Elts[i] = E[i];
518 void setComplexInt(APSInt R, APSInt I) {
519 assert(R.getBitWidth() == I.getBitWidth() &&
520 "Invalid complex int (type mismatch).");
521 assert(isComplexInt() && "Invalid accessor");
522 ((ComplexAPSInt *)(char *)Data.buffer)->Real = std::move(R);
523 ((ComplexAPSInt *)(char *)Data.buffer)->Imag = std::move(I);
525 void setComplexFloat(APFloat R, APFloat I) {
526 assert(&R.getSemantics() == &I.getSemantics() &&
527 "Invalid complex float (type mismatch).");
528 assert(isComplexFloat() && "Invalid accessor");
529 ((ComplexAPFloat *)(char *)Data.buffer)->Real = std::move(R);
530 ((ComplexAPFloat *)(char *)Data.buffer)->Imag = std::move(I);
532 void setLValue(LValueBase B, const CharUnits &O, NoLValuePath,
534 void setLValue(LValueBase B, const CharUnits &O,
535 ArrayRef<LValuePathEntry> Path, bool OnePastTheEnd,
537 void setUnion(const FieldDecl *Field, const APValue &Value) {
538 assert(isUnion() && "Invalid accessor");
539 ((UnionData*)(char*)Data.buffer)->Field = Field;
540 *((UnionData*)(char*)Data.buffer)->Value = Value;
542 void setAddrLabelDiff(const AddrLabelExpr* LHSExpr,
543 const AddrLabelExpr* RHSExpr) {
544 ((AddrLabelDiffData*)(char*)Data.buffer)->LHSExpr = LHSExpr;
545 ((AddrLabelDiffData*)(char*)Data.buffer)->RHSExpr = RHSExpr;
548 /// Assign by swapping from a copy of the RHS.
549 APValue &operator=(APValue RHS) {
555 void DestroyDataAndMakeUninit();
557 assert(isAbsent() && "Bad state change");
558 new ((void*)Data.buffer) APSInt(1);
562 assert(isAbsent() && "Bad state change");
563 new ((void*)(char*)Data.buffer) APFloat(0.0);
566 void MakeFixedPoint(APFixedPoint &&FX) {
567 assert(isAbsent() && "Bad state change");
568 new ((void *)(char *)Data.buffer) APFixedPoint(std::move(FX));
572 assert(isAbsent() && "Bad state change");
573 new ((void*)(char*)Data.buffer) Vec();
576 void MakeComplexInt() {
577 assert(isAbsent() && "Bad state change");
578 new ((void*)(char*)Data.buffer) ComplexAPSInt();
581 void MakeComplexFloat() {
582 assert(isAbsent() && "Bad state change");
583 new ((void*)(char*)Data.buffer) ComplexAPFloat();
587 void MakeArray(unsigned InitElts, unsigned Size);
588 void MakeStruct(unsigned B, unsigned M) {
589 assert(isAbsent() && "Bad state change");
590 new ((void*)(char*)Data.buffer) StructData(B, M);
594 assert(isAbsent() && "Bad state change");
595 new ((void*)(char*)Data.buffer) UnionData();
598 void MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
599 ArrayRef<const CXXRecordDecl*> Path);
600 void MakeAddrLabelDiff() {
601 assert(isAbsent() && "Bad state change");
602 new ((void*)(char*)Data.buffer) AddrLabelDiffData();
603 Kind = AddrLabelDiff;
607 } // end namespace clang.
610 template<> struct DenseMapInfo<clang::APValue::LValueBase> {
611 static clang::APValue::LValueBase getEmptyKey();
612 static clang::APValue::LValueBase getTombstoneKey();
613 static unsigned getHashValue(const clang::APValue::LValueBase &Base);
614 static bool isEqual(const clang::APValue::LValueBase &LHS,
615 const clang::APValue::LValueBase &RHS);