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       : Kind(Uninitialized) {
    140     MakeLValue(); setLValue(B, O, N, CallIndex);
    141   }
    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   }
    147   APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(Uninitialized) {
    148     MakeArray(InitElts, Size);
    149   }
    150   APValue(UninitStruct, unsigned B, unsigned M) : Kind(Uninitialized) {
    151     MakeStruct(B, M);
    152   }
    153   explicit APValue(const FieldDecl *D, const APValue &V = APValue())
    154       : Kind(Uninitialized) {
    155     MakeUnion(); setUnion(D, V);
    156   }
    157   APValue(const ValueDecl *Member, bool IsDerivedMember,
    158           ArrayRef<const CXXRecordDecl*> Path) : Kind(Uninitialized) {
    159     MakeMemberPointer(Member, IsDerivedMember, Path);
    160   }
    161   APValue(const AddrLabelExpr* LHSExpr, const AddrLabelExpr* RHSExpr)
    162       : Kind(Uninitialized) {
    163     MakeAddrLabelDiff(); setAddrLabelDiff(LHSExpr, RHSExpr);
    164   }
    165 
    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 
    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; }
    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 
    200   APSInt &getInt() {
    201     assert(isInt() && "Invalid accessor");
    202     return *(APSInt*)(char*)Data.buffer;
    203   }
    204   const APSInt &getInt() const {
    205     return const_cast<APValue*>(this)->getInt();
    206   }
    207 
    208   APFloat &getFloat() {
    209     assert(isFloat() && "Invalid accessor");
    210     return *(APFloat*)(char*)Data.buffer;
    211   }
    212   const APFloat &getFloat() const {
    213     return const_cast<APValue*>(this)->getFloat();
    214   }
    215 
    216   APSInt &getComplexIntReal() {
    217     assert(isComplexInt() && "Invalid accessor");
    218     return ((ComplexAPSInt*)(char*)Data.buffer)->Real;
    219   }
    220   const APSInt &getComplexIntReal() const {
    221     return const_cast<APValue*>(this)->getComplexIntReal();
    222   }
    223 
    224   APSInt &getComplexIntImag() {
    225     assert(isComplexInt() && "Invalid accessor");
    226     return ((ComplexAPSInt*)(char*)Data.buffer)->Imag;
    227   }
    228   const APSInt &getComplexIntImag() const {
    229     return const_cast<APValue*>(this)->getComplexIntImag();
    230   }
    231 
    232   APFloat &getComplexFloatReal() {
    233     assert(isComplexFloat() && "Invalid accessor");
    234     return ((ComplexAPFloat*)(char*)Data.buffer)->Real;
    235   }
    236   const APFloat &getComplexFloatReal() const {
    237     return const_cast<APValue*>(this)->getComplexFloatReal();
    238   }
    239 
    240   APFloat &getComplexFloatImag() {
    241     assert(isComplexFloat() && "Invalid accessor");
    242     return ((ComplexAPFloat*)(char*)Data.buffer)->Imag;
    243   }
    244   const APFloat &getComplexFloatImag() const {
    245     return const_cast<APValue*>(this)->getComplexFloatImag();
    246   }
    247 
    248   const LValueBase getLValueBase() const;
    249   CharUnits &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 
    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   }
    263   const APValue &getVectorElt(unsigned I) const {
    264     return const_cast<APValue*>(this)->getVectorElt(I);
    265   }
    266   unsigned getVectorLength() const {
    267     assert(isVector() && "Invalid accessor");
    268     return ((const Vec*)(const void *)Data.buffer)->NumElts;
    269   }
    270 
    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   }
    276   const APValue &getArrayInitializedElt(unsigned I) const {
    277     return const_cast<APValue*>(this)->getArrayInitializedElt(I);
    278   }
    279   bool hasArrayFiller() const {
    280     return getArrayInitializedElts() != getArraySize();
    281   }
    282   APValue &getArrayFiller() {
    283     assert(isArray() && "Invalid accessor");
    284     assert(hasArrayFiller() && "No array filler");
    285     return ((Arr*)(char*)Data.buffer)->Elts[getArrayInitializedElts()];
    286   }
    287   const APValue &getArrayFiller() const {
    288     return const_cast<APValue*>(this)->getArrayFiller();
    289   }
    290   unsigned getArrayInitializedElts() const {
    291     assert(isArray() && "Invalid accessor");
    292     return ((const Arr*)(const void *)Data.buffer)->NumElts;
    293   }
    294   unsigned getArraySize() const {
    295     assert(isArray() && "Invalid accessor");
    296     return ((const Arr*)(const void *)Data.buffer)->ArrSize;
    297   }
    298 
    299   unsigned getStructNumBases() const {
    300     assert(isStruct() && "Invalid accessor");
    301     return ((const StructData*)(const char*)Data.buffer)->NumBases;
    302   }
    303   unsigned getStructNumFields() const {
    304     assert(isStruct() && "Invalid accessor");
    305     return ((const StructData*)(const char*)Data.buffer)->NumFields;
    306   }
    307   APValue &getStructBase(unsigned i) {
    308     assert(isStruct() && "Invalid accessor");
    309     return ((StructData*)(char*)Data.buffer)->Elts[i];
    310   }
    311   APValue &getStructField(unsigned i) {
    312     assert(isStruct() && "Invalid accessor");
    313     return ((StructData*)(char*)Data.buffer)->Elts[getStructNumBases() + i];
    314   }
    315   const APValue &getStructBase(unsigned i) const {
    316     return const_cast<APValue*>(this)->getStructBase(i);
    317   }
    318   const APValue &getStructField(unsigned i) const {
    319     return const_cast<APValue*>(this)->getStructField(i);
    320   }
    321 
    322   const FieldDecl *getUnionField() const {
    323     assert(isUnion() && "Invalid accessor");
    324     return ((const UnionData*)(const char*)Data.buffer)->Field;
    325   }
    326   APValue &getUnionValue() {
    327     assert(isUnion() && "Invalid accessor");
    328     return *((UnionData*)(char*)Data.buffer)->Value;
    329   }
    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 
    338   const AddrLabelExpr* getAddrLabelDiffLHS() const {
    339     assert(isAddrLabelDiff() && "Invalid accessor");
    340     return ((const AddrLabelDiffData*)(const char*)Data.buffer)->LHSExpr;
    341   }
    342   const AddrLabelExpr* getAddrLabelDiffRHS() const {
    343     assert(isAddrLabelDiff() && "Invalid accessor");
    344     return ((const AddrLabelDiffData*)(const char*)Data.buffer)->RHSExpr;
    345   }
    346 
    347   void setInt(APSInt I) {
    348     assert(isInt() && "Invalid accessor");
    349     *(APSInt *)(char *)Data.buffer = std::move(I);
    350   }
    351   void setFloat(APFloat F) {
    352     assert(isFloat() && "Invalid accessor");
    353     *(APFloat *)(char *)Data.buffer = std::move(F);
    354   }
    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   }
    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   }
    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);
    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   }
    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();
    400   void MakeUninit() {
    401     if (Kind != Uninitialized)
    402       DestroyDataAndMakeUninit();
    403   }
    404   void MakeInt() {
    405     assert(isUninit() && "Bad state change");
    406     new ((void*)Data.buffer) APSInt(1);
    407     Kind = Int;
    408   }
    409   void MakeFloat() {
    410     assert(isUninit() && "Bad state change");
    411     new ((void*)(char*)Data.buffer) APFloat(0.0);
    412     Kind = Float;
    413   }
    414   void MakeVector() {
    415     assert(isUninit() && "Bad state change");
    416     new ((void*)(char*)Data.buffer) Vec();
    417     Kind = Vector;
    418   }
    419   void MakeComplexInt() {
    420     assert(isUninit() && "Bad state change");
    421     new ((void*)(char*)Data.buffer) ComplexAPSInt();
    422     Kind = ComplexInt;
    423   }
    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);
    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   }
    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);
    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