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 Returns whether the object performed allocations.
173 /// If APValues are constructed via placement new, \c needsCleanup()
174 /// indicates whether the destructor must be called in order to correctly
175 /// free all allocated memory.
176 bool needsCleanup() const;
178 /// \brief Swaps the contents of this and the given APValue.
179 void swap(APValue &RHS);
181 ValueKind getKind() const { return Kind; }
182 bool isUninit() const { return Kind == Uninitialized; }
183 bool isInt() const { return Kind == Int; }
184 bool isFloat() const { return Kind == Float; }
185 bool isComplexInt() const { return Kind == ComplexInt; }
186 bool isComplexFloat() const { return Kind == ComplexFloat; }
187 bool isLValue() const { return Kind == LValue; }
188 bool isVector() const { return Kind == Vector; }
189 bool isArray() const { return Kind == Array; }
190 bool isStruct() const { return Kind == Struct; }
191 bool isUnion() const { return Kind == Union; }
192 bool isMemberPointer() const { return Kind == MemberPointer; }
193 bool isAddrLabelDiff() const { return Kind == AddrLabelDiff; }
196 void dump(raw_ostream &OS) const;
198 void printPretty(raw_ostream &OS, ASTContext &Ctx, QualType Ty) const;
199 std::string getAsString(ASTContext &Ctx, QualType Ty) const;
202 assert(isInt() && "Invalid accessor");
203 return *(APSInt*)(char*)Data;
205 const APSInt &getInt() const {
206 return const_cast<APValue*>(this)->getInt();
209 APFloat &getFloat() {
210 assert(isFloat() && "Invalid accessor");
211 return *(APFloat*)(char*)Data;
213 const APFloat &getFloat() const {
214 return const_cast<APValue*>(this)->getFloat();
217 APSInt &getComplexIntReal() {
218 assert(isComplexInt() && "Invalid accessor");
219 return ((ComplexAPSInt*)(char*)Data)->Real;
221 const APSInt &getComplexIntReal() const {
222 return const_cast<APValue*>(this)->getComplexIntReal();
225 APSInt &getComplexIntImag() {
226 assert(isComplexInt() && "Invalid accessor");
227 return ((ComplexAPSInt*)(char*)Data)->Imag;
229 const APSInt &getComplexIntImag() const {
230 return const_cast<APValue*>(this)->getComplexIntImag();
233 APFloat &getComplexFloatReal() {
234 assert(isComplexFloat() && "Invalid accessor");
235 return ((ComplexAPFloat*)(char*)Data)->Real;
237 const APFloat &getComplexFloatReal() const {
238 return const_cast<APValue*>(this)->getComplexFloatReal();
241 APFloat &getComplexFloatImag() {
242 assert(isComplexFloat() && "Invalid accessor");
243 return ((ComplexAPFloat*)(char*)Data)->Imag;
245 const APFloat &getComplexFloatImag() const {
246 return const_cast<APValue*>(this)->getComplexFloatImag();
249 const LValueBase getLValueBase() const;
250 CharUnits &getLValueOffset();
251 const CharUnits &getLValueOffset() const {
252 return const_cast<APValue*>(this)->getLValueOffset();
254 bool isLValueOnePastTheEnd() const;
255 bool hasLValuePath() const;
256 ArrayRef<LValuePathEntry> getLValuePath() const;
257 unsigned getLValueCallIndex() const;
259 APValue &getVectorElt(unsigned I) {
260 assert(isVector() && "Invalid accessor");
261 assert(I < getVectorLength() && "Index out of range");
262 return ((Vec*)(char*)Data)->Elts[I];
264 const APValue &getVectorElt(unsigned I) const {
265 return const_cast<APValue*>(this)->getVectorElt(I);
267 unsigned getVectorLength() const {
268 assert(isVector() && "Invalid accessor");
269 return ((const Vec*)(const void *)Data)->NumElts;
272 APValue &getArrayInitializedElt(unsigned I) {
273 assert(isArray() && "Invalid accessor");
274 assert(I < getArrayInitializedElts() && "Index out of range");
275 return ((Arr*)(char*)Data)->Elts[I];
277 const APValue &getArrayInitializedElt(unsigned I) const {
278 return const_cast<APValue*>(this)->getArrayInitializedElt(I);
280 bool hasArrayFiller() const {
281 return getArrayInitializedElts() != getArraySize();
283 APValue &getArrayFiller() {
284 assert(isArray() && "Invalid accessor");
285 assert(hasArrayFiller() && "No array filler");
286 return ((Arr*)(char*)Data)->Elts[getArrayInitializedElts()];
288 const APValue &getArrayFiller() const {
289 return const_cast<APValue*>(this)->getArrayFiller();
291 unsigned getArrayInitializedElts() const {
292 assert(isArray() && "Invalid accessor");
293 return ((const Arr*)(const void *)Data)->NumElts;
295 unsigned getArraySize() const {
296 assert(isArray() && "Invalid accessor");
297 return ((const Arr*)(const void *)Data)->ArrSize;
300 unsigned getStructNumBases() const {
301 assert(isStruct() && "Invalid accessor");
302 return ((const StructData*)(const char*)Data)->NumBases;
304 unsigned getStructNumFields() const {
305 assert(isStruct() && "Invalid accessor");
306 return ((const StructData*)(const char*)Data)->NumFields;
308 APValue &getStructBase(unsigned i) {
309 assert(isStruct() && "Invalid accessor");
310 return ((StructData*)(char*)Data)->Elts[i];
312 APValue &getStructField(unsigned i) {
313 assert(isStruct() && "Invalid accessor");
314 return ((StructData*)(char*)Data)->Elts[getStructNumBases() + i];
316 const APValue &getStructBase(unsigned i) const {
317 return const_cast<APValue*>(this)->getStructBase(i);
319 const APValue &getStructField(unsigned i) const {
320 return const_cast<APValue*>(this)->getStructField(i);
323 const FieldDecl *getUnionField() const {
324 assert(isUnion() && "Invalid accessor");
325 return ((const UnionData*)(const char*)Data)->Field;
327 APValue &getUnionValue() {
328 assert(isUnion() && "Invalid accessor");
329 return *((UnionData*)(char*)Data)->Value;
331 const APValue &getUnionValue() const {
332 return const_cast<APValue*>(this)->getUnionValue();
335 const ValueDecl *getMemberPointerDecl() const;
336 bool isMemberPointerToDerivedMember() const;
337 ArrayRef<const CXXRecordDecl*> getMemberPointerPath() const;
339 const AddrLabelExpr* getAddrLabelDiffLHS() const {
340 assert(isAddrLabelDiff() && "Invalid accessor");
341 return ((const AddrLabelDiffData*)(const char*)Data)->LHSExpr;
343 const AddrLabelExpr* getAddrLabelDiffRHS() const {
344 assert(isAddrLabelDiff() && "Invalid accessor");
345 return ((const AddrLabelDiffData*)(const char*)Data)->RHSExpr;
348 void setInt(const APSInt &I) {
349 assert(isInt() && "Invalid accessor");
350 *(APSInt*)(char*)Data = I;
352 void setFloat(const APFloat &F) {
353 assert(isFloat() && "Invalid accessor");
354 *(APFloat*)(char*)Data = F;
356 void setVector(const APValue *E, unsigned N) {
357 assert(isVector() && "Invalid accessor");
358 ((Vec*)(char*)Data)->Elts = new APValue[N];
359 ((Vec*)(char*)Data)->NumElts = N;
360 for (unsigned i = 0; i != N; ++i)
361 ((Vec*)(char*)Data)->Elts[i] = E[i];
363 void setComplexInt(const APSInt &R, const APSInt &I) {
364 assert(R.getBitWidth() == I.getBitWidth() &&
365 "Invalid complex int (type mismatch).");
366 assert(isComplexInt() && "Invalid accessor");
367 ((ComplexAPSInt*)(char*)Data)->Real = R;
368 ((ComplexAPSInt*)(char*)Data)->Imag = I;
370 void setComplexFloat(const APFloat &R, const APFloat &I) {
371 assert(&R.getSemantics() == &I.getSemantics() &&
372 "Invalid complex float (type mismatch).");
373 assert(isComplexFloat() && "Invalid accessor");
374 ((ComplexAPFloat*)(char*)Data)->Real = R;
375 ((ComplexAPFloat*)(char*)Data)->Imag = I;
377 void setLValue(LValueBase B, const CharUnits &O, NoLValuePath,
379 void setLValue(LValueBase B, const CharUnits &O,
380 ArrayRef<LValuePathEntry> Path, bool OnePastTheEnd,
382 void setUnion(const FieldDecl *Field, const APValue &Value) {
383 assert(isUnion() && "Invalid accessor");
384 ((UnionData*)(char*)Data)->Field = Field;
385 *((UnionData*)(char*)Data)->Value = Value;
387 void setAddrLabelDiff(const AddrLabelExpr* LHSExpr,
388 const AddrLabelExpr* RHSExpr) {
389 ((AddrLabelDiffData*)(char*)Data)->LHSExpr = LHSExpr;
390 ((AddrLabelDiffData*)(char*)Data)->RHSExpr = RHSExpr;
393 /// Assign by swapping from a copy of the RHS.
394 APValue &operator=(APValue RHS) {
400 void DestroyDataAndMakeUninit();
402 if (Kind != Uninitialized)
403 DestroyDataAndMakeUninit();
406 assert(isUninit() && "Bad state change");
407 new ((void*)Data) APSInt(1);
411 assert(isUninit() && "Bad state change");
412 new ((void*)(char*)Data) APFloat(0.0);
416 assert(isUninit() && "Bad state change");
417 new ((void*)(char*)Data) Vec();
420 void MakeComplexInt() {
421 assert(isUninit() && "Bad state change");
422 new ((void*)(char*)Data) ComplexAPSInt();
425 void MakeComplexFloat() {
426 assert(isUninit() && "Bad state change");
427 new ((void*)(char*)Data) ComplexAPFloat();
431 void MakeArray(unsigned InitElts, unsigned Size);
432 void MakeStruct(unsigned B, unsigned M) {
433 assert(isUninit() && "Bad state change");
434 new ((void*)(char*)Data) StructData(B, M);
438 assert(isUninit() && "Bad state change");
439 new ((void*)(char*)Data) UnionData();
442 void MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
443 ArrayRef<const CXXRecordDecl*> Path);
444 void MakeAddrLabelDiff() {
445 assert(isUninit() && "Bad state change");
446 new ((void*)(char*)Data) AddrLabelDiffData();
447 Kind = AddrLabelDiff;
451 } // end namespace clang.