blob: e89546ecb0185eec0932efc42896d82ce8a4ce9f [file] [log] [blame]
Shih-wei Liaof8fd82b2010-02-10 11:10:31 -08001//== BasicConstraintManager.cpp - Manage basic constraints.------*- 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 BasicConstraintManager, a class that tracks simple
11// equality and inequality constraints on symbolic values of GRState.
12//
13//===----------------------------------------------------------------------===//
14
15#include "SimpleConstraintManager.h"
16#include "clang/Checker/PathSensitive/GRState.h"
17#include "clang/Checker/PathSensitive/GRStateTrait.h"
18#include "clang/Checker/PathSensitive/GRTransferFuncs.h"
19#include "llvm/Support/raw_ostream.h"
20
21using namespace clang;
22
23
24namespace { class ConstNotEq {}; }
25namespace { class ConstEq {}; }
26
27typedef llvm::ImmutableMap<SymbolRef,GRState::IntSetTy> ConstNotEqTy;
28typedef llvm::ImmutableMap<SymbolRef,const llvm::APSInt*> ConstEqTy;
29
30static int ConstEqIndex = 0;
31static int ConstNotEqIndex = 0;
32
33namespace clang {
34template<>
35struct GRStateTrait<ConstNotEq> : public GRStatePartialTrait<ConstNotEqTy> {
36 static inline void* GDMIndex() { return &ConstNotEqIndex; }
37};
38
39template<>
40struct GRStateTrait<ConstEq> : public GRStatePartialTrait<ConstEqTy> {
41 static inline void* GDMIndex() { return &ConstEqIndex; }
42};
43}
44
45namespace {
46// BasicConstraintManager only tracks equality and inequality constraints of
47// constants and integer variables.
48class BasicConstraintManager
49 : public SimpleConstraintManager {
50 GRState::IntSetTy::Factory ISetFactory;
51public:
52 BasicConstraintManager(GRStateManager &statemgr, GRSubEngine &subengine)
53 : SimpleConstraintManager(subengine),
54 ISetFactory(statemgr.getAllocator()) {}
55
56 const GRState* AssumeSymNE(const GRState* state, SymbolRef sym,
57 const llvm::APSInt& V);
58
59 const GRState* AssumeSymEQ(const GRState* state, SymbolRef sym,
60 const llvm::APSInt& V);
61
62 const GRState* AssumeSymLT(const GRState* state, SymbolRef sym,
63 const llvm::APSInt& V);
64
65 const GRState* AssumeSymGT(const GRState* state, SymbolRef sym,
66 const llvm::APSInt& V);
67
68 const GRState* AssumeSymGE(const GRState* state, SymbolRef sym,
69 const llvm::APSInt& V);
70
71 const GRState* AssumeSymLE(const GRState* state, SymbolRef sym,
72 const llvm::APSInt& V);
73
74 const GRState* AddEQ(const GRState* state, SymbolRef sym, const llvm::APSInt& V);
75
76 const GRState* AddNE(const GRState* state, SymbolRef sym, const llvm::APSInt& V);
77
78 const llvm::APSInt* getSymVal(const GRState* state, SymbolRef sym) const;
79 bool isNotEqual(const GRState* state, SymbolRef sym, const llvm::APSInt& V)
80 const;
81 bool isEqual(const GRState* state, SymbolRef sym, const llvm::APSInt& V)
82 const;
83
84 const GRState* RemoveDeadBindings(const GRState* state, SymbolReaper& SymReaper);
85
86 void print(const GRState* state, llvm::raw_ostream& Out,
87 const char* nl, const char *sep);
88};
89
90} // end anonymous namespace
91
92ConstraintManager* clang::CreateBasicConstraintManager(GRStateManager& statemgr,
93 GRSubEngine &subengine) {
94 return new BasicConstraintManager(statemgr, subengine);
95}
96
97const GRState*
98BasicConstraintManager::AssumeSymNE(const GRState *state, SymbolRef sym,
99 const llvm::APSInt& V) {
100 // First, determine if sym == X, where X != V.
101 if (const llvm::APSInt* X = getSymVal(state, sym)) {
102 bool isFeasible = (*X != V);
103 return isFeasible ? state : NULL;
104 }
105
106 // Second, determine if sym != V.
107 if (isNotEqual(state, sym, V))
108 return state;
109
110 // If we reach here, sym is not a constant and we don't know if it is != V.
111 // Make that assumption.
112 return AddNE(state, sym, V);
113}
114
115const GRState *BasicConstraintManager::AssumeSymEQ(const GRState *state,
116 SymbolRef sym,
117 const llvm::APSInt &V) {
118 // First, determine if sym == X, where X != V.
119 if (const llvm::APSInt* X = getSymVal(state, sym)) {
120 bool isFeasible = *X == V;
121 return isFeasible ? state : NULL;
122 }
123
124 // Second, determine if sym != V.
125 if (isNotEqual(state, sym, V))
126 return NULL;
127
128 // If we reach here, sym is not a constant and we don't know if it is == V.
129 // Make that assumption.
130 return AddEQ(state, sym, V);
131}
132
133// These logic will be handled in another ConstraintManager.
134const GRState *BasicConstraintManager::AssumeSymLT(const GRState *state,
135 SymbolRef sym,
136 const llvm::APSInt& V) {
137 // Is 'V' the smallest possible value?
138 if (V == llvm::APSInt::getMinValue(V.getBitWidth(), V.isUnsigned())) {
139 // sym cannot be any value less than 'V'. This path is infeasible.
140 return NULL;
141 }
142
143 // FIXME: For now have assuming x < y be the same as assuming sym != V;
144 return AssumeSymNE(state, sym, V);
145}
146
147const GRState *BasicConstraintManager::AssumeSymGT(const GRState *state,
148 SymbolRef sym,
149 const llvm::APSInt& V) {
150
151 // Is 'V' the largest possible value?
152 if (V == llvm::APSInt::getMaxValue(V.getBitWidth(), V.isUnsigned())) {
153 // sym cannot be any value greater than 'V'. This path is infeasible.
154 return NULL;
155 }
156
157 // FIXME: For now have assuming x > y be the same as assuming sym != V;
158 return AssumeSymNE(state, sym, V);
159}
160
161const GRState *BasicConstraintManager::AssumeSymGE(const GRState *state,
162 SymbolRef sym,
163 const llvm::APSInt &V) {
164
165 // Reject a path if the value of sym is a constant X and !(X >= V).
166 if (const llvm::APSInt *X = getSymVal(state, sym)) {
167 bool isFeasible = *X >= V;
168 return isFeasible ? state : NULL;
169 }
170
171 // Sym is not a constant, but it is worth looking to see if V is the
172 // maximum integer value.
173 if (V == llvm::APSInt::getMaxValue(V.getBitWidth(), V.isUnsigned())) {
174 // If we know that sym != V, then this condition is infeasible since
175 // there is no other value greater than V.
176 bool isFeasible = !isNotEqual(state, sym, V);
177
178 // If the path is still feasible then as a consequence we know that
179 // 'sym == V' because we cannot have 'sym > V' (no larger values).
180 // Add this constraint.
181 return isFeasible ? AddEQ(state, sym, V) : NULL;
182 }
183
184 return state;
185}
186
187const GRState*
188BasicConstraintManager::AssumeSymLE(const GRState* state, SymbolRef sym,
189 const llvm::APSInt& V) {
190
191 // Reject a path if the value of sym is a constant X and !(X <= V).
192 if (const llvm::APSInt* X = getSymVal(state, sym)) {
193 bool isFeasible = *X <= V;
194 return isFeasible ? state : NULL;
195 }
196
197 // Sym is not a constant, but it is worth looking to see if V is the
198 // minimum integer value.
199 if (V == llvm::APSInt::getMinValue(V.getBitWidth(), V.isUnsigned())) {
200 // If we know that sym != V, then this condition is infeasible since
201 // there is no other value less than V.
202 bool isFeasible = !isNotEqual(state, sym, V);
203
204 // If the path is still feasible then as a consequence we know that
205 // 'sym == V' because we cannot have 'sym < V' (no smaller values).
206 // Add this constraint.
207 return isFeasible ? AddEQ(state, sym, V) : NULL;
208 }
209
210 return state;
211}
212
213const GRState* BasicConstraintManager::AddEQ(const GRState* state, SymbolRef sym,
214 const llvm::APSInt& V) {
215 // Create a new state with the old binding replaced.
216 return state->set<ConstEq>(sym, &V);
217}
218
219const GRState* BasicConstraintManager::AddNE(const GRState* state, SymbolRef sym,
220 const llvm::APSInt& V) {
221
222 // First, retrieve the NE-set associated with the given symbol.
223 ConstNotEqTy::data_type* T = state->get<ConstNotEq>(sym);
224 GRState::IntSetTy S = T ? *T : ISetFactory.GetEmptySet();
225
226 // Now add V to the NE set.
227 S = ISetFactory.Add(S, &V);
228
229 // Create a new state with the old binding replaced.
230 return state->set<ConstNotEq>(sym, S);
231}
232
233const llvm::APSInt* BasicConstraintManager::getSymVal(const GRState* state,
234 SymbolRef sym) const {
235 const ConstEqTy::data_type* T = state->get<ConstEq>(sym);
236 return T ? *T : NULL;
237}
238
239bool BasicConstraintManager::isNotEqual(const GRState* state, SymbolRef sym,
240 const llvm::APSInt& V) const {
241
242 // Retrieve the NE-set associated with the given symbol.
243 const ConstNotEqTy::data_type* T = state->get<ConstNotEq>(sym);
244
245 // See if V is present in the NE-set.
246 return T ? T->contains(&V) : false;
247}
248
249bool BasicConstraintManager::isEqual(const GRState* state, SymbolRef sym,
250 const llvm::APSInt& V) const {
251 // Retrieve the EQ-set associated with the given symbol.
252 const ConstEqTy::data_type* T = state->get<ConstEq>(sym);
253 // See if V is present in the EQ-set.
254 return T ? **T == V : false;
255}
256
257/// Scan all symbols referenced by the constraints. If the symbol is not alive
258/// as marked in LSymbols, mark it as dead in DSymbols.
259const GRState*
260BasicConstraintManager::RemoveDeadBindings(const GRState* state,
261 SymbolReaper& SymReaper) {
262
263 ConstEqTy CE = state->get<ConstEq>();
264 ConstEqTy::Factory& CEFactory = state->get_context<ConstEq>();
265
266 for (ConstEqTy::iterator I = CE.begin(), E = CE.end(); I!=E; ++I) {
267 SymbolRef sym = I.getKey();
268 if (SymReaper.maybeDead(sym)) CE = CEFactory.Remove(CE, sym);
269 }
270 state = state->set<ConstEq>(CE);
271
272 ConstNotEqTy CNE = state->get<ConstNotEq>();
273 ConstNotEqTy::Factory& CNEFactory = state->get_context<ConstNotEq>();
274
275 for (ConstNotEqTy::iterator I = CNE.begin(), E = CNE.end(); I != E; ++I) {
276 SymbolRef sym = I.getKey();
277 if (SymReaper.maybeDead(sym)) CNE = CNEFactory.Remove(CNE, sym);
278 }
279
280 return state->set<ConstNotEq>(CNE);
281}
282
283void BasicConstraintManager::print(const GRState* state, llvm::raw_ostream& Out,
284 const char* nl, const char *sep) {
285 // Print equality constraints.
286
287 ConstEqTy CE = state->get<ConstEq>();
288
289 if (!CE.isEmpty()) {
290 Out << nl << sep << "'==' constraints:";
291 for (ConstEqTy::iterator I = CE.begin(), E = CE.end(); I!=E; ++I)
292 Out << nl << " $" << I.getKey() << " : " << *I.getData();
293 }
294
295 // Print != constraints.
296
297 ConstNotEqTy CNE = state->get<ConstNotEq>();
298
299 if (!CNE.isEmpty()) {
300 Out << nl << sep << "'!=' constraints:";
301
302 for (ConstNotEqTy::iterator I = CNE.begin(), EI = CNE.end(); I!=EI; ++I) {
303 Out << nl << " $" << I.getKey() << " : ";
304 bool isFirst = true;
305
306 GRState::IntSetTy::iterator J = I.getData().begin(),
307 EJ = I.getData().end();
308
309 for ( ; J != EJ; ++J) {
310 if (isFirst) isFirst = false;
311 else Out << ", ";
312
313 Out << (*J)->getSExtValue(); // Hack: should print to raw_ostream.
314 }
315 }
316 }
317}