blob: 246beead1208ce98ed36d54e58ca8270ac64dcbf [file] [log] [blame]
Shih-wei Liaof8fd82b2010-02-10 11:10:31 -08001//=== BasicValueFactory.cpp - 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 GRExprEngine
12// and related classes.
13//
14//===----------------------------------------------------------------------===//
15
16#include "clang/Checker/PathSensitive/BasicValueFactory.h"
17
18using namespace clang;
19
20void CompoundValData::Profile(llvm::FoldingSetNodeID& ID, QualType T,
21 llvm::ImmutableList<SVal> L) {
22 T.Profile(ID);
23 ID.AddPointer(L.getInternalPointer());
24}
25
26void LazyCompoundValData::Profile(llvm::FoldingSetNodeID& ID,
27 const void *store,const TypedRegion *region) {
28 ID.AddPointer(store);
29 ID.AddPointer(region);
30}
31
32typedef std::pair<SVal, uintptr_t> SValData;
33typedef std::pair<SVal, SVal> SValPair;
34
35namespace llvm {
36template<> struct FoldingSetTrait<SValData> {
37 static inline void Profile(const SValData& X, llvm::FoldingSetNodeID& ID) {
38 X.first.Profile(ID);
39 ID.AddPointer( (void*) X.second);
40 }
41};
42
43template<> struct FoldingSetTrait<SValPair> {
44 static inline void Profile(const SValPair& X, llvm::FoldingSetNodeID& ID) {
45 X.first.Profile(ID);
46 X.second.Profile(ID);
47 }
48};
49}
50
51typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<SValData> >
52 PersistentSValsTy;
53
54typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<SValPair> >
55 PersistentSValPairsTy;
56
57BasicValueFactory::~BasicValueFactory() {
58 // Note that the dstor for the contents of APSIntSet will never be called,
59 // so we iterate over the set and invoke the dstor for each APSInt. This
60 // frees an aux. memory allocated to represent very large constants.
61 for (APSIntSetTy::iterator I=APSIntSet.begin(), E=APSIntSet.end(); I!=E; ++I)
62 I->getValue().~APSInt();
63
64 delete (PersistentSValsTy*) PersistentSVals;
65 delete (PersistentSValPairsTy*) PersistentSValPairs;
66}
67
68const llvm::APSInt& BasicValueFactory::getValue(const llvm::APSInt& X) {
69 llvm::FoldingSetNodeID ID;
70 void* InsertPos;
71 typedef llvm::FoldingSetNodeWrapper<llvm::APSInt> FoldNodeTy;
72
73 X.Profile(ID);
74 FoldNodeTy* P = APSIntSet.FindNodeOrInsertPos(ID, InsertPos);
75
76 if (!P) {
77 P = (FoldNodeTy*) BPAlloc.Allocate<FoldNodeTy>();
78 new (P) FoldNodeTy(X);
79 APSIntSet.InsertNode(P, InsertPos);
80 }
81
82 return *P;
83}
84
85const llvm::APSInt& BasicValueFactory::getValue(const llvm::APInt& X,
86 bool isUnsigned) {
87 llvm::APSInt V(X, isUnsigned);
88 return getValue(V);
89}
90
91const llvm::APSInt& BasicValueFactory::getValue(uint64_t X, unsigned BitWidth,
92 bool isUnsigned) {
93 llvm::APSInt V(BitWidth, isUnsigned);
94 V = X;
95 return getValue(V);
96}
97
98const llvm::APSInt& BasicValueFactory::getValue(uint64_t X, QualType T) {
99
100 unsigned bits = Ctx.getTypeSize(T);
101 llvm::APSInt V(bits, T->isUnsignedIntegerType() || Loc::IsLocType(T));
102 V = X;
103 return getValue(V);
104}
105
106const CompoundValData*
107BasicValueFactory::getCompoundValData(QualType T,
108 llvm::ImmutableList<SVal> Vals) {
109
110 llvm::FoldingSetNodeID ID;
111 CompoundValData::Profile(ID, T, Vals);
112 void* InsertPos;
113
114 CompoundValData* D = CompoundValDataSet.FindNodeOrInsertPos(ID, InsertPos);
115
116 if (!D) {
117 D = (CompoundValData*) BPAlloc.Allocate<CompoundValData>();
118 new (D) CompoundValData(T, Vals);
119 CompoundValDataSet.InsertNode(D, InsertPos);
120 }
121
122 return D;
123}
124
125const LazyCompoundValData*
126BasicValueFactory::getLazyCompoundValData(const void *store,
127 const TypedRegion *region) {
128 llvm::FoldingSetNodeID ID;
129 LazyCompoundValData::Profile(ID, store, region);
130 void* InsertPos;
131
132 LazyCompoundValData *D =
133 LazyCompoundValDataSet.FindNodeOrInsertPos(ID, InsertPos);
134
135 if (!D) {
136 D = (LazyCompoundValData*) BPAlloc.Allocate<LazyCompoundValData>();
137 new (D) LazyCompoundValData(store, region);
138 LazyCompoundValDataSet.InsertNode(D, InsertPos);
139 }
140
141 return D;
142}
143
144const llvm::APSInt*
145BasicValueFactory::EvaluateAPSInt(BinaryOperator::Opcode Op,
146 const llvm::APSInt& V1, const llvm::APSInt& V2) {
147
148 switch (Op) {
149 default:
150 assert (false && "Invalid Opcode.");
151
152 case BinaryOperator::Mul:
153 return &getValue( V1 * V2 );
154
155 case BinaryOperator::Div:
156 return &getValue( V1 / V2 );
157
158 case BinaryOperator::Rem:
159 return &getValue( V1 % V2 );
160
161 case BinaryOperator::Add:
162 return &getValue( V1 + V2 );
163
164 case BinaryOperator::Sub:
165 return &getValue( V1 - V2 );
166
167 case BinaryOperator::Shl: {
168
169 // FIXME: This logic should probably go higher up, where we can
170 // test these conditions symbolically.
171
172 // FIXME: Expand these checks to include all undefined behavior.
173
174 if (V2.isSigned() && V2.isNegative())
175 return NULL;
176
177 uint64_t Amt = V2.getZExtValue();
178
179 if (Amt > V1.getBitWidth())
180 return NULL;
181
182 return &getValue( V1.operator<<( (unsigned) Amt ));
183 }
184
185 case BinaryOperator::Shr: {
186
187 // FIXME: This logic should probably go higher up, where we can
188 // test these conditions symbolically.
189
190 // FIXME: Expand these checks to include all undefined behavior.
191
192 if (V2.isSigned() && V2.isNegative())
193 return NULL;
194
195 uint64_t Amt = V2.getZExtValue();
196
197 if (Amt > V1.getBitWidth())
198 return NULL;
199
200 return &getValue( V1.operator>>( (unsigned) Amt ));
201 }
202
203 case BinaryOperator::LT:
204 return &getTruthValue( V1 < V2 );
205
206 case BinaryOperator::GT:
207 return &getTruthValue( V1 > V2 );
208
209 case BinaryOperator::LE:
210 return &getTruthValue( V1 <= V2 );
211
212 case BinaryOperator::GE:
213 return &getTruthValue( V1 >= V2 );
214
215 case BinaryOperator::EQ:
216 return &getTruthValue( V1 == V2 );
217
218 case BinaryOperator::NE:
219 return &getTruthValue( V1 != V2 );
220
221 // Note: LAnd, LOr, Comma are handled specially by higher-level logic.
222
223 case BinaryOperator::And:
224 return &getValue( V1 & V2 );
225
226 case BinaryOperator::Or:
227 return &getValue( V1 | V2 );
228
229 case BinaryOperator::Xor:
230 return &getValue( V1 ^ V2 );
231 }
232}
233
234
235const std::pair<SVal, uintptr_t>&
236BasicValueFactory::getPersistentSValWithData(const SVal& V, uintptr_t Data) {
237
238 // Lazily create the folding set.
239 if (!PersistentSVals) PersistentSVals = new PersistentSValsTy();
240
241 llvm::FoldingSetNodeID ID;
242 void* InsertPos;
243 V.Profile(ID);
244 ID.AddPointer((void*) Data);
245
246 PersistentSValsTy& Map = *((PersistentSValsTy*) PersistentSVals);
247
248 typedef llvm::FoldingSetNodeWrapper<SValData> FoldNodeTy;
249 FoldNodeTy* P = Map.FindNodeOrInsertPos(ID, InsertPos);
250
251 if (!P) {
252 P = (FoldNodeTy*) BPAlloc.Allocate<FoldNodeTy>();
253 new (P) FoldNodeTy(std::make_pair(V, Data));
254 Map.InsertNode(P, InsertPos);
255 }
256
257 return P->getValue();
258}
259
260const std::pair<SVal, SVal>&
261BasicValueFactory::getPersistentSValPair(const SVal& V1, const SVal& V2) {
262
263 // Lazily create the folding set.
264 if (!PersistentSValPairs) PersistentSValPairs = new PersistentSValPairsTy();
265
266 llvm::FoldingSetNodeID ID;
267 void* InsertPos;
268 V1.Profile(ID);
269 V2.Profile(ID);
270
271 PersistentSValPairsTy& Map = *((PersistentSValPairsTy*) PersistentSValPairs);
272
273 typedef llvm::FoldingSetNodeWrapper<SValPair> FoldNodeTy;
274 FoldNodeTy* P = Map.FindNodeOrInsertPos(ID, InsertPos);
275
276 if (!P) {
277 P = (FoldNodeTy*) BPAlloc.Allocate<FoldNodeTy>();
278 new (P) FoldNodeTy(std::make_pair(V1, V2));
279 Map.InsertNode(P, InsertPos);
280 }
281
282 return P->getValue();
283}
284
285const SVal* BasicValueFactory::getPersistentSVal(SVal X) {
286 return &getPersistentSValWithData(X, 0).first;
287}
288
289