Index: lib/Analysis/BasicConstraintManager.cpp
===================================================================
--- lib/Analysis/BasicConstraintManager.cpp	(revision 63488)
+++ lib/Analysis/BasicConstraintManager.cpp	(working copy)
@@ -17,29 +17,364 @@
 #include "clang/Analysis/PathSensitive/GRStateTrait.h"
 #include "clang/Analysis/PathSensitive/GRTransferFuncs.h"
 #include "llvm/Support/Compiler.h"
+#include "llvm/ADT/FoldingSet.h"
 #include "llvm/Support/raw_ostream.h"
 
+#include <iostream>
+#include <set>
+
 using namespace clang;
 
+namespace { class VISIBILITY_HIDDEN ConstRange {}; }
 
-namespace { class VISIBILITY_HIDDEN ConstNotEq {}; }
-namespace { class VISIBILITY_HIDDEN ConstEq {}; }
+static int ConstRangeIndex = 0;
 
-typedef llvm::ImmutableMap<SymbolRef,GRState::IntSetTy> ConstNotEqTy;
-typedef llvm::ImmutableMap<SymbolRef,const llvm::APSInt*> ConstEqTy;
-  
-static int ConstEqIndex = 0;
-static int ConstNotEqIndex = 0;
+class Range : public std::pair<llvm::APSInt, llvm::APSInt> {
+public:
+  Range(const llvm::APSInt &from, const llvm::APSInt &to)
+    : std::pair<llvm::APSInt, llvm::APSInt>(from, to) {
+    std::cerr << "Range(" << from.toString(10) << ", " << to.toString(10)
+              << ')' << std::endl;
+    assert(from <= to);
+  }
+  bool Includes(const llvm::APSInt &v) const {
+    return first <= v && v <= second;
+  }
+  const llvm::APSInt &From() const {
+    return first;
+  }
+  const llvm::APSInt &To() const {
+    return second;
+  }
 
-namespace clang {
-template<>
-struct GRStateTrait<ConstNotEq> : public GRStatePartialTrait<ConstNotEqTy> {
-  static inline void* GDMIndex() { return &ConstNotEqIndex; }  
+  void Profile(llvm::FoldingSetNodeID &ID) const {
+    From().Profile(ID);
+    To().Profile(ID);
+  }
 };
 
+struct RangeCmp {
+  bool operator()(const Range &r1, const Range &r2) {
+    if(r1.From() < r2.From()) {
+      assert(!r1.Includes(r2.From()));
+      assert(!r2.Includes(r1.To()));
+      return true;
+    } else if(r1.From() > r2.From()) {
+      assert(!r1.Includes(r2.To()));
+      assert(!r2.Includes(r1.From()));
+      return false;
+    } else
+      assert(!"Ranges should never be equal in the same set");
+  }
+};
+
+typedef std::set<Range, RangeCmp> PrimRangeSet;
+
+class RangeSet;
+std::ostream &operator<<(std::ostream &os, const RangeSet &r);
+
+class RangeSet {
+  PrimRangeSet ranges;
+  bool noValues;  // if true, no value is possible
+
+  static const llvm::APSInt Max(const llvm::APSInt &v) {
+    return llvm::APSInt::getMaxValue(v.getBitWidth(), v.isUnsigned());
+  }
+  static const llvm::APSInt Min(const llvm::APSInt &v) {
+     return llvm::APSInt::getMinValue(v.getBitWidth(), v.isUnsigned());
+  }
+  static const llvm::APSInt One(const llvm::APSInt &v) {
+    return llvm::APSInt(llvm::APInt(v.getBitWidth(), 1), v.isUnsigned());
+  }
+
+public:
+  RangeSet() : noValues(false) {
+  }
+  void Profile(llvm::FoldingSetNodeID &ID) const {
+    for(PrimRangeSet::const_iterator i = ranges.begin() ; i != ranges.end() ; ++i) {
+      i->Profile(ID);
+    }
+  }
+
+  bool CouldBeNE(const llvm::APSInt &ne) const {
+    std::cerr << "CouldBeNE(" << ne.toString(10) << ") " << *this << std::endl;
+    // FIXME: do I mean this? empty means all values are possible, therefore != possible, right?
+    if(ranges.empty())
+      return false;
+    // FIXME: if there are no possible values, then can't be !=, surely?
+    if(noValues)
+      return true;
+    for(PrimRangeSet::const_iterator i = ranges.begin() ; i != ranges.end() ; ++i)
+      if(i->Includes(ne))
+        return false;
+    return true;
+  }
+
+  bool CouldBeEQ(const llvm::APSInt &eq) const {
+    std::cerr << "CouldBeEQ(" << eq.toString(10) << ") " << *this << std::endl;
+    if(ranges.empty())
+      return true;
+    // FIXME: if there are no possible values, then can't be ==, surely?
+    if(noValues)
+      return true;
+    for(PrimRangeSet::const_iterator i = ranges.begin() ; i != ranges.end() ; ++i)
+      if(i->Includes(eq))
+        return true;
+    return false;
+  }
+
+  bool CouldBeLT(const llvm::APSInt &lt) const {
+    std::cerr << "CouldBeLT(" << lt.toString(10) << ") " << *this << std::endl;
+    // FIXME: should test if lt == min -> false here, since that's
+    // impossible to meet.
+    if(ranges.empty())
+      return true;
+    if(noValues)
+      return false;
+    for(PrimRangeSet::const_iterator i = ranges.begin() ; i != ranges.end() ; ++i)
+      if(i->From() < lt)
+        return true;
+    return false;
+  }
+
+  bool CouldBeLE(const llvm::APSInt &le) const {
+    std::cerr << "CouldBeLE(" << le.toString(10) << ") " << *this << std::endl;
+    if(ranges.empty())
+      return true;
+    if(noValues)
+      return false;
+    for(PrimRangeSet::const_iterator i = ranges.begin() ; i != ranges.end() ; ++i)
+      if(i->From() <= le)
+        return true;
+    return false;
+  }
+
+  bool CouldBeGT(const llvm::APSInt &gt) const {
+    std::cerr << "CouldBeGT(" << gt.toString(10) << ") " << *this << std::endl;
+    // FIXME: should we test if gt == max -> false here, since that's
+    // impossible to meet.
+    if(ranges.empty())
+      return true;
+    if(noValues)
+      return false;
+    for(PrimRangeSet::const_iterator i = ranges.begin() ; i != ranges.end() ; ++i)
+      if(i->To() > gt)
+        return true;
+    return false;
+  }
+
+  bool CouldBeGE(const llvm::APSInt &ge) const {
+    std::cerr << "CouldBeGE(" << ge.toString(10) << ") " << *this << std::endl;
+    if(ranges.empty())
+      return true;
+    if(noValues)
+      return false;
+    for(PrimRangeSet::const_iterator i = ranges.begin() ; i != ranges.end() ; ++i)
+      if(i->To() >= ge)
+        return true;
+    return false;
+  }
+
+  // Make all existing ranges fall within this new range
+  void Restrict(const llvm::APSInt &from, const llvm::APSInt &to) {
+    if(ranges.empty()) {
+      ranges.insert(Range(from, to));
+      return;
+    }
+
+    PrimRangeSet newRanges;
+
+    for(PrimRangeSet::const_iterator i = ranges.begin() ; i != ranges.end() ; ++i) {
+      if(i->Includes(from)) {
+        if(i->Includes(to)) {
+          newRanges.insert(Range(from, to));
+        } else {
+          newRanges.insert(Range(from, i->To()));
+        }
+      } else if(i->Includes(to)) {
+        newRanges.insert(Range(i->From(), to));
+      }
+    }
+    ranges = newRanges;
+  }
+
+  void AddEQ(const llvm::APSInt &eq) {
+    std::cerr << "AddEQ(" << eq.toString(10) << ") " << *this << " -> ";
+
+    PrimRangeSet newRanges;
+    newRanges.insert(Range(eq, eq));
+    ranges = newRanges;
+    std::cerr << *this << std::endl;
+  }
+
+  void AddNE(const llvm::APSInt &ne) {
+    std::cerr << "AddNE(" << ne.toString(10) << ") " << *this << " -> ";
+
+    const llvm::APSInt max = Max(ne);
+    const llvm::APSInt min = Min(ne);
+    const llvm::APSInt one = One(ne);
+
+    if(ranges.empty()) {
+      if(ne != max)
+        ranges.insert(Range(ne + one, max));
+      if(ne != min)
+        ranges.insert(Range(min, ne - one));
+      std::cerr << *this << std::endl;
+      return;
+    }
+
+    PrimRangeSet newRanges;
+
+    for(PrimRangeSet::const_iterator i = ranges.begin() ; i != ranges.end() ; ++i) {
+      if(i->Includes(ne)) {
+        if(ne != i->From())
+          newRanges.insert(Range(i->From(), ne - one));
+        if(ne != i->To())
+          newRanges.insert(Range(ne + one, i->To()));
+      } else {
+        newRanges.insert(*i);
+      }
+    }
+    ranges = newRanges;
+    std::cerr << *this << std::endl;
+  }
+
+  void AddLT(const llvm::APSInt &lt) {
+    std::cerr << "AddLT(" << lt.toString(10) << ") " << *this << " -> ";
+    const llvm::APSInt min = Min(lt);
+    const llvm::APSInt one = One(lt);
+
+    if(ranges.empty()) {
+      if(lt != min)
+        ranges.insert(Range(min, lt - one));
+      else
+        noValues = true;
+      std::cerr << *this << std::endl;
+      return;
+    }
+
+    PrimRangeSet newRanges;
+
+    for(PrimRangeSet::const_iterator i = ranges.begin() ; i != ranges.end() ; ++i) {
+      if(i->Includes(lt))
+        newRanges.insert(Range(i->From(), lt - one));
+      else if(i->To() < lt)
+        newRanges.insert(*i);
+    }
+    ranges = newRanges;
+    if(ranges.empty())
+      noValues = true;
+    std::cerr << *this << std::endl;
+  }
+
+  void AddLE(const llvm::APSInt &le) {
+    std::cerr << "AddLE(" << le.toString(10) << ") " << *this << " -> ";
+    const llvm::APSInt min = Min(le);
+
+    if(ranges.empty()) {
+      ranges.insert(Range(min, le));
+      std::cerr << *this << std::endl;
+      return;
+    }
+
+    PrimRangeSet newRanges;
+
+    for(PrimRangeSet::const_iterator i = ranges.begin() ; i != ranges.end() ; ++i) {
+      // Strictly we should test for includes le + 1, but no harm is
+      // done by this formulation
+      if(i->Includes(le))
+        newRanges.insert(Range(i->From(), le));
+      else if(i->To() <= le)
+        newRanges.insert(*i);
+    }
+    ranges = newRanges;
+    if(ranges.empty())
+      noValues = true;
+    std::cerr << *this << std::endl;
+  }
+
+  void AddGT(const llvm::APSInt &gt) {
+    std::cerr << "AddGT(" << gt.toString(10) << ") " << *this << " -> ";
+    const llvm::APSInt max = Max(gt);
+    const llvm::APSInt one = One(gt);
+
+    if(ranges.empty()) {
+      ranges.insert(Range(gt + one, max));
+      std::cerr << *this << std::endl;
+      return;
+    }
+
+    PrimRangeSet newRanges;
+
+    for(PrimRangeSet::const_iterator i = ranges.begin() ; i != ranges.end() ; ++i) {
+      if(i->Includes(gt) && i->To() > gt)
+        newRanges.insert(Range(gt + one, i->To()));
+      else if(i->From() > gt)
+        newRanges.insert(*i);
+    }
+    ranges = newRanges;
+    if(ranges.empty())
+      noValues = true;
+    std::cerr << *this << std::endl;
+  }
+
+  void AddGE(const llvm::APSInt &ge) {
+    std::cerr << "AddLE(" << ge.toString(10) << ") " << *this << " -> ";
+    const llvm::APSInt max = Max(ge);
+
+    if(ranges.empty()) {
+      ranges.insert(Range(ge, max));
+      std::cerr << *this << std::endl;
+      return;
+    }
+
+    PrimRangeSet newRanges;
+
+    for(PrimRangeSet::const_iterator i = ranges.begin() ; i != ranges.end() ; ++i) {
+      // Strictly we should test for includes ge - 1, but no harm is
+      // done by this formulation
+      if(i->Includes(ge))
+        newRanges.insert(Range(ge, i->To()));
+      else if(i->From() >= ge)
+        newRanges.insert(*i);
+    }
+    ranges = newRanges;
+    if(ranges.empty())
+      noValues = true;
+    std::cerr << *this << std::endl;
+  }
+
+  void Print(std::ostream &os) const {
+    os << "{ ";
+    if(noValues) {
+      os << "**no values** }";
+      return;
+    }
+    for(PrimRangeSet::const_iterator i = ranges.begin() ; i != ranges.end() ; ++i) {
+      if(i != ranges.begin())
+        os << ", ";
+      os << '[' << i->From().toString(10) << ", " << i->To().toString(10)
+         << ']';
+    }
+    os << " }";
+  }
+
+  bool operator==(const RangeSet &other) const {
+    return ranges == other.ranges;
+  }
+};
+
+std::ostream &operator<<(std::ostream &os, const RangeSet &r) {
+  r.Print(os);
+  return os;
+}
+
+typedef llvm::ImmutableMap<SymbolRef,RangeSet> ConstRangeTy;
+
+namespace clang {
 template<>
-struct GRStateTrait<ConstEq> : public GRStatePartialTrait<ConstEqTy> {
-  static inline void* GDMIndex() { return &ConstEqIndex; }  
+struct GRStateTrait<ConstRange> : public GRStatePartialTrait<ConstRangeTy> {
+  static inline void* GDMIndex() { return &ConstRangeIndex; }  
 };
 }  
   
@@ -96,13 +431,28 @@
 
   const GRState* AddNE(const GRState* St, SymbolRef sym, const llvm::APSInt& V);
 
+  const GRState* AddLT(const GRState* St, SymbolRef sym, const llvm::APSInt& V);
+
+  const GRState* AddLE(const GRState* St, SymbolRef sym, const llvm::APSInt& V);
+
+  const GRState* AddGT(const GRState* St, SymbolRef sym, const llvm::APSInt& V);
+
+  const GRState* AddGE(const GRState* St, SymbolRef sym, const llvm::APSInt& V);
+
+  // FIXME: these two are required because they are pure virtual, but
+  // are they useful with ranges? Neither is used in this file.
   const llvm::APSInt* getSymVal(const GRState* St, SymbolRef sym);
-  bool isNotEqual(const GRState* St, SymbolRef sym, const llvm::APSInt& V) const;
   bool isEqual(const GRState* St, SymbolRef sym, const llvm::APSInt& V) const;
 
+  bool CouldBeEQ(const GRState* St, SymbolRef sym, const llvm::APSInt& V) const;
+  bool CouldBeNE(const GRState* St, SymbolRef sym, const llvm::APSInt& V) const;
+
+  bool CouldBeLT(const GRState* St, SymbolRef sym, const llvm::APSInt& V) const;
+  bool CouldBeLE(const GRState* St, SymbolRef sym, const llvm::APSInt& V) const;
+  bool CouldBeGT(const GRState* St, SymbolRef sym, const llvm::APSInt& V) const;
+  bool CouldBeGE(const GRState* St, SymbolRef sym, const llvm::APSInt& V) const;
   const GRState* RemoveDeadBindings(const GRState* St, SymbolReaper& SymReaper);
 
-
   void print(const GRState* St, std::ostream& Out, 
              const char* nl, const char *sep);
 
@@ -299,44 +649,19 @@
 const GRState*
 BasicConstraintManager::AssumeSymNE(const GRState* St, SymbolRef sym,
                                     const llvm::APSInt& V, bool& isFeasible) {
-  // First, determine if sym == X, where X != V.
-  if (const llvm::APSInt* X = getSymVal(St, sym)) {
-    isFeasible = (*X != V);
-    return St;
-  }
-
-  // Second, determine if sym != V.
-  if (isNotEqual(St, sym, V)) {
-    isFeasible = true;
-    return St;
-  }
-
-  // If we reach here, sym is not a constant and we don't know if it is != V.
-  // Make that assumption.
-  isFeasible = true;
-  return AddNE(St, sym, V);
+  isFeasible = CouldBeNE(St, sym, V);
+  if (isFeasible)
+    return AddNE(St, sym, V);
+  return St;
 }
 
 const GRState*
 BasicConstraintManager::AssumeSymEQ(const GRState* St, SymbolRef sym,
                                     const llvm::APSInt& V, bool& isFeasible) {
-  // First, determine if sym == X, where X != V.
-  if (const llvm::APSInt* X = getSymVal(St, sym)) {
-    isFeasible = *X == V;
-    return St;
-  }
-
-  // Second, determine if sym != V.
-  if (isNotEqual(St, sym, V)) {
-    isFeasible = false;
-    return St;
-  }
-
-  // If we reach here, sym is not a constant and we don't know if it is == V.
-  // Make that assumption.
-
-  isFeasible = true;
-  return AddEQ(St, sym, V);
+  isFeasible = CouldBeEQ(St, sym, V);
+  if (isFeasible)
+    return AddEQ(St, sym, V);
+  return St;
 }
 
 // These logic will be handled in another ConstraintManager.
@@ -351,8 +676,11 @@
     return St;
   }
 
-  // FIXME: For now have assuming x < y be the same as assuming sym != V;
-  return AssumeSymNE(St, sym, V, isFeasible);
+  isFeasible = CouldBeLT(St, sym, V);
+  if (isFeasible)
+    return AddLT(St, sym, V);
+
+  return St;
 }
 
 const GRState*
@@ -366,35 +694,20 @@
     return St;
   }
 
-  // FIXME: For now have assuming x > y be the same as assuming sym != V;
-  return AssumeSymNE(St, sym, V, isFeasible);
+  isFeasible = CouldBeGT(St, sym, V);
+  if (isFeasible)
+    return AddGT(St, sym, V);
+
+  return St;
 }
 
 const GRState*
 BasicConstraintManager::AssumeSymGE(const GRState* St, SymbolRef sym,
                                     const llvm::APSInt& V, bool& isFeasible) {
 
-  // Reject a path if the value of sym is a constant X and !(X >= V).
-  if (const llvm::APSInt* X = getSymVal(St, sym)) {
-    isFeasible = *X >= V;
-    return St;
-  }
-  
-  // Sym is not a constant, but it is worth looking to see if V is the
-  // maximum integer value.
-  if (V == llvm::APSInt::getMaxValue(V.getBitWidth(), V.isUnsigned())) {
-    // If we know that sym != V, then this condition is infeasible since
-    // there is no other value greater than V.    
-    isFeasible = !isNotEqual(St, sym, V);
-    
-    // If the path is still feasible then as a consequence we know that
-    // 'sym == V' because we cannot have 'sym > V' (no larger values).
-    // Add this constraint.
-    if (isFeasible)
-      return AddEQ(St, sym, V);
-  }
-  else
-    isFeasible = true;
+  isFeasible = CouldBeGE(St, sym, V);
+  if (isFeasible)
+    return AddGE(St, sym, V);
 
   return St;
 }
@@ -403,28 +716,10 @@
 BasicConstraintManager::AssumeSymLE(const GRState* St, SymbolRef sym,
                                     const llvm::APSInt& V, bool& isFeasible) {
 
-  // Reject a path if the value of sym is a constant X and !(X <= V).
-  if (const llvm::APSInt* X = getSymVal(St, sym)) {
-    isFeasible = *X <= V;
-    return St;
-  }
-  
-  // Sym is not a constant, but it is worth looking to see if V is the
-  // minimum integer value.
-  if (V == llvm::APSInt::getMinValue(V.getBitWidth(), V.isUnsigned())) {
-    // If we know that sym != V, then this condition is infeasible since
-    // there is no other value less than V.    
-    isFeasible = !isNotEqual(St, sym, V);
+  isFeasible = CouldBeLT(St, sym, V);
+  if (isFeasible)
+    return AddLE(St, sym, V);
     
-    // If the path is still feasible then as a consequence we know that
-    // 'sym == V' because we cannot have 'sym < V' (no smaller values).
-    // Add this constraint.
-    if (isFeasible)
-      return AddEQ(St, sym, V);
-  }
-  else
-    isFeasible = true;
-    
   return St;
 }
 
@@ -455,53 +750,138 @@
   return St;
 }
 
-
 const GRState* BasicConstraintManager::AddEQ(const GRState* St, SymbolRef sym,
                                              const llvm::APSInt& V) {
   // Create a new state with the old binding replaced.
   GRStateRef state(St, StateMgr);
-  return state.set<ConstEq>(sym, &V);
+  RangeSet R;
+  R.AddEQ(V);
+  return state.set<ConstRange>(sym, R);
 }
 
 const GRState* BasicConstraintManager::AddNE(const GRState* St, SymbolRef sym,
                                              const llvm::APSInt& V) {
+  GRStateRef state(St, StateMgr);
 
+  // First, retrieve the raange-set associated with the given symbol.
+  ConstRangeTy::data_type* T = state.get<ConstRange>(sym);
+  RangeSet R;
+  if (T)
+    R = *T;
+  // And add the != constraint to it
+  R.AddNE(V);
+  return state.set<ConstRange>(sym, R);
+}
+
+const GRState* BasicConstraintManager::AddLT(const GRState* St, SymbolRef sym,
+                                             const llvm::APSInt& V) {
   GRStateRef state(St, StateMgr);
 
-  // First, retrieve the NE-set associated with the given symbol.
-  ConstNotEqTy::data_type* T = state.get<ConstNotEq>(sym);
-  GRState::IntSetTy S = T ? *T : ISetFactory.GetEmptySet();
+  // First, retrieve the raange-set associated with the given symbol.
+  ConstRangeTy::data_type* T = state.get<ConstRange>(sym);
+  RangeSet R;
+  if (T)
+    R = *T;
+  // And add the <= constraint to it
+  R.AddLT(V);
+  return state.set<ConstRange>(sym, R);
+}
 
-  
-  // Now add V to the NE set.
-  S = ISetFactory.Add(S, &V);
-  
-  // Create a new state with the old binding replaced.
-  return state.set<ConstNotEq>(sym, S);
+const GRState* BasicConstraintManager::AddLE(const GRState* St, SymbolRef sym,
+                                             const llvm::APSInt& V) {
+  GRStateRef state(St, StateMgr);
+
+  // First, retrieve the raange-set associated with the given symbol.
+  ConstRangeTy::data_type* T = state.get<ConstRange>(sym);
+  RangeSet R;
+  if (T)
+    R = *T;
+  // And add the <= constraint to it
+  R.AddLE(V);
+  return state.set<ConstRange>(sym, R);
 }
 
+const GRState* BasicConstraintManager::AddGT(const GRState* St, SymbolRef sym,
+                                             const llvm::APSInt& V) {
+  GRStateRef state(St, StateMgr);
+
+  // First, retrieve the raange-set associated with the given symbol.
+  ConstRangeTy::data_type* T = state.get<ConstRange>(sym);
+  RangeSet R;
+  if (T)
+    R = *T;
+  // And add the > constraint to it
+  R.AddGT(V);
+  return state.set<ConstRange>(sym, R);
+}
+
+const GRState* BasicConstraintManager::AddGE(const GRState* St, SymbolRef sym,
+                                             const llvm::APSInt& V) {
+  GRStateRef state(St, StateMgr);
+
+  // First, retrieve the raange-set associated with the given symbol.
+  ConstRangeTy::data_type* T = state.get<ConstRange>(sym);
+  RangeSet R;
+  if (T)
+    R = *T;
+  // And add the <= constraint to it
+  R.AddGE(V);
+  return state.set<ConstRange>(sym, R);
+}
+
 const llvm::APSInt* BasicConstraintManager::getSymVal(const GRState* St,
                                                       SymbolRef sym) {
-  const ConstEqTy::data_type* T = St->get<ConstEq>(sym);
-  return T ? *T : NULL;  
+  //  const ConstEqTy::data_type* T = St->get<ConstEq>(sym);
+  //  return T ? *T : NULL;  
+  return NULL;
 }
 
-bool BasicConstraintManager::isNotEqual(const GRState* St, SymbolRef sym, 
-                                        const llvm::APSInt& V) const {
 
-  // Retrieve the NE-set associated with the given symbol.
-  const ConstNotEqTy::data_type* T = St->get<ConstNotEq>(sym);
+bool BasicConstraintManager::CouldBeLT(const GRState* St, SymbolRef sym, 
+                                       const llvm::APSInt& V) const {
+  const ConstRangeTy::data_type *T = St->get<ConstRange>(sym);
+  return T ? T->CouldBeLT(V) : true;
+}
 
-  // See if V is present in the NE-set.
-  return T ? T->contains(&V) : false;
+bool BasicConstraintManager::CouldBeLE(const GRState* St, SymbolRef sym, 
+                                       const llvm::APSInt& V) const {
+  const ConstRangeTy::data_type *T = St->get<ConstRange>(sym);
+  return T ? T->CouldBeLE(V) : true;
 }
 
+bool BasicConstraintManager::CouldBeGT(const GRState* St, SymbolRef sym, 
+                                       const llvm::APSInt& V) const {
+  const ConstRangeTy::data_type *T = St->get<ConstRange>(sym);
+  return T ? T->CouldBeGT(V) : true;
+}
+
+bool BasicConstraintManager::CouldBeGE(const GRState* St, SymbolRef sym, 
+                                       const llvm::APSInt& V) const {
+  const ConstRangeTy::data_type *T = St->get<ConstRange>(sym);
+  return T ? T->CouldBeGE(V) : true;
+}
+
+bool BasicConstraintManager::CouldBeNE(const GRState* St, SymbolRef sym, 
+                                        const llvm::APSInt& V) const {
+  // Retrieve the range-set associated with the given symbol.
+  const ConstRangeTy::data_type *T = St->get<ConstRange>(sym);
+  return T ? T->CouldBeNE(V) : true;
+}
+
+bool BasicConstraintManager::CouldBeEQ(const GRState* St, SymbolRef sym, 
+                                        const llvm::APSInt& V) const {
+  // Retrieve the range-set associated with the given symbol.
+  const ConstRangeTy::data_type *T = St->get<ConstRange>(sym);
+  return T ? T->CouldBeEQ(V) : true;
+}
+
 bool BasicConstraintManager::isEqual(const GRState* St, SymbolRef sym,
                                      const llvm::APSInt& V) const {
-  // Retrieve the EQ-set associated with the given symbol.
-  const ConstEqTy::data_type* T = St->get<ConstEq>(sym);
-  // See if V is present in the EQ-set.
-  return T ? **T == V : false;
+  // FIXME: in the old version, using EQ-set, this can only return
+  // true if the only possible value is equal, but with ranges it can
+  // return true of equality is one of the possibilities. Is this
+  // wrong? In any case, isEqual is not used in this file.
+  return CouldBeEQ(St, sym, V);
 }
 
 /// Scan all symbols referenced by the constraints. If the symbol is not alive
@@ -509,30 +889,22 @@
 const GRState*
 BasicConstraintManager::RemoveDeadBindings(const GRState* St,
                                            SymbolReaper& SymReaper) {
-
   GRStateRef state(St, StateMgr);
-  ConstEqTy CE = state.get<ConstEq>();
-  ConstEqTy::Factory& CEFactory = state.get_context<ConstEq>();
 
-  for (ConstEqTy::iterator I = CE.begin(), E = CE.end(); I!=E; ++I) {
-    SymbolRef sym = I.getKey();
-    if (SymReaper.maybeDead(sym)) CE = CEFactory.Remove(CE, sym);
-  }
-  state = state.set<ConstEq>(CE);
+  ConstRangeTy CR = state.get<ConstRange>();
+  ConstRangeTy::Factory& CRFactory = state.get_context<ConstRange>();
 
-  ConstNotEqTy CNE = state.get<ConstNotEq>();
-  ConstNotEqTy::Factory& CNEFactory = state.get_context<ConstNotEq>();
-
-  for (ConstNotEqTy::iterator I = CNE.begin(), E = CNE.end(); I != E; ++I) {
+  for (ConstRangeTy::iterator I = CR.begin(), E = CR.end(); I != E; ++I) {
     SymbolRef sym = I.getKey();    
-    if (SymReaper.maybeDead(sym)) CNE = CNEFactory.Remove(CNE, sym);
+    if (SymReaper.maybeDead(sym)) CR = CRFactory.Remove(CR, sym);
   }
   
-  return state.set<ConstNotEq>(CNE);
+  return state.set<ConstRange>(CR);
 }
 
 void BasicConstraintManager::print(const GRState* St, std::ostream& Out, 
                                    const char* nl, const char *sep) {
+  /*
   // Print equality constraints.
 
   ConstEqTy CE = St->get<ConstEq>();
@@ -569,4 +941,6 @@
       }
     }
   }
+  */
+  Out << nl << "Implement range printing";
 }
