Home | History | Annotate | Download | only in PathSensitive
      1 //=== BasicValueFactory.h - Basic values for Path Sens analysis --*- 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 BasicValueFactory, a class that manages the lifetime
     11 //  of APSInt objects and symbolic constraints used by ExprEngine
     12 //  and related classes.
     13 //
     14 //===----------------------------------------------------------------------===//
     15 
     16 #ifndef LLVM_CLANG_GR_BASICVALUEFACTORY_H
     17 #define LLVM_CLANG_GR_BASICVALUEFACTORY_H
     18 
     19 #include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
     20 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
     21 
     22 namespace clang {
     23 namespace ento {
     24 
     25 class CompoundValData : public llvm::FoldingSetNode {
     26   QualType T;
     27   llvm::ImmutableList<SVal> L;
     28 
     29 public:
     30   CompoundValData(QualType t, llvm::ImmutableList<SVal> l)
     31     : T(t), L(l) {}
     32 
     33   typedef llvm::ImmutableList<SVal>::iterator iterator;
     34   iterator begin() const { return L.begin(); }
     35   iterator end() const { return L.end(); }
     36 
     37   static void Profile(llvm::FoldingSetNodeID& ID, QualType T,
     38                       llvm::ImmutableList<SVal> L);
     39 
     40   void Profile(llvm::FoldingSetNodeID& ID) { Profile(ID, T, L); }
     41 };
     42 
     43 class LazyCompoundValData : public llvm::FoldingSetNode {
     44   StoreRef store;
     45   const TypedValueRegion *region;
     46 public:
     47   LazyCompoundValData(const StoreRef &st, const TypedValueRegion *r)
     48     : store(st), region(r) {}
     49 
     50   const void *getStore() const { return store.getStore(); }
     51   const TypedValueRegion *getRegion() const { return region; }
     52 
     53   static void Profile(llvm::FoldingSetNodeID& ID,
     54                       const StoreRef &store,
     55                       const TypedValueRegion *region);
     56 
     57   void Profile(llvm::FoldingSetNodeID& ID) { Profile(ID, store, region); }
     58 };
     59 
     60 class BasicValueFactory {
     61   typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<llvm::APSInt> >
     62           APSIntSetTy;
     63 
     64   ASTContext &Ctx;
     65   llvm::BumpPtrAllocator& BPAlloc;
     66 
     67   APSIntSetTy   APSIntSet;
     68   void *        PersistentSVals;
     69   void *        PersistentSValPairs;
     70 
     71   llvm::ImmutableList<SVal>::Factory SValListFactory;
     72   llvm::FoldingSet<CompoundValData>  CompoundValDataSet;
     73   llvm::FoldingSet<LazyCompoundValData> LazyCompoundValDataSet;
     74 
     75 public:
     76   BasicValueFactory(ASTContext &ctx, llvm::BumpPtrAllocator& Alloc)
     77   : Ctx(ctx), BPAlloc(Alloc), PersistentSVals(0), PersistentSValPairs(0),
     78     SValListFactory(Alloc) {}
     79 
     80   ~BasicValueFactory();
     81 
     82   ASTContext &getContext() const { return Ctx; }
     83 
     84   const llvm::APSInt& getValue(const llvm::APSInt& X);
     85   const llvm::APSInt& getValue(const llvm::APInt& X, bool isUnsigned);
     86   const llvm::APSInt& getValue(uint64_t X, unsigned BitWidth, bool isUnsigned);
     87   const llvm::APSInt& getValue(uint64_t X, QualType T);
     88 
     89   /// Convert - Create a new persistent APSInt with the same value as 'From'
     90   ///  but with the bitwidth and signedness of 'To'.
     91   const llvm::APSInt &Convert(const llvm::APSInt& To,
     92                               const llvm::APSInt& From) {
     93 
     94     if (To.isUnsigned() == From.isUnsigned() &&
     95         To.getBitWidth() == From.getBitWidth())
     96       return From;
     97 
     98     return getValue(From.getSExtValue(), To.getBitWidth(), To.isUnsigned());
     99   }
    100 
    101   const llvm::APSInt &Convert(QualType T, const llvm::APSInt &From) {
    102     assert(T->isIntegerType() || Loc::isLocType(T));
    103     unsigned bitwidth = Ctx.getTypeSize(T);
    104     bool isUnsigned
    105       = T->isUnsignedIntegerOrEnumerationType() || Loc::isLocType(T);
    106 
    107     if (isUnsigned == From.isUnsigned() && bitwidth == From.getBitWidth())
    108       return From;
    109 
    110     return getValue(From.getSExtValue(), bitwidth, isUnsigned);
    111   }
    112 
    113   const llvm::APSInt& getIntValue(uint64_t X, bool isUnsigned) {
    114     QualType T = isUnsigned ? Ctx.UnsignedIntTy : Ctx.IntTy;
    115     return getValue(X, T);
    116   }
    117 
    118   inline const llvm::APSInt& getMaxValue(const llvm::APSInt &v) {
    119     return getValue(llvm::APSInt::getMaxValue(v.getBitWidth(), v.isUnsigned()));
    120   }
    121 
    122   inline const llvm::APSInt& getMinValue(const llvm::APSInt &v) {
    123     return getValue(llvm::APSInt::getMinValue(v.getBitWidth(), v.isUnsigned()));
    124   }
    125 
    126   inline const llvm::APSInt& getMaxValue(QualType T) {
    127     assert(T->isIntegerType() || Loc::isLocType(T));
    128     bool isUnsigned
    129       = T->isUnsignedIntegerOrEnumerationType() || Loc::isLocType(T);
    130     return getValue(llvm::APSInt::getMaxValue(Ctx.getTypeSize(T), isUnsigned));
    131   }
    132 
    133   inline const llvm::APSInt& getMinValue(QualType T) {
    134     assert(T->isIntegerType() || Loc::isLocType(T));
    135     bool isUnsigned
    136       = T->isUnsignedIntegerOrEnumerationType() || Loc::isLocType(T);
    137     return getValue(llvm::APSInt::getMinValue(Ctx.getTypeSize(T), isUnsigned));
    138   }
    139 
    140   inline const llvm::APSInt& Add1(const llvm::APSInt& V) {
    141     llvm::APSInt X = V;
    142     ++X;
    143     return getValue(X);
    144   }
    145 
    146   inline const llvm::APSInt& Sub1(const llvm::APSInt& V) {
    147     llvm::APSInt X = V;
    148     --X;
    149     return getValue(X);
    150   }
    151 
    152   inline const llvm::APSInt& getZeroWithPtrWidth(bool isUnsigned = true) {
    153     return getValue(0, Ctx.getTypeSize(Ctx.VoidPtrTy), isUnsigned);
    154   }
    155 
    156   inline const llvm::APSInt &getIntWithPtrWidth(uint64_t X, bool isUnsigned) {
    157     return getValue(X, Ctx.getTypeSize(Ctx.VoidPtrTy), isUnsigned);
    158   }
    159 
    160   inline const llvm::APSInt& getTruthValue(bool b, QualType T) {
    161     return getValue(b ? 1 : 0, Ctx.getTypeSize(T), false);
    162   }
    163 
    164   inline const llvm::APSInt& getTruthValue(bool b) {
    165     return getTruthValue(b, Ctx.getLogicalOperationType());
    166   }
    167 
    168   const CompoundValData *getCompoundValData(QualType T,
    169                                             llvm::ImmutableList<SVal> Vals);
    170 
    171   const LazyCompoundValData *getLazyCompoundValData(const StoreRef &store,
    172                                             const TypedValueRegion *region);
    173 
    174   llvm::ImmutableList<SVal> getEmptySValList() {
    175     return SValListFactory.getEmptyList();
    176   }
    177 
    178   llvm::ImmutableList<SVal> consVals(SVal X, llvm::ImmutableList<SVal> L) {
    179     return SValListFactory.add(X, L);
    180   }
    181 
    182   const llvm::APSInt* evalAPSInt(BinaryOperator::Opcode Op,
    183                                      const llvm::APSInt& V1,
    184                                      const llvm::APSInt& V2);
    185 
    186   const std::pair<SVal, uintptr_t>&
    187   getPersistentSValWithData(const SVal& V, uintptr_t Data);
    188 
    189   const std::pair<SVal, SVal>&
    190   getPersistentSValPair(const SVal& V1, const SVal& V2);
    191 
    192   const SVal* getPersistentSVal(SVal X);
    193 };
    194 
    195 } // end GR namespace
    196 
    197 } // end clang namespace
    198 
    199 #endif
    200