blob: efe5b93da4051665d711d274c24e0333b3539bb5 [file] [log] [blame]
Zhongxing Xu30ad1672008-08-27 14:03:33 +00001#include "clang/Analysis/PathSensitive/ConstraintManager.h"
2#include "clang/Analysis/PathSensitive/GRState.h"
3#include "llvm/Support/Compiler.h"
4
5using namespace clang;
6
7namespace {
8
9// BasicConstraintManager only tracks equality and inequality constraints of
10// constants and integer variables.
11class VISIBILITY_HIDDEN BasicConstraintManager : public ConstraintManager {
12 typedef llvm::ImmutableMap<SymbolID, GRState::IntSetTy> ConstNotEqTy;
13 typedef llvm::ImmutableMap<SymbolID, const llvm::APSInt*> ConstEqTy;
14
15 GRStateManager& StateMgr;
16
17public:
18 BasicConstraintManager(GRStateManager& statemgr) : StateMgr(statemgr) {}
19
20 virtual const GRState* Assume(const GRState* St, RVal Cond,
21 bool Assumption, bool& isFeasible);
22
23 const GRState* Assume(const GRState* St, LVal Cond, bool Assumption,
24 bool& isFeasible);
25
26 const GRState* AssumeAux(const GRState* St, LVal Cond,bool Assumption,
27 bool& isFeasible);
28
29 const GRState* Assume(const GRState* St, NonLVal Cond, bool Assumption,
30 bool& isFeasible);
31
32 const GRState* AssumeAux(const GRState* St, NonLVal Cond, bool Assumption,
33 bool& isFeasible);
34
35 const GRState* AssumeSymInt(const GRState* St, bool Assumption,
36 const SymIntConstraint& C, bool& isFeasible);
37
38 const GRState* AssumeSymNE(const GRState* St, SymbolID sym,
39 const llvm::APSInt& V, bool& isFeasible);
40
41 const GRState* AssumeSymEQ(const GRState* St, SymbolID sym,
42 const llvm::APSInt& V, bool& isFeasible);
43
44 const GRState* AssumeSymLT(const GRState* St, SymbolID sym,
45 const llvm::APSInt& V, bool& isFeasible);
46
47 const GRState* AssumeSymGT(const GRState* St, SymbolID sym,
48 const llvm::APSInt& V, bool& isFeasible);
49
50 const GRState* AssumeSymGE(const GRState* St, SymbolID sym,
51 const llvm::APSInt& V, bool& isFeasible);
52
53 const GRState* AssumeSymLE(const GRState* St, SymbolID sym,
54 const llvm::APSInt& V, bool& isFeasible);
55 };
56
57} // end anonymous namespace
58
59ConstraintManager* clang::CreateBasicConstraintManager(GRStateManager& StateMgr)
60{
61 return new BasicConstraintManager(StateMgr);
62}
63
64const GRState* BasicConstraintManager::Assume(const GRState* St, RVal Cond,
65 bool Assumption, bool& isFeasible) {
66 if (Cond.isUnknown()) {
67 isFeasible = true;
68 return St;
69 }
70
71 if (isa<NonLVal>(Cond))
72 return Assume(St, cast<NonLVal>(Cond), Assumption, isFeasible);
73 else
74 return Assume(St, cast<LVal>(Cond), Assumption, isFeasible);
75}
76
77const GRState* BasicConstraintManager::Assume(const GRState* St, LVal Cond,
78 bool Assumption, bool& isFeasible) {
79 St = AssumeAux(St, Cond, Assumption, isFeasible);
80 // TF->EvalAssume(*this, St, Cond, Assumption, isFeasible)
81 return St;
82}
83
84const GRState* BasicConstraintManager::AssumeAux(const GRState* St, LVal Cond,
85 bool Assumption, bool& isFeasible) {
86 BasicValueFactory& BasicVals = StateMgr.getBasicVals();
87
88 switch (Cond.getSubKind()) {
89 default:
90 assert (false && "'Assume' not implemented for this LVal.");
91 return St;
92
93 case lval::SymbolValKind:
94 if (Assumption)
95 return AssumeSymNE(St, cast<lval::SymbolVal>(Cond).getSymbol(),
96 BasicVals.getZeroWithPtrWidth(), isFeasible);
97 else
98 return AssumeSymEQ(St, cast<lval::SymbolVal>(Cond).getSymbol(),
99 BasicVals.getZeroWithPtrWidth(), isFeasible);
100
101 case lval::DeclValKind:
102 case lval::FuncValKind:
103 case lval::GotoLabelKind:
104 case lval::StringLiteralValKind:
105 isFeasible = Assumption;
106 return St;
107
108 case lval::FieldOffsetKind:
109 return AssumeAux(St, cast<lval::FieldOffset>(Cond).getBase(),
110 Assumption, isFeasible);
111
112 case lval::ArrayOffsetKind:
113 return AssumeAux(St, cast<lval::ArrayOffset>(Cond).getBase(),
114 Assumption, isFeasible);
115
116 case lval::ConcreteIntKind: {
117 bool b = cast<lval::ConcreteInt>(Cond).getValue() != 0;
118 isFeasible = b ? Assumption : !Assumption;
119 return St;
120 }
121 } // end switch
122}
123
124const GRState*
125BasicConstraintManager::Assume(const GRState* St, NonLVal Cond, bool Assumption,
126 bool& isFeasible) {
127 St = AssumeAux(St, Cond, Assumption, isFeasible);
128 // TF->EvalAssume() does nothing now.
129 return St;
130}
131
132const GRState*
133BasicConstraintManager::AssumeAux(const GRState* St,NonLVal Cond,
134 bool Assumption, bool& isFeasible) {
135 BasicValueFactory& BasicVals = StateMgr.getBasicVals();
136 SymbolManager& SymMgr = StateMgr.getSymbolManager();
137
138 switch (Cond.getSubKind()) {
139 default:
140 assert(false && "'Assume' not implemented for this NonLVal");
141
142 case nonlval::SymbolValKind: {
143 nonlval::SymbolVal& SV = cast<nonlval::SymbolVal>(Cond);
144 SymbolID sym = SV.getSymbol();
145
146 if (Assumption)
147 return AssumeSymNE(St, sym, BasicVals.getValue(0, SymMgr.getType(sym)),
148 isFeasible);
149 else
150 return AssumeSymEQ(St, sym, BasicVals.getValue(0, SymMgr.getType(sym)),
151 isFeasible);
152 }
153
154 case nonlval::SymIntConstraintValKind:
155 return
156 AssumeSymInt(St, Assumption,
157 cast<nonlval::SymIntConstraintVal>(Cond).getConstraint(),
158 isFeasible);
159
160 case nonlval::ConcreteIntKind: {
161 bool b = cast<nonlval::ConcreteInt>(Cond).getValue() != 0;
162 isFeasible = b ? Assumption : !Assumption;
163 return St;
164 }
165
166 case nonlval::LValAsIntegerKind:
167 return AssumeAux(St, cast<nonlval::LValAsInteger>(Cond).getLVal(),
168 Assumption, isFeasible);
169 } // end switch
170}
171
172const GRState*
173BasicConstraintManager::AssumeSymInt(const GRState* St, bool Assumption,
174 const SymIntConstraint& C, bool& isFeasible) {
175
176 switch (C.getOpcode()) {
177 default:
178 // No logic yet for other operators.
179 isFeasible = true;
180 return St;
181
182 case BinaryOperator::EQ:
183 if (Assumption)
184 return AssumeSymEQ(St, C.getSymbol(), C.getInt(), isFeasible);
185 else
186 return AssumeSymNE(St, C.getSymbol(), C.getInt(), isFeasible);
187
188 case BinaryOperator::NE:
189 if (Assumption)
190 return AssumeSymNE(St, C.getSymbol(), C.getInt(), isFeasible);
191 else
192 return AssumeSymEQ(St, C.getSymbol(), C.getInt(), isFeasible);
193
194 case BinaryOperator::GE:
195 if (Assumption)
196 return AssumeSymGE(St, C.getSymbol(), C.getInt(), isFeasible);
197 else
198 return AssumeSymLT(St, C.getSymbol(), C.getInt(), isFeasible);
199
200 case BinaryOperator::LE:
201 if (Assumption)
202 return AssumeSymLE(St, C.getSymbol(), C.getInt(), isFeasible);
203 else
204 return AssumeSymGT(St, C.getSymbol(), C.getInt(), isFeasible);
205 } // end switch
206}
207
208const GRState*
209BasicConstraintManager::AssumeSymNE(const GRState* St, SymbolID sym,
210 const llvm::APSInt& V, bool& isFeasible) {
211 // First, determine if sym == X, where X != V.
212 if (const llvm::APSInt* X = St->getSymVal(sym)) {
213 isFeasible = (*X != V);
214 return St;
215 }
216
217 // Second, determine if sym != V.
218 if (St->isNotEqual(sym, V)) {
219 isFeasible = true;
220 return St;
221 }
222
223 // If we reach here, sym is not a constant and we don't know if it is != V.
224 // Make that assumption.
225 isFeasible = true;
226 return StateMgr.AddNE(St, sym, V);
227}
228
229const GRState*
230BasicConstraintManager::AssumeSymEQ(const GRState* St, SymbolID sym,
231 const llvm::APSInt& V, bool& isFeasible) {
232 // First, determine if sym == X, where X != V.
233 if (const llvm::APSInt* X = St->getSymVal(sym)) {
234 isFeasible = *X == V;
235 return St;
236 }
237
238 // Second, determine if sym != V.
239 if (St->isNotEqual(sym, V)) {
240 isFeasible = false;
241 return St;
242 }
243
244 // If we reach here, sym is not a constant and we don't know if it is == V.
245 // Make that assumption.
246
247 isFeasible = true;
248 return StateMgr.AddEQ(St, sym, V);
249}
250
251// These logic will be handled in another ConstraintManager.
252const GRState*
253BasicConstraintManager::AssumeSymLT(const GRState* St, SymbolID sym,
254 const llvm::APSInt& V, bool& isFeasible) {
255
256 // FIXME: For now have assuming x < y be the same as assuming sym != V;
257 return AssumeSymNE(St, sym, V, isFeasible);
258}
259
260const GRState*
261BasicConstraintManager::AssumeSymGT(const GRState* St, SymbolID sym,
262 const llvm::APSInt& V, bool& isFeasible) {
263
264 // FIXME: For now have assuming x > y be the same as assuming sym != V;
265 return AssumeSymNE(St, sym, V, isFeasible);
266}
267
268const GRState*
269BasicConstraintManager::AssumeSymGE(const GRState* St, SymbolID sym,
270 const llvm::APSInt& V, bool& isFeasible) {
271
272 // FIXME: Primitive logic for now. Only reject a path if the value of
273 // sym is a constant X and !(X >= V).
274
275 if (const llvm::APSInt* X = St->getSymVal(sym)) {
276 isFeasible = *X >= V;
277 return St;
278 }
279
280 isFeasible = true;
281 return St;
282}
283
284const GRState*
285BasicConstraintManager::AssumeSymLE(const GRState* St, SymbolID sym,
286 const llvm::APSInt& V, bool& isFeasible) {
287
288 // FIXME: Primitive logic for now. Only reject a path if the value of
289 // sym is a constant X and !(X <= V).
290
291 if (const llvm::APSInt* X = St->getSymVal(sym)) {
292 isFeasible = *X <= V;
293 return St;
294 }
295
296 isFeasible = true;
297 return St;
298}