blob: 7298d355c4b17f8e153110eda7f079a6af4c8b05 [file] [log] [blame]
Zhongxing Xu30ad1672008-08-27 14:03:33 +00001#include "clang/Analysis/PathSensitive/ConstraintManager.h"
2#include "clang/Analysis/PathSensitive/GRState.h"
Zhongxing Xu39cfed32008-08-29 14:52:36 +00003#include "clang/Analysis/PathSensitive/GRStateTrait.h"
Zhongxing Xu30ad1672008-08-27 14:03:33 +00004#include "llvm/Support/Compiler.h"
Zhongxing Xu39cfed32008-08-29 14:52:36 +00005#include "llvm/Support/raw_ostream.h"
Zhongxing Xu30ad1672008-08-27 14:03:33 +00006
7using namespace clang;
8
9namespace {
10
Zhongxing Xu39cfed32008-08-29 14:52:36 +000011typedef llvm::ImmutableMap<SymbolID,GRState::IntSetTy> ConstNotEqTy;
12typedef llvm::ImmutableMap<SymbolID,const llvm::APSInt*> ConstEqTy;
13
Zhongxing Xu30ad1672008-08-27 14:03:33 +000014// BasicConstraintManager only tracks equality and inequality constraints of
15// constants and integer variables.
16class VISIBILITY_HIDDEN BasicConstraintManager : public ConstraintManager {
Zhongxing Xu30ad1672008-08-27 14:03:33 +000017 GRStateManager& StateMgr;
18
19public:
20 BasicConstraintManager(GRStateManager& statemgr) : StateMgr(statemgr) {}
21
22 virtual const GRState* Assume(const GRState* St, RVal Cond,
23 bool Assumption, bool& isFeasible);
24
25 const GRState* Assume(const GRState* St, LVal Cond, bool Assumption,
26 bool& isFeasible);
27
28 const GRState* AssumeAux(const GRState* St, LVal Cond,bool Assumption,
29 bool& isFeasible);
30
31 const GRState* Assume(const GRState* St, NonLVal Cond, bool Assumption,
32 bool& isFeasible);
33
34 const GRState* AssumeAux(const GRState* St, NonLVal Cond, bool Assumption,
35 bool& isFeasible);
36
37 const GRState* AssumeSymInt(const GRState* St, bool Assumption,
38 const SymIntConstraint& C, bool& isFeasible);
39
40 const GRState* AssumeSymNE(const GRState* St, SymbolID sym,
41 const llvm::APSInt& V, bool& isFeasible);
42
43 const GRState* AssumeSymEQ(const GRState* St, SymbolID sym,
44 const llvm::APSInt& V, bool& isFeasible);
45
46 const GRState* AssumeSymLT(const GRState* St, SymbolID sym,
47 const llvm::APSInt& V, bool& isFeasible);
48
49 const GRState* AssumeSymGT(const GRState* St, SymbolID sym,
50 const llvm::APSInt& V, bool& isFeasible);
51
52 const GRState* AssumeSymGE(const GRState* St, SymbolID sym,
53 const llvm::APSInt& V, bool& isFeasible);
54
55 const GRState* AssumeSymLE(const GRState* St, SymbolID sym,
56 const llvm::APSInt& V, bool& isFeasible);
Zhongxing Xu39cfed32008-08-29 14:52:36 +000057
58 const GRState* AddEQ(const GRState* St, SymbolID sym, const llvm::APSInt& V);
59
60 const GRState* AddNE(const GRState* St, SymbolID sym, const llvm::APSInt& V);
61
62 const llvm::APSInt* getSymVal(const GRState* St, SymbolID sym);
63 bool isNotEqual(const GRState* St, SymbolID sym, const llvm::APSInt& V) const;
64 bool isEqual(const GRState* St, SymbolID sym, const llvm::APSInt& V) const;
65
66 const GRState* RemoveDeadBindings(const GRState* St,
67 StoreManager::LiveSymbolsTy& LSymbols,
68 StoreManager::DeadSymbolsTy& DSymbols);
69
70 void print(const GRState* St, std::ostream& Out,
71 const char* nl, const char *sep);
72};
Zhongxing Xu30ad1672008-08-27 14:03:33 +000073
74} // end anonymous namespace
75
76ConstraintManager* clang::CreateBasicConstraintManager(GRStateManager& StateMgr)
77{
78 return new BasicConstraintManager(StateMgr);
79}
80
81const GRState* BasicConstraintManager::Assume(const GRState* St, RVal Cond,
82 bool Assumption, bool& isFeasible) {
83 if (Cond.isUnknown()) {
84 isFeasible = true;
85 return St;
86 }
87
88 if (isa<NonLVal>(Cond))
89 return Assume(St, cast<NonLVal>(Cond), Assumption, isFeasible);
90 else
91 return Assume(St, cast<LVal>(Cond), Assumption, isFeasible);
92}
93
94const GRState* BasicConstraintManager::Assume(const GRState* St, LVal Cond,
95 bool Assumption, bool& isFeasible) {
96 St = AssumeAux(St, Cond, Assumption, isFeasible);
97 // TF->EvalAssume(*this, St, Cond, Assumption, isFeasible)
98 return St;
99}
100
101const GRState* BasicConstraintManager::AssumeAux(const GRState* St, LVal Cond,
102 bool Assumption, bool& isFeasible) {
103 BasicValueFactory& BasicVals = StateMgr.getBasicVals();
104
105 switch (Cond.getSubKind()) {
106 default:
107 assert (false && "'Assume' not implemented for this LVal.");
108 return St;
109
110 case lval::SymbolValKind:
111 if (Assumption)
112 return AssumeSymNE(St, cast<lval::SymbolVal>(Cond).getSymbol(),
113 BasicVals.getZeroWithPtrWidth(), isFeasible);
114 else
115 return AssumeSymEQ(St, cast<lval::SymbolVal>(Cond).getSymbol(),
116 BasicVals.getZeroWithPtrWidth(), isFeasible);
117
118 case lval::DeclValKind:
119 case lval::FuncValKind:
120 case lval::GotoLabelKind:
121 case lval::StringLiteralValKind:
122 isFeasible = Assumption;
123 return St;
124
125 case lval::FieldOffsetKind:
126 return AssumeAux(St, cast<lval::FieldOffset>(Cond).getBase(),
127 Assumption, isFeasible);
128
129 case lval::ArrayOffsetKind:
130 return AssumeAux(St, cast<lval::ArrayOffset>(Cond).getBase(),
131 Assumption, isFeasible);
132
133 case lval::ConcreteIntKind: {
134 bool b = cast<lval::ConcreteInt>(Cond).getValue() != 0;
135 isFeasible = b ? Assumption : !Assumption;
136 return St;
137 }
138 } // end switch
139}
140
141const GRState*
142BasicConstraintManager::Assume(const GRState* St, NonLVal Cond, bool Assumption,
143 bool& isFeasible) {
144 St = AssumeAux(St, Cond, Assumption, isFeasible);
145 // TF->EvalAssume() does nothing now.
146 return St;
147}
148
149const GRState*
150BasicConstraintManager::AssumeAux(const GRState* St,NonLVal Cond,
151 bool Assumption, bool& isFeasible) {
152 BasicValueFactory& BasicVals = StateMgr.getBasicVals();
153 SymbolManager& SymMgr = StateMgr.getSymbolManager();
154
155 switch (Cond.getSubKind()) {
156 default:
157 assert(false && "'Assume' not implemented for this NonLVal");
158
159 case nonlval::SymbolValKind: {
160 nonlval::SymbolVal& SV = cast<nonlval::SymbolVal>(Cond);
161 SymbolID sym = SV.getSymbol();
162
163 if (Assumption)
164 return AssumeSymNE(St, sym, BasicVals.getValue(0, SymMgr.getType(sym)),
165 isFeasible);
166 else
167 return AssumeSymEQ(St, sym, BasicVals.getValue(0, SymMgr.getType(sym)),
168 isFeasible);
169 }
170
171 case nonlval::SymIntConstraintValKind:
172 return
173 AssumeSymInt(St, Assumption,
174 cast<nonlval::SymIntConstraintVal>(Cond).getConstraint(),
175 isFeasible);
176
177 case nonlval::ConcreteIntKind: {
178 bool b = cast<nonlval::ConcreteInt>(Cond).getValue() != 0;
179 isFeasible = b ? Assumption : !Assumption;
180 return St;
181 }
182
183 case nonlval::LValAsIntegerKind:
184 return AssumeAux(St, cast<nonlval::LValAsInteger>(Cond).getLVal(),
185 Assumption, isFeasible);
186 } // end switch
187}
188
189const GRState*
190BasicConstraintManager::AssumeSymInt(const GRState* St, bool Assumption,
191 const SymIntConstraint& C, bool& isFeasible) {
192
193 switch (C.getOpcode()) {
194 default:
195 // No logic yet for other operators.
196 isFeasible = true;
197 return St;
198
199 case BinaryOperator::EQ:
200 if (Assumption)
201 return AssumeSymEQ(St, C.getSymbol(), C.getInt(), isFeasible);
202 else
203 return AssumeSymNE(St, C.getSymbol(), C.getInt(), isFeasible);
204
205 case BinaryOperator::NE:
206 if (Assumption)
207 return AssumeSymNE(St, C.getSymbol(), C.getInt(), isFeasible);
208 else
209 return AssumeSymEQ(St, C.getSymbol(), C.getInt(), isFeasible);
210
211 case BinaryOperator::GE:
212 if (Assumption)
213 return AssumeSymGE(St, C.getSymbol(), C.getInt(), isFeasible);
214 else
215 return AssumeSymLT(St, C.getSymbol(), C.getInt(), isFeasible);
216
217 case BinaryOperator::LE:
218 if (Assumption)
219 return AssumeSymLE(St, C.getSymbol(), C.getInt(), isFeasible);
220 else
221 return AssumeSymGT(St, C.getSymbol(), C.getInt(), isFeasible);
222 } // end switch
223}
224
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000225
226
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000227const GRState*
228BasicConstraintManager::AssumeSymNE(const GRState* St, SymbolID sym,
229 const llvm::APSInt& V, bool& isFeasible) {
230 // First, determine if sym == X, where X != V.
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000231 if (const llvm::APSInt* X = getSymVal(St, sym)) {
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000232 isFeasible = (*X != V);
233 return St;
234 }
235
236 // Second, determine if sym != V.
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000237 if (isNotEqual(St, sym, V)) {
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000238 isFeasible = true;
239 return St;
240 }
241
242 // If we reach here, sym is not a constant and we don't know if it is != V.
243 // Make that assumption.
244 isFeasible = true;
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000245 return AddNE(St, sym, V);
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000246}
247
248const GRState*
249BasicConstraintManager::AssumeSymEQ(const GRState* St, SymbolID sym,
250 const llvm::APSInt& V, bool& isFeasible) {
251 // First, determine if sym == X, where X != V.
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000252 if (const llvm::APSInt* X = getSymVal(St, sym)) {
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000253 isFeasible = *X == V;
254 return St;
255 }
256
257 // Second, determine if sym != V.
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000258 if (isNotEqual(St, sym, V)) {
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000259 isFeasible = false;
260 return St;
261 }
262
263 // If we reach here, sym is not a constant and we don't know if it is == V.
264 // Make that assumption.
265
266 isFeasible = true;
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000267 return AddEQ(St, sym, V);
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000268}
269
270// These logic will be handled in another ConstraintManager.
271const GRState*
272BasicConstraintManager::AssumeSymLT(const GRState* St, SymbolID sym,
273 const llvm::APSInt& V, bool& isFeasible) {
274
275 // FIXME: For now have assuming x < y be the same as assuming sym != V;
276 return AssumeSymNE(St, sym, V, isFeasible);
277}
278
279const GRState*
280BasicConstraintManager::AssumeSymGT(const GRState* St, SymbolID sym,
281 const llvm::APSInt& V, bool& isFeasible) {
282
283 // FIXME: For now have assuming x > y be the same as assuming sym != V;
284 return AssumeSymNE(St, sym, V, isFeasible);
285}
286
287const GRState*
288BasicConstraintManager::AssumeSymGE(const GRState* St, SymbolID sym,
289 const llvm::APSInt& V, bool& isFeasible) {
290
291 // FIXME: Primitive logic for now. Only reject a path if the value of
292 // sym is a constant X and !(X >= V).
293
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000294 if (const llvm::APSInt* X = getSymVal(St, sym)) {
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000295 isFeasible = *X >= V;
296 return St;
297 }
298
299 isFeasible = true;
300 return St;
301}
302
303const GRState*
304BasicConstraintManager::AssumeSymLE(const GRState* St, SymbolID sym,
305 const llvm::APSInt& V, bool& isFeasible) {
306
307 // FIXME: Primitive logic for now. Only reject a path if the value of
308 // sym is a constant X and !(X <= V).
309
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000310 if (const llvm::APSInt* X = getSymVal(St, sym)) {
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000311 isFeasible = *X <= V;
312 return St;
313 }
314
315 isFeasible = true;
316 return St;
317}
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000318
319static int ConstEqTyIndex = 0;
320static int ConstNotEqTyIndex = 0;
321
322namespace clang {
323 template<>
324 struct GRStateTrait<ConstNotEqTy> : public GRStatePartialTrait<ConstNotEqTy> {
325 static inline void* GDMIndex() { return &ConstNotEqTyIndex; }
326 };
327
328 template<>
329 struct GRStateTrait<ConstEqTy> : public GRStatePartialTrait<ConstEqTy> {
330 static inline void* GDMIndex() { return &ConstEqTyIndex; }
331 };
332}
333
334const GRState* BasicConstraintManager::AddEQ(const GRState* St, SymbolID sym,
335 const llvm::APSInt& V) {
336 // Create a new state with the old binding replaced.
337 GRStateRef state(St, StateMgr);
338 return state.set<ConstEqTy>(sym, &V);
339}
340
341const GRState* BasicConstraintManager::AddNE(const GRState* St, SymbolID sym,
342 const llvm::APSInt& V) {
343 GRState::IntSetTy::Factory ISetFactory(StateMgr.getAllocator());
344 GRStateRef state(St, StateMgr);
345
346 // First, retrieve the NE-set associated with the given symbol.
347 ConstNotEqTy::data_type* T = state.get<ConstNotEqTy>(sym);
348 GRState::IntSetTy S = T ? *T : ISetFactory.GetEmptySet();
349
350
351 // Now add V to the NE set.
352 S = ISetFactory.Add(S, &V);
353
354 // Create a new state with the old binding replaced.
355 return state.set<ConstNotEqTy>(sym, S);
356}
357
358const llvm::APSInt* BasicConstraintManager::getSymVal(const GRState* St,
359 SymbolID sym) {
360 const ConstEqTy::data_type* T = St->get<ConstEqTy>(sym);
361 return T ? *T : NULL;
362}
363
364bool BasicConstraintManager::isNotEqual(const GRState* St, SymbolID sym,
365 const llvm::APSInt& V) const {
366
367 // Retrieve the NE-set associated with the given symbol.
368 const ConstNotEqTy::data_type* T = St->get<ConstNotEqTy>(sym);
369
370 // See if V is present in the NE-set.
371 return T ? T->contains(&V) : false;
372}
373
374bool BasicConstraintManager::isEqual(const GRState* St, SymbolID sym,
375 const llvm::APSInt& V) const {
376 // Retrieve the EQ-set associated with the given symbol.
377 const ConstEqTy::data_type* T = St->get<ConstEqTy>(sym);
378 // See if V is present in the EQ-set.
379 return T ? **T == V : false;
380}
381
382const GRState* BasicConstraintManager::RemoveDeadBindings(const GRState* St,
383 StoreManager::LiveSymbolsTy& LSymbols,
384 StoreManager::DeadSymbolsTy& DSymbols) {
385 GRStateRef state(St, StateMgr);
386 ConstEqTy CE = state.get<ConstEqTy>();
387 ConstEqTy::Factory& CEFactory = state.get_context<ConstEqTy>();
388
389 for (ConstEqTy::iterator I = CE.begin(), E = CE.end(); I!=E; ++I) {
390 SymbolID sym = I.getKey();
391 if (!LSymbols.count(sym)) {
392 DSymbols.insert(sym);
393 CE = CEFactory.Remove(CE, sym);
394 }
395 }
396 state = state.set<ConstEqTy>(CE);
397
398 ConstNotEqTy CNE = state.get<ConstNotEqTy>();
399 ConstNotEqTy::Factory& CNEFactory = state.get_context<ConstNotEqTy>();
400
401 for (ConstNotEqTy::iterator I = CNE.begin(), E = CNE.end(); I != E; ++I) {
402 SymbolID sym = I.getKey();
403 if (!LSymbols.count(sym)) {
404 DSymbols.insert(sym);
405 CNE = CNEFactory.Remove(CNE, sym);
406 }
407 }
408
409 return state.set<ConstNotEqTy>(CNE);
410}
411
412void BasicConstraintManager::print(const GRState* St, std::ostream& Out,
413 const char* nl, const char *sep) {
414 // Print equality constraints.
415
416 ConstEqTy CE = St->get<ConstEqTy>();
417
418 if (!CE.isEmpty()) {
419 Out << nl << sep << "'==' constraints:";
420
421 for (ConstEqTy::iterator I = CE.begin(), E = CE.end(); I!=E; ++I) {
422 Out << nl << " $" << I.getKey();
423 llvm::raw_os_ostream OS(Out);
424 OS << " : " << *I.getData();
425 }
426 }
427
428 // Print != constraints.
429
430 ConstNotEqTy CNE = St->get<ConstNotEqTy>();
431
432 if (!CNE.isEmpty()) {
433 Out << nl << sep << "'!=' constraints:";
434
435 for (ConstNotEqTy::iterator I = CNE.begin(), EI = CNE.end(); I!=EI; ++I) {
436 Out << nl << " $" << I.getKey() << " : ";
437 bool isFirst = true;
438
439 GRState::IntSetTy::iterator J = I.getData().begin(),
440 EJ = I.getData().end();
441
442 for ( ; J != EJ; ++J) {
443 if (isFirst) isFirst = false;
444 else Out << ", ";
445
446 Out << *J;
447 }
448 }
449 }
450}