Home | History | Annotate | Download | only in AST
      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;
     73     ComplexAPSInt() : Real(1), Imag(1) {}
     74   };
     75   struct ComplexAPFloat {
     76     APFloat Real, Imag;
     77     ComplexAPFloat() : Real(0.0), Imag(0.0) {}
     78   };
     79   struct LV;
     80   struct Vec {
     81     APValue *Elts;
     82     unsigned NumElts;
     83     Vec() : Elts(nullptr), NumElts(0) {}
     84     ~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:
    120   APValue() : Kind(Uninitialized) {}
    121   explicit APValue(APSInt I) : Kind(Uninitialized) {
    122     MakeInt(); setInt(std::move(I));
    123   }
    124   explicit APValue(APFloat F) : Kind(Uninitialized) {
    125     MakeFloat(); setFloat(std::move(F));
    126   }
    127   explicit APValue(const APValue *E, unsigned N) : Kind(Uninitialized) {
    128     MakeVector(); setVector(E, N);
    129   }
    130   APValue(APSInt R, APSInt I) : Kind(Uninitialized) {
    131     MakeComplexInt(); setComplexInt(std::move(R), std::move(I));
    132   }
    133   APValue(APFloat R, APFloat I) : Kind(Uninitialized) {
    134     MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I));
    135   }
    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           bool IsNullPtr = false)
    140       : Kind(Uninitialized) {
    141     MakeLValue(); setLValue(B, O, N, CallIndex, IsNullPtr);
    142   }
    143   APValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path,
    144           bool OnePastTheEnd, unsigned CallIndex, bool IsNullPtr = false)
    145       : Kind(Uninitialized) {
    146     MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, CallIndex, IsNullPtr);
    147   }
    148   APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(Uninitialized) {
    149     MakeArray(InitElts, Size);
    150   }
    151   APValue(UninitStruct, unsigned B, unsigned M) : Kind(Uninitialized) {
    152     MakeStruct(B, M);
    153   }
    154   explicit APValue(const FieldDecl *D, const APValue &V = APValue())
    155       : Kind(Uninitialized) {
    156     MakeUnion(); setUnion(D, V);
    157   }
    158   APValue(const ValueDecl *Member, bool IsDerivedMember,
    159           ArrayRef<const CXXRecordDecl*> Path) : Kind(Uninitialized) {
    160     MakeMemberPointer(Member, IsDerivedMember, Path);
    161   }
    162   APValue(const AddrLabelExpr* LHSExpr, const AddrLabelExpr* RHSExpr)
    163       : Kind(Uninitialized) {
    164     MakeAddrLabelDiff(); setAddrLabelDiff(LHSExpr, RHSExpr);
    165   }
    166 
    167   ~APValue() {
    168     MakeUninit();
    169   }
    170 
    171   /// \brief Returns whether the object performed allocations.
    172   ///
    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;
    177 
    178   /// \brief Swaps the contents of this and the given APValue.
    179   void swap(APValue &RHS);
    180 
    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; }
    194 
    195   void dump() const;
    196   void dump(raw_ostream &OS) const;
    197 
    198   void printPretty(raw_ostream &OS, ASTContext &Ctx, QualType Ty) const;
    199   std::string getAsString(ASTContext &Ctx, QualType Ty) const;
    200 
    201   APSInt &getInt() {
    202     assert(isInt() && "Invalid accessor");
    203     return *(APSInt*)(char*)Data.buffer;
    204   }
    205   const APSInt &getInt() const {
    206     return const_cast<APValue*>(this)->getInt();
    207   }
    208 
    209   APFloat &getFloat() {
    210     assert(isFloat() && "Invalid accessor");
    211     return *(APFloat*)(char*)Data.buffer;
    212   }
    213   const APFloat &getFloat() const {
    214     return const_cast<APValue*>(this)->getFloat();
    215   }
    216 
    217   APSInt &getComplexIntReal() {
    218     assert(isComplexInt() && "Invalid accessor");
    219     return ((ComplexAPSInt*)(char*)Data.buffer)->Real;
    220   }
    221   const APSInt &getComplexIntReal() const {
    222     return const_cast<APValue*>(this)->getComplexIntReal();
    223   }
    224 
    225   APSInt &getComplexIntImag() {
    226     assert(isComplexInt() && "Invalid accessor");
    227     return ((ComplexAPSInt*)(char*)Data.buffer)->Imag;
    228   }
    229   const APSInt &getComplexIntImag() const {
    230     return const_cast<APValue*>(this)->getComplexIntImag();
    231   }
    232 
    233   APFloat &getComplexFloatReal() {
    234     assert(isComplexFloat() && "Invalid accessor");
    235     return ((ComplexAPFloat*)(char*)Data.buffer)->Real;
    236   }
    237   const APFloat &getComplexFloatReal() const {
    238     return const_cast<APValue*>(this)->getComplexFloatReal();
    239   }
    240 
    241   APFloat &getComplexFloatImag() {
    242     assert(isComplexFloat() && "Invalid accessor");
    243     return ((ComplexAPFloat*)(char*)Data.buffer)->Imag;
    244   }
    245   const APFloat &getComplexFloatImag() const {
    246     return const_cast<APValue*>(this)->getComplexFloatImag();
    247   }
    248 
    249   const LValueBase getLValueBase() const;
    250   CharUnits &getLValueOffset();
    251   const CharUnits &getLValueOffset() const {
    252     return const_cast<APValue*>(this)->getLValueOffset();
    253   }
    254   bool isLValueOnePastTheEnd() const;
    255   bool hasLValuePath() const;
    256   ArrayRef<LValuePathEntry> getLValuePath() const;
    257   unsigned getLValueCallIndex() const;
    258   bool isNullPointer() const;
    259 
    260   APValue &getVectorElt(unsigned I) {
    261     assert(isVector() && "Invalid accessor");
    262     assert(I < getVectorLength() && "Index out of range");
    263     return ((Vec*)(char*)Data.buffer)->Elts[I];
    264   }
    265   const APValue &getVectorElt(unsigned I) const {
    266     return const_cast<APValue*>(this)->getVectorElt(I);
    267   }
    268   unsigned getVectorLength() const {
    269     assert(isVector() && "Invalid accessor");
    270     return ((const Vec*)(const void *)Data.buffer)->NumElts;
    271   }
    272 
    273   APValue &getArrayInitializedElt(unsigned I) {
    274     assert(isArray() && "Invalid accessor");
    275     assert(I < getArrayInitializedElts() && "Index out of range");
    276     return ((Arr*)(char*)Data.buffer)->Elts[I];
    277   }
    278   const APValue &getArrayInitializedElt(unsigned I) const {
    279     return const_cast<APValue*>(this)->getArrayInitializedElt(I);
    280   }
    281   bool hasArrayFiller() const {
    282     return getArrayInitializedElts() != getArraySize();
    283   }
    284   APValue &getArrayFiller() {
    285     assert(isArray() && "Invalid accessor");
    286     assert(hasArrayFiller() && "No array filler");
    287     return ((Arr*)(char*)Data.buffer)->Elts[getArrayInitializedElts()];
    288   }
    289   const APValue &getArrayFiller() const {
    290     return const_cast<APValue*>(this)->getArrayFiller();
    291   }
    292   unsigned getArrayInitializedElts() const {
    293     assert(isArray() && "Invalid accessor");
    294     return ((const Arr*)(const void *)Data.buffer)->NumElts;
    295   }
    296   unsigned getArraySize() const {
    297     assert(isArray() && "Invalid accessor");
    298     return ((const Arr*)(const void *)Data.buffer)->ArrSize;
    299   }
    300 
    301   unsigned getStructNumBases() const {
    302     assert(isStruct() && "Invalid accessor");
    303     return ((const StructData*)(const char*)Data.buffer)->NumBases;
    304   }
    305   unsigned getStructNumFields() const {
    306     assert(isStruct() && "Invalid accessor");
    307     return ((const StructData*)(const char*)Data.buffer)->NumFields;
    308   }
    309   APValue &getStructBase(unsigned i) {
    310     assert(isStruct() && "Invalid accessor");
    311     return ((StructData*)(char*)Data.buffer)->Elts[i];
    312   }
    313   APValue &getStructField(unsigned i) {
    314     assert(isStruct() && "Invalid accessor");
    315     return ((StructData*)(char*)Data.buffer)->Elts[getStructNumBases() + i];
    316   }
    317   const APValue &getStructBase(unsigned i) const {
    318     return const_cast<APValue*>(this)->getStructBase(i);
    319   }
    320   const APValue &getStructField(unsigned i) const {
    321     return const_cast<APValue*>(this)->getStructField(i);
    322   }
    323 
    324   const FieldDecl *getUnionField() const {
    325     assert(isUnion() && "Invalid accessor");
    326     return ((const UnionData*)(const char*)Data.buffer)->Field;
    327   }
    328   APValue &getUnionValue() {
    329     assert(isUnion() && "Invalid accessor");
    330     return *((UnionData*)(char*)Data.buffer)->Value;
    331   }
    332   const APValue &getUnionValue() const {
    333     return const_cast<APValue*>(this)->getUnionValue();
    334   }
    335 
    336   const ValueDecl *getMemberPointerDecl() const;
    337   bool isMemberPointerToDerivedMember() const;
    338   ArrayRef<const CXXRecordDecl*> getMemberPointerPath() const;
    339 
    340   const AddrLabelExpr* getAddrLabelDiffLHS() const {
    341     assert(isAddrLabelDiff() && "Invalid accessor");
    342     return ((const AddrLabelDiffData*)(const char*)Data.buffer)->LHSExpr;
    343   }
    344   const AddrLabelExpr* getAddrLabelDiffRHS() const {
    345     assert(isAddrLabelDiff() && "Invalid accessor");
    346     return ((const AddrLabelDiffData*)(const char*)Data.buffer)->RHSExpr;
    347   }
    348 
    349   void setInt(APSInt I) {
    350     assert(isInt() && "Invalid accessor");
    351     *(APSInt *)(char *)Data.buffer = std::move(I);
    352   }
    353   void setFloat(APFloat F) {
    354     assert(isFloat() && "Invalid accessor");
    355     *(APFloat *)(char *)Data.buffer = std::move(F);
    356   }
    357   void setVector(const APValue *E, unsigned N) {
    358     assert(isVector() && "Invalid accessor");
    359     ((Vec*)(char*)Data.buffer)->Elts = new APValue[N];
    360     ((Vec*)(char*)Data.buffer)->NumElts = N;
    361     for (unsigned i = 0; i != N; ++i)
    362       ((Vec*)(char*)Data.buffer)->Elts[i] = E[i];
    363   }
    364   void setComplexInt(APSInt R, APSInt I) {
    365     assert(R.getBitWidth() == I.getBitWidth() &&
    366            "Invalid complex int (type mismatch).");
    367     assert(isComplexInt() && "Invalid accessor");
    368     ((ComplexAPSInt *)(char *)Data.buffer)->Real = std::move(R);
    369     ((ComplexAPSInt *)(char *)Data.buffer)->Imag = std::move(I);
    370   }
    371   void setComplexFloat(APFloat R, APFloat I) {
    372     assert(&R.getSemantics() == &I.getSemantics() &&
    373            "Invalid complex float (type mismatch).");
    374     assert(isComplexFloat() && "Invalid accessor");
    375     ((ComplexAPFloat *)(char *)Data.buffer)->Real = std::move(R);
    376     ((ComplexAPFloat *)(char *)Data.buffer)->Imag = std::move(I);
    377   }
    378   void setLValue(LValueBase B, const CharUnits &O, NoLValuePath,
    379                  unsigned CallIndex, bool IsNullPtr);
    380   void setLValue(LValueBase B, const CharUnits &O,
    381                  ArrayRef<LValuePathEntry> Path, bool OnePastTheEnd,
    382                  unsigned CallIndex, bool IsNullPtr);
    383   void setUnion(const FieldDecl *Field, const APValue &Value) {
    384     assert(isUnion() && "Invalid accessor");
    385     ((UnionData*)(char*)Data.buffer)->Field = Field;
    386     *((UnionData*)(char*)Data.buffer)->Value = Value;
    387   }
    388   void setAddrLabelDiff(const AddrLabelExpr* LHSExpr,
    389                         const AddrLabelExpr* RHSExpr) {
    390     ((AddrLabelDiffData*)(char*)Data.buffer)->LHSExpr = LHSExpr;
    391     ((AddrLabelDiffData*)(char*)Data.buffer)->RHSExpr = RHSExpr;
    392   }
    393 
    394   /// Assign by swapping from a copy of the RHS.
    395   APValue &operator=(APValue RHS) {
    396     swap(RHS);
    397     return *this;
    398   }
    399 
    400 private:
    401   void DestroyDataAndMakeUninit();
    402   void MakeUninit() {
    403     if (Kind != Uninitialized)
    404       DestroyDataAndMakeUninit();
    405   }
    406   void MakeInt() {
    407     assert(isUninit() && "Bad state change");
    408     new ((void*)Data.buffer) APSInt(1);
    409     Kind = Int;
    410   }
    411   void MakeFloat() {
    412     assert(isUninit() && "Bad state change");
    413     new ((void*)(char*)Data.buffer) APFloat(0.0);
    414     Kind = Float;
    415   }
    416   void MakeVector() {
    417     assert(isUninit() && "Bad state change");
    418     new ((void*)(char*)Data.buffer) Vec();
    419     Kind = Vector;
    420   }
    421   void MakeComplexInt() {
    422     assert(isUninit() && "Bad state change");
    423     new ((void*)(char*)Data.buffer) ComplexAPSInt();
    424     Kind = ComplexInt;
    425   }
    426   void MakeComplexFloat() {
    427     assert(isUninit() && "Bad state change");
    428     new ((void*)(char*)Data.buffer) ComplexAPFloat();
    429     Kind = ComplexFloat;
    430   }
    431   void MakeLValue();
    432   void MakeArray(unsigned InitElts, unsigned Size);
    433   void MakeStruct(unsigned B, unsigned M) {
    434     assert(isUninit() && "Bad state change");
    435     new ((void*)(char*)Data.buffer) StructData(B, M);
    436     Kind = Struct;
    437   }
    438   void MakeUnion() {
    439     assert(isUninit() && "Bad state change");
    440     new ((void*)(char*)Data.buffer) UnionData();
    441     Kind = Union;
    442   }
    443   void MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
    444                          ArrayRef<const CXXRecordDecl*> Path);
    445   void MakeAddrLabelDiff() {
    446     assert(isUninit() && "Bad state change");
    447     new ((void*)(char*)Data.buffer) AddrLabelDiffData();
    448     Kind = AddrLabelDiff;
    449   }
    450 };
    451 
    452 } // end namespace clang.
    453 
    454 #endif
    455