Warning: That file was not part of the compilation database. It may have many parsing errors.
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 | |
23 | namespace 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] |
38 | class APValue { |
39 | typedef llvm::APSInt APSInt; |
40 | typedef llvm::APFloat APFloat; |
41 | public: |
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 {}; |
119 | private: |
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 | |
170 | public: |
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 | |
452 | private: |
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 | |
506 | namespace llvm { |
507 | template<> 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 |
Warning: That file was not part of the compilation database. It may have many parsing errors.