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: CompoundValData(QualType t,llvm::ImmutableList<SVal> l)30 CompoundValData(QualType t, llvm::ImmutableList<SVal> l) 31 : T(t), L(l) {} 32 33 typedef llvm::ImmutableList<SVal>::iterator iterator; begin()34 iterator begin() const { return L.begin(); } end()35 iterator end() const { return L.end(); } 36 37 static void Profile(llvm::FoldingSetNodeID& ID, QualType T, 38 llvm::ImmutableList<SVal> L); 39 Profile(llvm::FoldingSetNodeID & ID)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: LazyCompoundValData(const StoreRef & st,const TypedValueRegion * r)47 LazyCompoundValData(const StoreRef &st, const TypedValueRegion *r) 48 : store(st), region(r) {} 49 getStore()50 const void *getStore() const { return store.getStore(); } getRegion()51 const TypedValueRegion *getRegion() const { return region; } 52 53 static void Profile(llvm::FoldingSetNodeID& ID, 54 const StoreRef &store, 55 const TypedValueRegion *region); 56 Profile(llvm::FoldingSetNodeID & ID)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: BasicValueFactory(ASTContext & ctx,llvm::BumpPtrAllocator & Alloc)76 BasicValueFactory(ASTContext &ctx, llvm::BumpPtrAllocator& Alloc) 77 : Ctx(ctx), BPAlloc(Alloc), PersistentSVals(0), PersistentSValPairs(0), 78 SValListFactory(Alloc) {} 79 80 ~BasicValueFactory(); 81 getContext()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'. Convert(const llvm::APSInt & To,const llvm::APSInt & From)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 Convert(QualType T,const llvm::APSInt & From)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 getIntValue(uint64_t X,bool isUnsigned)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 getMaxValue(const llvm::APSInt & v)118 inline const llvm::APSInt& getMaxValue(const llvm::APSInt &v) { 119 return getValue(llvm::APSInt::getMaxValue(v.getBitWidth(), v.isUnsigned())); 120 } 121 getMinValue(const llvm::APSInt & v)122 inline const llvm::APSInt& getMinValue(const llvm::APSInt &v) { 123 return getValue(llvm::APSInt::getMinValue(v.getBitWidth(), v.isUnsigned())); 124 } 125 getMaxValue(QualType T)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 getMinValue(QualType T)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 Add1(const llvm::APSInt & V)140 inline const llvm::APSInt& Add1(const llvm::APSInt& V) { 141 llvm::APSInt X = V; 142 ++X; 143 return getValue(X); 144 } 145 Sub1(const llvm::APSInt & V)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 getIntWithPtrWidth(uint64_t X,bool isUnsigned)156 inline const llvm::APSInt &getIntWithPtrWidth(uint64_t X, bool isUnsigned) { 157 return getValue(X, Ctx.getTypeSize(Ctx.VoidPtrTy), isUnsigned); 158 } 159 getTruthValue(bool b,QualType T)160 inline const llvm::APSInt& getTruthValue(bool b, QualType T) { 161 return getValue(b ? 1 : 0, Ctx.getTypeSize(T), false); 162 } 163 getTruthValue(bool b)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 getEmptySValList()174 llvm::ImmutableList<SVal> getEmptySValList() { 175 return SValListFactory.getEmptyList(); 176 } 177 consVals(SVal X,llvm::ImmutableList<SVal> L)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