1 //===--- APValue.h - Union class for APFloat/APSInt/Complex -----*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines the APValue class.
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_CLANG_AST_APVALUE_H
15 #define LLVM_CLANG_AST_APVALUE_H
17 #include "clang/Basic/LLVM.h"
18 #include "llvm/ADT/APFloat.h"
19 #include "llvm/ADT/APSInt.h"
20 #include "llvm/ADT/PointerIntPair.h"
21 #include "llvm/ADT/PointerUnion.h"
27 class DiagnosticBuilder;
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]
39 typedef llvm::APSInt APSInt;
40 typedef llvm::APFloat APFloat;
56 typedef llvm::PointerUnion<const ValueDecl *, const Expr *> LValueBase;
57 typedef llvm::PointerIntPair<const Decl *, 1, bool> BaseOrMemberType;
58 union LValuePathEntry {
59 /// BaseOrMember - The FieldDecl or CXXRecordDecl indicating the next item
60 /// in the path. An opaque value of type BaseOrMemberType.
62 /// ArrayIndex - The array index of the next item in the path.
65 struct NoLValuePath {};
66 struct UninitArray {};
67 struct UninitStruct {};
71 struct ComplexAPSInt {
73 ComplexAPSInt() : Real(1), Imag(1) {}
75 struct ComplexAPFloat {
77 ComplexAPFloat() : Real(0.0), Imag(0.0) {}
83 Vec() : Elts(nullptr), NumElts(0) {}
84 ~Vec() { delete[] Elts; }
88 unsigned NumElts, ArrSize;
89 Arr(unsigned NumElts, unsigned ArrSize);
96 StructData(unsigned NumBases, unsigned NumFields);
100 const FieldDecl *Field;
105 struct AddrLabelDiffData {
106 const AddrLabelExpr* LHSExpr;
107 const AddrLabelExpr* RHSExpr;
109 struct MemberPointerData;
111 // We ensure elsewhere that Data is big enough for LV and MemberPointerData.
112 typedef llvm::AlignedCharArrayUnion<void *, APSInt, APFloat, ComplexAPSInt,
113 ComplexAPFloat, Vec, Arr, StructData,
114 UnionData, AddrLabelDiffData> DataType;
115 static const size_t DataSize = sizeof(DataType);
120 APValue() : Kind(Uninitialized) {}
121 explicit APValue(APSInt I) : Kind(Uninitialized) {
122 MakeInt(); setInt(std::move(I));
124 explicit APValue(APFloat F) : Kind(Uninitialized) {
125 MakeFloat(); setFloat(std::move(F));
127 explicit APValue(const APValue *E, unsigned N) : Kind(Uninitialized) {
128 MakeVector(); setVector(E, N);
130 APValue(APSInt R, APSInt I) : Kind(Uninitialized) {
131 MakeComplexInt(); setComplexInt(std::move(R), std::move(I));
133 APValue(APFloat R, APFloat I) : Kind(Uninitialized) {
134 MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I));
136 APValue(const APValue &RHS);
137 APValue(APValue &&RHS) : Kind(Uninitialized) { swap(RHS); }
138 APValue(LValueBase B, const CharUnits &O, NoLValuePath N, unsigned CallIndex)
139 : Kind(Uninitialized) {
140 MakeLValue(); setLValue(B, O, N, CallIndex);
142 APValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path,
143 bool OnePastTheEnd, unsigned CallIndex)
144 : Kind(Uninitialized) {
145 MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, CallIndex);
147 APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(Uninitialized) {
148 MakeArray(InitElts, Size);
150 APValue(UninitStruct, unsigned B, unsigned M) : Kind(Uninitialized) {
153 explicit APValue(const FieldDecl *D, const APValue &V = APValue())
154 : Kind(Uninitialized) {
155 MakeUnion(); setUnion(D, V);
157 APValue(const ValueDecl *Member, bool IsDerivedMember,
158 ArrayRef<const CXXRecordDecl*> Path) : Kind(Uninitialized) {
159 MakeMemberPointer(Member, IsDerivedMember, Path);
161 APValue(const AddrLabelExpr* LHSExpr, const AddrLabelExpr* RHSExpr)
162 : Kind(Uninitialized) {
163 MakeAddrLabelDiff(); setAddrLabelDiff(LHSExpr, RHSExpr);
170 /// \brief Returns whether the object performed allocations.
172 /// If APValues are constructed via placement new, \c needsCleanup()
173 /// indicates whether the destructor must be called in order to correctly
174 /// free all allocated memory.
175 bool needsCleanup() const;
177 /// \brief Swaps the contents of this and the given APValue.
178 void swap(APValue &RHS);
180 ValueKind getKind() const { return Kind; }
181 bool isUninit() const { return Kind == Uninitialized; }
182 bool isInt() const { return Kind == Int; }
183 bool isFloat() const { return Kind == Float; }
184 bool isComplexInt() const { return Kind == ComplexInt; }
185 bool isComplexFloat() const { return Kind == ComplexFloat; }
186 bool isLValue() const { return Kind == LValue; }
187 bool isVector() const { return Kind == Vector; }
188 bool isArray() const { return Kind == Array; }
189 bool isStruct() const { return Kind == Struct; }
190 bool isUnion() const { return Kind == Union; }
191 bool isMemberPointer() const { return Kind == MemberPointer; }
192 bool isAddrLabelDiff() const { return Kind == AddrLabelDiff; }
195 void dump(raw_ostream &OS) const;
197 void printPretty(raw_ostream &OS, ASTContext &Ctx, QualType Ty) const;
198 std::string getAsString(ASTContext &Ctx, QualType Ty) const;
201 assert(isInt() && "Invalid accessor");
202 return *(APSInt*)(char*)Data.buffer;
204 const APSInt &getInt() const {
205 return const_cast<APValue*>(this)->getInt();
208 APFloat &getFloat() {
209 assert(isFloat() && "Invalid accessor");
210 return *(APFloat*)(char*)Data.buffer;
212 const APFloat &getFloat() const {
213 return const_cast<APValue*>(this)->getFloat();
216 APSInt &getComplexIntReal() {
217 assert(isComplexInt() && "Invalid accessor");
218 return ((ComplexAPSInt*)(char*)Data.buffer)->Real;
220 const APSInt &getComplexIntReal() const {
221 return const_cast<APValue*>(this)->getComplexIntReal();
224 APSInt &getComplexIntImag() {
225 assert(isComplexInt() && "Invalid accessor");
226 return ((ComplexAPSInt*)(char*)Data.buffer)->Imag;
228 const APSInt &getComplexIntImag() const {
229 return const_cast<APValue*>(this)->getComplexIntImag();
232 APFloat &getComplexFloatReal() {
233 assert(isComplexFloat() && "Invalid accessor");
234 return ((ComplexAPFloat*)(char*)Data.buffer)->Real;
236 const APFloat &getComplexFloatReal() const {
237 return const_cast<APValue*>(this)->getComplexFloatReal();
240 APFloat &getComplexFloatImag() {
241 assert(isComplexFloat() && "Invalid accessor");
242 return ((ComplexAPFloat*)(char*)Data.buffer)->Imag;
244 const APFloat &getComplexFloatImag() const {
245 return const_cast<APValue*>(this)->getComplexFloatImag();
248 const LValueBase getLValueBase() const;
249 CharUnits &getLValueOffset();
250 const CharUnits &getLValueOffset() const {
251 return const_cast<APValue*>(this)->getLValueOffset();
253 bool isLValueOnePastTheEnd() const;
254 bool hasLValuePath() const;
255 ArrayRef<LValuePathEntry> getLValuePath() const;
256 unsigned getLValueCallIndex() const;
258 APValue &getVectorElt(unsigned I) {
259 assert(isVector() && "Invalid accessor");
260 assert(I < getVectorLength() && "Index out of range");
261 return ((Vec*)(char*)Data.buffer)->Elts[I];
263 const APValue &getVectorElt(unsigned I) const {
264 return const_cast<APValue*>(this)->getVectorElt(I);
266 unsigned getVectorLength() const {
267 assert(isVector() && "Invalid accessor");
268 return ((const Vec*)(const void *)Data.buffer)->NumElts;
271 APValue &getArrayInitializedElt(unsigned I) {
272 assert(isArray() && "Invalid accessor");
273 assert(I < getArrayInitializedElts() && "Index out of range");
274 return ((Arr*)(char*)Data.buffer)->Elts[I];
276 const APValue &getArrayInitializedElt(unsigned I) const {
277 return const_cast<APValue*>(this)->getArrayInitializedElt(I);
279 bool hasArrayFiller() const {
280 return getArrayInitializedElts() != getArraySize();
282 APValue &getArrayFiller() {
283 assert(isArray() && "Invalid accessor");
284 assert(hasArrayFiller() && "No array filler");
285 return ((Arr*)(char*)Data.buffer)->Elts[getArrayInitializedElts()];
287 const APValue &getArrayFiller() const {
288 return const_cast<APValue*>(this)->getArrayFiller();
290 unsigned getArrayInitializedElts() const {
291 assert(isArray() && "Invalid accessor");
292 return ((const Arr*)(const void *)Data.buffer)->NumElts;
294 unsigned getArraySize() const {
295 assert(isArray() && "Invalid accessor");
296 return ((const Arr*)(const void *)Data.buffer)->ArrSize;
299 unsigned getStructNumBases() const {
300 assert(isStruct() && "Invalid accessor");
301 return ((const StructData*)(const char*)Data.buffer)->NumBases;
303 unsigned getStructNumFields() const {
304 assert(isStruct() && "Invalid accessor");
305 return ((const StructData*)(const char*)Data.buffer)->NumFields;
307 APValue &getStructBase(unsigned i) {
308 assert(isStruct() && "Invalid accessor");
309 return ((StructData*)(char*)Data.buffer)->Elts[i];
311 APValue &getStructField(unsigned i) {
312 assert(isStruct() && "Invalid accessor");
313 return ((StructData*)(char*)Data.buffer)->Elts[getStructNumBases() + i];
315 const APValue &getStructBase(unsigned i) const {
316 return const_cast<APValue*>(this)->getStructBase(i);
318 const APValue &getStructField(unsigned i) const {
319 return const_cast<APValue*>(this)->getStructField(i);
322 const FieldDecl *getUnionField() const {
323 assert(isUnion() && "Invalid accessor");
324 return ((const UnionData*)(const char*)Data.buffer)->Field;
326 APValue &getUnionValue() {
327 assert(isUnion() && "Invalid accessor");
328 return *((UnionData*)(char*)Data.buffer)->Value;
330 const APValue &getUnionValue() const {
331 return const_cast<APValue*>(this)->getUnionValue();
334 const ValueDecl *getMemberPointerDecl() const;
335 bool isMemberPointerToDerivedMember() const;
336 ArrayRef<const CXXRecordDecl*> getMemberPointerPath() const;
338 const AddrLabelExpr* getAddrLabelDiffLHS() const {
339 assert(isAddrLabelDiff() && "Invalid accessor");
340 return ((const AddrLabelDiffData*)(const char*)Data.buffer)->LHSExpr;
342 const AddrLabelExpr* getAddrLabelDiffRHS() const {
343 assert(isAddrLabelDiff() && "Invalid accessor");
344 return ((const AddrLabelDiffData*)(const char*)Data.buffer)->RHSExpr;
347 void setInt(APSInt I) {
348 assert(isInt() && "Invalid accessor");
349 *(APSInt *)(char *)Data.buffer = std::move(I);
351 void setFloat(APFloat F) {
352 assert(isFloat() && "Invalid accessor");
353 *(APFloat *)(char *)Data.buffer = std::move(F);
355 void setVector(const APValue *E, unsigned N) {
356 assert(isVector() && "Invalid accessor");
357 ((Vec*)(char*)Data.buffer)->Elts = new APValue[N];
358 ((Vec*)(char*)Data.buffer)->NumElts = N;
359 for (unsigned i = 0; i != N; ++i)
360 ((Vec*)(char*)Data.buffer)->Elts[i] = E[i];
362 void setComplexInt(APSInt R, APSInt I) {
363 assert(R.getBitWidth() == I.getBitWidth() &&
364 "Invalid complex int (type mismatch).");
365 assert(isComplexInt() && "Invalid accessor");
366 ((ComplexAPSInt *)(char *)Data.buffer)->Real = std::move(R);
367 ((ComplexAPSInt *)(char *)Data.buffer)->Imag = std::move(I);
369 void setComplexFloat(APFloat R, APFloat I) {
370 assert(&R.getSemantics() == &I.getSemantics() &&
371 "Invalid complex float (type mismatch).");
372 assert(isComplexFloat() && "Invalid accessor");
373 ((ComplexAPFloat *)(char *)Data.buffer)->Real = std::move(R);
374 ((ComplexAPFloat *)(char *)Data.buffer)->Imag = std::move(I);
376 void setLValue(LValueBase B, const CharUnits &O, NoLValuePath,
378 void setLValue(LValueBase B, const CharUnits &O,
379 ArrayRef<LValuePathEntry> Path, bool OnePastTheEnd,
381 void setUnion(const FieldDecl *Field, const APValue &Value) {
382 assert(isUnion() && "Invalid accessor");
383 ((UnionData*)(char*)Data.buffer)->Field = Field;
384 *((UnionData*)(char*)Data.buffer)->Value = Value;
386 void setAddrLabelDiff(const AddrLabelExpr* LHSExpr,
387 const AddrLabelExpr* RHSExpr) {
388 ((AddrLabelDiffData*)(char*)Data.buffer)->LHSExpr = LHSExpr;
389 ((AddrLabelDiffData*)(char*)Data.buffer)->RHSExpr = RHSExpr;
392 /// Assign by swapping from a copy of the RHS.
393 APValue &operator=(APValue RHS) {
399 void DestroyDataAndMakeUninit();
401 if (Kind != Uninitialized)
402 DestroyDataAndMakeUninit();
405 assert(isUninit() && "Bad state change");
406 new ((void*)Data.buffer) APSInt(1);
410 assert(isUninit() && "Bad state change");
411 new ((void*)(char*)Data.buffer) APFloat(0.0);
415 assert(isUninit() && "Bad state change");
416 new ((void*)(char*)Data.buffer) Vec();
419 void MakeComplexInt() {
420 assert(isUninit() && "Bad state change");
421 new ((void*)(char*)Data.buffer) ComplexAPSInt();
424 void MakeComplexFloat() {
425 assert(isUninit() && "Bad state change");
426 new ((void*)(char*)Data.buffer) ComplexAPFloat();
430 void MakeArray(unsigned InitElts, unsigned Size);
431 void MakeStruct(unsigned B, unsigned M) {
432 assert(isUninit() && "Bad state change");
433 new ((void*)(char*)Data.buffer) StructData(B, M);
437 assert(isUninit() && "Bad state change");
438 new ((void*)(char*)Data.buffer) UnionData();
441 void MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
442 ArrayRef<const CXXRecordDecl*> Path);
443 void MakeAddrLabelDiff() {
444 assert(isUninit() && "Bad state change");
445 new ((void*)(char*)Data.buffer) AddrLabelDiffData();
446 Kind = AddrLabelDiff;
450 } // end namespace clang.