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/LLVM.h" |
17 | #include "llvm/ADT/APFixedPoint.h" |
18 | #include "llvm/ADT/APFloat.h" |
19 | #include "llvm/ADT/APSInt.h" |
20 | #include "llvm/ADT/FoldingSet.h" |
21 | #include "llvm/ADT/PointerIntPair.h" |
22 | #include "llvm/ADT/PointerUnion.h" |
23 | #include "llvm/Support/AlignOf.h" |
24 | |
25 | namespace clang { |
26 | namespace serialization { |
27 | template <typename T> class BasicReaderBase; |
28 | } // end namespace serialization |
29 | |
30 | class AddrLabelExpr; |
31 | class ASTContext; |
32 | class CharUnits; |
33 | class CXXRecordDecl; |
34 | class Decl; |
35 | class DiagnosticBuilder; |
36 | class Expr; |
37 | class FieldDecl; |
38 | struct PrintingPolicy; |
39 | class Type; |
40 | class ValueDecl; |
41 | class QualType; |
42 | |
43 | /// Symbolic representation of typeid(T) for some type T. |
44 | class TypeInfoLValue { |
45 | const Type *T; |
46 | |
47 | public: |
48 | TypeInfoLValue() : T() {} |
49 | explicit TypeInfoLValue(const Type *T); |
50 | |
51 | const Type *getType() const { return T; } |
52 | explicit operator bool() const { return T; } |
53 | |
54 | void *getOpaqueValue() { return const_cast<Type*>(T); } |
55 | static TypeInfoLValue getFromOpaqueValue(void *Value) { |
56 | TypeInfoLValue V; |
57 | V.T = reinterpret_cast<const Type*>(Value); |
58 | return V; |
59 | } |
60 | |
61 | void print(llvm::raw_ostream &Out, const PrintingPolicy &Policy) const; |
62 | }; |
63 | |
64 | /// Symbolic representation of a dynamic allocation. |
65 | class DynamicAllocLValue { |
66 | unsigned Index; |
67 | |
68 | public: |
69 | DynamicAllocLValue() : Index(0) {} |
70 | explicit DynamicAllocLValue(unsigned Index) : Index(Index + 1) {} |
71 | unsigned getIndex() { return Index - 1; } |
72 | |
73 | explicit operator bool() const { return Index != 0; } |
74 | |
75 | void *getOpaqueValue() { |
76 | return reinterpret_cast<void *>(static_cast<uintptr_t>(Index) |
77 | << NumLowBitsAvailable); |
78 | } |
79 | static DynamicAllocLValue getFromOpaqueValue(void *Value) { |
80 | DynamicAllocLValue V; |
81 | V.Index = reinterpret_cast<uintptr_t>(Value) >> NumLowBitsAvailable; |
82 | return V; |
83 | } |
84 | |
85 | static unsigned getMaxIndex() { |
86 | return (std::numeric_limits<unsigned>::max() >> NumLowBitsAvailable) - 1; |
87 | } |
88 | |
89 | static constexpr int NumLowBitsAvailable = 3; |
90 | }; |
91 | } |
92 | |
93 | namespace llvm { |
94 | template<> struct PointerLikeTypeTraits<clang::TypeInfoLValue> { |
95 | static void *getAsVoidPointer(clang::TypeInfoLValue V) { |
96 | return V.getOpaqueValue(); |
97 | } |
98 | static clang::TypeInfoLValue getFromVoidPointer(void *P) { |
99 | return clang::TypeInfoLValue::getFromOpaqueValue(Value: P); |
100 | } |
101 | // Validated by static_assert in APValue.cpp; hardcoded to avoid needing |
102 | // to include Type.h. |
103 | static constexpr int NumLowBitsAvailable = 3; |
104 | }; |
105 | |
106 | template<> struct PointerLikeTypeTraits<clang::DynamicAllocLValue> { |
107 | static void *getAsVoidPointer(clang::DynamicAllocLValue V) { |
108 | return V.getOpaqueValue(); |
109 | } |
110 | static clang::DynamicAllocLValue getFromVoidPointer(void *P) { |
111 | return clang::DynamicAllocLValue::getFromOpaqueValue(Value: P); |
112 | } |
113 | static constexpr int NumLowBitsAvailable = |
114 | clang::DynamicAllocLValue::NumLowBitsAvailable; |
115 | }; |
116 | } |
117 | |
118 | namespace clang { |
119 | /// APValue - This class implements a discriminated union of [uninitialized] |
120 | /// [APSInt] [APFloat], [Complex APSInt] [Complex APFloat], [Expr + Offset], |
121 | /// [Vector: N * APValue], [Array: N * APValue] |
122 | class APValue { |
123 | typedef llvm::APFixedPoint APFixedPoint; |
124 | typedef llvm::APSInt APSInt; |
125 | typedef llvm::APFloat APFloat; |
126 | public: |
127 | enum ValueKind { |
128 | /// There is no such object (it's outside its lifetime). |
129 | None, |
130 | /// This object has an indeterminate value (C++ [basic.indet]). |
131 | Indeterminate, |
132 | Int, |
133 | Float, |
134 | FixedPoint, |
135 | ComplexInt, |
136 | ComplexFloat, |
137 | LValue, |
138 | Vector, |
139 | Array, |
140 | Struct, |
141 | Union, |
142 | MemberPointer, |
143 | AddrLabelDiff |
144 | }; |
145 | |
146 | class LValueBase { |
147 | typedef llvm::PointerUnion<const ValueDecl *, const Expr *, TypeInfoLValue, |
148 | DynamicAllocLValue> |
149 | PtrTy; |
150 | |
151 | public: |
152 | LValueBase() : Local{} {} |
153 | LValueBase(const ValueDecl *P, unsigned I = 0, unsigned V = 0); |
154 | LValueBase(const Expr *P, unsigned I = 0, unsigned V = 0); |
155 | static LValueBase getDynamicAlloc(DynamicAllocLValue LV, QualType Type); |
156 | static LValueBase getTypeInfo(TypeInfoLValue LV, QualType TypeInfo); |
157 | |
158 | void Profile(llvm::FoldingSetNodeID &ID) const; |
159 | |
160 | template <class T> |
161 | bool is() const { return Ptr.is<T>(); } |
162 | |
163 | template <class T> |
164 | T get() const { return Ptr.get<T>(); } |
165 | |
166 | template <class T> |
167 | T dyn_cast() const { return Ptr.dyn_cast<T>(); } |
168 | |
169 | void *getOpaqueValue() const; |
170 | |
171 | bool isNull() const; |
172 | |
173 | explicit operator bool() const; |
174 | |
175 | unsigned getCallIndex() const; |
176 | unsigned getVersion() const; |
177 | QualType getTypeInfoType() const; |
178 | QualType getDynamicAllocType() const; |
179 | |
180 | QualType getType() const; |
181 | |
182 | friend bool operator==(const LValueBase &LHS, const LValueBase &RHS); |
183 | friend bool operator!=(const LValueBase &LHS, const LValueBase &RHS) { |
184 | return !(LHS == RHS); |
185 | } |
186 | friend llvm::hash_code hash_value(const LValueBase &Base); |
187 | friend struct llvm::DenseMapInfo<LValueBase>; |
188 | |
189 | private: |
190 | PtrTy Ptr; |
191 | struct LocalState { |
192 | unsigned CallIndex, Version; |
193 | }; |
194 | union { |
195 | LocalState Local; |
196 | /// The type std::type_info, if this is a TypeInfoLValue. |
197 | void *TypeInfoType; |
198 | /// The QualType, if this is a DynamicAllocLValue. |
199 | void *DynamicAllocType; |
200 | }; |
201 | }; |
202 | |
203 | /// A FieldDecl or CXXRecordDecl, along with a flag indicating whether we |
204 | /// mean a virtual or non-virtual base class subobject. |
205 | typedef llvm::PointerIntPair<const Decl *, 1, bool> BaseOrMemberType; |
206 | |
207 | /// A non-discriminated union of a base, field, or array index. |
208 | class LValuePathEntry { |
209 | static_assert(sizeof(uintptr_t) <= sizeof(uint64_t), |
210 | "pointer doesn't fit in 64 bits?" ); |
211 | uint64_t Value; |
212 | |
213 | public: |
214 | LValuePathEntry() : Value() {} |
215 | LValuePathEntry(BaseOrMemberType BaseOrMember); |
216 | static LValuePathEntry ArrayIndex(uint64_t Index) { |
217 | LValuePathEntry Result; |
218 | Result.Value = Index; |
219 | return Result; |
220 | } |
221 | |
222 | BaseOrMemberType getAsBaseOrMember() const { |
223 | return BaseOrMemberType::getFromOpaqueValue( |
224 | V: reinterpret_cast<void *>(Value)); |
225 | } |
226 | uint64_t getAsArrayIndex() const { return Value; } |
227 | |
228 | void Profile(llvm::FoldingSetNodeID &ID) const; |
229 | |
230 | friend bool operator==(LValuePathEntry A, LValuePathEntry B) { |
231 | return A.Value == B.Value; |
232 | } |
233 | friend bool operator!=(LValuePathEntry A, LValuePathEntry B) { |
234 | return A.Value != B.Value; |
235 | } |
236 | friend llvm::hash_code hash_value(LValuePathEntry A) { |
237 | return llvm::hash_value(value: A.Value); |
238 | } |
239 | }; |
240 | class LValuePathSerializationHelper { |
241 | const void *Ty; |
242 | |
243 | public: |
244 | ArrayRef<LValuePathEntry> Path; |
245 | |
246 | LValuePathSerializationHelper(ArrayRef<LValuePathEntry>, QualType); |
247 | QualType getType(); |
248 | }; |
249 | struct NoLValuePath {}; |
250 | struct UninitArray {}; |
251 | struct UninitStruct {}; |
252 | |
253 | template <typename Impl> friend class clang::serialization::BasicReaderBase; |
254 | friend class ASTImporter; |
255 | friend class ASTNodeImporter; |
256 | |
257 | private: |
258 | ValueKind Kind; |
259 | |
260 | struct ComplexAPSInt { |
261 | APSInt Real, Imag; |
262 | ComplexAPSInt() : Real(1), Imag(1) {} |
263 | }; |
264 | struct ComplexAPFloat { |
265 | APFloat Real, Imag; |
266 | ComplexAPFloat() : Real(0.0), Imag(0.0) {} |
267 | }; |
268 | struct LV; |
269 | struct Vec { |
270 | APValue *Elts = nullptr; |
271 | unsigned NumElts = 0; |
272 | Vec() = default; |
273 | Vec(const Vec &) = delete; |
274 | Vec &operator=(const Vec &) = delete; |
275 | ~Vec() { delete[] Elts; } |
276 | }; |
277 | struct Arr { |
278 | APValue *Elts; |
279 | unsigned NumElts, ArrSize; |
280 | Arr(unsigned NumElts, unsigned ArrSize); |
281 | Arr(const Arr &) = delete; |
282 | Arr &operator=(const Arr &) = delete; |
283 | ~Arr(); |
284 | }; |
285 | struct StructData { |
286 | APValue *Elts; |
287 | unsigned NumBases; |
288 | unsigned NumFields; |
289 | StructData(unsigned NumBases, unsigned NumFields); |
290 | StructData(const StructData &) = delete; |
291 | StructData &operator=(const StructData &) = delete; |
292 | ~StructData(); |
293 | }; |
294 | struct UnionData { |
295 | const FieldDecl *Field; |
296 | APValue *Value; |
297 | UnionData(); |
298 | UnionData(const UnionData &) = delete; |
299 | UnionData &operator=(const UnionData &) = delete; |
300 | ~UnionData(); |
301 | }; |
302 | struct AddrLabelDiffData { |
303 | const AddrLabelExpr* LHSExpr; |
304 | const AddrLabelExpr* RHSExpr; |
305 | }; |
306 | struct MemberPointerData; |
307 | |
308 | // We ensure elsewhere that Data is big enough for LV and MemberPointerData. |
309 | typedef llvm::AlignedCharArrayUnion<void *, APSInt, APFloat, ComplexAPSInt, |
310 | ComplexAPFloat, Vec, Arr, StructData, |
311 | UnionData, AddrLabelDiffData> DataType; |
312 | static const size_t DataSize = sizeof(DataType); |
313 | |
314 | DataType Data; |
315 | |
316 | public: |
317 | APValue() : Kind(None) {} |
318 | explicit APValue(APSInt I) : Kind(None) { |
319 | MakeInt(); setInt(std::move(I)); |
320 | } |
321 | explicit APValue(APFloat F) : Kind(None) { |
322 | MakeFloat(); setFloat(std::move(F)); |
323 | } |
324 | explicit APValue(APFixedPoint FX) : Kind(None) { |
325 | MakeFixedPoint(FX: std::move(FX)); |
326 | } |
327 | explicit APValue(const APValue *E, unsigned N) : Kind(None) { |
328 | MakeVector(); setVector(E, N); |
329 | } |
330 | APValue(APSInt R, APSInt I) : Kind(None) { |
331 | MakeComplexInt(); setComplexInt(R: std::move(R), I: std::move(I)); |
332 | } |
333 | APValue(APFloat R, APFloat I) : Kind(None) { |
334 | MakeComplexFloat(); setComplexFloat(R: std::move(R), I: std::move(I)); |
335 | } |
336 | APValue(const APValue &RHS); |
337 | APValue(APValue &&RHS); |
338 | APValue(LValueBase B, const CharUnits &O, NoLValuePath N, |
339 | bool IsNullPtr = false) |
340 | : Kind(None) { |
341 | MakeLValue(); setLValue(B, O, N, IsNullPtr); |
342 | } |
343 | APValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path, |
344 | bool OnePastTheEnd, bool IsNullPtr = false) |
345 | : Kind(None) { |
346 | MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, IsNullPtr); |
347 | } |
348 | APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(None) { |
349 | MakeArray(InitElts, Size); |
350 | } |
351 | APValue(UninitStruct, unsigned B, unsigned M) : Kind(None) { |
352 | MakeStruct(B, M); |
353 | } |
354 | explicit APValue(const FieldDecl *D, const APValue &V = APValue()) |
355 | : Kind(None) { |
356 | MakeUnion(); setUnion(Field: D, Value: V); |
357 | } |
358 | APValue(const ValueDecl *Member, bool IsDerivedMember, |
359 | ArrayRef<const CXXRecordDecl*> Path) : Kind(None) { |
360 | MakeMemberPointer(Member, IsDerivedMember, Path); |
361 | } |
362 | APValue(const AddrLabelExpr* LHSExpr, const AddrLabelExpr* RHSExpr) |
363 | : Kind(None) { |
364 | MakeAddrLabelDiff(); setAddrLabelDiff(LHSExpr, RHSExpr); |
365 | } |
366 | static APValue IndeterminateValue() { |
367 | APValue Result; |
368 | Result.Kind = Indeterminate; |
369 | return Result; |
370 | } |
371 | |
372 | APValue &operator=(const APValue &RHS); |
373 | APValue &operator=(APValue &&RHS); |
374 | |
375 | ~APValue() { |
376 | if (Kind != None && Kind != Indeterminate) |
377 | DestroyDataAndMakeUninit(); |
378 | } |
379 | |
380 | /// Returns whether the object performed allocations. |
381 | /// |
382 | /// If APValues are constructed via placement new, \c needsCleanup() |
383 | /// indicates whether the destructor must be called in order to correctly |
384 | /// free all allocated memory. |
385 | bool needsCleanup() const; |
386 | |
387 | /// Swaps the contents of this and the given APValue. |
388 | void swap(APValue &RHS); |
389 | |
390 | /// profile this value. There is no guarantee that values of different |
391 | /// types will not produce the same profiled value, so the type should |
392 | /// typically also be profiled if it's not implied by the context. |
393 | void Profile(llvm::FoldingSetNodeID &ID) const; |
394 | |
395 | ValueKind getKind() const { return Kind; } |
396 | |
397 | bool isAbsent() const { return Kind == None; } |
398 | bool isIndeterminate() const { return Kind == Indeterminate; } |
399 | bool hasValue() const { return Kind != None && Kind != Indeterminate; } |
400 | |
401 | bool isInt() const { return Kind == Int; } |
402 | bool isFloat() const { return Kind == Float; } |
403 | bool isFixedPoint() const { return Kind == FixedPoint; } |
404 | bool isComplexInt() const { return Kind == ComplexInt; } |
405 | bool isComplexFloat() const { return Kind == ComplexFloat; } |
406 | bool isLValue() const { return Kind == LValue; } |
407 | bool isVector() const { return Kind == Vector; } |
408 | bool isArray() const { return Kind == Array; } |
409 | bool isStruct() const { return Kind == Struct; } |
410 | bool isUnion() const { return Kind == Union; } |
411 | bool isMemberPointer() const { return Kind == MemberPointer; } |
412 | bool isAddrLabelDiff() const { return Kind == AddrLabelDiff; } |
413 | |
414 | void dump() const; |
415 | void dump(raw_ostream &OS, const ASTContext &Context) const; |
416 | |
417 | void printPretty(raw_ostream &OS, const ASTContext &Ctx, QualType Ty) const; |
418 | void printPretty(raw_ostream &OS, const PrintingPolicy &Policy, QualType Ty, |
419 | const ASTContext *Ctx = nullptr) const; |
420 | |
421 | std::string getAsString(const ASTContext &Ctx, QualType Ty) const; |
422 | |
423 | APSInt &getInt() { |
424 | assert(isInt() && "Invalid accessor" ); |
425 | return *(APSInt *)(char *)&Data; |
426 | } |
427 | const APSInt &getInt() const { |
428 | return const_cast<APValue*>(this)->getInt(); |
429 | } |
430 | |
431 | /// Try to convert this value to an integral constant. This works if it's an |
432 | /// integer, null pointer, or offset from a null pointer. Returns true on |
433 | /// success. |
434 | bool toIntegralConstant(APSInt &Result, QualType SrcTy, |
435 | const ASTContext &Ctx) const; |
436 | |
437 | APFloat &getFloat() { |
438 | assert(isFloat() && "Invalid accessor" ); |
439 | return *(APFloat *)(char *)&Data; |
440 | } |
441 | const APFloat &getFloat() const { |
442 | return const_cast<APValue*>(this)->getFloat(); |
443 | } |
444 | |
445 | APFixedPoint &getFixedPoint() { |
446 | assert(isFixedPoint() && "Invalid accessor" ); |
447 | return *(APFixedPoint *)(char *)&Data; |
448 | } |
449 | const APFixedPoint &getFixedPoint() const { |
450 | return const_cast<APValue *>(this)->getFixedPoint(); |
451 | } |
452 | |
453 | APSInt &getComplexIntReal() { |
454 | assert(isComplexInt() && "Invalid accessor" ); |
455 | return ((ComplexAPSInt *)(char *)&Data)->Real; |
456 | } |
457 | const APSInt &getComplexIntReal() const { |
458 | return const_cast<APValue*>(this)->getComplexIntReal(); |
459 | } |
460 | |
461 | APSInt &getComplexIntImag() { |
462 | assert(isComplexInt() && "Invalid accessor" ); |
463 | return ((ComplexAPSInt *)(char *)&Data)->Imag; |
464 | } |
465 | const APSInt &getComplexIntImag() const { |
466 | return const_cast<APValue*>(this)->getComplexIntImag(); |
467 | } |
468 | |
469 | APFloat &getComplexFloatReal() { |
470 | assert(isComplexFloat() && "Invalid accessor" ); |
471 | return ((ComplexAPFloat *)(char *)&Data)->Real; |
472 | } |
473 | const APFloat &getComplexFloatReal() const { |
474 | return const_cast<APValue*>(this)->getComplexFloatReal(); |
475 | } |
476 | |
477 | APFloat &getComplexFloatImag() { |
478 | assert(isComplexFloat() && "Invalid accessor" ); |
479 | return ((ComplexAPFloat *)(char *)&Data)->Imag; |
480 | } |
481 | const APFloat &getComplexFloatImag() const { |
482 | return const_cast<APValue*>(this)->getComplexFloatImag(); |
483 | } |
484 | |
485 | const LValueBase getLValueBase() const; |
486 | CharUnits &getLValueOffset(); |
487 | const CharUnits &getLValueOffset() const { |
488 | return const_cast<APValue*>(this)->getLValueOffset(); |
489 | } |
490 | bool isLValueOnePastTheEnd() const; |
491 | bool hasLValuePath() const; |
492 | ArrayRef<LValuePathEntry> getLValuePath() const; |
493 | unsigned getLValueCallIndex() const; |
494 | unsigned getLValueVersion() const; |
495 | bool isNullPointer() const; |
496 | |
497 | APValue &getVectorElt(unsigned I) { |
498 | assert(isVector() && "Invalid accessor" ); |
499 | assert(I < getVectorLength() && "Index out of range" ); |
500 | return ((Vec *)(char *)&Data)->Elts[I]; |
501 | } |
502 | const APValue &getVectorElt(unsigned I) const { |
503 | return const_cast<APValue*>(this)->getVectorElt(I); |
504 | } |
505 | unsigned getVectorLength() const { |
506 | assert(isVector() && "Invalid accessor" ); |
507 | return ((const Vec *)(const void *)&Data)->NumElts; |
508 | } |
509 | |
510 | APValue &getArrayInitializedElt(unsigned I) { |
511 | assert(isArray() && "Invalid accessor" ); |
512 | assert(I < getArrayInitializedElts() && "Index out of range" ); |
513 | return ((Arr *)(char *)&Data)->Elts[I]; |
514 | } |
515 | const APValue &getArrayInitializedElt(unsigned I) const { |
516 | return const_cast<APValue*>(this)->getArrayInitializedElt(I); |
517 | } |
518 | bool hasArrayFiller() const { |
519 | return getArrayInitializedElts() != getArraySize(); |
520 | } |
521 | APValue &getArrayFiller() { |
522 | assert(isArray() && "Invalid accessor" ); |
523 | assert(hasArrayFiller() && "No array filler" ); |
524 | return ((Arr *)(char *)&Data)->Elts[getArrayInitializedElts()]; |
525 | } |
526 | const APValue &getArrayFiller() const { |
527 | return const_cast<APValue*>(this)->getArrayFiller(); |
528 | } |
529 | unsigned getArrayInitializedElts() const { |
530 | assert(isArray() && "Invalid accessor" ); |
531 | return ((const Arr *)(const void *)&Data)->NumElts; |
532 | } |
533 | unsigned getArraySize() const { |
534 | assert(isArray() && "Invalid accessor" ); |
535 | return ((const Arr *)(const void *)&Data)->ArrSize; |
536 | } |
537 | |
538 | unsigned getStructNumBases() const { |
539 | assert(isStruct() && "Invalid accessor" ); |
540 | return ((const StructData *)(const char *)&Data)->NumBases; |
541 | } |
542 | unsigned getStructNumFields() const { |
543 | assert(isStruct() && "Invalid accessor" ); |
544 | return ((const StructData *)(const char *)&Data)->NumFields; |
545 | } |
546 | APValue &getStructBase(unsigned i) { |
547 | assert(isStruct() && "Invalid accessor" ); |
548 | assert(i < getStructNumBases() && "base class index OOB" ); |
549 | return ((StructData *)(char *)&Data)->Elts[i]; |
550 | } |
551 | APValue &getStructField(unsigned i) { |
552 | assert(isStruct() && "Invalid accessor" ); |
553 | assert(i < getStructNumFields() && "field index OOB" ); |
554 | return ((StructData *)(char *)&Data)->Elts[getStructNumBases() + i]; |
555 | } |
556 | const APValue &getStructBase(unsigned i) const { |
557 | return const_cast<APValue*>(this)->getStructBase(i); |
558 | } |
559 | const APValue &getStructField(unsigned i) const { |
560 | return const_cast<APValue*>(this)->getStructField(i); |
561 | } |
562 | |
563 | const FieldDecl *getUnionField() const { |
564 | assert(isUnion() && "Invalid accessor" ); |
565 | return ((const UnionData *)(const char *)&Data)->Field; |
566 | } |
567 | APValue &getUnionValue() { |
568 | assert(isUnion() && "Invalid accessor" ); |
569 | return *((UnionData *)(char *)&Data)->Value; |
570 | } |
571 | const APValue &getUnionValue() const { |
572 | return const_cast<APValue*>(this)->getUnionValue(); |
573 | } |
574 | |
575 | const ValueDecl *getMemberPointerDecl() const; |
576 | bool isMemberPointerToDerivedMember() const; |
577 | ArrayRef<const CXXRecordDecl*> getMemberPointerPath() const; |
578 | |
579 | const AddrLabelExpr* getAddrLabelDiffLHS() const { |
580 | assert(isAddrLabelDiff() && "Invalid accessor" ); |
581 | return ((const AddrLabelDiffData *)(const char *)&Data)->LHSExpr; |
582 | } |
583 | const AddrLabelExpr* getAddrLabelDiffRHS() const { |
584 | assert(isAddrLabelDiff() && "Invalid accessor" ); |
585 | return ((const AddrLabelDiffData *)(const char *)&Data)->RHSExpr; |
586 | } |
587 | |
588 | void setInt(APSInt I) { |
589 | assert(isInt() && "Invalid accessor" ); |
590 | *(APSInt *)(char *)&Data = std::move(I); |
591 | } |
592 | void setFloat(APFloat F) { |
593 | assert(isFloat() && "Invalid accessor" ); |
594 | *(APFloat *)(char *)&Data = std::move(F); |
595 | } |
596 | void setFixedPoint(APFixedPoint FX) { |
597 | assert(isFixedPoint() && "Invalid accessor" ); |
598 | *(APFixedPoint *)(char *)&Data = std::move(FX); |
599 | } |
600 | void setVector(const APValue *E, unsigned N) { |
601 | MutableArrayRef<APValue> InternalElts = setVectorUninit(N); |
602 | for (unsigned i = 0; i != N; ++i) |
603 | InternalElts[i] = E[i]; |
604 | } |
605 | void setComplexInt(APSInt R, APSInt I) { |
606 | assert(R.getBitWidth() == I.getBitWidth() && |
607 | "Invalid complex int (type mismatch)." ); |
608 | assert(isComplexInt() && "Invalid accessor" ); |
609 | ((ComplexAPSInt *)(char *)&Data)->Real = std::move(R); |
610 | ((ComplexAPSInt *)(char *)&Data)->Imag = std::move(I); |
611 | } |
612 | void setComplexFloat(APFloat R, APFloat I) { |
613 | assert(&R.getSemantics() == &I.getSemantics() && |
614 | "Invalid complex float (type mismatch)." ); |
615 | assert(isComplexFloat() && "Invalid accessor" ); |
616 | ((ComplexAPFloat *)(char *)&Data)->Real = std::move(R); |
617 | ((ComplexAPFloat *)(char *)&Data)->Imag = std::move(I); |
618 | } |
619 | void setLValue(LValueBase B, const CharUnits &O, NoLValuePath, |
620 | bool IsNullPtr); |
621 | void setLValue(LValueBase B, const CharUnits &O, |
622 | ArrayRef<LValuePathEntry> Path, bool OnePastTheEnd, |
623 | bool IsNullPtr); |
624 | void setUnion(const FieldDecl *Field, const APValue &Value); |
625 | void setAddrLabelDiff(const AddrLabelExpr* LHSExpr, |
626 | const AddrLabelExpr* RHSExpr) { |
627 | ((AddrLabelDiffData *)(char *)&Data)->LHSExpr = LHSExpr; |
628 | ((AddrLabelDiffData *)(char *)&Data)->RHSExpr = RHSExpr; |
629 | } |
630 | |
631 | private: |
632 | void DestroyDataAndMakeUninit(); |
633 | void MakeInt() { |
634 | assert(isAbsent() && "Bad state change" ); |
635 | new ((void *)&Data) APSInt(1); |
636 | Kind = Int; |
637 | } |
638 | void MakeFloat() { |
639 | assert(isAbsent() && "Bad state change" ); |
640 | new ((void *)(char *)&Data) APFloat(0.0); |
641 | Kind = Float; |
642 | } |
643 | void MakeFixedPoint(APFixedPoint &&FX) { |
644 | assert(isAbsent() && "Bad state change" ); |
645 | new ((void *)(char *)&Data) APFixedPoint(std::move(FX)); |
646 | Kind = FixedPoint; |
647 | } |
648 | void MakeVector() { |
649 | assert(isAbsent() && "Bad state change" ); |
650 | new ((void *)(char *)&Data) Vec(); |
651 | Kind = Vector; |
652 | } |
653 | void MakeComplexInt() { |
654 | assert(isAbsent() && "Bad state change" ); |
655 | new ((void *)(char *)&Data) ComplexAPSInt(); |
656 | Kind = ComplexInt; |
657 | } |
658 | void MakeComplexFloat() { |
659 | assert(isAbsent() && "Bad state change" ); |
660 | new ((void *)(char *)&Data) ComplexAPFloat(); |
661 | Kind = ComplexFloat; |
662 | } |
663 | void MakeLValue(); |
664 | void MakeArray(unsigned InitElts, unsigned Size); |
665 | void MakeStruct(unsigned B, unsigned M) { |
666 | assert(isAbsent() && "Bad state change" ); |
667 | new ((void *)(char *)&Data) StructData(B, M); |
668 | Kind = Struct; |
669 | } |
670 | void MakeUnion() { |
671 | assert(isAbsent() && "Bad state change" ); |
672 | new ((void *)(char *)&Data) UnionData(); |
673 | Kind = Union; |
674 | } |
675 | void MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember, |
676 | ArrayRef<const CXXRecordDecl*> Path); |
677 | void MakeAddrLabelDiff() { |
678 | assert(isAbsent() && "Bad state change" ); |
679 | new ((void *)(char *)&Data) AddrLabelDiffData(); |
680 | Kind = AddrLabelDiff; |
681 | } |
682 | |
683 | private: |
684 | /// The following functions are used as part of initialization, during |
685 | /// deserialization and importing. Reserve the space so that it can be |
686 | /// filled in by those steps. |
687 | MutableArrayRef<APValue> setVectorUninit(unsigned N) { |
688 | assert(isVector() && "Invalid accessor" ); |
689 | Vec *V = ((Vec *)(char *)&Data); |
690 | V->Elts = new APValue[N]; |
691 | V->NumElts = N; |
692 | return {V->Elts, V->NumElts}; |
693 | } |
694 | MutableArrayRef<LValuePathEntry> |
695 | setLValueUninit(LValueBase B, const CharUnits &O, unsigned Size, |
696 | bool OnePastTheEnd, bool IsNullPtr); |
697 | MutableArrayRef<const CXXRecordDecl *> |
698 | setMemberPointerUninit(const ValueDecl *Member, bool IsDerivedMember, |
699 | unsigned Size); |
700 | }; |
701 | |
702 | } // end namespace clang. |
703 | |
704 | namespace llvm { |
705 | template<> struct DenseMapInfo<clang::APValue::LValueBase> { |
706 | static clang::APValue::LValueBase getEmptyKey(); |
707 | static clang::APValue::LValueBase getTombstoneKey(); |
708 | static unsigned getHashValue(const clang::APValue::LValueBase &Base); |
709 | static bool isEqual(const clang::APValue::LValueBase &LHS, |
710 | const clang::APValue::LValueBase &RHS); |
711 | }; |
712 | } |
713 | |
714 | #endif |
715 | |