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