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