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(0), 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;
112 MaxSize = (sizeof(ComplexAPSInt) > sizeof(ComplexAPFloat) ?
113 sizeof(ComplexAPSInt) : sizeof(ComplexAPFloat))
122 APValue() : Kind(Uninitialized) {}
123 explicit APValue(const APSInt &I) : Kind(Uninitialized) {
124 MakeInt(); setInt(I);
126 explicit APValue(const APFloat &F) : Kind(Uninitialized) {
127 MakeFloat(); setFloat(F);
129 explicit APValue(const APValue *E, unsigned N) : Kind(Uninitialized) {
130 MakeVector(); setVector(E, N);
132 APValue(const APSInt &R, const APSInt &I) : Kind(Uninitialized) {
133 MakeComplexInt(); setComplexInt(R, I);
135 APValue(const APFloat &R, const APFloat &I) : Kind(Uninitialized) {
136 MakeComplexFloat(); setComplexFloat(R, I);
138 APValue(const APValue &RHS);
139 APValue(LValueBase B, const CharUnits &O, NoLValuePath N, unsigned CallIndex)
140 : Kind(Uninitialized) {
141 MakeLValue(); setLValue(B, O, N, CallIndex);
143 APValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path,
144 bool OnePastTheEnd, unsigned CallIndex)
145 : Kind(Uninitialized) {
146 MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, CallIndex);
148 APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(Uninitialized) {
149 MakeArray(InitElts, Size);
151 APValue(UninitStruct, unsigned B, unsigned M) : Kind(Uninitialized) {
154 explicit APValue(const FieldDecl *D, const APValue &V = APValue())
155 : Kind(Uninitialized) {
156 MakeUnion(); setUnion(D, V);
158 APValue(const ValueDecl *Member, bool IsDerivedMember,
159 ArrayRef<const CXXRecordDecl*> Path) : Kind(Uninitialized) {
160 MakeMemberPointer(Member, IsDerivedMember, Path);
162 APValue(const AddrLabelExpr* LHSExpr, const AddrLabelExpr* RHSExpr)
163 : Kind(Uninitialized) {
164 MakeAddrLabelDiff(); setAddrLabelDiff(LHSExpr, RHSExpr);
171 /// \brief Swaps the contents of this and the given APValue.
172 void swap(APValue &RHS);
174 ValueKind getKind() const { return Kind; }
175 bool isUninit() const { return Kind == Uninitialized; }
176 bool isInt() const { return Kind == Int; }
177 bool isFloat() const { return Kind == Float; }
178 bool isComplexInt() const { return Kind == ComplexInt; }
179 bool isComplexFloat() const { return Kind == ComplexFloat; }
180 bool isLValue() const { return Kind == LValue; }
181 bool isVector() const { return Kind == Vector; }
182 bool isArray() const { return Kind == Array; }
183 bool isStruct() const { return Kind == Struct; }
184 bool isUnion() const { return Kind == Union; }
185 bool isMemberPointer() const { return Kind == MemberPointer; }
186 bool isAddrLabelDiff() const { return Kind == AddrLabelDiff; }
189 void dump(raw_ostream &OS) const;
191 void printPretty(raw_ostream &OS, ASTContext &Ctx, QualType Ty) const;
192 std::string getAsString(ASTContext &Ctx, QualType Ty) const;
195 assert(isInt() && "Invalid accessor");
196 return *(APSInt*)(char*)Data;
198 const APSInt &getInt() const {
199 return const_cast<APValue*>(this)->getInt();
202 APFloat &getFloat() {
203 assert(isFloat() && "Invalid accessor");
204 return *(APFloat*)(char*)Data;
206 const APFloat &getFloat() const {
207 return const_cast<APValue*>(this)->getFloat();
210 APSInt &getComplexIntReal() {
211 assert(isComplexInt() && "Invalid accessor");
212 return ((ComplexAPSInt*)(char*)Data)->Real;
214 const APSInt &getComplexIntReal() const {
215 return const_cast<APValue*>(this)->getComplexIntReal();
218 APSInt &getComplexIntImag() {
219 assert(isComplexInt() && "Invalid accessor");
220 return ((ComplexAPSInt*)(char*)Data)->Imag;
222 const APSInt &getComplexIntImag() const {
223 return const_cast<APValue*>(this)->getComplexIntImag();
226 APFloat &getComplexFloatReal() {
227 assert(isComplexFloat() && "Invalid accessor");
228 return ((ComplexAPFloat*)(char*)Data)->Real;
230 const APFloat &getComplexFloatReal() const {
231 return const_cast<APValue*>(this)->getComplexFloatReal();
234 APFloat &getComplexFloatImag() {
235 assert(isComplexFloat() && "Invalid accessor");
236 return ((ComplexAPFloat*)(char*)Data)->Imag;
238 const APFloat &getComplexFloatImag() const {
239 return const_cast<APValue*>(this)->getComplexFloatImag();
242 const LValueBase getLValueBase() const;
243 CharUnits &getLValueOffset();
244 const CharUnits &getLValueOffset() const {
245 return const_cast<APValue*>(this)->getLValueOffset();
247 bool isLValueOnePastTheEnd() const;
248 bool hasLValuePath() const;
249 ArrayRef<LValuePathEntry> getLValuePath() const;
250 unsigned getLValueCallIndex() const;
252 APValue &getVectorElt(unsigned I) {
253 assert(isVector() && "Invalid accessor");
254 assert(I < getVectorLength() && "Index out of range");
255 return ((Vec*)(char*)Data)->Elts[I];
257 const APValue &getVectorElt(unsigned I) const {
258 return const_cast<APValue*>(this)->getVectorElt(I);
260 unsigned getVectorLength() const {
261 assert(isVector() && "Invalid accessor");
262 return ((const Vec*)(const void *)Data)->NumElts;
265 APValue &getArrayInitializedElt(unsigned I) {
266 assert(isArray() && "Invalid accessor");
267 assert(I < getArrayInitializedElts() && "Index out of range");
268 return ((Arr*)(char*)Data)->Elts[I];
270 const APValue &getArrayInitializedElt(unsigned I) const {
271 return const_cast<APValue*>(this)->getArrayInitializedElt(I);
273 bool hasArrayFiller() const {
274 return getArrayInitializedElts() != getArraySize();
276 APValue &getArrayFiller() {
277 assert(isArray() && "Invalid accessor");
278 assert(hasArrayFiller() && "No array filler");
279 return ((Arr*)(char*)Data)->Elts[getArrayInitializedElts()];
281 const APValue &getArrayFiller() const {
282 return const_cast<APValue*>(this)->getArrayFiller();
284 unsigned getArrayInitializedElts() const {
285 assert(isArray() && "Invalid accessor");
286 return ((const Arr*)(const void *)Data)->NumElts;
288 unsigned getArraySize() const {
289 assert(isArray() && "Invalid accessor");
290 return ((const Arr*)(const void *)Data)->ArrSize;
293 unsigned getStructNumBases() const {
294 assert(isStruct() && "Invalid accessor");
295 return ((const StructData*)(const char*)Data)->NumBases;
297 unsigned getStructNumFields() const {
298 assert(isStruct() && "Invalid accessor");
299 return ((const StructData*)(const char*)Data)->NumFields;
301 APValue &getStructBase(unsigned i) {
302 assert(isStruct() && "Invalid accessor");
303 return ((StructData*)(char*)Data)->Elts[i];
305 APValue &getStructField(unsigned i) {
306 assert(isStruct() && "Invalid accessor");
307 return ((StructData*)(char*)Data)->Elts[getStructNumBases() + i];
309 const APValue &getStructBase(unsigned i) const {
310 return const_cast<APValue*>(this)->getStructBase(i);
312 const APValue &getStructField(unsigned i) const {
313 return const_cast<APValue*>(this)->getStructField(i);
316 const FieldDecl *getUnionField() const {
317 assert(isUnion() && "Invalid accessor");
318 return ((const UnionData*)(const char*)Data)->Field;
320 APValue &getUnionValue() {
321 assert(isUnion() && "Invalid accessor");
322 return *((UnionData*)(char*)Data)->Value;
324 const APValue &getUnionValue() const {
325 return const_cast<APValue*>(this)->getUnionValue();
328 const ValueDecl *getMemberPointerDecl() const;
329 bool isMemberPointerToDerivedMember() const;
330 ArrayRef<const CXXRecordDecl*> getMemberPointerPath() const;
332 const AddrLabelExpr* getAddrLabelDiffLHS() const {
333 assert(isAddrLabelDiff() && "Invalid accessor");
334 return ((const AddrLabelDiffData*)(const char*)Data)->LHSExpr;
336 const AddrLabelExpr* getAddrLabelDiffRHS() const {
337 assert(isAddrLabelDiff() && "Invalid accessor");
338 return ((const AddrLabelDiffData*)(const char*)Data)->RHSExpr;
341 void setInt(const APSInt &I) {
342 assert(isInt() && "Invalid accessor");
343 *(APSInt*)(char*)Data = I;
345 void setFloat(const APFloat &F) {
346 assert(isFloat() && "Invalid accessor");
347 *(APFloat*)(char*)Data = F;
349 void setVector(const APValue *E, unsigned N) {
350 assert(isVector() && "Invalid accessor");
351 ((Vec*)(char*)Data)->Elts = new APValue[N];
352 ((Vec*)(char*)Data)->NumElts = N;
353 for (unsigned i = 0; i != N; ++i)
354 ((Vec*)(char*)Data)->Elts[i] = E[i];
356 void setComplexInt(const APSInt &R, const APSInt &I) {
357 assert(R.getBitWidth() == I.getBitWidth() &&
358 "Invalid complex int (type mismatch).");
359 assert(isComplexInt() && "Invalid accessor");
360 ((ComplexAPSInt*)(char*)Data)->Real = R;
361 ((ComplexAPSInt*)(char*)Data)->Imag = I;
363 void setComplexFloat(const APFloat &R, const APFloat &I) {
364 assert(&R.getSemantics() == &I.getSemantics() &&
365 "Invalid complex float (type mismatch).");
366 assert(isComplexFloat() && "Invalid accessor");
367 ((ComplexAPFloat*)(char*)Data)->Real = R;
368 ((ComplexAPFloat*)(char*)Data)->Imag = I;
370 void setLValue(LValueBase B, const CharUnits &O, NoLValuePath,
372 void setLValue(LValueBase B, const CharUnits &O,
373 ArrayRef<LValuePathEntry> Path, bool OnePastTheEnd,
375 void setUnion(const FieldDecl *Field, const APValue &Value) {
376 assert(isUnion() && "Invalid accessor");
377 ((UnionData*)(char*)Data)->Field = Field;
378 *((UnionData*)(char*)Data)->Value = Value;
380 void setAddrLabelDiff(const AddrLabelExpr* LHSExpr,
381 const AddrLabelExpr* RHSExpr) {
382 ((AddrLabelDiffData*)(char*)Data)->LHSExpr = LHSExpr;
383 ((AddrLabelDiffData*)(char*)Data)->RHSExpr = RHSExpr;
386 /// Assign by swapping from a copy of the RHS.
387 APValue &operator=(APValue RHS) {
393 void DestroyDataAndMakeUninit();
395 if (Kind != Uninitialized)
396 DestroyDataAndMakeUninit();
399 assert(isUninit() && "Bad state change");
400 new ((void*)Data) APSInt(1);
404 assert(isUninit() && "Bad state change");
405 new ((void*)(char*)Data) APFloat(0.0);
409 assert(isUninit() && "Bad state change");
410 new ((void*)(char*)Data) Vec();
413 void MakeComplexInt() {
414 assert(isUninit() && "Bad state change");
415 new ((void*)(char*)Data) ComplexAPSInt();
418 void MakeComplexFloat() {
419 assert(isUninit() && "Bad state change");
420 new ((void*)(char*)Data) ComplexAPFloat();
424 void MakeArray(unsigned InitElts, unsigned Size);
425 void MakeStruct(unsigned B, unsigned M) {
426 assert(isUninit() && "Bad state change");
427 new ((void*)(char*)Data) StructData(B, M);
431 assert(isUninit() && "Bad state change");
432 new ((void*)(char*)Data) UnionData();
435 void MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
436 ArrayRef<const CXXRecordDecl*> Path);
437 void MakeAddrLabelDiff() {
438 assert(isUninit() && "Bad state change");
439 new ((void*)(char*)Data) AddrLabelDiffData();
440 Kind = AddrLabelDiff;
444 } // end namespace clang.