blob: 450c38f20b96d3c39728330301649149ae837948 [file] [log] [blame]
Zhongxing Xud19e21b2008-08-29 15:09:12 +00001//== 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
Zhongxing Xu30ad1672008-08-27 14:03:33 +000015#include "clang/Analysis/PathSensitive/ConstraintManager.h"
16#include "clang/Analysis/PathSensitive/GRState.h"
Zhongxing Xu39cfed32008-08-29 14:52:36 +000017#include "clang/Analysis/PathSensitive/GRStateTrait.h"
Ted Kremenek2fb78a72008-12-17 21:50:35 +000018#include "clang/Analysis/PathSensitive/GRTransferFuncs.h"
Zhongxing Xu30ad1672008-08-27 14:03:33 +000019#include "llvm/Support/Compiler.h"
Zhongxing Xu39cfed32008-08-29 14:52:36 +000020#include "llvm/Support/raw_ostream.h"
Zhongxing Xu30ad1672008-08-27 14:03:33 +000021
22using namespace clang;
23
24namespace {
25
Ted Kremenek2dabd432008-12-05 02:27:51 +000026typedef llvm::ImmutableMap<SymbolRef,GRState::IntSetTy> ConstNotEqTy;
27typedef llvm::ImmutableMap<SymbolRef,const llvm::APSInt*> ConstEqTy;
Zhongxing Xu39cfed32008-08-29 14:52:36 +000028
Zhongxing Xu30ad1672008-08-27 14:03:33 +000029// BasicConstraintManager only tracks equality and inequality constraints of
30// constants and integer variables.
31class VISIBILITY_HIDDEN BasicConstraintManager : public ConstraintManager {
Zhongxing Xu30ad1672008-08-27 14:03:33 +000032 GRStateManager& StateMgr;
Zhongxing Xuf0bc50e2008-11-27 06:08:40 +000033 GRState::IntSetTy::Factory ISetFactory;
Zhongxing Xu30ad1672008-08-27 14:03:33 +000034public:
Zhongxing Xuf0bc50e2008-11-27 06:08:40 +000035 BasicConstraintManager(GRStateManager& statemgr)
36 : StateMgr(statemgr), ISetFactory(statemgr.getAllocator()) {}
Zhongxing Xu30ad1672008-08-27 14:03:33 +000037
Zhongxing Xu1c96b242008-10-17 05:57:07 +000038 virtual const GRState* Assume(const GRState* St, SVal Cond,
Zhongxing Xu30ad1672008-08-27 14:03:33 +000039 bool Assumption, bool& isFeasible);
40
Zhongxing Xu1c96b242008-10-17 05:57:07 +000041 const GRState* Assume(const GRState* St, Loc Cond, bool Assumption,
Zhongxing Xu30ad1672008-08-27 14:03:33 +000042 bool& isFeasible);
43
Zhongxing Xu1c96b242008-10-17 05:57:07 +000044 const GRState* AssumeAux(const GRState* St, Loc Cond,bool Assumption,
Zhongxing Xu30ad1672008-08-27 14:03:33 +000045 bool& isFeasible);
46
Zhongxing Xu1c96b242008-10-17 05:57:07 +000047 const GRState* Assume(const GRState* St, NonLoc Cond, bool Assumption,
Zhongxing Xu30ad1672008-08-27 14:03:33 +000048 bool& isFeasible);
49
Zhongxing Xu1c96b242008-10-17 05:57:07 +000050 const GRState* AssumeAux(const GRState* St, NonLoc Cond, bool Assumption,
Zhongxing Xu30ad1672008-08-27 14:03:33 +000051 bool& isFeasible);
52
53 const GRState* AssumeSymInt(const GRState* St, bool Assumption,
54 const SymIntConstraint& C, bool& isFeasible);
55
Ted Kremenek2dabd432008-12-05 02:27:51 +000056 const GRState* AssumeSymNE(const GRState* St, SymbolRef sym,
Zhongxing Xu30ad1672008-08-27 14:03:33 +000057 const llvm::APSInt& V, bool& isFeasible);
58
Ted Kremenek2dabd432008-12-05 02:27:51 +000059 const GRState* AssumeSymEQ(const GRState* St, SymbolRef sym,
Zhongxing Xu30ad1672008-08-27 14:03:33 +000060 const llvm::APSInt& V, bool& isFeasible);
61
Ted Kremenek2dabd432008-12-05 02:27:51 +000062 const GRState* AssumeSymLT(const GRState* St, SymbolRef sym,
Zhongxing Xu30ad1672008-08-27 14:03:33 +000063 const llvm::APSInt& V, bool& isFeasible);
64
Ted Kremenek2dabd432008-12-05 02:27:51 +000065 const GRState* AssumeSymGT(const GRState* St, SymbolRef sym,
Zhongxing Xu30ad1672008-08-27 14:03:33 +000066 const llvm::APSInt& V, bool& isFeasible);
67
Ted Kremenek2dabd432008-12-05 02:27:51 +000068 const GRState* AssumeSymGE(const GRState* St, SymbolRef sym,
Zhongxing Xu30ad1672008-08-27 14:03:33 +000069 const llvm::APSInt& V, bool& isFeasible);
70
Ted Kremenek2dabd432008-12-05 02:27:51 +000071 const GRState* AssumeSymLE(const GRState* St, SymbolRef sym,
Zhongxing Xu30ad1672008-08-27 14:03:33 +000072 const llvm::APSInt& V, bool& isFeasible);
Zhongxing Xu39cfed32008-08-29 14:52:36 +000073
Zhongxing Xue8a964b2008-11-22 13:21:46 +000074 const GRState* AssumeInBound(const GRState* St, SVal Idx, SVal UpperBound,
75 bool Assumption, bool& isFeasible);
76
Ted Kremenek2dabd432008-12-05 02:27:51 +000077 const GRState* AddEQ(const GRState* St, SymbolRef sym, const llvm::APSInt& V);
Zhongxing Xu39cfed32008-08-29 14:52:36 +000078
Ted Kremenek2dabd432008-12-05 02:27:51 +000079 const GRState* AddNE(const GRState* St, SymbolRef sym, const llvm::APSInt& V);
Zhongxing Xu39cfed32008-08-29 14:52:36 +000080
Ted Kremenek2dabd432008-12-05 02:27:51 +000081 const llvm::APSInt* getSymVal(const GRState* St, SymbolRef sym);
82 bool isNotEqual(const GRState* St, SymbolRef sym, const llvm::APSInt& V) const;
83 bool isEqual(const GRState* St, SymbolRef sym, const llvm::APSInt& V) const;
Zhongxing Xu39cfed32008-08-29 14:52:36 +000084
Ted Kremenek241677a2009-01-21 22:26:05 +000085 const GRState* RemoveDeadBindings(const GRState* St, SymbolReaper& SymReaper);
86
Zhongxing Xu39cfed32008-08-29 14:52:36 +000087
88 void print(const GRState* St, std::ostream& Out,
89 const char* nl, const char *sep);
Zhongxing Xue8a964b2008-11-22 13:21:46 +000090
91private:
92 BasicValueFactory& getBasicVals() { return StateMgr.getBasicVals(); }
Zhongxing Xu39cfed32008-08-29 14:52:36 +000093};
Zhongxing Xu30ad1672008-08-27 14:03:33 +000094
95} // end anonymous namespace
96
97ConstraintManager* clang::CreateBasicConstraintManager(GRStateManager& StateMgr)
98{
99 return new BasicConstraintManager(StateMgr);
100}
101
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000102const GRState* BasicConstraintManager::Assume(const GRState* St, SVal Cond,
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000103 bool Assumption, bool& isFeasible) {
104 if (Cond.isUnknown()) {
105 isFeasible = true;
106 return St;
107 }
108
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000109 if (isa<NonLoc>(Cond))
110 return Assume(St, cast<NonLoc>(Cond), Assumption, isFeasible);
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000111 else
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000112 return Assume(St, cast<Loc>(Cond), Assumption, isFeasible);
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000113}
114
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000115const GRState* BasicConstraintManager::Assume(const GRState* St, Loc Cond,
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000116 bool Assumption, bool& isFeasible) {
117 St = AssumeAux(St, Cond, Assumption, isFeasible);
Ted Kremenek2fb78a72008-12-17 21:50:35 +0000118
119 if (!isFeasible)
120 return St;
121
122 // EvalAssume is used to call into the GRTransferFunction object to perform
123 // any checker-specific update of the state based on this assumption being
124 // true or false.
125 return StateMgr.getTransferFuncs().EvalAssume(StateMgr, St, Cond, Assumption,
126 isFeasible);
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000127}
128
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000129const GRState* BasicConstraintManager::AssumeAux(const GRState* St, Loc Cond,
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000130 bool Assumption, bool& isFeasible) {
131 BasicValueFactory& BasicVals = StateMgr.getBasicVals();
132
133 switch (Cond.getSubKind()) {
134 default:
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000135 assert (false && "'Assume' not implemented for this Loc.");
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000136 return St;
137
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000138 case loc::SymbolValKind:
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000139 if (Assumption)
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000140 return AssumeSymNE(St, cast<loc::SymbolVal>(Cond).getSymbol(),
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000141 BasicVals.getZeroWithPtrWidth(), isFeasible);
142 else
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000143 return AssumeSymEQ(St, cast<loc::SymbolVal>(Cond).getSymbol(),
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000144 BasicVals.getZeroWithPtrWidth(), isFeasible);
145
Ted Kremenekc5234712008-10-17 21:22:20 +0000146 case loc::MemRegionKind: {
147 // FIXME: Should this go into the storemanager?
148
149 const MemRegion* R = cast<loc::MemRegionVal>(Cond).getRegion();
150
151 while (R) {
152 if (const SubRegion* SubR = dyn_cast<SubRegion>(R)) {
153 R = SubR->getSuperRegion();
154 continue;
155 }
156 else if (const SymbolicRegion* SymR = dyn_cast<SymbolicRegion>(R))
157 return AssumeAux(St, loc::SymbolVal(SymR->getSymbol()), Assumption,
158 isFeasible);
159
160 break;
161 }
162
163 // FALL-THROUGH.
164 }
165
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000166 case loc::FuncValKind:
167 case loc::GotoLabelKind:
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000168 isFeasible = Assumption;
169 return St;
170
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000171 case loc::ConcreteIntKind: {
172 bool b = cast<loc::ConcreteInt>(Cond).getValue() != 0;
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000173 isFeasible = b ? Assumption : !Assumption;
174 return St;
175 }
176 } // end switch
177}
178
179const GRState*
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000180BasicConstraintManager::Assume(const GRState* St, NonLoc Cond, bool Assumption,
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000181 bool& isFeasible) {
182 St = AssumeAux(St, Cond, Assumption, isFeasible);
Ted Kremenek2fb78a72008-12-17 21:50:35 +0000183
184 if (!isFeasible)
185 return St;
186
187 // EvalAssume is used to call into the GRTransferFunction object to perform
188 // any checker-specific update of the state based on this assumption being
189 // true or false.
190 return StateMgr.getTransferFuncs().EvalAssume(StateMgr, St, Cond, Assumption,
191 isFeasible);
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000192}
193
194const GRState*
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000195BasicConstraintManager::AssumeAux(const GRState* St,NonLoc Cond,
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000196 bool Assumption, bool& isFeasible) {
197 BasicValueFactory& BasicVals = StateMgr.getBasicVals();
198 SymbolManager& SymMgr = StateMgr.getSymbolManager();
199
200 switch (Cond.getSubKind()) {
201 default:
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000202 assert(false && "'Assume' not implemented for this NonLoc");
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000203
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000204 case nonloc::SymbolValKind: {
205 nonloc::SymbolVal& SV = cast<nonloc::SymbolVal>(Cond);
Ted Kremenek2dabd432008-12-05 02:27:51 +0000206 SymbolRef sym = SV.getSymbol();
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000207
208 if (Assumption)
209 return AssumeSymNE(St, sym, BasicVals.getValue(0, SymMgr.getType(sym)),
210 isFeasible);
211 else
212 return AssumeSymEQ(St, sym, BasicVals.getValue(0, SymMgr.getType(sym)),
213 isFeasible);
214 }
215
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000216 case nonloc::SymIntConstraintValKind:
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000217 return
218 AssumeSymInt(St, Assumption,
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000219 cast<nonloc::SymIntConstraintVal>(Cond).getConstraint(),
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000220 isFeasible);
221
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000222 case nonloc::ConcreteIntKind: {
223 bool b = cast<nonloc::ConcreteInt>(Cond).getValue() != 0;
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000224 isFeasible = b ? Assumption : !Assumption;
225 return St;
226 }
227
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000228 case nonloc::LocAsIntegerKind:
229 return AssumeAux(St, cast<nonloc::LocAsInteger>(Cond).getLoc(),
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000230 Assumption, isFeasible);
231 } // end switch
232}
233
234const GRState*
235BasicConstraintManager::AssumeSymInt(const GRState* St, bool Assumption,
236 const SymIntConstraint& C, bool& isFeasible) {
237
238 switch (C.getOpcode()) {
239 default:
240 // No logic yet for other operators.
241 isFeasible = true;
242 return St;
243
244 case BinaryOperator::EQ:
245 if (Assumption)
246 return AssumeSymEQ(St, C.getSymbol(), C.getInt(), isFeasible);
247 else
248 return AssumeSymNE(St, C.getSymbol(), C.getInt(), isFeasible);
249
250 case BinaryOperator::NE:
251 if (Assumption)
252 return AssumeSymNE(St, C.getSymbol(), C.getInt(), isFeasible);
253 else
254 return AssumeSymEQ(St, C.getSymbol(), C.getInt(), isFeasible);
255
Zhongxing Xu94b83122008-09-19 06:07:59 +0000256 case BinaryOperator::GT:
257 if (Assumption)
258 return AssumeSymGT(St, C.getSymbol(), C.getInt(), isFeasible);
259 else
260 return AssumeSymLE(St, C.getSymbol(), C.getInt(), isFeasible);
261
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000262 case BinaryOperator::GE:
263 if (Assumption)
264 return AssumeSymGE(St, C.getSymbol(), C.getInt(), isFeasible);
265 else
266 return AssumeSymLT(St, C.getSymbol(), C.getInt(), isFeasible);
267
Ted Kremenek8c3e7fb2008-09-16 23:24:45 +0000268 case BinaryOperator::LT:
269 if (Assumption)
270 return AssumeSymLT(St, C.getSymbol(), C.getInt(), isFeasible);
271 else
272 return AssumeSymGE(St, C.getSymbol(), C.getInt(), isFeasible);
273
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000274 case BinaryOperator::LE:
275 if (Assumption)
276 return AssumeSymLE(St, C.getSymbol(), C.getInt(), isFeasible);
277 else
278 return AssumeSymGT(St, C.getSymbol(), C.getInt(), isFeasible);
279 } // end switch
280}
281
282const GRState*
Ted Kremenek2dabd432008-12-05 02:27:51 +0000283BasicConstraintManager::AssumeSymNE(const GRState* St, SymbolRef sym,
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000284 const llvm::APSInt& V, bool& isFeasible) {
285 // First, determine if sym == X, where X != V.
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000286 if (const llvm::APSInt* X = getSymVal(St, sym)) {
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000287 isFeasible = (*X != V);
288 return St;
289 }
290
291 // Second, determine if sym != V.
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000292 if (isNotEqual(St, sym, V)) {
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000293 isFeasible = true;
294 return St;
295 }
296
297 // If we reach here, sym is not a constant and we don't know if it is != V.
298 // Make that assumption.
299 isFeasible = true;
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000300 return AddNE(St, sym, V);
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000301}
302
303const GRState*
Ted Kremenek2dabd432008-12-05 02:27:51 +0000304BasicConstraintManager::AssumeSymEQ(const GRState* St, SymbolRef sym,
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000305 const llvm::APSInt& V, bool& isFeasible) {
306 // First, determine if sym == X, where X != V.
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000307 if (const llvm::APSInt* X = getSymVal(St, sym)) {
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000308 isFeasible = *X == V;
309 return St;
310 }
311
312 // Second, determine if sym != V.
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000313 if (isNotEqual(St, sym, V)) {
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000314 isFeasible = false;
315 return St;
316 }
317
318 // If we reach here, sym is not a constant and we don't know if it is == V.
319 // Make that assumption.
320
321 isFeasible = true;
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000322 return AddEQ(St, sym, V);
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000323}
324
325// These logic will be handled in another ConstraintManager.
326const GRState*
Ted Kremenek2dabd432008-12-05 02:27:51 +0000327BasicConstraintManager::AssumeSymLT(const GRState* St, SymbolRef sym,
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000328 const llvm::APSInt& V, bool& isFeasible) {
Ted Kremenek73abd132008-12-03 18:56:12 +0000329
330 // Is 'V' the smallest possible value?
331 if (V == llvm::APSInt::getMinValue(V.getBitWidth(), V.isSigned())) {
332 // sym cannot be any value less than 'V'. This path is infeasible.
333 isFeasible = false;
334 return St;
335 }
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000336
337 // FIXME: For now have assuming x < y be the same as assuming sym != V;
338 return AssumeSymNE(St, sym, V, isFeasible);
339}
340
341const GRState*
Ted Kremenek2dabd432008-12-05 02:27:51 +0000342BasicConstraintManager::AssumeSymGT(const GRState* St, SymbolRef sym,
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000343 const llvm::APSInt& V, bool& isFeasible) {
344
Ted Kremenekd7ff4872008-12-03 19:06:30 +0000345 // Is 'V' the largest possible value?
346 if (V == llvm::APSInt::getMaxValue(V.getBitWidth(), V.isSigned())) {
347 // sym cannot be any value greater than 'V'. This path is infeasible.
348 isFeasible = false;
349 return St;
350 }
351
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000352 // FIXME: For now have assuming x > y be the same as assuming sym != V;
353 return AssumeSymNE(St, sym, V, isFeasible);
354}
355
356const GRState*
Ted Kremenek2dabd432008-12-05 02:27:51 +0000357BasicConstraintManager::AssumeSymGE(const GRState* St, SymbolRef sym,
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000358 const llvm::APSInt& V, bool& isFeasible) {
359
Ted Kremenek8c3e7fb2008-09-16 23:24:45 +0000360 // Reject a path if the value of sym is a constant X and !(X >= V).
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000361 if (const llvm::APSInt* X = getSymVal(St, sym)) {
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000362 isFeasible = *X >= V;
363 return St;
364 }
Ted Kremenekd7ff4872008-12-03 19:06:30 +0000365
366 // Sym is not a constant, but it is worth looking to see if V is the
367 // maximum integer value.
368 if (V == llvm::APSInt::getMaxValue(V.getBitWidth(), V.isSigned())) {
369 // If we know that sym != V, then this condition is infeasible since
370 // there is no other value greater than V.
371 isFeasible = !isNotEqual(St, sym, V);
372
373 // If the path is still feasible then as a consequence we know that
374 // 'sym == V' because we cannot have 'sym > V' (no larger values).
375 // Add this constraint.
376 if (isFeasible)
377 return AddEQ(St, sym, V);
378 }
379 else
380 isFeasible = true;
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000381
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000382 return St;
383}
384
385const GRState*
Ted Kremenek2dabd432008-12-05 02:27:51 +0000386BasicConstraintManager::AssumeSymLE(const GRState* St, SymbolRef sym,
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000387 const llvm::APSInt& V, bool& isFeasible) {
388
Ted Kremenek73abd132008-12-03 18:56:12 +0000389 // Reject a path if the value of sym is a constant X and !(X <= V).
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000390 if (const llvm::APSInt* X = getSymVal(St, sym)) {
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000391 isFeasible = *X <= V;
392 return St;
393 }
Ted Kremenek0a41e5a2008-09-19 18:00:36 +0000394
Ted Kremenek73abd132008-12-03 18:56:12 +0000395 // Sym is not a constant, but it is worth looking to see if V is the
396 // minimum integer value.
397 if (V == llvm::APSInt::getMinValue(V.getBitWidth(), V.isSigned())) {
398 // If we know that sym != V, then this condition is infeasible since
399 // there is no other value less than V.
400 isFeasible = !isNotEqual(St, sym, V);
401
402 // If the path is still feasible then as a consequence we know that
403 // 'sym == V' because we cannot have 'sym < V' (no smaller values).
404 // Add this constraint.
405 if (isFeasible)
406 return AddEQ(St, sym, V);
407 }
408 else
409 isFeasible = true;
410
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000411 return St;
412}
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000413
Zhongxing Xue8a964b2008-11-22 13:21:46 +0000414const GRState*
415BasicConstraintManager::AssumeInBound(const GRState* St, SVal Idx,
416 SVal UpperBound, bool Assumption,
417 bool& isFeasible) {
418 // Only support ConcreteInt for now.
419 if (!(isa<nonloc::ConcreteInt>(Idx) && isa<nonloc::ConcreteInt>(UpperBound))){
420 isFeasible = true;
421 return St;
422 }
423
424 const llvm::APSInt& Zero = getBasicVals().getZeroWithPtrWidth(false);
Sebastian Redle95db4f2008-11-24 19:35:33 +0000425 llvm::APSInt IdxV = cast<nonloc::ConcreteInt>(Idx).getValue();
426 // IdxV might be too narrow.
427 if (IdxV.getBitWidth() < Zero.getBitWidth())
428 IdxV.extend(Zero.getBitWidth());
429 // UBV might be too narrow, too.
430 llvm::APSInt UBV = cast<nonloc::ConcreteInt>(UpperBound).getValue();
431 if (UBV.getBitWidth() < Zero.getBitWidth())
432 UBV.extend(Zero.getBitWidth());
Zhongxing Xue8a964b2008-11-22 13:21:46 +0000433
434 bool InBound = (Zero <= IdxV) && (IdxV < UBV);
435
436 isFeasible = Assumption ? InBound : !InBound;
437
438 return St;
439}
440
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000441static int ConstEqTyIndex = 0;
442static int ConstNotEqTyIndex = 0;
443
444namespace clang {
445 template<>
446 struct GRStateTrait<ConstNotEqTy> : public GRStatePartialTrait<ConstNotEqTy> {
447 static inline void* GDMIndex() { return &ConstNotEqTyIndex; }
448 };
449
450 template<>
451 struct GRStateTrait<ConstEqTy> : public GRStatePartialTrait<ConstEqTy> {
452 static inline void* GDMIndex() { return &ConstEqTyIndex; }
453 };
454}
455
Ted Kremenek2dabd432008-12-05 02:27:51 +0000456const GRState* BasicConstraintManager::AddEQ(const GRState* St, SymbolRef sym,
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000457 const llvm::APSInt& V) {
458 // Create a new state with the old binding replaced.
459 GRStateRef state(St, StateMgr);
460 return state.set<ConstEqTy>(sym, &V);
461}
462
Ted Kremenek2dabd432008-12-05 02:27:51 +0000463const GRState* BasicConstraintManager::AddNE(const GRState* St, SymbolRef sym,
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000464 const llvm::APSInt& V) {
Zhongxing Xuf0bc50e2008-11-27 06:08:40 +0000465
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000466 GRStateRef state(St, StateMgr);
467
468 // First, retrieve the NE-set associated with the given symbol.
469 ConstNotEqTy::data_type* T = state.get<ConstNotEqTy>(sym);
470 GRState::IntSetTy S = T ? *T : ISetFactory.GetEmptySet();
471
472
473 // Now add V to the NE set.
474 S = ISetFactory.Add(S, &V);
475
476 // Create a new state with the old binding replaced.
477 return state.set<ConstNotEqTy>(sym, S);
478}
479
480const llvm::APSInt* BasicConstraintManager::getSymVal(const GRState* St,
Ted Kremenek2dabd432008-12-05 02:27:51 +0000481 SymbolRef sym) {
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000482 const ConstEqTy::data_type* T = St->get<ConstEqTy>(sym);
483 return T ? *T : NULL;
484}
485
Ted Kremenek2dabd432008-12-05 02:27:51 +0000486bool BasicConstraintManager::isNotEqual(const GRState* St, SymbolRef sym,
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000487 const llvm::APSInt& V) const {
488
489 // Retrieve the NE-set associated with the given symbol.
490 const ConstNotEqTy::data_type* T = St->get<ConstNotEqTy>(sym);
491
492 // See if V is present in the NE-set.
493 return T ? T->contains(&V) : false;
494}
495
Ted Kremenek2dabd432008-12-05 02:27:51 +0000496bool BasicConstraintManager::isEqual(const GRState* St, SymbolRef sym,
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000497 const llvm::APSInt& V) const {
498 // Retrieve the EQ-set associated with the given symbol.
499 const ConstEqTy::data_type* T = St->get<ConstEqTy>(sym);
500 // See if V is present in the EQ-set.
501 return T ? **T == V : false;
502}
503
Zhongxing Xu8fd9b352008-11-27 02:39:34 +0000504/// Scan all symbols referenced by the constraints. If the symbol is not alive
505/// as marked in LSymbols, mark it as dead in DSymbols.
Ted Kremenek241677a2009-01-21 22:26:05 +0000506const GRState*
507BasicConstraintManager::RemoveDeadBindings(const GRState* St,
508 SymbolReaper& SymReaper) {
509
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000510 GRStateRef state(St, StateMgr);
511 ConstEqTy CE = state.get<ConstEqTy>();
512 ConstEqTy::Factory& CEFactory = state.get_context<ConstEqTy>();
513
514 for (ConstEqTy::iterator I = CE.begin(), E = CE.end(); I!=E; ++I) {
Ted Kremenek241677a2009-01-21 22:26:05 +0000515 SymbolRef sym = I.getKey();
516 if (SymReaper.maybeDead(sym)) CE = CEFactory.Remove(CE, sym);
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000517 }
518 state = state.set<ConstEqTy>(CE);
519
520 ConstNotEqTy CNE = state.get<ConstNotEqTy>();
521 ConstNotEqTy::Factory& CNEFactory = state.get_context<ConstNotEqTy>();
522
523 for (ConstNotEqTy::iterator I = CNE.begin(), E = CNE.end(); I != E; ++I) {
Ted Kremenek2dabd432008-12-05 02:27:51 +0000524 SymbolRef sym = I.getKey();
Ted Kremenek241677a2009-01-21 22:26:05 +0000525 if (SymReaper.maybeDead(sym)) CNE = CNEFactory.Remove(CNE, sym);
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000526 }
527
528 return state.set<ConstNotEqTy>(CNE);
529}
530
531void BasicConstraintManager::print(const GRState* St, std::ostream& Out,
532 const char* nl, const char *sep) {
533 // Print equality constraints.
534
535 ConstEqTy CE = St->get<ConstEqTy>();
536
537 if (!CE.isEmpty()) {
538 Out << nl << sep << "'==' constraints:";
539
540 for (ConstEqTy::iterator I = CE.begin(), E = CE.end(); I!=E; ++I) {
541 Out << nl << " $" << I.getKey();
542 llvm::raw_os_ostream OS(Out);
543 OS << " : " << *I.getData();
544 }
545 }
546
547 // Print != constraints.
548
549 ConstNotEqTy CNE = St->get<ConstNotEqTy>();
550
551 if (!CNE.isEmpty()) {
552 Out << nl << sep << "'!=' constraints:";
553
554 for (ConstNotEqTy::iterator I = CNE.begin(), EI = CNE.end(); I!=EI; ++I) {
555 Out << nl << " $" << I.getKey() << " : ";
556 bool isFirst = true;
557
558 GRState::IntSetTy::iterator J = I.getData().begin(),
559 EJ = I.getData().end();
560
561 for ( ; J != EJ; ++J) {
562 if (isFirst) isFirst = false;
563 else Out << ", ";
564
Zhongxing Xu7d94e262008-11-10 05:00:06 +0000565 Out << (*J)->getSExtValue(); // Hack: should print to raw_ostream.
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000566 }
567 }
568 }
Daniel Dunbar0e194dd2008-08-30 02:06:22 +0000569}