• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===--- APValue.h - Union class for APFloat/APSInt/Complex -----*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //  This file defines the APValue class.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_CLANG_AST_APVALUE_H
15 #define LLVM_CLANG_AST_APVALUE_H
16 
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"
22 
23 namespace clang {
24   class AddrLabelExpr;
25   class ASTContext;
26   class CharUnits;
27   class DiagnosticBuilder;
28   class Expr;
29   class FieldDecl;
30   class Decl;
31   class ValueDecl;
32   class CXXRecordDecl;
33   class QualType;
34 
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]
38 class APValue {
39   typedef llvm::APSInt APSInt;
40   typedef llvm::APFloat APFloat;
41 public:
42   enum ValueKind {
43     Uninitialized,
44     Int,
45     Float,
46     ComplexInt,
47     ComplexFloat,
48     LValue,
49     Vector,
50     Array,
51     Struct,
52     Union,
53     MemberPointer,
54     AddrLabelDiff
55   };
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.
61     void *BaseOrMember;
62     /// ArrayIndex - The array index of the next item in the path.
63     uint64_t ArrayIndex;
64   };
65   struct NoLValuePath {};
66   struct UninitArray {};
67   struct UninitStruct {};
68 private:
69   ValueKind Kind;
70 
71   struct ComplexAPSInt {
72     APSInt Real, Imag;
ComplexAPSIntComplexAPSInt73     ComplexAPSInt() : Real(1), Imag(1) {}
74   };
75   struct ComplexAPFloat {
76     APFloat Real, Imag;
ComplexAPFloatComplexAPFloat77     ComplexAPFloat() : Real(0.0), Imag(0.0) {}
78   };
79   struct LV;
80   struct Vec {
81     APValue *Elts;
82     unsigned NumElts;
VecVec83     Vec() : Elts(nullptr), NumElts(0) {}
~VecVec84     ~Vec() { delete[] Elts; }
85   };
86   struct Arr {
87     APValue *Elts;
88     unsigned NumElts, ArrSize;
89     Arr(unsigned NumElts, unsigned ArrSize);
90     ~Arr();
91   };
92   struct StructData {
93     APValue *Elts;
94     unsigned NumBases;
95     unsigned NumFields;
96     StructData(unsigned NumBases, unsigned NumFields);
97     ~StructData();
98   };
99   struct UnionData {
100     const FieldDecl *Field;
101     APValue *Value;
102     UnionData();
103     ~UnionData();
104   };
105   struct AddrLabelDiffData {
106     const AddrLabelExpr* LHSExpr;
107     const AddrLabelExpr* RHSExpr;
108   };
109   struct MemberPointerData;
110 
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);
116 
117   DataType Data;
118 
119 public:
APValue()120   APValue() : Kind(Uninitialized) {}
APValue(APSInt I)121   explicit APValue(APSInt I) : Kind(Uninitialized) {
122     MakeInt(); setInt(std::move(I));
123   }
APValue(APFloat F)124   explicit APValue(APFloat F) : Kind(Uninitialized) {
125     MakeFloat(); setFloat(std::move(F));
126   }
APValue(const APValue * E,unsigned N)127   explicit APValue(const APValue *E, unsigned N) : Kind(Uninitialized) {
128     MakeVector(); setVector(E, N);
129   }
APValue(APSInt R,APSInt I)130   APValue(APSInt R, APSInt I) : Kind(Uninitialized) {
131     MakeComplexInt(); setComplexInt(std::move(R), std::move(I));
132   }
APValue(APFloat R,APFloat I)133   APValue(APFloat R, APFloat I) : Kind(Uninitialized) {
134     MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I));
135   }
136   APValue(const APValue &RHS);
APValue(APValue && RHS)137   APValue(APValue &&RHS) : Kind(Uninitialized) { swap(RHS); }
APValue(LValueBase B,const CharUnits & O,NoLValuePath N,unsigned CallIndex)138   APValue(LValueBase B, const CharUnits &O, NoLValuePath N, unsigned CallIndex)
139       : Kind(Uninitialized) {
140     MakeLValue(); setLValue(B, O, N, CallIndex);
141   }
APValue(LValueBase B,const CharUnits & O,ArrayRef<LValuePathEntry> Path,bool OnePastTheEnd,unsigned 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);
146   }
APValue(UninitArray,unsigned InitElts,unsigned Size)147   APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(Uninitialized) {
148     MakeArray(InitElts, Size);
149   }
APValue(UninitStruct,unsigned B,unsigned M)150   APValue(UninitStruct, unsigned B, unsigned M) : Kind(Uninitialized) {
151     MakeStruct(B, M);
152   }
153   explicit APValue(const FieldDecl *D, const APValue &V = APValue())
Kind(Uninitialized)154       : Kind(Uninitialized) {
155     MakeUnion(); setUnion(D, V);
156   }
APValue(const ValueDecl * Member,bool IsDerivedMember,ArrayRef<const CXXRecordDecl * > Path)157   APValue(const ValueDecl *Member, bool IsDerivedMember,
158           ArrayRef<const CXXRecordDecl*> Path) : Kind(Uninitialized) {
159     MakeMemberPointer(Member, IsDerivedMember, Path);
160   }
APValue(const AddrLabelExpr * LHSExpr,const AddrLabelExpr * RHSExpr)161   APValue(const AddrLabelExpr* LHSExpr, const AddrLabelExpr* RHSExpr)
162       : Kind(Uninitialized) {
163     MakeAddrLabelDiff(); setAddrLabelDiff(LHSExpr, RHSExpr);
164   }
165 
~APValue()166   ~APValue() {
167     MakeUninit();
168   }
169 
170   /// \brief Returns whether the object performed allocations.
171   ///
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;
176 
177   /// \brief Swaps the contents of this and the given APValue.
178   void swap(APValue &RHS);
179 
getKind()180   ValueKind getKind() const { return Kind; }
isUninit()181   bool isUninit() const { return Kind == Uninitialized; }
isInt()182   bool isInt() const { return Kind == Int; }
isFloat()183   bool isFloat() const { return Kind == Float; }
isComplexInt()184   bool isComplexInt() const { return Kind == ComplexInt; }
isComplexFloat()185   bool isComplexFloat() const { return Kind == ComplexFloat; }
isLValue()186   bool isLValue() const { return Kind == LValue; }
isVector()187   bool isVector() const { return Kind == Vector; }
isArray()188   bool isArray() const { return Kind == Array; }
isStruct()189   bool isStruct() const { return Kind == Struct; }
isUnion()190   bool isUnion() const { return Kind == Union; }
isMemberPointer()191   bool isMemberPointer() const { return Kind == MemberPointer; }
isAddrLabelDiff()192   bool isAddrLabelDiff() const { return Kind == AddrLabelDiff; }
193 
194   void dump() const;
195   void dump(raw_ostream &OS) const;
196 
197   void printPretty(raw_ostream &OS, ASTContext &Ctx, QualType Ty) const;
198   std::string getAsString(ASTContext &Ctx, QualType Ty) const;
199 
getInt()200   APSInt &getInt() {
201     assert(isInt() && "Invalid accessor");
202     return *(APSInt*)(char*)Data.buffer;
203   }
getInt()204   const APSInt &getInt() const {
205     return const_cast<APValue*>(this)->getInt();
206   }
207 
getFloat()208   APFloat &getFloat() {
209     assert(isFloat() && "Invalid accessor");
210     return *(APFloat*)(char*)Data.buffer;
211   }
getFloat()212   const APFloat &getFloat() const {
213     return const_cast<APValue*>(this)->getFloat();
214   }
215 
getComplexIntReal()216   APSInt &getComplexIntReal() {
217     assert(isComplexInt() && "Invalid accessor");
218     return ((ComplexAPSInt*)(char*)Data.buffer)->Real;
219   }
getComplexIntReal()220   const APSInt &getComplexIntReal() const {
221     return const_cast<APValue*>(this)->getComplexIntReal();
222   }
223 
getComplexIntImag()224   APSInt &getComplexIntImag() {
225     assert(isComplexInt() && "Invalid accessor");
226     return ((ComplexAPSInt*)(char*)Data.buffer)->Imag;
227   }
getComplexIntImag()228   const APSInt &getComplexIntImag() const {
229     return const_cast<APValue*>(this)->getComplexIntImag();
230   }
231 
getComplexFloatReal()232   APFloat &getComplexFloatReal() {
233     assert(isComplexFloat() && "Invalid accessor");
234     return ((ComplexAPFloat*)(char*)Data.buffer)->Real;
235   }
getComplexFloatReal()236   const APFloat &getComplexFloatReal() const {
237     return const_cast<APValue*>(this)->getComplexFloatReal();
238   }
239 
getComplexFloatImag()240   APFloat &getComplexFloatImag() {
241     assert(isComplexFloat() && "Invalid accessor");
242     return ((ComplexAPFloat*)(char*)Data.buffer)->Imag;
243   }
getComplexFloatImag()244   const APFloat &getComplexFloatImag() const {
245     return const_cast<APValue*>(this)->getComplexFloatImag();
246   }
247 
248   const LValueBase getLValueBase() const;
249   CharUnits &getLValueOffset();
getLValueOffset()250   const CharUnits &getLValueOffset() const {
251     return const_cast<APValue*>(this)->getLValueOffset();
252   }
253   bool isLValueOnePastTheEnd() const;
254   bool hasLValuePath() const;
255   ArrayRef<LValuePathEntry> getLValuePath() const;
256   unsigned getLValueCallIndex() const;
257 
getVectorElt(unsigned I)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];
262   }
getVectorElt(unsigned I)263   const APValue &getVectorElt(unsigned I) const {
264     return const_cast<APValue*>(this)->getVectorElt(I);
265   }
getVectorLength()266   unsigned getVectorLength() const {
267     assert(isVector() && "Invalid accessor");
268     return ((const Vec*)(const void *)Data.buffer)->NumElts;
269   }
270 
getArrayInitializedElt(unsigned I)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];
275   }
getArrayInitializedElt(unsigned I)276   const APValue &getArrayInitializedElt(unsigned I) const {
277     return const_cast<APValue*>(this)->getArrayInitializedElt(I);
278   }
hasArrayFiller()279   bool hasArrayFiller() const {
280     return getArrayInitializedElts() != getArraySize();
281   }
getArrayFiller()282   APValue &getArrayFiller() {
283     assert(isArray() && "Invalid accessor");
284     assert(hasArrayFiller() && "No array filler");
285     return ((Arr*)(char*)Data.buffer)->Elts[getArrayInitializedElts()];
286   }
getArrayFiller()287   const APValue &getArrayFiller() const {
288     return const_cast<APValue*>(this)->getArrayFiller();
289   }
getArrayInitializedElts()290   unsigned getArrayInitializedElts() const {
291     assert(isArray() && "Invalid accessor");
292     return ((const Arr*)(const void *)Data.buffer)->NumElts;
293   }
getArraySize()294   unsigned getArraySize() const {
295     assert(isArray() && "Invalid accessor");
296     return ((const Arr*)(const void *)Data.buffer)->ArrSize;
297   }
298 
getStructNumBases()299   unsigned getStructNumBases() const {
300     assert(isStruct() && "Invalid accessor");
301     return ((const StructData*)(const char*)Data.buffer)->NumBases;
302   }
getStructNumFields()303   unsigned getStructNumFields() const {
304     assert(isStruct() && "Invalid accessor");
305     return ((const StructData*)(const char*)Data.buffer)->NumFields;
306   }
getStructBase(unsigned i)307   APValue &getStructBase(unsigned i) {
308     assert(isStruct() && "Invalid accessor");
309     return ((StructData*)(char*)Data.buffer)->Elts[i];
310   }
getStructField(unsigned i)311   APValue &getStructField(unsigned i) {
312     assert(isStruct() && "Invalid accessor");
313     return ((StructData*)(char*)Data.buffer)->Elts[getStructNumBases() + i];
314   }
getStructBase(unsigned i)315   const APValue &getStructBase(unsigned i) const {
316     return const_cast<APValue*>(this)->getStructBase(i);
317   }
getStructField(unsigned i)318   const APValue &getStructField(unsigned i) const {
319     return const_cast<APValue*>(this)->getStructField(i);
320   }
321 
getUnionField()322   const FieldDecl *getUnionField() const {
323     assert(isUnion() && "Invalid accessor");
324     return ((const UnionData*)(const char*)Data.buffer)->Field;
325   }
getUnionValue()326   APValue &getUnionValue() {
327     assert(isUnion() && "Invalid accessor");
328     return *((UnionData*)(char*)Data.buffer)->Value;
329   }
getUnionValue()330   const APValue &getUnionValue() const {
331     return const_cast<APValue*>(this)->getUnionValue();
332   }
333 
334   const ValueDecl *getMemberPointerDecl() const;
335   bool isMemberPointerToDerivedMember() const;
336   ArrayRef<const CXXRecordDecl*> getMemberPointerPath() const;
337 
getAddrLabelDiffLHS()338   const AddrLabelExpr* getAddrLabelDiffLHS() const {
339     assert(isAddrLabelDiff() && "Invalid accessor");
340     return ((const AddrLabelDiffData*)(const char*)Data.buffer)->LHSExpr;
341   }
getAddrLabelDiffRHS()342   const AddrLabelExpr* getAddrLabelDiffRHS() const {
343     assert(isAddrLabelDiff() && "Invalid accessor");
344     return ((const AddrLabelDiffData*)(const char*)Data.buffer)->RHSExpr;
345   }
346 
setInt(APSInt I)347   void setInt(APSInt I) {
348     assert(isInt() && "Invalid accessor");
349     *(APSInt *)(char *)Data.buffer = std::move(I);
350   }
setFloat(APFloat F)351   void setFloat(APFloat F) {
352     assert(isFloat() && "Invalid accessor");
353     *(APFloat *)(char *)Data.buffer = std::move(F);
354   }
setVector(const APValue * E,unsigned N)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];
361   }
setComplexInt(APSInt R,APSInt 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);
368   }
setComplexFloat(APFloat R,APFloat 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);
375   }
376   void setLValue(LValueBase B, const CharUnits &O, NoLValuePath,
377                  unsigned CallIndex);
378   void setLValue(LValueBase B, const CharUnits &O,
379                  ArrayRef<LValuePathEntry> Path, bool OnePastTheEnd,
380                  unsigned CallIndex);
setUnion(const FieldDecl * Field,const APValue & Value)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;
385   }
setAddrLabelDiff(const AddrLabelExpr * LHSExpr,const AddrLabelExpr * RHSExpr)386   void setAddrLabelDiff(const AddrLabelExpr* LHSExpr,
387                         const AddrLabelExpr* RHSExpr) {
388     ((AddrLabelDiffData*)(char*)Data.buffer)->LHSExpr = LHSExpr;
389     ((AddrLabelDiffData*)(char*)Data.buffer)->RHSExpr = RHSExpr;
390   }
391 
392   /// Assign by swapping from a copy of the RHS.
393   APValue &operator=(APValue RHS) {
394     swap(RHS);
395     return *this;
396   }
397 
398 private:
399   void DestroyDataAndMakeUninit();
MakeUninit()400   void MakeUninit() {
401     if (Kind != Uninitialized)
402       DestroyDataAndMakeUninit();
403   }
MakeInt()404   void MakeInt() {
405     assert(isUninit() && "Bad state change");
406     new ((void*)Data.buffer) APSInt(1);
407     Kind = Int;
408   }
MakeFloat()409   void MakeFloat() {
410     assert(isUninit() && "Bad state change");
411     new ((void*)(char*)Data.buffer) APFloat(0.0);
412     Kind = Float;
413   }
MakeVector()414   void MakeVector() {
415     assert(isUninit() && "Bad state change");
416     new ((void*)(char*)Data.buffer) Vec();
417     Kind = Vector;
418   }
MakeComplexInt()419   void MakeComplexInt() {
420     assert(isUninit() && "Bad state change");
421     new ((void*)(char*)Data.buffer) ComplexAPSInt();
422     Kind = ComplexInt;
423   }
MakeComplexFloat()424   void MakeComplexFloat() {
425     assert(isUninit() && "Bad state change");
426     new ((void*)(char*)Data.buffer) ComplexAPFloat();
427     Kind = ComplexFloat;
428   }
429   void MakeLValue();
430   void MakeArray(unsigned InitElts, unsigned Size);
MakeStruct(unsigned B,unsigned M)431   void MakeStruct(unsigned B, unsigned M) {
432     assert(isUninit() && "Bad state change");
433     new ((void*)(char*)Data.buffer) StructData(B, M);
434     Kind = Struct;
435   }
MakeUnion()436   void MakeUnion() {
437     assert(isUninit() && "Bad state change");
438     new ((void*)(char*)Data.buffer) UnionData();
439     Kind = Union;
440   }
441   void MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
442                          ArrayRef<const CXXRecordDecl*> Path);
MakeAddrLabelDiff()443   void MakeAddrLabelDiff() {
444     assert(isUninit() && "Bad state change");
445     new ((void*)(char*)Data.buffer) AddrLabelDiffData();
446     Kind = AddrLabelDiff;
447   }
448 };
449 
450 } // end namespace clang.
451 
452 #endif
453