blob: 8eb7e69aad93710895f5e50c18f6559ff99f7c6a [file] [log] [blame]
Ted Kremenek45021952009-02-14 17:08:39 +00001//== RangeConstraintManager.cpp - Manage range 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 RangeConstraintManager, 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/Analysis/PathSensitive/GRState.h"
17#include "clang/Analysis/PathSensitive/GRStateTrait.h"
18#include "clang/Analysis/PathSensitive/GRTransferFuncs.h"
19#include "clang/Driver/ManagerRegistry.h"
20#include "llvm/Support/Compiler.h"
21#include "llvm/Support/Debug.h"
22#include "llvm/ADT/FoldingSet.h"
23#include "llvm/ADT/ImmutableSet.h"
24#include "llvm/Support/raw_ostream.h"
25
26using namespace clang;
27
28namespace { class VISIBILITY_HIDDEN ConstRange {}; }
29
30static int ConstRangeIndex = 0;
31
32// A Range represents the closed range [from, to]. The caller must
33// guarantee that from <= to. Note that Range is immutable, so as not
34// to subvert RangeSet's immutability.
35class Range : public std::pair<llvm::APSInt, llvm::APSInt> {
36public:
37 Range(const llvm::APSInt &from, const llvm::APSInt &to)
38 : std::pair<llvm::APSInt, llvm::APSInt>(from, to) {
39 assert(from <= to);
40 }
41 bool Includes(const llvm::APSInt &v) const {
42 return first <= v && v <= second;
43 }
44 const llvm::APSInt &From() const {
45 return first;
46 }
47 const llvm::APSInt &To() const {
48 return second;
49 }
50 const llvm::APSInt *HasConcreteValue() const {
51 return From() == To() ? &From() : NULL;
52 }
53
54 void Profile(llvm::FoldingSetNodeID &ID) const {
55 From().Profile(ID);
56 To().Profile(ID);
57 }
58};
59
60struct RangeCmp {
61 bool operator()(const Range &r1, const Range &r2) {
62 if (r1.From() < r2.From()) {
63 assert(!r1.Includes(r2.From()));
64 assert(!r2.Includes(r1.To()));
65 return true;
66 } else if (r1.From() > r2.From()) {
67 assert(!r1.Includes(r2.To()));
68 assert(!r2.Includes(r1.From()));
69 return false;
70 } else
71 assert(!"Ranges should never be equal in the same set");
72 }
73};
74
75typedef llvm::ImmutableSet<Range> PrimRangeSet;
76
77class RangeSet;
78std::ostream &operator<<(std::ostream &os, const RangeSet &r);
79
80
81// A RangeSet contains a set of ranges. If the set is empty, then
82// noValues -> Nothing matches.
83// !noValues -> Everything (in range of the bit representation) matches.
84class RangeSet {
85 PrimRangeSet ranges; // no need to make const, since it is an
86 // ImmutableSet - this allows default operator=
87 // to work.
88 bool noValues; // if true, no value is possible (should never happen)
89
90 static const llvm::APSInt Max(const llvm::APSInt &v) {
91 return llvm::APSInt::getMaxValue(v.getBitWidth(), v.isUnsigned());
92 }
93 static const llvm::APSInt Min(const llvm::APSInt &v) {
94 return llvm::APSInt::getMinValue(v.getBitWidth(), v.isUnsigned());
95 }
96 static const llvm::APSInt One(const llvm::APSInt &v) {
97 return llvm::APSInt(llvm::APInt(v.getBitWidth(), 1), v.isUnsigned());
98 }
99
100public:
101 // Create a RangeSet that allows all possible values.
102 RangeSet(PrimRangeSet::Factory *factory) : ranges(factory->GetEmptySet()),
103 noValues(false) {
104 }
105 // Note that if the empty set is passed, then there are no possible
106 // values. To create a RangeSet that covers all values when the
107 // empty set is passed, use RangeSet(r, false).
108 RangeSet(const PrimRangeSet &r) : ranges(r), noValues(r.isEmpty()) {
109 }
110 // Allow an empty set to be passed meaning "all values" instead of
111 // "no values".
112 RangeSet(const PrimRangeSet &r, bool n) : ranges(r), noValues(n) {
113 assert(!n);
114 }
115 void Profile(llvm::FoldingSetNodeID &ID) const {
116 ranges.Profile(ID);
117 ID.AddBoolean(noValues);
118 }
119
120 const llvm::APSInt *HasConcreteValue() const {
121 if (!ranges.isSingleton())
122 return NULL;
123 return ranges.begin()->HasConcreteValue();
124 }
125
126 bool CouldBeNE(const llvm::APSInt &ne) const {
127 DOUT << "CouldBeNE(" << ne.toString(10) << ") " << *this << std::endl;
128 assert(!noValues);
129 const llvm::APSInt *v = HasConcreteValue();
130 if (v && *v == ne)
131 return false;
132 return true;
133 }
134
135 bool CouldBeEQ(const llvm::APSInt &eq) const {
136 DOUT << "CouldBeEQ(" << eq.toString(10) << ") " << *this << std::endl;
137 assert(!noValues);
138 if (ranges.isEmpty())
139 return true;
140 for (PrimRangeSet::iterator i = ranges.begin() ; i != ranges.end() ; ++i)
141 if (i->Includes(eq))
142 return true;
143 return false;
144 }
145
146 bool CouldBeLT(const llvm::APSInt &lt) const {
147 DOUT << "CouldBeLT(" << lt.toString(10) << ") " << *this << std::endl;
148 assert(!noValues);
149 // FIXME: should test if lt == min -> false here, since that's
150 // impossible to meet.
151 if (ranges.isEmpty())
152 return true;
153 for (PrimRangeSet::iterator i = ranges.begin() ; i != ranges.end() ; ++i)
154 if (i->From() < lt)
155 return true;
156 return false;
157 }
158
159 bool CouldBeLE(const llvm::APSInt &le) const {
160 DOUT << "CouldBeLE(" << le.toString(10) << ") " << *this << std::endl;
161 assert(!noValues);
162 if (ranges.isEmpty())
163 return true;
164 for (PrimRangeSet::iterator i = ranges.begin() ; i != ranges.end() ; ++i)
165 if (i->From() <= le)
166 return true;
167 return false;
168 }
169
170 bool CouldBeGT(const llvm::APSInt &gt) const {
171 DOUT << "CouldBeGT(" << gt.toString(10) << ") " << *this << std::endl;
172 assert(!noValues);
173 // FIXME: should we test if gt == max -> false here, since that's
174 // impossible to meet.
175 if (ranges.isEmpty())
176 return true;
177 for (PrimRangeSet::iterator i = ranges.begin() ; i != ranges.end() ; ++i)
178 if (i->To() > gt)
179 return true;
180 return false;
181 }
182
183 bool CouldBeGE(const llvm::APSInt &ge) const {
184 DOUT << "CouldBeGE(" << ge.toString(10) << ") " << *this << std::endl;
185 assert(!noValues);
186 if (ranges.isEmpty())
187 return true;
188 for (PrimRangeSet::iterator i = ranges.begin() ; i != ranges.end() ; ++i)
189 if (i->To() >= ge)
190 return true;
191 return false;
192 }
193
194 // Make all existing ranges fall within this new range
195 RangeSet Restrict(PrimRangeSet::Factory *factory, const llvm::APSInt &from,
196 const llvm::APSInt &to) const {
197 if (ranges.isEmpty())
198 return factory->Add(ranges, Range(from, to));;
199
200 PrimRangeSet newRanges = factory->GetEmptySet();
201
202 for (PrimRangeSet::iterator i = ranges.begin() ; i != ranges.end() ; ++i) {
203 if (i->Includes(from)) {
204 if (i->Includes(to)) {
205 newRanges = factory->Add(newRanges, Range(from, to));
206 } else {
207 newRanges = factory->Add(newRanges, Range(from, i->To()));
208 }
209 } else if (i->Includes(to)) {
210 newRanges = factory->Add(newRanges, Range(i->From(), to));
211 }
212 }
213 return RangeSet(newRanges);
214 }
215
216 // Create a new RangeSet with the additional constraint that the
217 // range must be == eq. In other words the range becomes [eq,
218 // eq]. Note that this RangeSet must have included eq in the first
219 // place, or we shouldn't be here.
220 RangeSet AddEQ(PrimRangeSet::Factory *factory, const llvm::APSInt &eq) {
221 DOUT << "AddEQ(" << eq.toString(10) << ") " << *this << " -> ";
222 assert(CouldBeEQ(eq));
223 RangeSet r(factory->Add(factory->GetEmptySet(), Range(eq, eq)));
224 DOUT << r << std::endl;
225 return r;
226 }
227
228 RangeSet AddNE(PrimRangeSet::Factory *factory, const llvm::APSInt &ne) {
229 DOUT << "AddNE(" << ne.toString(10) << ") " << *this << " -> ";
230
231 const llvm::APSInt max = Max(ne);
232 const llvm::APSInt min = Min(ne);
233 const llvm::APSInt one = One(ne);
234
235 PrimRangeSet newRanges = factory->GetEmptySet();
236
237 if (ranges.isEmpty()) {
238 if (ne != max)
239 newRanges = factory->Add(newRanges, Range(ne + one, max));
240 if (ne != min)
241 newRanges = factory->Add(newRanges, Range(min, ne - one));
242 RangeSet r(newRanges);
243 DOUT << r << std::endl;
244 return r;
245 }
246
247 for (PrimRangeSet::iterator i = ranges.begin() ; i != ranges.end() ; ++i) {
248 if (i->Includes(ne)) {
249 if (ne != i->From())
250 newRanges = factory->Add(newRanges, Range(i->From(), ne - one));
251 if (ne != i->To())
252 newRanges = factory->Add(newRanges, Range(ne + one, i->To()));
253 } else {
254 newRanges = factory->Add(newRanges, *i);
255 }
256 }
257 RangeSet r(newRanges);
258 DOUT << r << std::endl;
259 return r;
260 }
261
262 RangeSet AddLT(PrimRangeSet::Factory *factory, const llvm::APSInt &lt) {
263 DOUT << "AddLT(" << lt.toString(10) << ") " << *this << " -> ";
264 const llvm::APSInt min = Min(lt);
265 const llvm::APSInt one = One(lt);
266
267 if (ranges.isEmpty()) {
268 PrimRangeSet pr = factory->GetEmptySet();
269 if (lt != min)
270 pr = factory->Add(pr, Range(min, lt - one));
271 RangeSet r(pr, false);
272 DOUT << r << std::endl;
273 return r;
274 }
275
276 PrimRangeSet newRanges = factory->GetEmptySet();
277
278 for (PrimRangeSet::iterator i = ranges.begin() ; i != ranges.end() ; ++i) {
279 if (i->Includes(lt) && i->From() < lt)
280 newRanges = factory->Add(newRanges, Range(i->From(), lt - one));
281 else if (i->To() < lt)
282 newRanges = factory->Add(newRanges, *i);
283 }
284 RangeSet r(newRanges);
285 DOUT << r << std::endl;
286 return r;
287 }
288
289 RangeSet AddLE(PrimRangeSet::Factory *factory, const llvm::APSInt &le) {
290 DOUT << "AddLE(" << le.toString(10) << ") " << *this << " -> ";
291 const llvm::APSInt min = Min(le);
292
293 if (ranges.isEmpty()) {
294 RangeSet r(factory->Add(ranges, Range(min, le)));
295 DOUT << r << std::endl;
296 return r;
297 }
298
299 PrimRangeSet newRanges = factory->GetEmptySet();
300
301 for (PrimRangeSet::iterator i = ranges.begin() ; i != ranges.end() ; ++i) {
302 // Strictly we should test for includes le + 1, but no harm is
303 // done by this formulation
304 if (i->Includes(le))
305 newRanges = factory->Add(newRanges, Range(i->From(), le));
306 else if (i->To() <= le)
307 newRanges = factory->Add(newRanges, *i);
308 }
309 RangeSet r(newRanges);
310 DOUT << r << std::endl;
311 return r;
312 }
313
314 RangeSet AddGT(PrimRangeSet::Factory *factory, const llvm::APSInt &gt) {
315 DOUT << "AddGT(" << gt.toString(10) << ") " << *this << " -> ";
316 const llvm::APSInt max = Max(gt);
317 const llvm::APSInt one = One(gt);
318
319 if (ranges.isEmpty()) {
320 RangeSet r(factory->Add(ranges, Range(gt + one, max)));
321 DOUT << r << std::endl;
322 return r;
323 }
324
325 PrimRangeSet newRanges = factory->GetEmptySet();
326
327 for (PrimRangeSet::iterator i = ranges.begin() ; i != ranges.end() ; ++i) {
328 if (i->Includes(gt) && i->To() > gt)
329 newRanges = factory->Add(newRanges, Range(gt + one, i->To()));
330 else if (i->From() > gt)
331 newRanges = factory->Add(newRanges, *i);
332 }
333 RangeSet r(newRanges);
334 DOUT << r << std::endl;
335 return r;
336 }
337
338 RangeSet AddGE(PrimRangeSet::Factory *factory, const llvm::APSInt &ge) {
339 DOUT << "AddGE(" << ge.toString(10) << ") " << *this << " -> ";
340 const llvm::APSInt max = Max(ge);
341
342 if (ranges.isEmpty()) {
343 RangeSet r(factory->Add(ranges, Range(ge, max)));
344 DOUT << r << std::endl;
345 return r;
346 }
347
348 PrimRangeSet newRanges = factory->GetEmptySet();
349
350 for (PrimRangeSet::iterator i = ranges.begin() ; i != ranges.end() ; ++i) {
351 // Strictly we should test for includes ge - 1, but no harm is
352 // done by this formulation
353 if (i->Includes(ge))
354 newRanges = factory->Add(newRanges, Range(ge, i->To()));
355 else if (i->From() >= ge)
356 newRanges = factory->Add(newRanges, *i);
357 }
358
359 RangeSet r(newRanges);
360 DOUT << r << std::endl;
361 return r;
362 }
363
364 void Print(std::ostream &os) const {
365 os << "{ ";
366 if (noValues) {
367 os << "**no values** }";
368 return;
369 }
370 for (PrimRangeSet::iterator i = ranges.begin() ; i != ranges.end() ; ++i) {
371 if (i != ranges.begin())
372 os << ", ";
373 os << '[' << i->From().toString(10) << ", " << i->To().toString(10)
374 << ']';
375 }
376 os << " }";
377
378}
379 bool operator==(const RangeSet &other) const {
380 return ranges == other.ranges;
381 }
382};
383
384std::ostream &operator<<(std::ostream &os, const RangeSet &r) {
385 r.Print(os);
386 return os;
387}
388
389typedef llvm::ImmutableMap<SymbolRef,RangeSet> ConstRangeTy;
390
391namespace clang {
392template<>
393struct GRStateTrait<ConstRange> : public GRStatePartialTrait<ConstRangeTy> {
394 static inline void* GDMIndex() { return &ConstRangeIndex; }
395};
396}
397
398namespace {
399class VISIBILITY_HIDDEN RangeConstraintManager
400 : public SimpleConstraintManager {
401public:
402 RangeConstraintManager(GRStateManager& statemgr)
403 : SimpleConstraintManager(statemgr) {}
404
405 const GRState* AssumeSymNE(const GRState* St, SymbolRef sym,
406 const llvm::APSInt& V, bool& isFeasible);
407
408 const GRState* AssumeSymEQ(const GRState* St, SymbolRef sym,
409 const llvm::APSInt& V, bool& isFeasible);
410
411 const GRState* AssumeSymLT(const GRState* St, SymbolRef sym,
412 const llvm::APSInt& V, bool& isFeasible);
413
414 const GRState* AssumeSymGT(const GRState* St, SymbolRef sym,
415 const llvm::APSInt& V, bool& isFeasible);
416
417 const GRState* AssumeSymGE(const GRState* St, SymbolRef sym,
418 const llvm::APSInt& V, bool& isFeasible);
419
420 const GRState* AssumeSymLE(const GRState* St, SymbolRef sym,
421 const llvm::APSInt& V, bool& isFeasible);
422
423 const GRState* AddEQ(const GRState* St, SymbolRef sym, const llvm::APSInt& V);
424
425 const GRState* AddNE(const GRState* St, SymbolRef sym, const llvm::APSInt& V);
426
427 const GRState* AddLT(const GRState* St, SymbolRef sym, const llvm::APSInt& V);
428
429 const GRState* AddLE(const GRState* St, SymbolRef sym, const llvm::APSInt& V);
430
431 const GRState* AddGT(const GRState* St, SymbolRef sym, const llvm::APSInt& V);
432
433 const GRState* AddGE(const GRState* St, SymbolRef sym, const llvm::APSInt& V);
434
435 // FIXME: these two are required because they are pure virtual, but
436 // are they useful with ranges? Neither is used in this file.
437 const llvm::APSInt* getSymVal(const GRState* St, SymbolRef sym) const;
438 bool isEqual(const GRState* St, SymbolRef sym, const llvm::APSInt& V) const;
439
440 bool CouldBeEQ(const GRState* St, SymbolRef sym, const llvm::APSInt& V) const;
441 bool CouldBeNE(const GRState* St, SymbolRef sym, const llvm::APSInt& V) const;
442
443 bool CouldBeLT(const GRState* St, SymbolRef sym, const llvm::APSInt& V) const;
444 bool CouldBeLE(const GRState* St, SymbolRef sym, const llvm::APSInt& V) const;
445 bool CouldBeGT(const GRState* St, SymbolRef sym, const llvm::APSInt& V) const;
446 bool CouldBeGE(const GRState* St, SymbolRef sym, const llvm::APSInt& V) const;
447 const GRState* RemoveDeadBindings(const GRState* St, SymbolReaper& SymReaper);
448
449 void print(const GRState* St, std::ostream& Out,
450 const char* nl, const char *sep);
451
452private:
453 PrimRangeSet::Factory factory;
454 BasicValueFactory& getBasicVals() { return StateMgr.getBasicVals(); }
455};
456
457} // end anonymous namespace
458
459ConstraintManager* clang::CreateRangeConstraintManager(GRStateManager& StateMgr)
460{
461 return new RangeConstraintManager(StateMgr);
462}
463
Ted Kremenek45021952009-02-14 17:08:39 +0000464const GRState*
465RangeConstraintManager::AssumeSymNE(const GRState* St, SymbolRef sym,
466 const llvm::APSInt& V, bool& isFeasible) {
467 isFeasible = CouldBeNE(St, sym, V);
468 if (isFeasible)
469 return AddNE(St, sym, V);
470 return St;
471}
472
473const GRState*
474RangeConstraintManager::AssumeSymEQ(const GRState* St, SymbolRef sym,
475 const llvm::APSInt& V, bool& isFeasible) {
476 isFeasible = CouldBeEQ(St, sym, V);
477 if (isFeasible)
478 return AddEQ(St, sym, V);
479 return St;
480}
481
482const GRState*
483RangeConstraintManager::AssumeSymLT(const GRState* St, SymbolRef sym,
484 const llvm::APSInt& V, bool& isFeasible) {
485
486 // Is 'V' the smallest possible value?
487 if (V == llvm::APSInt::getMinValue(V.getBitWidth(), V.isUnsigned())) {
488 // sym cannot be any value less than 'V'. This path is infeasible.
489 isFeasible = false;
490 return St;
491 }
492
493 isFeasible = CouldBeLT(St, sym, V);
494 if (isFeasible)
495 return AddLT(St, sym, V);
496
497 return St;
498}
499
500const GRState*
501RangeConstraintManager::AssumeSymGT(const GRState* St, SymbolRef sym,
502 const llvm::APSInt& V, bool& isFeasible) {
503
504 // Is 'V' the largest possible value?
505 if (V == llvm::APSInt::getMaxValue(V.getBitWidth(), V.isUnsigned())) {
506 // sym cannot be any value greater than 'V'. This path is infeasible.
507 isFeasible = false;
508 return St;
509 }
510
511 isFeasible = CouldBeGT(St, sym, V);
512 if (isFeasible)
513 return AddGT(St, sym, V);
514
515 return St;
516}
517
518const GRState*
519RangeConstraintManager::AssumeSymGE(const GRState* St, SymbolRef sym,
520 const llvm::APSInt& V, bool& isFeasible) {
521
522 isFeasible = CouldBeGE(St, sym, V);
523 if (isFeasible)
524 return AddGE(St, sym, V);
525
526 return St;
527}
528
529const GRState*
530RangeConstraintManager::AssumeSymLE(const GRState* St, SymbolRef sym,
531 const llvm::APSInt& V, bool& isFeasible) {
532
533 isFeasible = CouldBeLT(St, sym, V);
534 if (isFeasible)
535 return AddLE(St, sym, V);
536
537 return St;
538}
539
540const GRState* RangeConstraintManager::AddEQ(const GRState* St, SymbolRef sym,
541 const llvm::APSInt& V) {
542 // Create a new state with the old binding replaced.
543 GRStateRef state(St, StateMgr);
544 RangeSet R(&factory);
545 R = R.AddEQ(&factory, V);
546 return state.set<ConstRange>(sym, R);
547}
548
549const GRState* RangeConstraintManager::AddNE(const GRState* St, SymbolRef sym,
550 const llvm::APSInt& V) {
551 GRStateRef state(St, StateMgr);
552
553 ConstRangeTy::data_type* T = state.get<ConstRange>(sym);
554 RangeSet R(&factory);
555 if (T)
556 R = *T;
557 R = R.AddNE(&factory, V);
558 return state.set<ConstRange>(sym, R);
559}
560
561const GRState* RangeConstraintManager::AddLT(const GRState* St, SymbolRef sym,
562 const llvm::APSInt& V) {
563 GRStateRef state(St, StateMgr);
564
565 ConstRangeTy::data_type* T = state.get<ConstRange>(sym);
566 RangeSet R(&factory);
567 if (T)
568 R = *T;
569 R = R.AddLT(&factory, V);
570 return state.set<ConstRange>(sym, R);
571}
572
573const GRState* RangeConstraintManager::AddLE(const GRState* St, SymbolRef sym,
574 const llvm::APSInt& V) {
575 GRStateRef state(St, StateMgr);
576
577 ConstRangeTy::data_type* T = state.get<ConstRange>(sym);
578 RangeSet R(&factory);
579 if (T)
580 R = *T;
581 R = R.AddLE(&factory, V);
582 return state.set<ConstRange>(sym, R);
583}
584
585const GRState* RangeConstraintManager::AddGT(const GRState* St, SymbolRef sym,
586 const llvm::APSInt& V) {
587 GRStateRef state(St, StateMgr);
588
589 ConstRangeTy::data_type* T = state.get<ConstRange>(sym);
590 RangeSet R(&factory);
591 if (T)
592 R = *T;
593 R = R.AddGT(&factory, V);
594 return state.set<ConstRange>(sym, R);
595}
596
597const GRState* RangeConstraintManager::AddGE(const GRState* St, SymbolRef sym,
598 const llvm::APSInt& V) {
599 GRStateRef state(St, StateMgr);
600
601 ConstRangeTy::data_type* T = state.get<ConstRange>(sym);
602 RangeSet R(&factory);
603 if (T)
604 R = *T;
605 R = R.AddGE(&factory, V);
606 return state.set<ConstRange>(sym, R);
607}
608
609const llvm::APSInt* RangeConstraintManager::getSymVal(const GRState* St,
610 SymbolRef sym) const {
611 const ConstRangeTy::data_type *T = St->get<ConstRange>(sym);
612 return T ? T->HasConcreteValue() : NULL;
613}
614
615bool RangeConstraintManager::CouldBeLT(const GRState* St, SymbolRef sym,
616 const llvm::APSInt& V) const {
617 const ConstRangeTy::data_type *T = St->get<ConstRange>(sym);
618 return T ? T->CouldBeLT(V) : true;
619}
620
621bool RangeConstraintManager::CouldBeLE(const GRState* St, SymbolRef sym,
622 const llvm::APSInt& V) const {
623 const ConstRangeTy::data_type *T = St->get<ConstRange>(sym);
624 return T ? T->CouldBeLE(V) : true;
625}
626
627bool RangeConstraintManager::CouldBeGT(const GRState* St, SymbolRef sym,
628 const llvm::APSInt& V) const {
629 const ConstRangeTy::data_type *T = St->get<ConstRange>(sym);
630 return T ? T->CouldBeGT(V) : true;
631}
632
633bool RangeConstraintManager::CouldBeGE(const GRState* St, SymbolRef sym,
634 const llvm::APSInt& V) const {
635 const ConstRangeTy::data_type *T = St->get<ConstRange>(sym);
636 return T ? T->CouldBeGE(V) : true;
637}
638
639bool RangeConstraintManager::CouldBeNE(const GRState* St, SymbolRef sym,
640 const llvm::APSInt& V) const {
641 const ConstRangeTy::data_type *T = St->get<ConstRange>(sym);
642 return T ? T->CouldBeNE(V) : true;
643}
644
645bool RangeConstraintManager::CouldBeEQ(const GRState* St, SymbolRef sym,
646 const llvm::APSInt& V) const {
647 const ConstRangeTy::data_type *T = St->get<ConstRange>(sym);
648 return T ? T->CouldBeEQ(V) : true;
649}
650
651bool RangeConstraintManager::isEqual(const GRState* St, SymbolRef sym,
652 const llvm::APSInt& V) const {
653 const llvm::APSInt *i = getSymVal(St, sym);
654 return i ? *i == V : false;
655}
656
657/// Scan all symbols referenced by the constraints. If the symbol is not alive
658/// as marked in LSymbols, mark it as dead in DSymbols.
659const GRState*
660RangeConstraintManager::RemoveDeadBindings(const GRState* St,
661 SymbolReaper& SymReaper) {
662 GRStateRef state(St, StateMgr);
663
664 ConstRangeTy CR = state.get<ConstRange>();
665 ConstRangeTy::Factory& CRFactory = state.get_context<ConstRange>();
666
667 for (ConstRangeTy::iterator I = CR.begin(), E = CR.end(); I != E; ++I) {
668 SymbolRef sym = I.getKey();
669 if (SymReaper.maybeDead(sym))
670 CR = CRFactory.Remove(CR, sym);
671 }
672
673 return state.set<ConstRange>(CR);
674}
675
676void RangeConstraintManager::print(const GRState* St, std::ostream& Out,
677 const char* nl, const char *sep) {
Ted Kremenekdd28d002009-02-16 18:42:56 +0000678
679 ConstRangeTy Ranges = St->get<ConstRange>();
680
681 if (Ranges.isEmpty())
682 return;
683
684 Out << nl << sep << "ranges of symbol values:";
685
686 for (ConstRangeTy::iterator I=Ranges.begin(), E=Ranges.end(); I!=E; ++I) {
687 Out << nl << " $" << I.getKey() << " : ";
688 I.getData().Print(Out);
Ted Kremenek45021952009-02-14 17:08:39 +0000689 }
Ted Kremenek45021952009-02-14 17:08:39 +0000690}