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