BasicValueFactory.h revision 5e9ebb3c0fb554d9285aa99c470abdf283272bd9
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 26namespace clang { 27 28namespace ento { 29 30 class GRState; 31 32class CompoundValData : public llvm::FoldingSetNode { 33 QualType T; 34 llvm::ImmutableList<SVal> L; 35 36public: 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 50class LazyCompoundValData : public llvm::FoldingSetNode { 51 StoreRef store; 52 const TypedRegion *region; 53public: 54 LazyCompoundValData(const StoreRef &st, const TypedRegion *r) 55 : store(st), region(r) {} 56 57 const void *getStore() const { return store.getStore(); } 58 const TypedRegion *getRegion() const { return region; } 59 60 static void Profile(llvm::FoldingSetNodeID& ID, 61 const StoreRef &store, 62 const TypedRegion *region); 63 64 void Profile(llvm::FoldingSetNodeID& ID) { Profile(ID, store, region); } 65}; 66 67class 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 82public: 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 TypedRegion *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