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/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"
22
23namespace clang {
24 class AddrLabelExpr;
25 class ASTContext;
26 class CharUnits;
27 class DiagnosticBuilder;
28 class Expr;
29 class FieldDecl;
30 class Decl;
31 class ValueDecl;
32 class CXXRecordDecl;
33 class QualType;
34
35/// APValue - This class implements a discriminated union of [uninitialized]
36/// [APSInt] [APFloat], [Complex APSInt] [Complex APFloat], [Expr + Offset],
37/// [Vector: N * APValue], [Array: N * APValue]
38class APValue {
39 typedef llvm::APSInt APSInt;
40 typedef llvm::APFloat APFloat;
41public:
42 enum ValueKind {
43 Uninitialized,
44 Int,
45 Float,
46 FixedPoint,
47 ComplexInt,
48 ComplexFloat,
49 LValue,
50 Vector,
51 Array,
52 Struct,
53 Union,
54 MemberPointer,
55 AddrLabelDiff
56 };
57
58 class LValueBase {
59 public:
60 typedef llvm::PointerUnion<const ValueDecl *, const Expr *> PtrTy;
61
62 LValueBase() : CallIndex(0), Version(0) {}
63
64 template <class T>
65 LValueBase(T P, unsigned I = 0, unsigned V = 0)
66 : Ptr(P), CallIndex(I), Version(V) {}
67
68 template <class T>
69 bool is() const { return Ptr.is<T>(); }
70
71 template <class T>
72 T get() const { return Ptr.get<T>(); }
73
74 template <class T>
75 T dyn_cast() const { return Ptr.dyn_cast<T>(); }
76
77 void *getOpaqueValue() const;
78
79 bool isNull() const;
80
81 explicit operator bool () const;
82
83 PtrTy getPointer() const {
84 return Ptr;
85 }
86
87 unsigned getCallIndex() const {
88 return CallIndex;
89 }
90
91 void setCallIndex(unsigned Index) {
92 CallIndex = Index;
93 }
94
95 unsigned getVersion() const {
96 return Version;
97 }
98
99 bool operator==(const LValueBase &Other) const {
100 return Ptr == Other.Ptr && CallIndex == Other.CallIndex &&
101 Version == Other.Version;
102 }
103
104 private:
105 PtrTy Ptr;
106 unsigned CallIndex, Version;
107 };
108
109 typedef llvm::PointerIntPair<const Decl *, 1, bool> BaseOrMemberType;
110 union LValuePathEntry {
111 /// BaseOrMember - The FieldDecl or CXXRecordDecl indicating the next item
112 /// in the path. An opaque value of type BaseOrMemberType.
113 void *BaseOrMember;
114 /// ArrayIndex - The array index of the next item in the path.
115 uint64_t ArrayIndex;
116 };
117 struct NoLValuePath {};
118 struct UninitArray {};
119 struct UninitStruct {};
120private:
121 ValueKind Kind;
122
123 struct ComplexAPSInt {
124 APSInt Real, Imag;
125 ComplexAPSInt() : Real(1), Imag(1) {}
126 };
127 struct ComplexAPFloat {
128 APFloat Real, Imag;
129 ComplexAPFloat() : Real(0.0), Imag(0.0) {}
130 };
131 struct LV;
132 struct Vec {
133 APValue *Elts;
134 unsigned NumElts;
135 Vec() : Elts(nullptr), NumElts(0) {}
136 ~Vec() { delete[] Elts; }
137 };
138 struct Arr {
139 APValue *Elts;
140 unsigned NumElts, ArrSize;
141 Arr(unsigned NumElts, unsigned ArrSize);
142 ~Arr();
143 };
144 struct StructData {
145 APValue *Elts;
146 unsigned NumBases;
147 unsigned NumFields;
148 StructData(unsigned NumBases, unsigned NumFields);
149 ~StructData();
150 };
151 struct UnionData {
152 const FieldDecl *Field;
153 APValue *Value;
154 UnionData();
155 ~UnionData();
156 };
157 struct AddrLabelDiffData {
158 const AddrLabelExpr* LHSExpr;
159 const AddrLabelExpr* RHSExpr;
160 };
161 struct MemberPointerData;
162
163 // We ensure elsewhere that Data is big enough for LV and MemberPointerData.
164 typedef llvm::AlignedCharArrayUnion<void *, APSInt, APFloat, ComplexAPSInt,
165 ComplexAPFloat, Vec, Arr, StructData,
166 UnionData, AddrLabelDiffData> DataType;
167 static const size_t DataSize = sizeof(DataType);
168
169 DataType Data;
170
171public:
172 APValue() : Kind(Uninitialized) {}
173 explicit APValue(APSInt I) : Kind(Uninitialized) {
174 MakeInt(); setInt(std::move(I));
175 }
176 explicit APValue(APFloat F) : Kind(Uninitialized) {
177 MakeFloat(); setFloat(std::move(F));
178 }
179 explicit APValue(APFixedPoint FX) : Kind(Uninitialized) {
180 MakeFixedPoint(std::move(FX));
181 }
182 explicit APValue(const APValue *E, unsigned N) : Kind(Uninitialized) {
183 MakeVector(); setVector(E, N);
184 }
185 APValue(APSInt R, APSInt I) : Kind(Uninitialized) {
186 MakeComplexInt(); setComplexInt(std::move(R), std::move(I));
187 }
188 APValue(APFloat R, APFloat I) : Kind(Uninitialized) {
189 MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I));
190 }
191 APValue(const APValue &RHS);
192 APValue(APValue &&RHS) : Kind(Uninitialized) { swap(RHS); }
193 APValue(LValueBase B, const CharUnits &O, NoLValuePath N,
194 bool IsNullPtr = false)
195 : Kind(Uninitialized) {
196 MakeLValue(); setLValue(B, O, N, IsNullPtr);
197 }
198 APValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path,
199 bool OnePastTheEnd, bool IsNullPtr = false)
200 : Kind(Uninitialized) {
201 MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, IsNullPtr);
202 }
203 APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(Uninitialized) {
204 MakeArray(InitElts, Size);
205 }
206 APValue(UninitStruct, unsigned B, unsigned M) : Kind(Uninitialized) {
207 MakeStruct(B, M);
208 }
209 explicit APValue(const FieldDecl *D, const APValue &V = APValue())
210 : Kind(Uninitialized) {
211 MakeUnion(); setUnion(D, V);
212 }
213 APValue(const ValueDecl *Member, bool IsDerivedMember,
214 ArrayRef<const CXXRecordDecl*> Path) : Kind(Uninitialized) {
215 MakeMemberPointer(Member, IsDerivedMember, Path);
216 }
217 APValue(const AddrLabelExpr* LHSExpr, const AddrLabelExpr* RHSExpr)
218 : Kind(Uninitialized) {
219 MakeAddrLabelDiff(); setAddrLabelDiff(LHSExpr, RHSExpr);
220 }
221
222 ~APValue() {
223 MakeUninit();
224 }
225
226 /// Returns whether the object performed allocations.
227 ///
228 /// If APValues are constructed via placement new, \c needsCleanup()
229 /// indicates whether the destructor must be called in order to correctly
230 /// free all allocated memory.
231 bool needsCleanup() const;
232
233 /// Swaps the contents of this and the given APValue.
234 void swap(APValue &RHS);
235
236 ValueKind getKind() const { return Kind; }
237 bool isUninit() const { return Kind == Uninitialized; }
238 bool isInt() const { return Kind == Int; }
239 bool isFloat() const { return Kind == Float; }
240 bool isFixedPoint() const { return Kind == FixedPoint; }
241 bool isComplexInt() const { return Kind == ComplexInt; }
242 bool isComplexFloat() const { return Kind == ComplexFloat; }
243 bool isLValue() const { return Kind == LValue; }
244 bool isVector() const { return Kind == Vector; }
245 bool isArray() const { return Kind == Array; }
246 bool isStruct() const { return Kind == Struct; }
247 bool isUnion() const { return Kind == Union; }
248 bool isMemberPointer() const { return Kind == MemberPointer; }
249 bool isAddrLabelDiff() const { return Kind == AddrLabelDiff; }
250
251 void dump() const;
252 void dump(raw_ostream &OS) const;
253
254 void printPretty(raw_ostream &OS, ASTContext &Ctx, QualType Ty) const;
255 std::string getAsString(ASTContext &Ctx, QualType Ty) const;
256
257 APSInt &getInt() {
258 assert(isInt() && "Invalid accessor");
259 return *(APSInt*)(char*)Data.buffer;
260 }
261 const APSInt &getInt() const {
262 return const_cast<APValue*>(this)->getInt();
263 }
264
265 APFloat &getFloat() {
266 assert(isFloat() && "Invalid accessor");
267 return *(APFloat*)(char*)Data.buffer;
268 }
269 const APFloat &getFloat() const {
270 return const_cast<APValue*>(this)->getFloat();
271 }
272
273 APFixedPoint &getFixedPoint() {
274 assert(isFixedPoint() && "Invalid accessor");
275 return *(APFixedPoint *)(char *)Data.buffer;
276 }
277 const APFixedPoint &getFixedPoint() const {
278 return const_cast<APValue *>(this)->getFixedPoint();
279 }
280
281 APSInt &getComplexIntReal() {
282 assert(isComplexInt() && "Invalid accessor");
283 return ((ComplexAPSInt*)(char*)Data.buffer)->Real;
284 }
285 const APSInt &getComplexIntReal() const {
286 return const_cast<APValue*>(this)->getComplexIntReal();
287 }
288
289 APSInt &getComplexIntImag() {
290 assert(isComplexInt() && "Invalid accessor");
291 return ((ComplexAPSInt*)(char*)Data.buffer)->Imag;
292 }
293 const APSInt &getComplexIntImag() const {
294 return const_cast<APValue*>(this)->getComplexIntImag();
295 }
296
297 APFloat &getComplexFloatReal() {
298 assert(isComplexFloat() && "Invalid accessor");
299 return ((ComplexAPFloat*)(char*)Data.buffer)->Real;
300 }
301 const APFloat &getComplexFloatReal() const {
302 return const_cast<APValue*>(this)->getComplexFloatReal();
303 }
304
305 APFloat &getComplexFloatImag() {
306 assert(isComplexFloat() && "Invalid accessor");
307 return ((ComplexAPFloat*)(char*)Data.buffer)->Imag;
308 }
309 const APFloat &getComplexFloatImag() const {
310 return const_cast<APValue*>(this)->getComplexFloatImag();
311 }
312
313 const LValueBase getLValueBase() const;
314 CharUnits &getLValueOffset();
315 const CharUnits &getLValueOffset() const {
316 return const_cast<APValue*>(this)->getLValueOffset();
317 }
318 bool isLValueOnePastTheEnd() const;
319 bool hasLValuePath() const;
320 ArrayRef<LValuePathEntry> getLValuePath() const;
321 unsigned getLValueCallIndex() const;
322 unsigned getLValueVersion() const;
323 bool isNullPointer() const;
324
325 APValue &getVectorElt(unsigned I) {
326 assert(isVector() && "Invalid accessor");
327 assert(I < getVectorLength() && "Index out of range");
328 return ((Vec*)(char*)Data.buffer)->Elts[I];
329 }
330 const APValue &getVectorElt(unsigned I) const {
331 return const_cast<APValue*>(this)->getVectorElt(I);
332 }
333 unsigned getVectorLength() const {
334 assert(isVector() && "Invalid accessor");
335 return ((const Vec*)(const void *)Data.buffer)->NumElts;
336 }
337
338 APValue &getArrayInitializedElt(unsigned I) {
339 assert(isArray() && "Invalid accessor");
340 assert(I < getArrayInitializedElts() && "Index out of range");
341 return ((Arr*)(char*)Data.buffer)->Elts[I];
342 }
343 const APValue &getArrayInitializedElt(unsigned I) const {
344 return const_cast<APValue*>(this)->getArrayInitializedElt(I);
345 }
346 bool hasArrayFiller() const {
347 return getArrayInitializedElts() != getArraySize();
348 }
349 APValue &getArrayFiller() {
350 assert(isArray() && "Invalid accessor");
351 assert(hasArrayFiller() && "No array filler");
352 return ((Arr*)(char*)Data.buffer)->Elts[getArrayInitializedElts()];
353 }
354 const APValue &getArrayFiller() const {
355 return const_cast<APValue*>(this)->getArrayFiller();
356 }
357 unsigned getArrayInitializedElts() const {
358 assert(isArray() && "Invalid accessor");
359 return ((const Arr*)(const void *)Data.buffer)->NumElts;
360 }
361 unsigned getArraySize() const {
362 assert(isArray() && "Invalid accessor");
363 return ((const Arr*)(const void *)Data.buffer)->ArrSize;
364 }
365
366 unsigned getStructNumBases() const {
367 assert(isStruct() && "Invalid accessor");
368 return ((const StructData*)(const char*)Data.buffer)->NumBases;
369 }
370 unsigned getStructNumFields() const {
371 assert(isStruct() && "Invalid accessor");
372 return ((const StructData*)(const char*)Data.buffer)->NumFields;
373 }
374 APValue &getStructBase(unsigned i) {
375 assert(isStruct() && "Invalid accessor");
376 return ((StructData*)(char*)Data.buffer)->Elts[i];
377 }
378 APValue &getStructField(unsigned i) {
379 assert(isStruct() && "Invalid accessor");
380 return ((StructData*)(char*)Data.buffer)->Elts[getStructNumBases() + i];
381 }
382 const APValue &getStructBase(unsigned i) const {
383 return const_cast<APValue*>(this)->getStructBase(i);
384 }
385 const APValue &getStructField(unsigned i) const {
386 return const_cast<APValue*>(this)->getStructField(i);
387 }
388
389 const FieldDecl *getUnionField() const {
390 assert(isUnion() && "Invalid accessor");
391 return ((const UnionData*)(const char*)Data.buffer)->Field;
392 }
393 APValue &getUnionValue() {
394 assert(isUnion() && "Invalid accessor");
395 return *((UnionData*)(char*)Data.buffer)->Value;
396 }
397 const APValue &getUnionValue() const {
398 return const_cast<APValue*>(this)->getUnionValue();
399 }
400
401 const ValueDecl *getMemberPointerDecl() const;
402 bool isMemberPointerToDerivedMember() const;
403 ArrayRef<const CXXRecordDecl*> getMemberPointerPath() const;
404
405 const AddrLabelExpr* getAddrLabelDiffLHS() const {
406 assert(isAddrLabelDiff() && "Invalid accessor");
407 return ((const AddrLabelDiffData*)(const char*)Data.buffer)->LHSExpr;
408 }
409 const AddrLabelExpr* getAddrLabelDiffRHS() const {
410 assert(isAddrLabelDiff() && "Invalid accessor");
411 return ((const AddrLabelDiffData*)(const char*)Data.buffer)->RHSExpr;
412 }
413
414 void setInt(APSInt I) {
415 assert(isInt() && "Invalid accessor");
416 *(APSInt *)(char *)Data.buffer = std::move(I);
417 }
418 void setFloat(APFloat F) {
419 assert(isFloat() && "Invalid accessor");
420 *(APFloat *)(char *)Data.buffer = std::move(F);
421 }
422 void setFixedPoint(APFixedPoint FX) {
423 assert(isFixedPoint() && "Invalid accessor");
424 *(APFixedPoint *)(char *)Data.buffer = std::move(FX);
425 }
426 void setVector(const APValue *E, unsigned N) {
427 assert(isVector() && "Invalid accessor");
428 ((Vec*)(char*)Data.buffer)->Elts = new APValue[N];
429 ((Vec*)(char*)Data.buffer)->NumElts = N;
430 for (unsigned i = 0; i != N; ++i)
431 ((Vec*)(char*)Data.buffer)->Elts[i] = E[i];
432 }
433 void setComplexInt(APSInt R, APSInt I) {
434 assert(R.getBitWidth() == I.getBitWidth() &&
435 "Invalid complex int (type mismatch).");
436 assert(isComplexInt() && "Invalid accessor");
437 ((ComplexAPSInt *)(char *)Data.buffer)->Real = std::move(R);
438 ((ComplexAPSInt *)(char *)Data.buffer)->Imag = std::move(I);
439 }
440 void setComplexFloat(APFloat R, APFloat I) {
441 assert(&R.getSemantics() == &I.getSemantics() &&
442 "Invalid complex float (type mismatch).");
443 assert(isComplexFloat() && "Invalid accessor");
444 ((ComplexAPFloat *)(char *)Data.buffer)->Real = std::move(R);
445 ((ComplexAPFloat *)(char *)Data.buffer)->Imag = std::move(I);
446 }
447 void setLValue(LValueBase B, const CharUnits &O, NoLValuePath,
448 bool IsNullPtr);
449 void setLValue(LValueBase B, const CharUnits &O,
450 ArrayRef<LValuePathEntry> Path, bool OnePastTheEnd,
451 bool IsNullPtr);
452 void setUnion(const FieldDecl *Field, const APValue &Value) {
453 assert(isUnion() && "Invalid accessor");
454 ((UnionData*)(char*)Data.buffer)->Field = Field;
455 *((UnionData*)(char*)Data.buffer)->Value = Value;
456 }
457 void setAddrLabelDiff(const AddrLabelExpr* LHSExpr,
458 const AddrLabelExpr* RHSExpr) {
459 ((AddrLabelDiffData*)(char*)Data.buffer)->LHSExpr = LHSExpr;
460 ((AddrLabelDiffData*)(char*)Data.buffer)->RHSExpr = RHSExpr;
461 }
462
463 /// Assign by swapping from a copy of the RHS.
464 APValue &operator=(APValue RHS) {
465 swap(RHS);
466 return *this;
467 }
468
469private:
470 void DestroyDataAndMakeUninit();
471 void MakeUninit() {
472 if (Kind != Uninitialized)
473 DestroyDataAndMakeUninit();
474 }
475 void MakeInt() {
476 assert(isUninit() && "Bad state change");
477 new ((void*)Data.buffer) APSInt(1);
478 Kind = Int;
479 }
480 void MakeFloat() {
481 assert(isUninit() && "Bad state change");
482 new ((void*)(char*)Data.buffer) APFloat(0.0);
483 Kind = Float;
484 }
485 void MakeFixedPoint(APFixedPoint &&FX) {
486 assert(isUninit() && "Bad state change");
487 new ((void *)(char *)Data.buffer) APFixedPoint(std::move(FX));
488 Kind = FixedPoint;
489 }
490 void MakeVector() {
491 assert(isUninit() && "Bad state change");
492 new ((void*)(char*)Data.buffer) Vec();
493 Kind = Vector;
494 }
495 void MakeComplexInt() {
496 assert(isUninit() && "Bad state change");
497 new ((void*)(char*)Data.buffer) ComplexAPSInt();
498 Kind = ComplexInt;
499 }
500 void MakeComplexFloat() {
501 assert(isUninit() && "Bad state change");
502 new ((void*)(char*)Data.buffer) ComplexAPFloat();
503 Kind = ComplexFloat;
504 }
505 void MakeLValue();
506 void MakeArray(unsigned InitElts, unsigned Size);
507 void MakeStruct(unsigned B, unsigned M) {
508 assert(isUninit() && "Bad state change");
509 new ((void*)(char*)Data.buffer) StructData(B, M);
510 Kind = Struct;
511 }
512 void MakeUnion() {
513 assert(isUninit() && "Bad state change");
514 new ((void*)(char*)Data.buffer) UnionData();
515 Kind = Union;
516 }
517 void MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
518 ArrayRef<const CXXRecordDecl*> Path);
519 void MakeAddrLabelDiff() {
520 assert(isUninit() && "Bad state change");
521 new ((void*)(char*)Data.buffer) AddrLabelDiffData();
522 Kind = AddrLabelDiff;
523 }
524};
525
526} // end namespace clang.
527
528namespace llvm {
529template<> struct DenseMapInfo<clang::APValue::LValueBase> {
530 static clang::APValue::LValueBase getEmptyKey();
531 static clang::APValue::LValueBase getTombstoneKey();
532 static unsigned getHashValue(const clang::APValue::LValueBase &Base);
533 static bool isEqual(const clang::APValue::LValueBase &LHS,
534 const clang::APValue::LValueBase &RHS);
535};
536}
537
538#endif
539