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 #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" 24 25 namespace clang { 26 namespace ento { 27 28 class CompoundValData : public llvm::FoldingSetNode { 29 QualType T; 30 llvm::ImmutableList<SVal> L; 31 32 public: 33 CompoundValData(QualType t, llvm::ImmutableList<SVal> l) : T(t), L(l) { 34 assert(NonLoc::isCompoundType(t)); 35 } 36 37 typedef llvm::ImmutableList<SVal>::iterator iterator; 38 iterator begin() const { return L.begin(); } 39 iterator end() const { return L.end(); } 40 41 static void Profile(llvm::FoldingSetNodeID& ID, QualType T, 42 llvm::ImmutableList<SVal> L); 43 44 void Profile(llvm::FoldingSetNodeID& ID) { Profile(ID, T, L); } 45 }; 46 47 class LazyCompoundValData : public llvm::FoldingSetNode { 48 StoreRef store; 49 const TypedValueRegion *region; 50 public: 51 LazyCompoundValData(const StoreRef &st, const TypedValueRegion *r) 52 : store(st), region(r) { 53 assert(NonLoc::isCompoundType(r->getValueType())); 54 } 55 56 const void *getStore() const { return store.getStore(); } 57 const TypedValueRegion *getRegion() const { return region; } 58 59 static void Profile(llvm::FoldingSetNodeID& ID, 60 const StoreRef &store, 61 const TypedValueRegion *region); 62 63 void Profile(llvm::FoldingSetNodeID& ID) { Profile(ID, store, region); } 64 }; 65 66 class PointerToMemberData: public llvm::FoldingSetNode { 67 const DeclaratorDecl *D; 68 llvm::ImmutableList<const CXXBaseSpecifier *> L; 69 70 public: 71 PointerToMemberData(const DeclaratorDecl *D, 72 llvm::ImmutableList<const CXXBaseSpecifier *> L) 73 : D(D), L(L) {} 74 75 typedef llvm::ImmutableList<const CXXBaseSpecifier *>::iterator iterator; 76 iterator begin() const { return L.begin(); } 77 iterator end() const { return L.end(); } 78 79 static void Profile(llvm::FoldingSetNodeID& ID, const DeclaratorDecl *D, 80 llvm::ImmutableList<const CXXBaseSpecifier *> L); 81 82 void Profile(llvm::FoldingSetNodeID& ID) { Profile(ID, D, L); } 83 const DeclaratorDecl *getDeclaratorDecl() const {return D;} 84 llvm::ImmutableList<const CXXBaseSpecifier *> getCXXBaseList() const { 85 return L; 86 } 87 }; 88 89 class BasicValueFactory { 90 typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<llvm::APSInt> > 91 APSIntSetTy; 92 93 ASTContext &Ctx; 94 llvm::BumpPtrAllocator& BPAlloc; 95 96 APSIntSetTy APSIntSet; 97 void * PersistentSVals; 98 void * PersistentSValPairs; 99 100 llvm::ImmutableList<SVal>::Factory SValListFactory; 101 llvm::ImmutableList<const CXXBaseSpecifier*>::Factory CXXBaseListFactory; 102 llvm::FoldingSet<CompoundValData> CompoundValDataSet; 103 llvm::FoldingSet<LazyCompoundValData> LazyCompoundValDataSet; 104 llvm::FoldingSet<PointerToMemberData> PointerToMemberDataSet; 105 106 // This is private because external clients should use the factory 107 // method that takes a QualType. 108 const llvm::APSInt& getValue(uint64_t X, unsigned BitWidth, bool isUnsigned); 109 110 public: 111 BasicValueFactory(ASTContext &ctx, llvm::BumpPtrAllocator &Alloc) 112 : Ctx(ctx), BPAlloc(Alloc), PersistentSVals(nullptr), 113 PersistentSValPairs(nullptr), SValListFactory(Alloc), 114 CXXBaseListFactory(Alloc) {} 115 116 ~BasicValueFactory(); 117 118 ASTContext &getContext() const { return Ctx; } 119 120 const llvm::APSInt& getValue(const llvm::APSInt& X); 121 const llvm::APSInt& getValue(const llvm::APInt& X, bool isUnsigned); 122 const llvm::APSInt& getValue(uint64_t X, QualType T); 123 124 /// Returns the type of the APSInt used to store values of the given QualType. 125 APSIntType getAPSIntType(QualType T) const { 126 assert(T->isIntegralOrEnumerationType() || Loc::isLocType(T)); 127 return APSIntType(Ctx.getIntWidth(T), 128 !T->isSignedIntegerOrEnumerationType()); 129 } 130 131 /// Convert - Create a new persistent APSInt with the same value as 'From' 132 /// but with the bitwidth and signedness of 'To'. 133 const llvm::APSInt &Convert(const llvm::APSInt& To, 134 const llvm::APSInt& From) { 135 APSIntType TargetType(To); 136 if (TargetType == APSIntType(From)) 137 return From; 138 139 return getValue(TargetType.convert(From)); 140 } 141 142 const llvm::APSInt &Convert(QualType T, const llvm::APSInt &From) { 143 APSIntType TargetType = getAPSIntType(T); 144 if (TargetType == APSIntType(From)) 145 return From; 146 147 return getValue(TargetType.convert(From)); 148 } 149 150 const llvm::APSInt& getIntValue(uint64_t X, bool isUnsigned) { 151 QualType T = isUnsigned ? Ctx.UnsignedIntTy : Ctx.IntTy; 152 return getValue(X, T); 153 } 154 155 inline const llvm::APSInt& getMaxValue(const llvm::APSInt &v) { 156 return getValue(APSIntType(v).getMaxValue()); 157 } 158 159 inline const llvm::APSInt& getMinValue(const llvm::APSInt &v) { 160 return getValue(APSIntType(v).getMinValue()); 161 } 162 163 inline const llvm::APSInt& getMaxValue(QualType T) { 164 return getValue(getAPSIntType(T).getMaxValue()); 165 } 166 167 inline const llvm::APSInt& getMinValue(QualType T) { 168 return getValue(getAPSIntType(T).getMinValue()); 169 } 170 171 inline const llvm::APSInt& Add1(const llvm::APSInt& V) { 172 llvm::APSInt X = V; 173 ++X; 174 return getValue(X); 175 } 176 177 inline const llvm::APSInt& Sub1(const llvm::APSInt& V) { 178 llvm::APSInt X = V; 179 --X; 180 return getValue(X); 181 } 182 183 inline const llvm::APSInt& getZeroWithTypeSize(QualType T) { 184 assert(T->isScalarType()); 185 return getValue(0, Ctx.getTypeSize(T), true); 186 } 187 188 inline const llvm::APSInt& getZeroWithPtrWidth(bool isUnsigned = true) { 189 return getValue(0, Ctx.getTypeSize(Ctx.VoidPtrTy), isUnsigned); 190 } 191 192 inline const llvm::APSInt &getIntWithPtrWidth(uint64_t X, bool isUnsigned) { 193 return getValue(X, Ctx.getTypeSize(Ctx.VoidPtrTy), isUnsigned); 194 } 195 196 inline const llvm::APSInt& getTruthValue(bool b, QualType T) { 197 return getValue(b ? 1 : 0, Ctx.getTypeSize(T), false); 198 } 199 200 inline const llvm::APSInt& getTruthValue(bool b) { 201 return getTruthValue(b, Ctx.getLogicalOperationType()); 202 } 203 204 const CompoundValData *getCompoundValData(QualType T, 205 llvm::ImmutableList<SVal> Vals); 206 207 const LazyCompoundValData *getLazyCompoundValData(const StoreRef &store, 208 const TypedValueRegion *region); 209 210 const PointerToMemberData *getPointerToMemberData( 211 const DeclaratorDecl *DD, 212 llvm::ImmutableList<const CXXBaseSpecifier *> L); 213 214 llvm::ImmutableList<SVal> getEmptySValList() { 215 return SValListFactory.getEmptyList(); 216 } 217 218 llvm::ImmutableList<SVal> prependSVal(SVal X, llvm::ImmutableList<SVal> L) { 219 return SValListFactory.add(X, L); 220 } 221 222 llvm::ImmutableList<const CXXBaseSpecifier *> getEmptyCXXBaseList() { 223 return CXXBaseListFactory.getEmptyList(); 224 } 225 226 llvm::ImmutableList<const CXXBaseSpecifier *> prependCXXBase( 227 const CXXBaseSpecifier *CBS, 228 llvm::ImmutableList<const CXXBaseSpecifier *> L) { 229 return CXXBaseListFactory.add(CBS, L); 230 } 231 232 const clang::ento::PointerToMemberData *accumCXXBase( 233 llvm::iterator_range<CastExpr::path_const_iterator> PathRange, 234 const nonloc::PointerToMember &PTM); 235 236 const llvm::APSInt* evalAPSInt(BinaryOperator::Opcode Op, 237 const llvm::APSInt& V1, 238 const llvm::APSInt& V2); 239 240 const std::pair<SVal, uintptr_t>& 241 getPersistentSValWithData(const SVal& V, uintptr_t Data); 242 243 const std::pair<SVal, SVal>& 244 getPersistentSValPair(const SVal& V1, const SVal& V2); 245 246 const SVal* getPersistentSVal(SVal X); 247 }; 248 249 } // end GR namespace 250 251 } // end clang namespace 252 253 #endif 254