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: CompoundValData(QualType t,llvm::ImmutableList<SVal> l)31 CompoundValData(QualType t, llvm::ImmutableList<SVal> l) 32 : T(t), L(l) {} 33 34 typedef llvm::ImmutableList<SVal>::iterator iterator; begin()35 iterator begin() const { return L.begin(); } end()36 iterator end() const { return L.end(); } 37 38 static void Profile(llvm::FoldingSetNodeID& ID, QualType T, 39 llvm::ImmutableList<SVal> L); 40 Profile(llvm::FoldingSetNodeID & ID)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: LazyCompoundValData(const StoreRef & st,const TypedValueRegion * r)48 LazyCompoundValData(const StoreRef &st, const TypedValueRegion *r) 49 : store(st), region(r) {} 50 getStore()51 const void *getStore() const { return store.getStore(); } getRegion()52 const TypedValueRegion *getRegion() const { return region; } 53 54 static void Profile(llvm::FoldingSetNodeID& ID, 55 const StoreRef &store, 56 const TypedValueRegion *region); 57 Profile(llvm::FoldingSetNodeID & ID)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: BasicValueFactory(ASTContext & ctx,llvm::BumpPtrAllocator & Alloc)81 BasicValueFactory(ASTContext &ctx, llvm::BumpPtrAllocator& Alloc) 82 : Ctx(ctx), BPAlloc(Alloc), PersistentSVals(0), PersistentSValPairs(0), 83 SValListFactory(Alloc) {} 84 85 ~BasicValueFactory(); 86 getContext()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. getAPSIntType(QualType T)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'. Convert(const llvm::APSInt & To,const llvm::APSInt & From)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 Convert(QualType T,const llvm::APSInt & From)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 getIntValue(uint64_t X,bool isUnsigned)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 getMaxValue(const llvm::APSInt & v)124 inline const llvm::APSInt& getMaxValue(const llvm::APSInt &v) { 125 return getValue(APSIntType(v).getMaxValue()); 126 } 127 getMinValue(const llvm::APSInt & v)128 inline const llvm::APSInt& getMinValue(const llvm::APSInt &v) { 129 return getValue(APSIntType(v).getMinValue()); 130 } 131 getMaxValue(QualType T)132 inline const llvm::APSInt& getMaxValue(QualType T) { 133 return getValue(getAPSIntType(T).getMaxValue()); 134 } 135 getMinValue(QualType T)136 inline const llvm::APSInt& getMinValue(QualType T) { 137 return getValue(getAPSIntType(T).getMinValue()); 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