/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/include/clang/AST/APValue.h
Line | Count | Source (jump to first uncovered line) |
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 | 5.84k | TypeInfoLValue() : T() {} |
49 | | explicit TypeInfoLValue(const Type *T); |
50 | | |
51 | 189 | const Type *getType() const { return T; } |
52 | 4.47k | explicit operator bool() const { return T; } |
53 | | |
54 | 1.33k | void *getOpaqueValue() { return const_cast<Type*>(T); } |
55 | 189 | static TypeInfoLValue getFromOpaqueValue(void *Value) { |
56 | 189 | TypeInfoLValue V; |
57 | 189 | V.T = reinterpret_cast<const Type*>(Value); |
58 | 189 | return V; |
59 | 189 | } |
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 | 38.1k | DynamicAllocLValue() : Index(0) {} |
70 | 822 | explicit DynamicAllocLValue(unsigned Index) : Index(Index + 1) {} |
71 | 19.2k | unsigned getIndex() { return Index - 1; } |
72 | | |
73 | 37.9k | explicit operator bool() const { return Index != 0; } |
74 | | |
75 | 822 | void *getOpaqueValue() { |
76 | 822 | return reinterpret_cast<void *>(static_cast<uintptr_t>(Index) |
77 | 822 | << NumLowBitsAvailable); |
78 | 822 | } |
79 | 2.86k | static DynamicAllocLValue getFromOpaqueValue(void *Value) { |
80 | 2.86k | DynamicAllocLValue V; |
81 | 2.86k | V.Index = reinterpret_cast<uintptr_t>(Value) >> NumLowBitsAvailable; |
82 | 2.86k | return V; |
83 | 2.86k | } |
84 | | |
85 | 822 | static unsigned getMaxIndex() { |
86 | 822 | return (std::numeric_limits<unsigned>::max() >> NumLowBitsAvailable) - 1; |
87 | 822 | } |
88 | | |
89 | | static constexpr int NumLowBitsAvailable = 3; |
90 | | }; |
91 | | } |
92 | | |
93 | | namespace llvm { |
94 | | template<> struct PointerLikeTypeTraits<clang::TypeInfoLValue> { |
95 | 1.33k | static void *getAsVoidPointer(clang::TypeInfoLValue V) { |
96 | 1.33k | return V.getOpaqueValue(); |
97 | 1.33k | } |
98 | 189 | static clang::TypeInfoLValue getFromVoidPointer(void *P) { |
99 | 189 | return clang::TypeInfoLValue::getFromOpaqueValue(P); |
100 | 189 | } |
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 | 822 | static void *getAsVoidPointer(clang::DynamicAllocLValue V) { |
108 | 822 | return V.getOpaqueValue(); |
109 | 822 | } |
110 | 2.86k | static clang::DynamicAllocLValue getFromVoidPointer(void *P) { |
111 | 2.86k | return clang::DynamicAllocLValue::getFromOpaqueValue(P); |
112 | 2.86k | } |
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 | 19.8M | 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 | 36.2M | bool is() const { return Ptr.is<T>(); } bool clang::APValue::LValueBase::is<clang::ValueDecl const*>() const Line | Count | Source | 161 | 10 | bool is() const { return Ptr.is<T>(); } |
bool clang::APValue::LValueBase::is<clang::TypeInfoLValue>() const Line | Count | Source | 161 | 18.1M | bool is() const { return Ptr.is<T>(); } |
bool clang::APValue::LValueBase::is<clang::DynamicAllocLValue>() const Line | Count | Source | 161 | 18.1M | bool is() const { return Ptr.is<T>(); } |
|
162 | | |
163 | | template <class T> |
164 | 2.09M | T get() const { return Ptr.get<T>(); } clang::DynamicAllocLValue clang::APValue::LValueBase::get<clang::DynamicAllocLValue>() const Line | Count | Source | 164 | 9 | T get() const { return Ptr.get<T>(); } |
clang::Expr const* clang::APValue::LValueBase::get<clang::Expr const*>() const Line | Count | Source | 164 | 2.09M | T get() const { return Ptr.get<T>(); } |
clang::ValueDecl const* clang::APValue::LValueBase::get<clang::ValueDecl const*>() const Line | Count | Source | 164 | 28 | T get() const { return Ptr.get<T>(); } |
clang::TypeInfoLValue clang::APValue::LValueBase::get<clang::TypeInfoLValue>() const Line | Count | Source | 164 | 2 | T get() const { return Ptr.get<T>(); } |
|
165 | | |
166 | | template <class T> |
167 | 34.9M | T dyn_cast() const { return Ptr.dyn_cast<T>(); } clang::ValueDecl const* clang::APValue::LValueBase::dyn_cast<clang::ValueDecl const*>() const Line | Count | Source | 167 | 27.7M | T dyn_cast() const { return Ptr.dyn_cast<T>(); } |
clang::DynamicAllocLValue clang::APValue::LValueBase::dyn_cast<clang::DynamicAllocLValue>() const Line | Count | Source | 167 | 38.1k | T dyn_cast() const { return Ptr.dyn_cast<T>(); } |
clang::Expr const* clang::APValue::LValueBase::dyn_cast<clang::Expr const*>() const Line | Count | Source | 167 | 7.16M | T dyn_cast() const { return Ptr.dyn_cast<T>(); } |
clang::TypeInfoLValue clang::APValue::LValueBase::dyn_cast<clang::TypeInfoLValue>() const Line | Count | Source | 167 | 4.47k | 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 | 102 | friend bool operator!=(const LValueBase &LHS, const LValueBase &RHS) { |
184 | 102 | return !(LHS == RHS); |
185 | 102 | } |
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 | 178k | LValuePathEntry() : Value() {} |
215 | | LValuePathEntry(BaseOrMemberType BaseOrMember); |
216 | 177k | static LValuePathEntry ArrayIndex(uint64_t Index) { |
217 | 177k | LValuePathEntry Result; |
218 | 177k | Result.Value = Index; |
219 | 177k | return Result; |
220 | 177k | } |
221 | | |
222 | 42.4k | BaseOrMemberType getAsBaseOrMember() const { |
223 | 42.4k | return BaseOrMemberType::getFromOpaqueValue( |
224 | 42.4k | reinterpret_cast<void *>(Value)); |
225 | 42.4k | } |
226 | 174k | uint64_t getAsArrayIndex() const { return Value; } |
227 | | |
228 | | void Profile(llvm::FoldingSetNodeID &ID) const; |
229 | | |
230 | 13.6k | friend bool operator==(LValuePathEntry A, LValuePathEntry B) { |
231 | 13.6k | return A.Value == B.Value; |
232 | 13.6k | } |
233 | 0 | friend bool operator!=(LValuePathEntry A, LValuePathEntry B) { |
234 | 0 | return A.Value != B.Value; |
235 | 0 | } |
236 | 22.5k | friend llvm::hash_code hash_value(LValuePathEntry A) { |
237 | 22.5k | return llvm::hash_value(A.Value); |
238 | 22.5k | } |
239 | | }; |
240 | | class LValuePathSerializationHelper { |
241 | | const void *ElemTy; |
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 | 309 | ComplexAPSInt() : Real(1), Imag(1) {} |
263 | | }; |
264 | | struct ComplexAPFloat { |
265 | | APFloat Real, Imag; |
266 | 418 | ComplexAPFloat() : Real(0.0), Imag(0.0) {} |
267 | | }; |
268 | | struct LV; |
269 | | struct Vec { |
270 | | APValue *Elts; |
271 | | unsigned NumElts; |
272 | 8.37k | Vec() : Elts(nullptr), NumElts(0) {} |
273 | 7.87k | ~Vec() { delete[] Elts; } |
274 | | }; |
275 | | struct Arr { |
276 | | APValue *Elts; |
277 | | unsigned NumElts, ArrSize; |
278 | | Arr(unsigned NumElts, unsigned ArrSize); |
279 | | ~Arr(); |
280 | | }; |
281 | | struct StructData { |
282 | | APValue *Elts; |
283 | | unsigned NumBases; |
284 | | unsigned NumFields; |
285 | | StructData(unsigned NumBases, unsigned NumFields); |
286 | | ~StructData(); |
287 | | }; |
288 | | struct UnionData { |
289 | | const FieldDecl *Field; |
290 | | APValue *Value; |
291 | | UnionData(); |
292 | | ~UnionData(); |
293 | | }; |
294 | | struct AddrLabelDiffData { |
295 | | const AddrLabelExpr* LHSExpr; |
296 | | const AddrLabelExpr* RHSExpr; |
297 | | }; |
298 | | struct MemberPointerData; |
299 | | |
300 | | // We ensure elsewhere that Data is big enough for LV and MemberPointerData. |
301 | | typedef llvm::AlignedCharArrayUnion<void *, APSInt, APFloat, ComplexAPSInt, |
302 | | ComplexAPFloat, Vec, Arr, StructData, |
303 | | UnionData, AddrLabelDiffData> DataType; |
304 | | static const size_t DataSize = sizeof(DataType); |
305 | | |
306 | | DataType Data; |
307 | | |
308 | | public: |
309 | 67.0M | APValue() : Kind(None) {} |
310 | 28.1M | explicit APValue(APSInt I) : Kind(None) { |
311 | 28.1M | MakeInt(); setInt(std::move(I)); |
312 | 28.1M | } |
313 | 42.7k | explicit APValue(APFloat F) : Kind(None) { |
314 | 42.7k | MakeFloat(); setFloat(std::move(F)); |
315 | 42.7k | } |
316 | 3.24k | explicit APValue(APFixedPoint FX) : Kind(None) { |
317 | 3.24k | MakeFixedPoint(std::move(FX)); |
318 | 3.24k | } |
319 | 5.11k | explicit APValue(const APValue *E, unsigned N) : Kind(None) { |
320 | 5.11k | MakeVector(); setVector(E, N); |
321 | 5.11k | } |
322 | 138 | APValue(APSInt R, APSInt I) : Kind(None) { |
323 | 138 | MakeComplexInt(); setComplexInt(std::move(R), std::move(I)); |
324 | 138 | } |
325 | 244 | APValue(APFloat R, APFloat I) : Kind(None) { |
326 | 244 | MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I)); |
327 | 244 | } |
328 | | APValue(const APValue &RHS); |
329 | | APValue(APValue &&RHS); |
330 | | APValue(LValueBase B, const CharUnits &O, NoLValuePath N, |
331 | | bool IsNullPtr = false) |
332 | 6.13k | : Kind(None) { |
333 | 6.13k | MakeLValue(); setLValue(B, O, N, IsNullPtr); |
334 | 6.13k | } |
335 | | APValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path, |
336 | | bool OnePastTheEnd, bool IsNullPtr = false) |
337 | 1.19M | : Kind(None) { |
338 | 1.19M | MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, IsNullPtr); |
339 | 1.19M | } |
340 | 14.1k | APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(None) { |
341 | 14.1k | MakeArray(InitElts, Size); |
342 | 14.1k | } |
343 | 56.8k | APValue(UninitStruct, unsigned B, unsigned M) : Kind(None) { |
344 | 56.8k | MakeStruct(B, M); |
345 | 56.8k | } |
346 | | explicit APValue(const FieldDecl *D, const APValue &V = APValue()) |
347 | 2.12k | : Kind(None) { |
348 | 2.12k | MakeUnion(); setUnion(D, V); |
349 | 2.12k | } |
350 | | APValue(const ValueDecl *Member, bool IsDerivedMember, |
351 | 1.56k | ArrayRef<const CXXRecordDecl*> Path) : Kind(None) { |
352 | 1.56k | MakeMemberPointer(Member, IsDerivedMember, Path); |
353 | 1.56k | } |
354 | | APValue(const AddrLabelExpr* LHSExpr, const AddrLabelExpr* RHSExpr) |
355 | 44 | : Kind(None) { |
356 | 44 | MakeAddrLabelDiff(); setAddrLabelDiff(LHSExpr, RHSExpr); |
357 | 44 | } |
358 | 28.0k | static APValue IndeterminateValue() { |
359 | 28.0k | APValue Result; |
360 | 28.0k | Result.Kind = Indeterminate; |
361 | 28.0k | return Result; |
362 | 28.0k | } |
363 | | |
364 | | APValue &operator=(const APValue &RHS); |
365 | | APValue &operator=(APValue &&RHS); |
366 | | |
367 | 102M | ~APValue() { |
368 | 102M | if (Kind != None && Kind != Indeterminate32.4M ) |
369 | 32.4M | DestroyDataAndMakeUninit(); |
370 | 102M | } |
371 | | |
372 | | /// Returns whether the object performed allocations. |
373 | | /// |
374 | | /// If APValues are constructed via placement new, \c needsCleanup() |
375 | | /// indicates whether the destructor must be called in order to correctly |
376 | | /// free all allocated memory. |
377 | | bool needsCleanup() const; |
378 | | |
379 | | /// Swaps the contents of this and the given APValue. |
380 | | void swap(APValue &RHS); |
381 | | |
382 | | /// profile this value. There is no guarantee that values of different |
383 | | /// types will not produce the same profiled value, so the type should |
384 | | /// typically also be profiled if it's not implied by the context. |
385 | | void Profile(llvm::FoldingSetNodeID &ID) const; |
386 | | |
387 | 15.1M | ValueKind getKind() const { return Kind; } |
388 | | |
389 | 39.0M | bool isAbsent() const { return Kind == None; } |
390 | 3.26M | bool isIndeterminate() const { return Kind == Indeterminate; } |
391 | 11.6M | bool hasValue() const { return Kind != None && Kind != Indeterminate11.6M ; } |
392 | | |
393 | 114M | bool isInt() const { return Kind == Int; } |
394 | 137k | bool isFloat() const { return Kind == Float; } |
395 | 4.95k | bool isFixedPoint() const { return Kind == FixedPoint; } |
396 | 1.59k | bool isComplexInt() const { return Kind == ComplexInt; } |
397 | 1.24k | bool isComplexFloat() const { return Kind == ComplexFloat; } |
398 | 29.5M | bool isLValue() const { return Kind == LValue; } |
399 | 44.6k | bool isVector() const { return Kind == Vector; } |
400 | 12.2M | bool isArray() const { return Kind == Array; } |
401 | 11.9M | bool isStruct() const { return Kind == Struct; } |
402 | 11.5M | bool isUnion() const { return Kind == Union; } |
403 | 11.4M | bool isMemberPointer() const { return Kind == MemberPointer; } |
404 | 1.62M | bool isAddrLabelDiff() const { return Kind == AddrLabelDiff; } |
405 | | |
406 | | void dump() const; |
407 | | void dump(raw_ostream &OS, const ASTContext &Context) const; |
408 | | |
409 | | void printPretty(raw_ostream &OS, const ASTContext &Ctx, QualType Ty) const; |
410 | | void printPretty(raw_ostream &OS, const PrintingPolicy &Policy, QualType Ty, |
411 | | const ASTContext *Ctx = nullptr) const; |
412 | | |
413 | | std::string getAsString(const ASTContext &Ctx, QualType Ty) const; |
414 | | |
415 | 56.3M | APSInt &getInt() { |
416 | 56.3M | assert(isInt() && "Invalid accessor"); |
417 | 56.3M | return *(APSInt *)(char *)&Data; |
418 | 56.3M | } |
419 | 22.2M | const APSInt &getInt() const { |
420 | 22.2M | return const_cast<APValue*>(this)->getInt(); |
421 | 22.2M | } |
422 | | |
423 | | /// Try to convert this value to an integral constant. This works if it's an |
424 | | /// integer, null pointer, or offset from a null pointer. Returns true on |
425 | | /// success. |
426 | | bool toIntegralConstant(APSInt &Result, QualType SrcTy, |
427 | | const ASTContext &Ctx) const; |
428 | | |
429 | 36.8k | APFloat &getFloat() { |
430 | 36.8k | assert(isFloat() && "Invalid accessor"); |
431 | 36.8k | return *(APFloat *)(char *)&Data; |
432 | 36.8k | } |
433 | 32.2k | const APFloat &getFloat() const { |
434 | 32.2k | return const_cast<APValue*>(this)->getFloat(); |
435 | 32.2k | } |
436 | | |
437 | 2.83k | APFixedPoint &getFixedPoint() { |
438 | 2.83k | assert(isFixedPoint() && "Invalid accessor"); |
439 | 2.83k | return *(APFixedPoint *)(char *)&Data; |
440 | 2.83k | } |
441 | 700 | const APFixedPoint &getFixedPoint() const { |
442 | 700 | return const_cast<APValue *>(this)->getFixedPoint(); |
443 | 700 | } |
444 | | |
445 | 333 | APSInt &getComplexIntReal() { |
446 | 333 | assert(isComplexInt() && "Invalid accessor"); |
447 | 333 | return ((ComplexAPSInt *)(char *)&Data)->Real; |
448 | 333 | } |
449 | 312 | const APSInt &getComplexIntReal() const { |
450 | 312 | return const_cast<APValue*>(this)->getComplexIntReal(); |
451 | 312 | } |
452 | | |
453 | 304 | APSInt &getComplexIntImag() { |
454 | 304 | assert(isComplexInt() && "Invalid accessor"); |
455 | 304 | return ((ComplexAPSInt *)(char *)&Data)->Imag; |
456 | 304 | } |
457 | 283 | const APSInt &getComplexIntImag() const { |
458 | 283 | return const_cast<APValue*>(this)->getComplexIntImag(); |
459 | 283 | } |
460 | | |
461 | 397 | APFloat &getComplexFloatReal() { |
462 | 397 | assert(isComplexFloat() && "Invalid accessor"); |
463 | 397 | return ((ComplexAPFloat *)(char *)&Data)->Real; |
464 | 397 | } |
465 | 395 | const APFloat &getComplexFloatReal() const { |
466 | 395 | return const_cast<APValue*>(this)->getComplexFloatReal(); |
467 | 395 | } |
468 | | |
469 | 343 | APFloat &getComplexFloatImag() { |
470 | 343 | assert(isComplexFloat() && "Invalid accessor"); |
471 | 343 | return ((ComplexAPFloat *)(char *)&Data)->Imag; |
472 | 343 | } |
473 | 341 | const APFloat &getComplexFloatImag() const { |
474 | 341 | return const_cast<APValue*>(this)->getComplexFloatImag(); |
475 | 341 | } |
476 | | |
477 | | const LValueBase getLValueBase() const; |
478 | | CharUnits &getLValueOffset(); |
479 | 743k | const CharUnits &getLValueOffset() const { |
480 | 743k | return const_cast<APValue*>(this)->getLValueOffset(); |
481 | 743k | } |
482 | | bool isLValueOnePastTheEnd() const; |
483 | | bool hasLValuePath() const; |
484 | | ArrayRef<LValuePathEntry> getLValuePath() const; |
485 | | unsigned getLValueCallIndex() const; |
486 | | unsigned getLValueVersion() const; |
487 | | bool isNullPointer() const; |
488 | | |
489 | 12.6k | APValue &getVectorElt(unsigned I) { |
490 | 12.6k | assert(isVector() && "Invalid accessor"); |
491 | 12.6k | assert(I < getVectorLength() && "Index out of range"); |
492 | 12.6k | return ((Vec *)(char *)&Data)->Elts[I]; |
493 | 12.6k | } |
494 | 9.83k | const APValue &getVectorElt(unsigned I) const { |
495 | 9.83k | return const_cast<APValue*>(this)->getVectorElt(I); |
496 | 9.83k | } |
497 | 20.2k | unsigned getVectorLength() const { |
498 | 20.2k | assert(isVector() && "Invalid accessor"); |
499 | 20.2k | return ((const Vec *)(const void *)&Data)->NumElts; |
500 | 20.2k | } |
501 | | |
502 | 240k | APValue &getArrayInitializedElt(unsigned I) { |
503 | 240k | assert(isArray() && "Invalid accessor"); |
504 | 240k | assert(I < getArrayInitializedElts() && "Index out of range"); |
505 | 240k | return ((Arr *)(char *)&Data)->Elts[I]; |
506 | 240k | } |
507 | 93.5k | const APValue &getArrayInitializedElt(unsigned I) const { |
508 | 93.5k | return const_cast<APValue*>(this)->getArrayInitializedElt(I); |
509 | 93.5k | } |
510 | 36.8k | bool hasArrayFiller() const { |
511 | 36.8k | return getArrayInitializedElts() != getArraySize(); |
512 | 36.8k | } |
513 | 18.9k | APValue &getArrayFiller() { |
514 | 18.9k | assert(isArray() && "Invalid accessor"); |
515 | 18.9k | assert(hasArrayFiller() && "No array filler"); |
516 | 18.9k | return ((Arr *)(char *)&Data)->Elts[getArrayInitializedElts()]; |
517 | 18.9k | } |
518 | 3.37k | const APValue &getArrayFiller() const { |
519 | 3.37k | return const_cast<APValue*>(this)->getArrayFiller(); |
520 | 3.37k | } |
521 | 323k | unsigned getArrayInitializedElts() const { |
522 | 323k | assert(isArray() && "Invalid accessor"); |
523 | 323k | return ((const Arr *)(const void *)&Data)->NumElts; |
524 | 323k | } |
525 | 42.0k | unsigned getArraySize() const { |
526 | 42.0k | assert(isArray() && "Invalid accessor"); |
527 | 42.0k | return ((const Arr *)(const void *)&Data)->ArrSize; |
528 | 42.0k | } |
529 | | |
530 | 142k | unsigned getStructNumBases() const { |
531 | 142k | assert(isStruct() && "Invalid accessor"); |
532 | 142k | return ((const StructData *)(const char *)&Data)->NumBases; |
533 | 142k | } |
534 | 132k | unsigned getStructNumFields() const { |
535 | 132k | assert(isStruct() && "Invalid accessor"); |
536 | 132k | return ((const StructData *)(const char *)&Data)->NumFields; |
537 | 132k | } |
538 | 9.84k | APValue &getStructBase(unsigned i) { |
539 | 9.84k | assert(isStruct() && "Invalid accessor"); |
540 | 9.84k | assert(i < getStructNumBases() && "base class index OOB"); |
541 | 9.84k | return ((StructData *)(char *)&Data)->Elts[i]; |
542 | 9.84k | } |
543 | 122k | APValue &getStructField(unsigned i) { |
544 | 122k | assert(isStruct() && "Invalid accessor"); |
545 | 122k | assert(i < getStructNumFields() && "field index OOB"); |
546 | 122k | return ((StructData *)(char *)&Data)->Elts[getStructNumBases() + i]; |
547 | 122k | } |
548 | 3.61k | const APValue &getStructBase(unsigned i) const { |
549 | 3.61k | return const_cast<APValue*>(this)->getStructBase(i); |
550 | 3.61k | } |
551 | 34.3k | const APValue &getStructField(unsigned i) const { |
552 | 34.3k | return const_cast<APValue*>(this)->getStructField(i); |
553 | 34.3k | } |
554 | | |
555 | 4.96k | const FieldDecl *getUnionField() const { |
556 | 4.96k | assert(isUnion() && "Invalid accessor"); |
557 | 4.96k | return ((const UnionData *)(const char *)&Data)->Field; |
558 | 4.96k | } |
559 | 4.08k | APValue &getUnionValue() { |
560 | 4.08k | assert(isUnion() && "Invalid accessor"); |
561 | 4.08k | return *((UnionData *)(char *)&Data)->Value; |
562 | 4.08k | } |
563 | 1.93k | const APValue &getUnionValue() const { |
564 | 1.93k | return const_cast<APValue*>(this)->getUnionValue(); |
565 | 1.93k | } |
566 | | |
567 | | const ValueDecl *getMemberPointerDecl() const; |
568 | | bool isMemberPointerToDerivedMember() const; |
569 | | ArrayRef<const CXXRecordDecl*> getMemberPointerPath() const; |
570 | | |
571 | 26 | const AddrLabelExpr* getAddrLabelDiffLHS() const { |
572 | 26 | assert(isAddrLabelDiff() && "Invalid accessor"); |
573 | 26 | return ((const AddrLabelDiffData *)(const char *)&Data)->LHSExpr; |
574 | 26 | } |
575 | 26 | const AddrLabelExpr* getAddrLabelDiffRHS() const { |
576 | 26 | assert(isAddrLabelDiff() && "Invalid accessor"); |
577 | 26 | return ((const AddrLabelDiffData *)(const char *)&Data)->RHSExpr; |
578 | 26 | } |
579 | | |
580 | 34.0M | void setInt(APSInt I) { |
581 | 34.0M | assert(isInt() && "Invalid accessor"); |
582 | 34.0M | *(APSInt *)(char *)&Data = std::move(I); |
583 | 34.0M | } |
584 | 55.9k | void setFloat(APFloat F) { |
585 | 55.9k | assert(isFloat() && "Invalid accessor"); |
586 | 55.9k | *(APFloat *)(char *)&Data = std::move(F); |
587 | 55.9k | } |
588 | 0 | void setFixedPoint(APFixedPoint FX) { |
589 | 0 | assert(isFixedPoint() && "Invalid accessor"); |
590 | 0 | *(APFixedPoint *)(char *)&Data = std::move(FX); |
591 | 0 | } |
592 | 8.37k | void setVector(const APValue *E, unsigned N) { |
593 | 8.37k | MutableArrayRef<APValue> InternalElts = setVectorUninit(N); |
594 | 58.3k | for (unsigned i = 0; i != N; ++i49.9k ) |
595 | 49.9k | InternalElts[i] = E[i]; |
596 | 8.37k | } |
597 | 309 | void setComplexInt(APSInt R, APSInt I) { |
598 | 309 | assert(R.getBitWidth() == I.getBitWidth() && |
599 | 309 | "Invalid complex int (type mismatch)."); |
600 | 309 | assert(isComplexInt() && "Invalid accessor"); |
601 | 309 | ((ComplexAPSInt *)(char *)&Data)->Real = std::move(R); |
602 | 309 | ((ComplexAPSInt *)(char *)&Data)->Imag = std::move(I); |
603 | 309 | } |
604 | 418 | void setComplexFloat(APFloat R, APFloat I) { |
605 | 418 | assert(&R.getSemantics() == &I.getSemantics() && |
606 | 418 | "Invalid complex float (type mismatch)."); |
607 | 418 | assert(isComplexFloat() && "Invalid accessor"); |
608 | 418 | ((ComplexAPFloat *)(char *)&Data)->Real = std::move(R); |
609 | 418 | ((ComplexAPFloat *)(char *)&Data)->Imag = std::move(I); |
610 | 418 | } |
611 | | void setLValue(LValueBase B, const CharUnits &O, NoLValuePath, |
612 | | bool IsNullPtr); |
613 | | void setLValue(LValueBase B, const CharUnits &O, |
614 | | ArrayRef<LValuePathEntry> Path, bool OnePastTheEnd, |
615 | | bool IsNullPtr); |
616 | | void setUnion(const FieldDecl *Field, const APValue &Value); |
617 | | void setAddrLabelDiff(const AddrLabelExpr* LHSExpr, |
618 | 63 | const AddrLabelExpr* RHSExpr) { |
619 | 63 | ((AddrLabelDiffData *)(char *)&Data)->LHSExpr = LHSExpr; |
620 | 63 | ((AddrLabelDiffData *)(char *)&Data)->RHSExpr = RHSExpr; |
621 | 63 | } |
622 | | |
623 | | private: |
624 | | void DestroyDataAndMakeUninit(); |
625 | 34.0M | void MakeInt() { |
626 | 34.0M | assert(isAbsent() && "Bad state change"); |
627 | 34.0M | new ((void *)&Data) APSInt(1); |
628 | 34.0M | Kind = Int; |
629 | 34.0M | } |
630 | 55.9k | void MakeFloat() { |
631 | 55.9k | assert(isAbsent() && "Bad state change"); |
632 | 55.9k | new ((void *)(char *)&Data) APFloat(0.0); |
633 | 55.9k | Kind = Float; |
634 | 55.9k | } |
635 | 3.25k | void MakeFixedPoint(APFixedPoint &&FX) { |
636 | 3.25k | assert(isAbsent() && "Bad state change"); |
637 | 3.25k | new ((void *)(char *)&Data) APFixedPoint(std::move(FX)); |
638 | 3.25k | Kind = FixedPoint; |
639 | 3.25k | } |
640 | 8.37k | void MakeVector() { |
641 | 8.37k | assert(isAbsent() && "Bad state change"); |
642 | 8.37k | new ((void *)(char *)&Data) Vec(); |
643 | 8.37k | Kind = Vector; |
644 | 8.37k | } |
645 | 309 | void MakeComplexInt() { |
646 | 309 | assert(isAbsent() && "Bad state change"); |
647 | 309 | new ((void *)(char *)&Data) ComplexAPSInt(); |
648 | 309 | Kind = ComplexInt; |
649 | 309 | } |
650 | 418 | void MakeComplexFloat() { |
651 | 418 | assert(isAbsent() && "Bad state change"); |
652 | 418 | new ((void *)(char *)&Data) ComplexAPFloat(); |
653 | 418 | Kind = ComplexFloat; |
654 | 418 | } |
655 | | void MakeLValue(); |
656 | | void MakeArray(unsigned InitElts, unsigned Size); |
657 | 61.2k | void MakeStruct(unsigned B, unsigned M) { |
658 | 61.2k | assert(isAbsent() && "Bad state change"); |
659 | 61.2k | new ((void *)(char *)&Data) StructData(B, M); |
660 | 61.2k | Kind = Struct; |
661 | 61.2k | } |
662 | 2.66k | void MakeUnion() { |
663 | 2.66k | assert(isAbsent() && "Bad state change"); |
664 | 2.66k | new ((void *)(char *)&Data) UnionData(); |
665 | 2.66k | Kind = Union; |
666 | 2.66k | } |
667 | | void MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember, |
668 | | ArrayRef<const CXXRecordDecl*> Path); |
669 | 63 | void MakeAddrLabelDiff() { |
670 | 63 | assert(isAbsent() && "Bad state change"); |
671 | 63 | new ((void *)(char *)&Data) AddrLabelDiffData(); |
672 | 63 | Kind = AddrLabelDiff; |
673 | 63 | } |
674 | | |
675 | | private: |
676 | | /// The following functions are used as part of initialization, during |
677 | | /// deserialization and importing. Reserve the space so that it can be |
678 | | /// filled in by those steps. |
679 | 8.37k | MutableArrayRef<APValue> setVectorUninit(unsigned N) { |
680 | 8.37k | assert(isVector() && "Invalid accessor"); |
681 | 8.37k | Vec *V = ((Vec *)(char *)&Data); |
682 | 8.37k | V->Elts = new APValue[N]; |
683 | 8.37k | V->NumElts = N; |
684 | 8.37k | return {V->Elts, V->NumElts}; |
685 | 8.37k | } |
686 | | MutableArrayRef<LValuePathEntry> |
687 | | setLValueUninit(LValueBase B, const CharUnits &O, unsigned Size, |
688 | | bool OnePastTheEnd, bool IsNullPtr); |
689 | | MutableArrayRef<const CXXRecordDecl *> |
690 | | setMemberPointerUninit(const ValueDecl *Member, bool IsDerivedMember, |
691 | | unsigned Size); |
692 | | }; |
693 | | |
694 | | } // end namespace clang. |
695 | | |
696 | | namespace llvm { |
697 | | template<> struct DenseMapInfo<clang::APValue::LValueBase> { |
698 | | static clang::APValue::LValueBase getEmptyKey(); |
699 | | static clang::APValue::LValueBase getTombstoneKey(); |
700 | | static unsigned getHashValue(const clang::APValue::LValueBase &Base); |
701 | | static bool isEqual(const clang::APValue::LValueBase &LHS, |
702 | | const clang::APValue::LValueBase &RHS); |
703 | | }; |
704 | | } |
705 | | |
706 | | #endif |