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_STATICANALYZER_CORE_PATHSENSITIVE_BASICVALUEFACTORY_H 17 #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_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: CompoundValData(QualType t,llvm::ImmutableList<SVal> l)32 CompoundValData(QualType t, llvm::ImmutableList<SVal> l) 33 : T(t), L(l) {} 34 35 typedef llvm::ImmutableList<SVal>::iterator iterator; begin()36 iterator begin() const { return L.begin(); } end()37 iterator end() const { return L.end(); } 38 39 static void Profile(llvm::FoldingSetNodeID& ID, QualType T, 40 llvm::ImmutableList<SVal> L); 41 Profile(llvm::FoldingSetNodeID & ID)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: LazyCompoundValData(const StoreRef & st,const TypedValueRegion * r)49 LazyCompoundValData(const StoreRef &st, const TypedValueRegion *r) 50 : store(st), region(r) {} 51 getStore()52 const void *getStore() const { return store.getStore(); } getRegion()53 const TypedValueRegion *getRegion() const { return region; } 54 55 static void Profile(llvm::FoldingSetNodeID& ID, 56 const StoreRef &store, 57 const TypedValueRegion *region); 58 Profile(llvm::FoldingSetNodeID & ID)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: BasicValueFactory(ASTContext & ctx,llvm::BumpPtrAllocator & Alloc)82 BasicValueFactory(ASTContext &ctx, llvm::BumpPtrAllocator &Alloc) 83 : Ctx(ctx), BPAlloc(Alloc), PersistentSVals(nullptr), 84 PersistentSValPairs(nullptr), SValListFactory(Alloc) {} 85 86 ~BasicValueFactory(); 87 getContext()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. getAPSIntType(QualType T)95 APSIntType getAPSIntType(QualType T) const { 96 assert(T->isIntegralOrEnumerationType() || 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'. Convert(const llvm::APSInt & To,const llvm::APSInt & From)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 Convert(QualType T,const llvm::APSInt & From)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 getIntValue(uint64_t X,bool isUnsigned)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 getMaxValue(const llvm::APSInt & v)125 inline const llvm::APSInt& getMaxValue(const llvm::APSInt &v) { 126 return getValue(APSIntType(v).getMaxValue()); 127 } 128 getMinValue(const llvm::APSInt & v)129 inline const llvm::APSInt& getMinValue(const llvm::APSInt &v) { 130 return getValue(APSIntType(v).getMinValue()); 131 } 132 getMaxValue(QualType T)133 inline const llvm::APSInt& getMaxValue(QualType T) { 134 return getValue(getAPSIntType(T).getMaxValue()); 135 } 136 getMinValue(QualType T)137 inline const llvm::APSInt& getMinValue(QualType T) { 138 return getValue(getAPSIntType(T).getMinValue()); 139 } 140 Add1(const llvm::APSInt & V)141 inline const llvm::APSInt& Add1(const llvm::APSInt& V) { 142 llvm::APSInt X = V; 143 ++X; 144 return getValue(X); 145 } 146 Sub1(const llvm::APSInt & V)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 getIntWithPtrWidth(uint64_t X,bool isUnsigned)157 inline const llvm::APSInt &getIntWithPtrWidth(uint64_t X, bool isUnsigned) { 158 return getValue(X, Ctx.getTypeSize(Ctx.VoidPtrTy), isUnsigned); 159 } 160 getTruthValue(bool b,QualType T)161 inline const llvm::APSInt& getTruthValue(bool b, QualType T) { 162 return getValue(b ? 1 : 0, Ctx.getTypeSize(T), false); 163 } 164 getTruthValue(bool b)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 getEmptySValList()175 llvm::ImmutableList<SVal> getEmptySValList() { 176 return SValListFactory.getEmptyList(); 177 } 178 consVals(SVal X,llvm::ImmutableList<SVal> L)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