blob: d9d97c601a7461bd04ef862f2df528f4ae7580af [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
85 const GRState* RemoveDeadBindings(const GRState* St,
86 StoreManager::LiveSymbolsTy& LSymbols,
87 StoreManager::DeadSymbolsTy& DSymbols);
88
89 void print(const GRState* St, std::ostream& Out,
90 const char* nl, const char *sep);
Zhongxing Xue8a964b2008-11-22 13:21:46 +000091
92private:
93 BasicValueFactory& getBasicVals() { return StateMgr.getBasicVals(); }
Zhongxing Xu39cfed32008-08-29 14:52:36 +000094};
Zhongxing Xu30ad1672008-08-27 14:03:33 +000095
96} // end anonymous namespace
97
98ConstraintManager* clang::CreateBasicConstraintManager(GRStateManager& StateMgr)
99{
100 return new BasicConstraintManager(StateMgr);
101}
102
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000103const GRState* BasicConstraintManager::Assume(const GRState* St, SVal Cond,
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000104 bool Assumption, bool& isFeasible) {
105 if (Cond.isUnknown()) {
106 isFeasible = true;
107 return St;
108 }
109
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000110 if (isa<NonLoc>(Cond))
111 return Assume(St, cast<NonLoc>(Cond), Assumption, isFeasible);
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000112 else
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000113 return Assume(St, cast<Loc>(Cond), Assumption, isFeasible);
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000114}
115
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000116const GRState* BasicConstraintManager::Assume(const GRState* St, Loc Cond,
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000117 bool Assumption, bool& isFeasible) {
118 St = AssumeAux(St, Cond, Assumption, isFeasible);
Ted Kremenek2fb78a72008-12-17 21:50:35 +0000119
120 if (!isFeasible)
121 return St;
122
123 // EvalAssume is used to call into the GRTransferFunction object to perform
124 // any checker-specific update of the state based on this assumption being
125 // true or false.
126 return StateMgr.getTransferFuncs().EvalAssume(StateMgr, St, Cond, Assumption,
127 isFeasible);
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000128}
129
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000130const GRState* BasicConstraintManager::AssumeAux(const GRState* St, Loc Cond,
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000131 bool Assumption, bool& isFeasible) {
132 BasicValueFactory& BasicVals = StateMgr.getBasicVals();
133
134 switch (Cond.getSubKind()) {
135 default:
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000136 assert (false && "'Assume' not implemented for this Loc.");
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000137 return St;
138
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000139 case loc::SymbolValKind:
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000140 if (Assumption)
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000141 return AssumeSymNE(St, cast<loc::SymbolVal>(Cond).getSymbol(),
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000142 BasicVals.getZeroWithPtrWidth(), isFeasible);
143 else
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000144 return AssumeSymEQ(St, cast<loc::SymbolVal>(Cond).getSymbol(),
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000145 BasicVals.getZeroWithPtrWidth(), isFeasible);
146
Ted Kremenekc5234712008-10-17 21:22:20 +0000147 case loc::MemRegionKind: {
148 // FIXME: Should this go into the storemanager?
149
150 const MemRegion* R = cast<loc::MemRegionVal>(Cond).getRegion();
151
152 while (R) {
153 if (const SubRegion* SubR = dyn_cast<SubRegion>(R)) {
154 R = SubR->getSuperRegion();
155 continue;
156 }
157 else if (const SymbolicRegion* SymR = dyn_cast<SymbolicRegion>(R))
158 return AssumeAux(St, loc::SymbolVal(SymR->getSymbol()), Assumption,
159 isFeasible);
160
161 break;
162 }
163
164 // FALL-THROUGH.
165 }
166
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000167 case loc::FuncValKind:
168 case loc::GotoLabelKind:
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000169 isFeasible = Assumption;
170 return St;
171
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000172 case loc::ConcreteIntKind: {
173 bool b = cast<loc::ConcreteInt>(Cond).getValue() != 0;
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000174 isFeasible = b ? Assumption : !Assumption;
175 return St;
176 }
177 } // end switch
178}
179
180const GRState*
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000181BasicConstraintManager::Assume(const GRState* St, NonLoc Cond, bool Assumption,
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000182 bool& isFeasible) {
183 St = AssumeAux(St, Cond, Assumption, isFeasible);
Ted Kremenek2fb78a72008-12-17 21:50:35 +0000184
185 if (!isFeasible)
186 return St;
187
188 // EvalAssume is used to call into the GRTransferFunction object to perform
189 // any checker-specific update of the state based on this assumption being
190 // true or false.
191 return StateMgr.getTransferFuncs().EvalAssume(StateMgr, St, Cond, Assumption,
192 isFeasible);
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000193}
194
195const GRState*
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000196BasicConstraintManager::AssumeAux(const GRState* St,NonLoc Cond,
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000197 bool Assumption, bool& isFeasible) {
198 BasicValueFactory& BasicVals = StateMgr.getBasicVals();
199 SymbolManager& SymMgr = StateMgr.getSymbolManager();
200
201 switch (Cond.getSubKind()) {
202 default:
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000203 assert(false && "'Assume' not implemented for this NonLoc");
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000204
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000205 case nonloc::SymbolValKind: {
206 nonloc::SymbolVal& SV = cast<nonloc::SymbolVal>(Cond);
Ted Kremenek2dabd432008-12-05 02:27:51 +0000207 SymbolRef sym = SV.getSymbol();
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000208
209 if (Assumption)
210 return AssumeSymNE(St, sym, BasicVals.getValue(0, SymMgr.getType(sym)),
211 isFeasible);
212 else
213 return AssumeSymEQ(St, sym, BasicVals.getValue(0, SymMgr.getType(sym)),
214 isFeasible);
215 }
216
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000217 case nonloc::SymIntConstraintValKind:
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000218 return
219 AssumeSymInt(St, Assumption,
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000220 cast<nonloc::SymIntConstraintVal>(Cond).getConstraint(),
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000221 isFeasible);
222
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000223 case nonloc::ConcreteIntKind: {
224 bool b = cast<nonloc::ConcreteInt>(Cond).getValue() != 0;
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000225 isFeasible = b ? Assumption : !Assumption;
226 return St;
227 }
228
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000229 case nonloc::LocAsIntegerKind:
230 return AssumeAux(St, cast<nonloc::LocAsInteger>(Cond).getLoc(),
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000231 Assumption, isFeasible);
232 } // end switch
233}
234
235const GRState*
236BasicConstraintManager::AssumeSymInt(const GRState* St, bool Assumption,
237 const SymIntConstraint& C, bool& isFeasible) {
238
239 switch (C.getOpcode()) {
240 default:
241 // No logic yet for other operators.
242 isFeasible = true;
243 return St;
244
245 case BinaryOperator::EQ:
246 if (Assumption)
247 return AssumeSymEQ(St, C.getSymbol(), C.getInt(), isFeasible);
248 else
249 return AssumeSymNE(St, C.getSymbol(), C.getInt(), isFeasible);
250
251 case BinaryOperator::NE:
252 if (Assumption)
253 return AssumeSymNE(St, C.getSymbol(), C.getInt(), isFeasible);
254 else
255 return AssumeSymEQ(St, C.getSymbol(), C.getInt(), isFeasible);
256
Zhongxing Xu94b83122008-09-19 06:07:59 +0000257 case BinaryOperator::GT:
258 if (Assumption)
259 return AssumeSymGT(St, C.getSymbol(), C.getInt(), isFeasible);
260 else
261 return AssumeSymLE(St, C.getSymbol(), C.getInt(), isFeasible);
262
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000263 case BinaryOperator::GE:
264 if (Assumption)
265 return AssumeSymGE(St, C.getSymbol(), C.getInt(), isFeasible);
266 else
267 return AssumeSymLT(St, C.getSymbol(), C.getInt(), isFeasible);
268
Ted Kremenek8c3e7fb2008-09-16 23:24:45 +0000269 case BinaryOperator::LT:
270 if (Assumption)
271 return AssumeSymLT(St, C.getSymbol(), C.getInt(), isFeasible);
272 else
273 return AssumeSymGE(St, C.getSymbol(), C.getInt(), isFeasible);
274
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000275 case BinaryOperator::LE:
276 if (Assumption)
277 return AssumeSymLE(St, C.getSymbol(), C.getInt(), isFeasible);
278 else
279 return AssumeSymGT(St, C.getSymbol(), C.getInt(), isFeasible);
280 } // end switch
281}
282
283const GRState*
Ted Kremenek2dabd432008-12-05 02:27:51 +0000284BasicConstraintManager::AssumeSymNE(const GRState* St, SymbolRef sym,
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000285 const llvm::APSInt& V, bool& isFeasible) {
286 // First, determine if sym == X, where X != V.
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000287 if (const llvm::APSInt* X = getSymVal(St, sym)) {
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000288 isFeasible = (*X != V);
289 return St;
290 }
291
292 // Second, determine if sym != V.
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000293 if (isNotEqual(St, sym, V)) {
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000294 isFeasible = true;
295 return St;
296 }
297
298 // If we reach here, sym is not a constant and we don't know if it is != V.
299 // Make that assumption.
300 isFeasible = true;
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000301 return AddNE(St, sym, V);
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000302}
303
304const GRState*
Ted Kremenek2dabd432008-12-05 02:27:51 +0000305BasicConstraintManager::AssumeSymEQ(const GRState* St, SymbolRef sym,
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000306 const llvm::APSInt& V, bool& isFeasible) {
307 // First, determine if sym == X, where X != V.
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000308 if (const llvm::APSInt* X = getSymVal(St, sym)) {
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000309 isFeasible = *X == V;
310 return St;
311 }
312
313 // Second, determine if sym != V.
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000314 if (isNotEqual(St, sym, V)) {
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000315 isFeasible = false;
316 return St;
317 }
318
319 // If we reach here, sym is not a constant and we don't know if it is == V.
320 // Make that assumption.
321
322 isFeasible = true;
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000323 return AddEQ(St, sym, V);
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000324}
325
326// These logic will be handled in another ConstraintManager.
327const GRState*
Ted Kremenek2dabd432008-12-05 02:27:51 +0000328BasicConstraintManager::AssumeSymLT(const GRState* St, SymbolRef sym,
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000329 const llvm::APSInt& V, bool& isFeasible) {
Ted Kremenek73abd132008-12-03 18:56:12 +0000330
331 // Is 'V' the smallest possible value?
332 if (V == llvm::APSInt::getMinValue(V.getBitWidth(), V.isSigned())) {
333 // sym cannot be any value less than 'V'. This path is infeasible.
334 isFeasible = false;
335 return St;
336 }
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000337
338 // FIXME: For now have assuming x < y be the same as assuming sym != V;
339 return AssumeSymNE(St, sym, V, isFeasible);
340}
341
342const GRState*
Ted Kremenek2dabd432008-12-05 02:27:51 +0000343BasicConstraintManager::AssumeSymGT(const GRState* St, SymbolRef sym,
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000344 const llvm::APSInt& V, bool& isFeasible) {
345
Ted Kremenekd7ff4872008-12-03 19:06:30 +0000346 // Is 'V' the largest possible value?
347 if (V == llvm::APSInt::getMaxValue(V.getBitWidth(), V.isSigned())) {
348 // sym cannot be any value greater than 'V'. This path is infeasible.
349 isFeasible = false;
350 return St;
351 }
352
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000353 // FIXME: For now have assuming x > y be the same as assuming sym != V;
354 return AssumeSymNE(St, sym, V, isFeasible);
355}
356
357const GRState*
Ted Kremenek2dabd432008-12-05 02:27:51 +0000358BasicConstraintManager::AssumeSymGE(const GRState* St, SymbolRef sym,
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000359 const llvm::APSInt& V, bool& isFeasible) {
360
Ted Kremenek8c3e7fb2008-09-16 23:24:45 +0000361 // Reject a path if the value of sym is a constant X and !(X >= V).
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000362 if (const llvm::APSInt* X = getSymVal(St, sym)) {
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000363 isFeasible = *X >= V;
364 return St;
365 }
Ted Kremenekd7ff4872008-12-03 19:06:30 +0000366
367 // Sym is not a constant, but it is worth looking to see if V is the
368 // maximum integer value.
369 if (V == llvm::APSInt::getMaxValue(V.getBitWidth(), V.isSigned())) {
370 // If we know that sym != V, then this condition is infeasible since
371 // there is no other value greater than V.
372 isFeasible = !isNotEqual(St, sym, V);
373
374 // If the path is still feasible then as a consequence we know that
375 // 'sym == V' because we cannot have 'sym > V' (no larger values).
376 // Add this constraint.
377 if (isFeasible)
378 return AddEQ(St, sym, V);
379 }
380 else
381 isFeasible = true;
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000382
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000383 return St;
384}
385
386const GRState*
Ted Kremenek2dabd432008-12-05 02:27:51 +0000387BasicConstraintManager::AssumeSymLE(const GRState* St, SymbolRef sym,
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000388 const llvm::APSInt& V, bool& isFeasible) {
389
Ted Kremenek73abd132008-12-03 18:56:12 +0000390 // Reject a path if the value of sym is a constant X and !(X <= V).
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000391 if (const llvm::APSInt* X = getSymVal(St, sym)) {
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000392 isFeasible = *X <= V;
393 return St;
394 }
Ted Kremenek0a41e5a2008-09-19 18:00:36 +0000395
Ted Kremenek73abd132008-12-03 18:56:12 +0000396 // Sym is not a constant, but it is worth looking to see if V is the
397 // minimum integer value.
398 if (V == llvm::APSInt::getMinValue(V.getBitWidth(), V.isSigned())) {
399 // If we know that sym != V, then this condition is infeasible since
400 // there is no other value less than V.
401 isFeasible = !isNotEqual(St, sym, V);
402
403 // If the path is still feasible then as a consequence we know that
404 // 'sym == V' because we cannot have 'sym < V' (no smaller values).
405 // Add this constraint.
406 if (isFeasible)
407 return AddEQ(St, sym, V);
408 }
409 else
410 isFeasible = true;
411
Zhongxing Xu30ad1672008-08-27 14:03:33 +0000412 return St;
413}
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000414
Zhongxing Xue8a964b2008-11-22 13:21:46 +0000415const GRState*
416BasicConstraintManager::AssumeInBound(const GRState* St, SVal Idx,
417 SVal UpperBound, bool Assumption,
418 bool& isFeasible) {
419 // Only support ConcreteInt for now.
420 if (!(isa<nonloc::ConcreteInt>(Idx) && isa<nonloc::ConcreteInt>(UpperBound))){
421 isFeasible = true;
422 return St;
423 }
424
425 const llvm::APSInt& Zero = getBasicVals().getZeroWithPtrWidth(false);
Sebastian Redle95db4f2008-11-24 19:35:33 +0000426 llvm::APSInt IdxV = cast<nonloc::ConcreteInt>(Idx).getValue();
427 // IdxV might be too narrow.
428 if (IdxV.getBitWidth() < Zero.getBitWidth())
429 IdxV.extend(Zero.getBitWidth());
430 // UBV might be too narrow, too.
431 llvm::APSInt UBV = cast<nonloc::ConcreteInt>(UpperBound).getValue();
432 if (UBV.getBitWidth() < Zero.getBitWidth())
433 UBV.extend(Zero.getBitWidth());
Zhongxing Xue8a964b2008-11-22 13:21:46 +0000434
435 bool InBound = (Zero <= IdxV) && (IdxV < UBV);
436
437 isFeasible = Assumption ? InBound : !InBound;
438
439 return St;
440}
441
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000442static int ConstEqTyIndex = 0;
443static int ConstNotEqTyIndex = 0;
444
445namespace clang {
446 template<>
447 struct GRStateTrait<ConstNotEqTy> : public GRStatePartialTrait<ConstNotEqTy> {
448 static inline void* GDMIndex() { return &ConstNotEqTyIndex; }
449 };
450
451 template<>
452 struct GRStateTrait<ConstEqTy> : public GRStatePartialTrait<ConstEqTy> {
453 static inline void* GDMIndex() { return &ConstEqTyIndex; }
454 };
455}
456
Ted Kremenek2dabd432008-12-05 02:27:51 +0000457const GRState* BasicConstraintManager::AddEQ(const GRState* St, SymbolRef sym,
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000458 const llvm::APSInt& V) {
459 // Create a new state with the old binding replaced.
460 GRStateRef state(St, StateMgr);
461 return state.set<ConstEqTy>(sym, &V);
462}
463
Ted Kremenek2dabd432008-12-05 02:27:51 +0000464const GRState* BasicConstraintManager::AddNE(const GRState* St, SymbolRef sym,
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000465 const llvm::APSInt& V) {
Zhongxing Xuf0bc50e2008-11-27 06:08:40 +0000466
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000467 GRStateRef state(St, StateMgr);
468
469 // First, retrieve the NE-set associated with the given symbol.
470 ConstNotEqTy::data_type* T = state.get<ConstNotEqTy>(sym);
471 GRState::IntSetTy S = T ? *T : ISetFactory.GetEmptySet();
472
473
474 // Now add V to the NE set.
475 S = ISetFactory.Add(S, &V);
476
477 // Create a new state with the old binding replaced.
478 return state.set<ConstNotEqTy>(sym, S);
479}
480
481const llvm::APSInt* BasicConstraintManager::getSymVal(const GRState* St,
Ted Kremenek2dabd432008-12-05 02:27:51 +0000482 SymbolRef sym) {
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000483 const ConstEqTy::data_type* T = St->get<ConstEqTy>(sym);
484 return T ? *T : NULL;
485}
486
Ted Kremenek2dabd432008-12-05 02:27:51 +0000487bool BasicConstraintManager::isNotEqual(const GRState* St, SymbolRef sym,
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000488 const llvm::APSInt& V) const {
489
490 // Retrieve the NE-set associated with the given symbol.
491 const ConstNotEqTy::data_type* T = St->get<ConstNotEqTy>(sym);
492
493 // See if V is present in the NE-set.
494 return T ? T->contains(&V) : false;
495}
496
Ted Kremenek2dabd432008-12-05 02:27:51 +0000497bool BasicConstraintManager::isEqual(const GRState* St, SymbolRef sym,
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000498 const llvm::APSInt& V) const {
499 // Retrieve the EQ-set associated with the given symbol.
500 const ConstEqTy::data_type* T = St->get<ConstEqTy>(sym);
501 // See if V is present in the EQ-set.
502 return T ? **T == V : false;
503}
504
Zhongxing Xu8fd9b352008-11-27 02:39:34 +0000505/// Scan all symbols referenced by the constraints. If the symbol is not alive
506/// as marked in LSymbols, mark it as dead in DSymbols.
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000507const GRState* BasicConstraintManager::RemoveDeadBindings(const GRState* St,
508 StoreManager::LiveSymbolsTy& LSymbols,
509 StoreManager::DeadSymbolsTy& DSymbols) {
510 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 Kremenek2dabd432008-12-05 02:27:51 +0000515 SymbolRef sym = I.getKey();
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000516 if (!LSymbols.count(sym)) {
517 DSymbols.insert(sym);
518 CE = CEFactory.Remove(CE, sym);
519 }
520 }
521 state = state.set<ConstEqTy>(CE);
522
523 ConstNotEqTy CNE = state.get<ConstNotEqTy>();
524 ConstNotEqTy::Factory& CNEFactory = state.get_context<ConstNotEqTy>();
525
526 for (ConstNotEqTy::iterator I = CNE.begin(), E = CNE.end(); I != E; ++I) {
Ted Kremenek2dabd432008-12-05 02:27:51 +0000527 SymbolRef sym = I.getKey();
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000528 if (!LSymbols.count(sym)) {
529 DSymbols.insert(sym);
530 CNE = CNEFactory.Remove(CNE, sym);
531 }
532 }
533
534 return state.set<ConstNotEqTy>(CNE);
535}
536
537void BasicConstraintManager::print(const GRState* St, std::ostream& Out,
538 const char* nl, const char *sep) {
539 // Print equality constraints.
540
541 ConstEqTy CE = St->get<ConstEqTy>();
542
543 if (!CE.isEmpty()) {
544 Out << nl << sep << "'==' constraints:";
545
546 for (ConstEqTy::iterator I = CE.begin(), E = CE.end(); I!=E; ++I) {
547 Out << nl << " $" << I.getKey();
548 llvm::raw_os_ostream OS(Out);
549 OS << " : " << *I.getData();
550 }
551 }
552
553 // Print != constraints.
554
555 ConstNotEqTy CNE = St->get<ConstNotEqTy>();
556
557 if (!CNE.isEmpty()) {
558 Out << nl << sep << "'!=' constraints:";
559
560 for (ConstNotEqTy::iterator I = CNE.begin(), EI = CNE.end(); I!=EI; ++I) {
561 Out << nl << " $" << I.getKey() << " : ";
562 bool isFirst = true;
563
564 GRState::IntSetTy::iterator J = I.getData().begin(),
565 EJ = I.getData().end();
566
567 for ( ; J != EJ; ++J) {
568 if (isFirst) isFirst = false;
569 else Out << ", ";
570
Zhongxing Xu7d94e262008-11-10 05:00:06 +0000571 Out << (*J)->getSExtValue(); // Hack: should print to raw_ostream.
Zhongxing Xu39cfed32008-08-29 14:52:36 +0000572 }
573 }
574 }
Daniel Dunbar0e194dd2008-08-30 02:06:22 +0000575}