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