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/APSIntType.h"
     20 #include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
     21 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
     22 
     23 namespace clang {
     24 namespace ento {
     25 
     26 class CompoundValData : public llvm::FoldingSetNode {
     27   QualType T;
     28   llvm::ImmutableList<SVal> L;
     29 
     30 public:
     31   CompoundValData(QualType t, llvm::ImmutableList<SVal> l)
     32     : T(t), L(l) {}
     33 
     34   typedef llvm::ImmutableList<SVal>::iterator iterator;
     35   iterator begin() const { return L.begin(); }
     36   iterator end() const { return L.end(); }
     37 
     38   static void Profile(llvm::FoldingSetNodeID& ID, QualType T,
     39                       llvm::ImmutableList<SVal> L);
     40 
     41   void Profile(llvm::FoldingSetNodeID& ID) { Profile(ID, T, L); }
     42 };
     43 
     44 class LazyCompoundValData : public llvm::FoldingSetNode {
     45   StoreRef store;
     46   const TypedValueRegion *region;
     47 public:
     48   LazyCompoundValData(const StoreRef &st, const TypedValueRegion *r)
     49     : store(st), region(r) {}
     50 
     51   const void *getStore() const { return store.getStore(); }
     52   const TypedValueRegion *getRegion() const { return region; }
     53 
     54   static void Profile(llvm::FoldingSetNodeID& ID,
     55                       const StoreRef &store,
     56                       const TypedValueRegion *region);
     57 
     58   void Profile(llvm::FoldingSetNodeID& ID) { Profile(ID, store, region); }
     59 };
     60 
     61 class BasicValueFactory {
     62   typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<llvm::APSInt> >
     63           APSIntSetTy;
     64 
     65   ASTContext &Ctx;
     66   llvm::BumpPtrAllocator& BPAlloc;
     67 
     68   APSIntSetTy   APSIntSet;
     69   void *        PersistentSVals;
     70   void *        PersistentSValPairs;
     71 
     72   llvm::ImmutableList<SVal>::Factory SValListFactory;
     73   llvm::FoldingSet<CompoundValData>  CompoundValDataSet;
     74   llvm::FoldingSet<LazyCompoundValData> LazyCompoundValDataSet;
     75 
     76   // This is private because external clients should use the factory
     77   // method that takes a QualType.
     78   const llvm::APSInt& getValue(uint64_t X, unsigned BitWidth, bool isUnsigned);
     79 
     80 public:
     81   BasicValueFactory(ASTContext &ctx, llvm::BumpPtrAllocator& Alloc)
     82   : Ctx(ctx), BPAlloc(Alloc), PersistentSVals(0), PersistentSValPairs(0),
     83     SValListFactory(Alloc) {}
     84 
     85   ~BasicValueFactory();
     86 
     87   ASTContext &getContext() const { return Ctx; }
     88 
     89   const llvm::APSInt& getValue(const llvm::APSInt& X);
     90   const llvm::APSInt& getValue(const llvm::APInt& X, bool isUnsigned);
     91   const llvm::APSInt& getValue(uint64_t X, QualType T);
     92 
     93   /// Returns the type of the APSInt used to store values of the given QualType.
     94   APSIntType getAPSIntType(QualType T) const {
     95     assert(T->isIntegerType() || Loc::isLocType(T));
     96     return APSIntType(Ctx.getTypeSize(T),
     97                       !T->isSignedIntegerOrEnumerationType());
     98   }
     99 
    100   /// Convert - Create a new persistent APSInt with the same value as 'From'
    101   ///  but with the bitwidth and signedness of 'To'.
    102   const llvm::APSInt &Convert(const llvm::APSInt& To,
    103                               const llvm::APSInt& From) {
    104     APSIntType TargetType(To);
    105     if (TargetType == APSIntType(From))
    106       return From;
    107 
    108     return getValue(TargetType.convert(From));
    109   }
    110 
    111   const llvm::APSInt &Convert(QualType T, const llvm::APSInt &From) {
    112     APSIntType TargetType = getAPSIntType(T);
    113     if (TargetType == APSIntType(From))
    114       return From;
    115 
    116     return getValue(TargetType.convert(From));
    117   }
    118 
    119   const llvm::APSInt& getIntValue(uint64_t X, bool isUnsigned) {
    120     QualType T = isUnsigned ? Ctx.UnsignedIntTy : Ctx.IntTy;
    121     return getValue(X, T);
    122   }
    123 
    124   inline const llvm::APSInt& getMaxValue(const llvm::APSInt &v) {
    125     return getValue(APSIntType(v).getMaxValue());
    126   }
    127 
    128   inline const llvm::APSInt& getMinValue(const llvm::APSInt &v) {
    129     return getValue(APSIntType(v).getMinValue());
    130   }
    131 
    132   inline const llvm::APSInt& getMaxValue(QualType T) {
    133     return getValue(getAPSIntType(T).getMaxValue());
    134   }
    135 
    136   inline const llvm::APSInt& getMinValue(QualType T) {
    137     return getValue(getAPSIntType(T).getMinValue());
    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