]> granicus.if.org Git - clang/commitdiff
analyzer infrastructure: make a bunch of changes to symbolic expressions that
authorTed Kremenek <kremenek@apple.com>
Thu, 26 Mar 2009 03:35:11 +0000 (03:35 +0000)
committerTed Kremenek <kremenek@apple.com>
Thu, 26 Mar 2009 03:35:11 +0000 (03:35 +0000)
Zhongxing and I discussed by email.

Main changes:
- Removed SymIntConstraintVal and SymIntConstraint
- Added SymExpr as a parent class to SymbolData, SymSymExpr, SymIntExpr
- Added nonloc::SymExprVal to wrap SymExpr
- SymbolRef is now just a typedef of 'const SymbolData*'
- Bunch of minor code cleanups in how some methods were invoked (no functionality change)

This changes are part of a long-term plan to have full symbolic expression
trees. This will be useful for lazily evaluating complicated expressions.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67731 91177308-0d34-0410-b5e6-96231b3b80d8

22 files changed:
include/clang/Analysis/PathSensitive/BasicValueFactory.h
include/clang/Analysis/PathSensitive/ConstraintManager.h
include/clang/Analysis/PathSensitive/GRExprEngine.h
include/clang/Analysis/PathSensitive/GRState.h
include/clang/Analysis/PathSensitive/GRTransferFuncs.h
include/clang/Analysis/PathSensitive/MemRegion.h
include/clang/Analysis/PathSensitive/SVals.h
include/clang/Analysis/PathSensitive/SymbolManager.h
lib/Analysis/BasicStore.cpp
lib/Analysis/BasicValueFactory.cpp
lib/Analysis/BugReporter.cpp
lib/Analysis/CFRefCount.cpp
lib/Analysis/GRExprEngine.cpp
lib/Analysis/GRSimpleVals.cpp
lib/Analysis/GRSimpleVals.h
lib/Analysis/GRTransferFuncs.cpp
lib/Analysis/MemRegion.cpp
lib/Analysis/RegionStore.cpp
lib/Analysis/SVals.cpp
lib/Analysis/SimpleConstraintManager.cpp
lib/Analysis/SimpleConstraintManager.h
lib/Analysis/SymbolManager.cpp

index 3a401d69dff3275d485482c014bbb32357099f5a..553f8a31bca842800bc802e2ea0b057da48d72f1 100644 (file)
@@ -47,15 +47,10 @@ class BasicValueFactory {
   typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<llvm::APSInt> >
           APSIntSetTy;
 
-  typedef llvm::FoldingSet<SymIntConstraint>
-          SymIntCSetTy;
-  
-
   ASTContext& Ctx;
   llvm::BumpPtrAllocator& BPAlloc;
 
   APSIntSetTy   APSIntSet;
-  SymIntCSetTy  SymIntCSet;
   void*         PersistentSVals;
   void*         PersistentSValPairs;
 
@@ -135,9 +130,6 @@ public:
     return getValue(b ? 1 : 0, Ctx.getTypeSize(Ctx.IntTy), false);
   }
   
-  const SymIntConstraint& getConstraint(SymbolRef sym, BinaryOperator::Opcode Op,
-                                        const llvm::APSInt& V);
-
   const CompoundValData* getCompoundValData(QualType T, 
                                             llvm::ImmutableList<SVal> Vals);
   
index 32e5bb0cb373540160b38fd742329e1072b971ff..c8e5e85c8a1ac4aa4de147d6a61ac63b341954ba 100644 (file)
@@ -26,7 +26,6 @@ namespace clang {
 class GRState;
 class GRStateManager;
 class SVal;
-class SymbolRef;
 
 class ConstraintManager {
 public:
index dc9767312c0dc6150df1fb53c4d0ee2043d1c146..4c0abdcb0942c060164fabebaf040addfdd45dda 100644 (file)
@@ -642,24 +642,24 @@ protected:
     return X.isValid() ? getTF().EvalComplement(*this, cast<NonLoc>(X)) : X;
   }
   
-  SVal EvalBinOp(BinaryOperator::Opcode Op, NonLoc L, NonLoc R) {
-    return R.isValid() ? getTF().DetermEvalBinOpNN(*this, Op, L, R)
+  SVal EvalBinOp(BinaryOperator::Opcode Op, NonLoc L, NonLoc R, QualType T) {
+    return R.isValid() ? getTF().DetermEvalBinOpNN(*this, Op, L, R, T)
                        : R;
   }
 
-  SVal EvalBinOp(BinaryOperator::Opcode Op, NonLoc L, SVal R) {
+  SVal EvalBinOp(BinaryOperator::Opcode Op, NonLoc L, SVal R, QualType T) {
     return R.isValid() ? getTF().DetermEvalBinOpNN(*this, Op, L,
-                                                   cast<NonLoc>(R)) : R;
+                                                   cast<NonLoc>(R), T) : R;
   }
   
   void EvalBinOp(ExplodedNodeSet<GRState>& Dst, Expr* Ex,
                  BinaryOperator::Opcode Op, NonLoc L, NonLoc R,
-                 ExplodedNode<GRState>* Pred);
+                 ExplodedNode<GRState>* Pred, QualType T);
   
   void EvalBinOp(GRStateSet& OStates, const GRState* St, Expr* Ex,
-                 BinaryOperator::Opcode Op, NonLoc L, NonLoc R);  
+                 BinaryOperator::Opcode Op, NonLoc L, NonLoc R, QualType T);  
   
-  SVal EvalBinOp(BinaryOperator::Opcode Op, SVal L, SVal R);
+  SVal EvalBinOp(BinaryOperator::Opcode Op, SVal L, SVal R, QualType T);
   
   void EvalCall(NodeSet& Dst, CallExpr* CE, SVal L, NodeTy* Pred) {
     assert (Builder && "GRStmtNodeBuilder must be defined.");
index 72418583ae3080dc9a0100b4d37a2b54fab44cc9..7110c7bc2d2416697114a5f503f58bf8a9f4654e 100644 (file)
@@ -310,7 +310,7 @@ public:
     ISetFactory(alloc),
     GDMFactory(alloc),
     BasicVals(Ctx, alloc),
-    SymMgr(Ctx, alloc),
+    SymMgr(Ctx, BasicVals, alloc),
     Alloc(alloc),
     cfg(c),
     codedecl(cd),
index 69a7a12dd28eb24e6ff01cefe63b4dcd30eccecb..bee139f96816975a60407ec684df265e9175d5d3 100644 (file)
@@ -32,7 +32,7 @@ class GRTransferFuncs {
 protected:
   virtual SVal DetermEvalBinOpNN(GRExprEngine& Eng,
                                  BinaryOperator::Opcode Op,
-                                 NonLoc L, NonLoc R) {
+                                 NonLoc L, NonLoc R, QualType T) {
     return UnknownVal();
   }
   
@@ -59,7 +59,8 @@ public:
   // for OStates
   virtual void EvalBinOpNN(GRStateSet& OStates, GRExprEngine& Eng,
                            const GRState* St, Expr* Ex,
-                           BinaryOperator::Opcode Op, NonLoc L, NonLoc R);
+                           BinaryOperator::Opcode Op, NonLoc L, NonLoc R,
+                           QualType T);
   
   virtual SVal EvalBinOp(GRExprEngine& Engine, BinaryOperator::Opcode Op,
                          Loc L, Loc R) = 0;
index 8cf084ad57cbcee17c4ba3565166fe29e9622441..b54efadd3a3254dbe9ca63538d1f79fd2c1b0b7a 100644 (file)
@@ -182,11 +182,10 @@ public:
 class SymbolicRegion : public TypedRegion {
 protected:
   const SymbolRef sym;
-  const SymbolManager& SymMgr;
 
 public:
-  SymbolicRegion(const SymbolRef s, const SymbolManager& mgr, MemRegion* sreg) 
-    : TypedRegion(sreg, SymbolicRegionKind), sym(s), SymMgr(mgr) {}
+  SymbolicRegion(const SymbolRef s, const MemRegion* sreg) 
+    : TypedRegion(sreg, SymbolicRegionKind), sym(s) {}
     
   SymbolRef getSymbol() const {
     return sym;
@@ -539,7 +538,7 @@ public:
   getCompoundLiteralRegion(const CompoundLiteralExpr* CL);  
   
   /// getSymbolicRegion - Retrieve or create a "symbolic" memory region.
-  SymbolicRegion* getSymbolicRegion(const SymbolRef sym, const SymbolManager&);
+  SymbolicRegion* getSymbolicRegion(SymbolRef sym);
 
   StringRegion* getStringRegion(const StringLiteral* Str);
 
index 030115387a514aaf4325595a877254a5227efbf5..a02532559089032ead92cd6880ea849dcf0eb635 100644 (file)
@@ -96,54 +96,45 @@ public:
   bool isZeroConstant() const;
   
   /// getAsLocSymbol - If this SVal is a location (subclasses Loc) and 
-  ///  wraps a symbol, return that SymbolRef.  Otherwise return a SymbolRef
-  ///  where 'isValid()' returns false.
+  ///  wraps a symbol, return that SymbolRef.  Otherwise return a SymbolData*
   SymbolRef getAsLocSymbol() const;
   
   /// getAsSymbol - If this Sval wraps a symbol return that SymbolRef.
   ///  Otherwise return a SymbolRef where 'isValid()' returns false.
   SymbolRef getAsSymbol() const;
+
+  /// getAsSymbolicExpression - If this Sval wraps a symbolic expression then
+  ///  return that expression.  Otherwise return NULL.
+  const SymExpr *getAsSymbolicExpression() const;
   
   void print(std::ostream& OS) const;
   void print(llvm::raw_ostream& OS) const;
   void printStdErr() const;
-  
+
+  // Iterators.
   class symbol_iterator {
-    SymbolRef SingleRef;
-    const SymbolRef* sptr;
+    llvm::SmallVector<const SymExpr*, 5> itr;
+    void expand();
   public:
+    symbol_iterator() {}
+    symbol_iterator(const SymExpr* SE);
     
-    bool operator==(const symbol_iterator& X) {
-      return SingleRef == X.SingleRef && sptr == X.sptr;
-    }
-    
-    bool operator!=(const symbol_iterator& X) {
-      return SingleRef != X.SingleRef || sptr != X.sptr;
-    }
-    
-    symbol_iterator& operator++() {
-      if (sptr)
-        ++sptr;
-      else
-        SingleRef = SymbolRef();
+    symbol_iterator& operator++();
+    SymbolRef operator*();
       
-      return *this;
-    }
-    
-    SymbolRef operator*() const {
-      if (sptr)
-        return *sptr;
-      
-      return SingleRef;
-    }
-    
-    symbol_iterator(SymbolRef x) : SingleRef(x), sptr(0) {}
-    symbol_iterator() : sptr(0) {}
-    symbol_iterator(const SymbolRef* x) : sptr(x) {}
+    bool operator==(const symbol_iterator& X) const;
+    bool operator!=(const symbol_iterator& X) const;
   };
   
-  symbol_iterator symbol_begin() const;
-  symbol_iterator symbol_end() const;
+  symbol_iterator symbol_begin() const {
+    const SymExpr *SE = getAsSymbolicExpression();
+    if (SE)
+      return symbol_iterator(SE);
+    else
+      return symbol_iterator();
+  }
+  
+  symbol_iterator symbol_end() const { return symbol_iterator(); }
   
   // Implement isa<T> support.
   static inline bool classof(const SVal*) { return true; }
@@ -178,14 +169,15 @@ public:
   void print(llvm::raw_ostream& Out) const;
   
   // Utility methods to create NonLocs.
-
   static NonLoc MakeVal(SymbolRef sym);
 
-  static NonLoc MakeVal(SymbolManager& SymMgr, SymbolRef lhs, 
-                        BinaryOperator::Opcode op, const llvm::APSInt& v);
+  static NonLoc MakeVal(SymbolManager& SymMgr, const SymExpr *lhs, 
+                        BinaryOperator::Opcode op, const llvm::APSInt& rhs,
+                        QualType T);
   
-  static NonLoc MakeVal(SymbolManager& SymMgr, SymbolRef lhs, 
-                        BinaryOperator::Opcode op, SymbolRef rhs);
+  static NonLoc MakeVal(SymbolManager& SymMgr, const SymExpr *lhs,
+                        BinaryOperator::Opcode op, const SymExpr *rhs,
+                        QualType T);
 
   static NonLoc MakeIntVal(BasicValueFactory& BasicVals, uint64_t X, 
                            bool isUnsigned);
@@ -219,8 +211,8 @@ protected:
     : SVal(const_cast<void*>(D), true, SubKind) {}
   
   // Equality operators.
-  NonLoc EQ(BasicValueFactory& BasicVals, const Loc& R) const;
-  NonLoc NE(BasicValueFactory& BasicVals, const Loc& R) const;
+  NonLoc EQ(SymbolManager& SM, const Loc& R) const;
+  NonLoc NE(SymbolManager& SM, const Loc& R) const;
   
 public:
   void print(llvm::raw_ostream& Out) const;
@@ -248,17 +240,15 @@ public:
 
 namespace nonloc {
   
-enum Kind { ConcreteIntKind, SymbolValKind, SymIntConstraintValKind,
+enum Kind { ConcreteIntKind, SymbolValKind, SymExprValKind,
             LocAsIntegerKind, CompoundValKind };
 
 class SymbolVal : public NonLoc {
 public:
-  SymbolVal(SymbolRef SymID)
-    : NonLoc(SymbolValKind,
-             reinterpret_cast<void*>((uintptr_t) SymID.getNumber())) {}
+  SymbolVal(SymbolRef sym) : NonLoc(SymbolValKind, sym) {}
   
   SymbolRef getSymbol() const {
-    return (SymbolRef) reinterpret_cast<uintptr_t>(Data);
+    return (const SymbolData*) Data;
   }
   
   static inline bool classof(const SVal* V) {
@@ -271,22 +261,22 @@ public:
   }
 };
 
-class SymIntConstraintVal : public NonLoc {    
+class SymExprVal : public NonLoc {    
 public:
-  SymIntConstraintVal(const SymIntConstraint& C)
-    : NonLoc(SymIntConstraintValKind, reinterpret_cast<const void*>(&C)) {}
+  SymExprVal(const SymExpr *SE)
+    : NonLoc(SymExprValKind, reinterpret_cast<const void*>(SE)) {}
 
-  const SymIntConstraint& getConstraint() const {
-    return *reinterpret_cast<SymIntConstraint*>(Data);
+  const SymExpr *getSymbolicExpression() const {
+    return reinterpret_cast<SymExpr*>(Data);
   }
   
   static inline bool classof(const SVal* V) {
     return V->getBaseKind() == NonLocKind &&
-           V->getSubKind() == SymIntConstraintValKind;
+           V->getSubKind() == SymExprValKind;
   }
   
   static inline bool classof(const NonLoc* V) {
-    return V->getSubKind() == SymIntConstraintValKind;
+    return V->getSubKind() == SymExprValKind;
   }
 };
 
@@ -387,12 +377,9 @@ enum Kind { SymbolValKind, GotoLabelKind, MemRegionKind, FuncValKind,
 
 class SymbolVal : public Loc {
 public:
-  SymbolVal(SymbolRef SymID)
-  : Loc(SymbolValKind, reinterpret_cast<void*>((uintptr_t) SymID.getNumber())){}
+  SymbolVal(SymbolRef sym) : Loc(SymbolValKind, sym) {}
   
-  SymbolRef getSymbol() const {
-    return (SymbolRef) reinterpret_cast<uintptr_t>(Data);
-  }
+  SymbolRef getSymbol() const { return (SymbolRef) Data; }
   
   static inline bool classof(const SVal* V) {
     return V->getBaseKind() == LocKind &&
index 72a8b7907f8ba17320ca50d9db304c682e2cb495..9bdbd88cae4002faa5985a603c9f66f5ed3bf275 100644 (file)
@@ -28,92 +28,64 @@ namespace llvm {
   class raw_ostream;
 }
 
+namespace clang {  
+  class MemRegion;
+  class ASTContext;
+  class BasicValueFactory;
+}
+
 namespace clang {
   
-class MemRegion;
-class SymbolManager;
-class ASTContext;
-
-class SymbolRef {
-  unsigned Data;
+class SymExpr : public llvm::FoldingSetNode {
 public:
-  SymbolRef() : Data(~0U - 2) {}
-  SymbolRef(unsigned x) : Data(x) {}
-
-  bool isValid() const { return Data != (unsigned) (~0U - 2);  }
-  unsigned getNumber() const { assert (isValid()); return Data; }
-  
-  bool operator<(const SymbolRef& X) const { return Data < X.Data; }
-  bool operator>(const SymbolRef& X) const { return Data > X.Data; }
-  bool operator==(const SymbolRef& X) const { return Data == X.Data; }
-  bool operator!=(const SymbolRef& X) const { return Data != X.Data; }
-      
-  void Profile(llvm::FoldingSetNodeID& ID) const { 
-    ID.AddInteger(Data);
-  }
-};
-} // end clang namespace
-
-namespace llvm {
-  llvm::raw_ostream& operator<<(llvm::raw_ostream& Out, clang::SymbolRef Sym);
-}
-namespace std {
-  std::ostream& operator<<(std::ostream& Out, clang::SymbolRef Sym);
-}
-
-namespace llvm {
-template <> struct DenseMapInfo<clang::SymbolRef> {
-  static inline clang::SymbolRef getEmptyKey() {
-    return clang::SymbolRef(~0U);
-  }
-  static inline clang::SymbolRef getTombstoneKey() {
-    return clang::SymbolRef(~0U - 1);
-  }
-  static unsigned getHashValue(clang::SymbolRef X) {
-    return X.getNumber();
-  }
-  static bool isEqual(clang::SymbolRef X, clang::SymbolRef Y) {
-    return X == Y;
-  }
-  static bool isPod() { return true; }
-};
-}
-
-// SymbolData: Used to record meta data about symbols.
+  enum Kind { BEGIN_SYMBOLS, RegionRValue, ConjuredKind, END_SYMBOLS,
+              SymIntKind, SymSymKind };
+private:
+  Kind K;
 
-namespace clang {
+protected:
+  SymExpr(Kind k) : K(k) {}  
   
-class SymbolData : public llvm::FoldingSetNode {
 public:
-  enum Kind { RegionRValue, ConjuredKind, SymIntKind, SymSymKind };
+  virtual ~SymExpr() {}
+  
+  Kind getKind() const { return K; }  
+  
+  virtual QualType getType(ASTContext&) const = 0;  
+  virtual void Profile(llvm::FoldingSetNodeID& profile) = 0;
+  
+  // Implement isa<T> support.
+  static inline bool classof(const SymExpr*) { return true; }
+};
+  
+typedef unsigned SymbolID;
   
+class SymbolData : public SymExpr {
 private:
-  Kind K;
-  SymbolRef Sym;
+  const SymbolID Sym;
   
 protected:
-  SymbolData(Kind k, SymbolRef sym) : K(k), Sym(sym) {}  
+  SymbolData(Kind k, SymbolID sym) : SymExpr(k), Sym(sym) {}  
 
 public:
   virtual ~SymbolData() {}
   
-  Kind getKind() const { return K; }  
-  
-  SymbolRef getSymbol() const { return Sym; }
+  SymbolID getSymbolID() const { return Sym; }
     
-  virtual QualType getType(ASTContext&) const = 0;
-  
-  virtual void Profile(llvm::FoldingSetNodeID& profile) = 0;
-  
   // Implement isa<T> support.
-  static inline bool classof(const SymbolData*) { return true; }
+  static inline bool classof(const SymExpr* SE) { 
+    Kind k = SE->getKind();
+    return k > BEGIN_SYMBOLS && k < END_SYMBOLS;
+  }
 };
+
+typedef const SymbolData* SymbolRef;
   
 class SymbolRegionRValue : public SymbolData {
   const MemRegion *R;
 public:
-  SymbolRegionRValue(SymbolRef MySym, const MemRegion *r)
-    : SymbolData(RegionRValue, MySym), R(r) {}
+  SymbolRegionRValue(SymbolID sym, const MemRegion *r)
+    : SymbolData(RegionRValue, sym), R(r) {}
   
   const MemRegion* getRegion() const { return R; }
 
@@ -129,8 +101,8 @@ public:
   QualType getType(ASTContext&) const;
 
   // Implement isa<T> support.
-  static inline bool classof(const SymbolData* D) {
-    return D->getKind() == RegionRValue;
+  static inline bool classof(const SymExpr* SE) {
+    return SE->getKind() == RegionRValue;
   }
 };
 
@@ -141,9 +113,9 @@ class SymbolConjured : public SymbolData {
   const void* SymbolTag;
 
 public:
-  SymbolConjured(SymbolRef Sym, const Stmt* s, QualType t, unsigned count,
+  SymbolConjured(SymbolID sym, const Stmt* s, QualType t, unsigned count,
                  const void* symbolTag)
-    : SymbolData(ConjuredKind, Sym), S(s), T(t), Count(count),
+    : SymbolData(ConjuredKind, sym), S(s), T(t), Count(count),
       SymbolTag(symbolTag) {}
   
   const Stmt* getStmt() const { return S; }
@@ -166,143 +138,135 @@ public:
   }
 
   // Implement isa<T> support.
-  static inline bool classof(const SymbolData* D) {
-    return D->getKind() == ConjuredKind;
+  static inline bool classof(const SymExpr* SE) {
+    return SE->getKind() == ConjuredKind;
   }  
 };
 
 // SymIntExpr - Represents symbolic expression like 'x' + 3.
-class SymIntExpr : public SymbolData {
-  SymbolRef LHS;
+class SymIntExpr : public SymExpr {
+  const SymExpr *LHS;
   BinaryOperator::Opcode Op;
-  const llvm::APSInt& Val;
+  const llvm::APSInt& RHS;
   QualType T;
 
 public:
-  SymIntExpr(SymbolRef sym, SymbolRef lhs, BinaryOperator::Opcode op,
-             const llvm::APSInt& V, QualType t)
-    : SymbolData(SymIntKind, sym), LHS(lhs), Op(op), Val(V), T(t) {}
+  SymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
+             const llvm::APSInt& rhs, QualType t)
+    : SymExpr(SymIntKind), LHS(lhs), Op(op), RHS(rhs), T(t) {}
 
-  QualType getType(ASTContext& C) const {
-    return T;
-  }
+  // FIXME: We probably need to make this out-of-line to avoid redundant
+  // generation of virtual functions.
+  QualType getType(ASTContext& C) const { return T; }  
+  
+  BinaryOperator::Opcode getOpcode() const { return Op; }
+  
+  const SymExpr *getLHS() const { return LHS; }
+  const llvm::APSInt &getRHS() const { return RHS; }
 
-  static void Profile(llvm::FoldingSetNodeID& ID, SymbolRef lhs, 
-                      BinaryOperator::Opcode op, const llvm::APSInt& V,
+  static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs, 
+                      BinaryOperator::Opcode op, const llvm::APSInt& rhs,
                       QualType t) {
-    lhs.Profile(ID);
+    ID.AddInteger((unsigned) SymIntKind);
+    ID.AddPointer(lhs);
     ID.AddInteger(op);
-    ID.AddPointer(&V);
+    ID.AddPointer(&rhs);
     ID.Add(t);
   }
 
   void Profile(llvm::FoldingSetNodeID& ID) {
-    Profile(ID, LHS, Op, Val, T);
+    Profile(ID, LHS, Op, RHS, T);
   }
+  
+  // Implement isa<T> support.
+  static inline bool classof(const SymExpr* SE) {
+    return SE->getKind() == SymIntKind;
+  }  
 };
 
 // SymSymExpr - Represents symbolic expression like 'x' + 'y'.
-class SymSymExpr : public SymbolData {
-  SymbolRef LHS;
+class SymSymExpr : public SymExpr {
+  const SymExpr *LHS;
   BinaryOperator::Opcode Op;
-  SymbolRef RHS;
+  const SymExpr *RHS;
   QualType T;
 
 public:
-  SymSymExpr(SymbolRef sym, SymbolRef lhs, BinaryOperator::Opcode op,
-             SymbolRef rhs, QualType t)
-    : SymbolData(SymSymKind, sym), LHS(lhs), Op(op), RHS(rhs), T(t) {}
+  SymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs,
+             QualType t)
+    : SymExpr(SymSymKind), LHS(lhs), Op(op), RHS(rhs), T(t) {}
 
-  QualType getType(ASTContext& C) const {
-    return T;
-  }
+  const SymExpr *getLHS() const { return LHS; }
+  const SymExpr *getRHS() const { return RHS; }
+  
+  // FIXME: We probably need to make this out-of-line to avoid redundant
+  // generation of virtual functions.
+  QualType getType(ASTContext& C) const { return T; }
 
-  static void Profile(llvm::FoldingSetNodeID& ID, SymbolRef lhs,
-                      BinaryOperator::Opcode op, SymbolRef rhs, QualType t) {
-    lhs.Profile(ID);
+  static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs,
+                      BinaryOperator::Opcode op, const SymExpr *rhs, QualType t) {
+    ID.AddInteger((unsigned) SymSymKind);
+    ID.AddPointer(lhs);
     ID.AddInteger(op);
-    rhs.Profile(ID);
+    ID.AddPointer(rhs);
     ID.Add(t);
   }
 
   void Profile(llvm::FoldingSetNodeID& ID) {
     Profile(ID, LHS, Op, RHS, T);
   }
-};
-
-// Constraints on symbols.  Usually wrapped by SValues.
-
-class SymIntConstraint : public llvm::FoldingSetNode {
-  SymbolRef Symbol;
-  BinaryOperator::Opcode Op;
-  const llvm::APSInt& Val;
-public:  
-  SymIntConstraint(SymbolRef sym, BinaryOperator::Opcode op, 
-                   const llvm::APSInt& V)
-  : Symbol(sym),
-  Op(op), Val(V) {}
-  
-  BinaryOperator::Opcode getOpcode() const { return Op; }
-  const SymbolRef& getSymbol() const { return Symbol; }
-  const llvm::APSInt& getInt() const { return Val; }
-  
-  static inline void Profile(llvm::FoldingSetNodeID& ID,
-                             SymbolRef Symbol,
-                             BinaryOperator::Opcode Op,
-                             const llvm::APSInt& Val) {
-    Symbol.Profile(ID);
-    ID.AddInteger(Op);
-    ID.AddPointer(&Val);
-  }
   
-  void Profile(llvm::FoldingSetNodeID& ID) {
-    Profile(ID, Symbol, Op, Val);
-  }
+  // Implement isa<T> support.
+  static inline bool classof(const SymExpr* SE) {
+    return SE->getKind() == SymSymKind;
+  }  
 };
 
-
 class SymbolManager {
-  typedef llvm::FoldingSet<SymbolData> DataSetTy;
-  typedef llvm::DenseMap<SymbolRef, SymbolData*> DataMapTy;
-  
-  DataSetTy DataSet;
-  DataMapTy DataMap;
-  
+  typedef llvm::FoldingSet<SymExpr> DataSetTy;
+  DataSetTy DataSet;  
   unsigned SymbolCounter;
   llvm::BumpPtrAllocator& BPAlloc;
+  BasicValueFactory &BV;
   ASTContext& Ctx;
   
 public:
-  SymbolManager(ASTContext& ctx, llvm::BumpPtrAllocator& bpalloc)
-    : SymbolCounter(0), BPAlloc(bpalloc), Ctx(ctx) {}
+  SymbolManager(ASTContext& ctx, BasicValueFactory &bv, 
+                llvm::BumpPtrAllocator& bpalloc)
+    : SymbolCounter(0), BPAlloc(bpalloc), BV(bv), Ctx(ctx) {}
   
   ~SymbolManager();
   
   static bool canSymbolicate(QualType T);
 
   /// Make a unique symbol for MemRegion R according to its kind.
-  SymbolRef getRegionRValueSymbol(const MemRegion* R);
-  SymbolRef getConjuredSymbol(const Stmt* E, QualType T, unsigned VisitCount,
-                              const void* SymbolTag = 0);
+  const SymbolRegionRValue* getRegionRValueSymbol(const MemRegion* R);
+  const SymbolConjured* getConjuredSymbol(const Stmt* E, QualType T,
+                                          unsigned VisitCount,
+                                          const void* SymbolTag = 0);
 
-  SymbolRef getConjuredSymbol(const Expr* E, unsigned VisitCount,
-                              const void* SymbolTag = 0) {    
+  const SymbolConjured* getConjuredSymbol(const Expr* E, unsigned VisitCount,
+                                          const void* SymbolTag = 0) {    
     return getConjuredSymbol(E, E->getType(), VisitCount, SymbolTag);
   }
 
-  SymbolRef getSymIntExpr(SymbolRef lhs, BinaryOperator::Opcode op, 
-                          const llvm::APSInt& v, QualType t);
-
-  SymbolRef getSymSymExpr(SymbolRef lhs, BinaryOperator::Opcode op,
-                          SymbolRef rhs, QualType t);
+  const SymIntExpr *getSymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op, 
+                                  const llvm::APSInt& rhs, QualType t);
   
-  const SymbolData& getSymbolData(SymbolRef ID) const;
+  const SymIntExpr *getSymIntExpr(const SymExpr &lhs, BinaryOperator::Opcode op,
+                                  const llvm::APSInt& rhs, QualType t) {
+    return getSymIntExpr(&lhs, op, rhs, t);
+  }
+
+  const SymSymExpr *getSymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
+                                  const SymExpr *rhs, QualType t);
   
-  QualType getType(SymbolRef ID) const {
-    return getSymbolData(ID).getType(Ctx);
+  QualType getType(const SymExpr *SE) const {
+    return SE->getType(Ctx);
   }
   
-  ASTContext& getContext() { return Ctx; }
+  ASTContext &getContext() { return Ctx; }
+  BasicValueFactory &getBasicVals() { return BV; }
 };
   
 class SymbolReaper {
@@ -353,4 +317,13 @@ public:
   
 } // end clang namespace
 
+namespace llvm {
+  llvm::raw_ostream& operator<<(llvm::raw_ostream& Out,
+                                const clang::SymExpr *SE);
+}
+namespace std {
+  std::ostream& operator<<(std::ostream& Out,
+                           const clang::SymExpr *SE);
+}
+
 #endif
index 01260480d19255281fdbe14a2df18de39a59b1d4..8c5b71f234128d4fb21b57e77bf1ab1062ffd216 100644 (file)
@@ -197,8 +197,8 @@ SVal BasicStoreManager::getLValueField(const GRState* St, SVal Base,
   
   switch(BaseL.getSubKind()) {
     case loc::SymbolValKind:
-      BaseR = MRMgr.getSymbolicRegion(cast<loc::SymbolVal>(&BaseL)->getSymbol(),
-                                      StateMgr.getSymbolManager());
+      BaseR =
+        MRMgr.getSymbolicRegion(cast<loc::SymbolVal>(&BaseL)->getSymbol());
       break;
       
     case loc::GotoLabelKind:
@@ -243,8 +243,7 @@ SVal BasicStoreManager::getLValueElement(const GRState* St, SVal Base,
       // Create a region to represent this symbol.
       // FIXME: In the future we may just use symbolic regions instead of
       //  SymbolVals to reason about symbolic memory chunks.
-      const MemRegion* SymR = MRMgr.getSymbolicRegion(Sym, 
-                                                  StateMgr.getSymbolManager());
+      const MemRegion* SymR = MRMgr.getSymbolicRegion(Sym);
       // Layered a typed region on top of this.
       QualType T = StateMgr.getSymbolManager().getType(Sym);
       BaseR = MRMgr.getTypedViewRegion(T, SymR);
index 6ceab93b08670ae89a0ba1f65ea6f0479bd919ce..72ad0a5ed8f1d3fabcfd6943ce9854eba2650af3 100644 (file)
@@ -97,25 +97,6 @@ const llvm::APSInt& BasicValueFactory::getValue(uint64_t X, QualType T) {
   return getValue(V);
 }
 
-const SymIntConstraint&
-BasicValueFactory::getConstraint(SymbolRef sym, BinaryOperator::Opcode Op,
-                            const llvm::APSInt& V) {
-  
-  llvm::FoldingSetNodeID ID;
-  SymIntConstraint::Profile(ID, sym, Op, V);
-  void* InsertPos;
-  
-  SymIntConstraint* C = SymIntCSet.FindNodeOrInsertPos(ID, InsertPos);
-  
-  if (!C) {
-    C = (SymIntConstraint*) BPAlloc.Allocate<SymIntConstraint>();
-    new (C) SymIntConstraint(sym, Op, V);
-    SymIntCSet.InsertNode(C, InsertPos);
-  }
-  
-  return *C;
-}
-
 const CompoundValData* 
 BasicValueFactory::getCompoundValData(QualType T,
                                       llvm::ImmutableList<SVal> Vals) {
index ffa1593fd564be91a91b4b22ed0c5e0e1a427ccf..6807c9f08e032b4b3fc189073904916b9a8da4a5 100644 (file)
@@ -443,7 +443,7 @@ public:
   bool HandleBinding(StoreManager& SMgr, Store store,
                      const MemRegion* R, SVal V) {
 
-    SymbolRef ScanSym;
+    SymbolRef ScanSym = 0;
     
     if (loc::SymbolVal* SV = dyn_cast<loc::SymbolVal>(&V))
       ScanSym = SV->getSymbol();
@@ -545,7 +545,7 @@ public:
   
   bool HandleBinding(StoreManager& SMgr, Store store,
                      const MemRegion* R, SVal V) {
-    SymbolRef ScanSym;
+    SymbolRef ScanSym = 0;
   
     if (loc::SymbolVal* SV = dyn_cast<loc::SymbolVal>(&V))
       ScanSym = SV->getSymbol();
@@ -554,7 +554,7 @@ public:
     else
       return true;
   
-    assert (ScanSym.isValid());
+    assert (ScanSym);
   
     if (!BR.isNotable(ScanSym))
       return true;
index be1d794252c70d558f01147268033cedc8c37188..6e43ec5fafb7076943de15d1e3826d032bd3aa61 100644 (file)
@@ -1591,8 +1591,8 @@ public:
 
 static void PrintPool(std::ostream &Out, SymbolRef Sym, const GRState *state) {
   Out << ' ';
-  if (Sym.isValid())
-    Out << Sym;
+  if (Sym)
+    Out << Sym->getSymbolID();
   else
     Out << "<pool>";
   Out << ":{";
@@ -1705,7 +1705,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
     SVal V = state.GetSValAsScalarOrLoc(*I);    
     SymbolRef Sym = V.getAsLocSymbol();
 
-    if (Sym.isValid())
+    if (Sym)
       if (RefBindings::data_type* T = state.get<RefBindings>(Sym)) {
         state = Update(state, Sym, *T, GetArgE(Summ, idx), hasErr);
         if (hasErr) {
@@ -1746,7 +1746,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
           SymbolRef Sym = state.GetSValAsScalarOrLoc(R).getAsLocSymbol();
           
           // Remove any existing reference-count binding.
-          if (Sym.isValid()) state = state.remove<RefBindings>(Sym);
+          if (Sym) state = state.remove<RefBindings>(Sym);
           
           if (R->isBoundable(Ctx)) {
             // Set the value of the variable to be a conjured symbol.
@@ -1833,7 +1833,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
   // Evaluate the effect on the message receiver.  
   if (!ErrorExpr && Receiver) {
     SymbolRef Sym = state.GetSValAsScalarOrLoc(Receiver).getAsLocSymbol();
-    if (Sym.isValid()) {
+    if (Sym) {
       if (const RefVal* T = state.get<RefBindings>(Sym)) {
         state = Update(state, Sym, *T, GetReceiverE(Summ), hasErr);
         if (hasErr) {
@@ -1977,7 +1977,7 @@ void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<GRState>& Dst,
     SVal V = Eng.getStateManager().GetSValAsScalarOrLoc(St, Receiver);
 
     SymbolRef Sym = V.getAsLocSymbol();
-    if (Sym.isValid()) {
+    if (Sym) {
       if (const RefVal* T  = St->get<RefBindings>(Sym)) {
         QualType Ty = T->getType();
         
@@ -2127,7 +2127,7 @@ void CFRefCount::EvalReturn(ExplodedNodeSet<GRState>& Dst,
   GRStateRef state(Builder.GetState(Pred), Eng.getStateManager());
   SymbolRef Sym = state.GetSValAsScalarOrLoc(RetE).getAsLocSymbol();
   
-  if (!Sym.isValid())
+  if (!Sym)
     return;
 
   // Get the reference count binding (if any).
@@ -2824,9 +2824,9 @@ class VISIBILITY_HIDDEN FindUniqueBinding :
     
   bool HandleBinding(StoreManager& SMgr, Store store, const MemRegion* R,
                      SVal val) {
-    SymbolRef SymV = val.getAsSymbol();
-    
-    if (!SymV.isValid() || SymV != Sym)
+
+    SymbolRef SymV = val.getAsSymbol();    
+    if (!SymV || SymV != Sym)
       return true;
     
     if (Binding) {
index 80467ebb273ce3d03fff9b992e1ceef8755b5195..2f3f0bf5ccbc9973cd9df9fccf7145ff6eab22d7 100644 (file)
@@ -782,7 +782,8 @@ void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) {
         
     do {
       nonloc::ConcreteInt CaseVal(getBasicVals().getValue(V1.Val.getInt()));      
-      SVal Res = EvalBinOp(BinaryOperator::EQ, CondV, CaseVal);
+      SVal Res = EvalBinOp(BinaryOperator::EQ, CondV, CaseVal,
+                           getContext().IntTy);
       
       // Now "assume" that the case matches.      
       bool isFeasible = false;      
@@ -1449,7 +1450,7 @@ void GRExprEngine::EvalEagerlyAssume(NodeSet &Dst, NodeSet &Src, Expr *Ex) {
 
     const GRState* state = Pred->getState();    
     SVal V = GetSVal(state, Ex);    
-    if (isa<nonloc::SymIntConstraintVal>(V)) {
+    if (isa<nonloc::SymExprVal>(V)) {
       // First assume that the condition is true.
       bool isFeasible = false;
       const GRState *stateTrue = Assume(state, V, true, isFeasible);
@@ -1940,8 +1941,7 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){
       }
 
       StoreManager& StoreMgr = getStoreManager();
-      const MemRegion* R =
-        StoreMgr.getRegionManager().getSymbolicRegion(Sym, getSymbolManager());
+      const MemRegion* R = StoreMgr.getRegionManager().getSymbolicRegion(Sym);
       
       // Delegate to store manager to get the result of casting a region
       // to a different type.
@@ -2394,7 +2394,8 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
             
             if (isa<Loc>(V)) {
               loc::ConcreteInt X(getBasicVals().getZeroWithPtrWidth());
-              SVal Result = EvalBinOp(BinaryOperator::EQ, cast<Loc>(V), X);
+              SVal Result = EvalBinOp(BinaryOperator::EQ, cast<Loc>(V), X,
+                                      U->getType());
               state = BindExpr(state, U, Result);
             }
             else {
@@ -2403,7 +2404,8 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
               SVal Result = EvalBinOp(BinaryOperator::EQ, cast<NonLoc>(V), X);
               state = SetSVal(state, U, Result);
 #else
-              EvalBinOp(Dst, U, BinaryOperator::EQ, cast<NonLoc>(V), X, *I);
+              EvalBinOp(Dst, U, BinaryOperator::EQ, cast<NonLoc>(V), X, *I,
+                        U->getType());
               continue;
 #endif
             }
@@ -2449,7 +2451,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
       BinaryOperator::Opcode Op = U->isIncrementOp() ? BinaryOperator::Add
                                                      : BinaryOperator::Sub;
 
-      SVal Result = EvalBinOp(Op, V2, MakeConstantVal(1U, U));    
+      SVal Result = EvalBinOp(Op, V2, MakeConstantVal(1U, U), U->getType());    
       
       // Conjure a new symbol if necessary to recover precision.
       if (Result.isUnknown() || !getConstraintManager().canReasonAbout(Result))
@@ -2643,7 +2645,6 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
     return;
   }
   
-  
   if (B->isAssignmentOp())
     VisitLValue(LHS, Pred, Tmp1);
   else
@@ -2716,7 +2717,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
           // Process non-assignements except commas or short-circuited
           // logical expressions (LAnd and LOr).
           
-          SVal Result = EvalBinOp(Op, LeftV, RightV);
+          SVal Result = EvalBinOp(Op, LeftV, RightV, B->getType());
           
           if (Result.isUnknown()) {
             if (OldSt != state) {
@@ -2828,7 +2829,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
         }
       
         // Compute the result of the operation.      
-        SVal Result = EvalCast(EvalBinOp(Op, V, RightV), B->getType());
+        SVal Result = EvalCast(EvalBinOp(Op, V, RightV, CTy), B->getType());
           
         if (Result.isUndef()) {
           // The operands were not undefined, but the result is undefined.
@@ -2882,10 +2883,10 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
 void GRExprEngine::EvalBinOp(ExplodedNodeSet<GRState>& Dst, Expr* Ex,
                              BinaryOperator::Opcode Op,
                              NonLoc L, NonLoc R,
-                             ExplodedNode<GRState>* Pred) {
+                             ExplodedNode<GRState>* Pred, QualType T) {
 
   GRStateSet OStates;
-  EvalBinOp(OStates, GetState(Pred), Ex, Op, L, R);
+  EvalBinOp(OStates, GetState(Pred), Ex, Op, L, R, T);
 
   for (GRStateSet::iterator I=OStates.begin(), E=OStates.end(); I!=E; ++I)
     MakeNode(Dst, Ex, Pred, *I);
@@ -2893,13 +2894,14 @@ void GRExprEngine::EvalBinOp(ExplodedNodeSet<GRState>& Dst, Expr* Ex,
 
 void GRExprEngine::EvalBinOp(GRStateSet& OStates, const GRState* state,
                              Expr* Ex, BinaryOperator::Opcode Op,
-                             NonLoc L, NonLoc R) {
+                             NonLoc L, NonLoc R, QualType T) {
   
   GRStateSet::AutoPopulate AP(OStates, state);
-  if (R.isValid()) getTF().EvalBinOpNN(OStates, *this, state, Ex, Op, L, R);
+  if (R.isValid()) getTF().EvalBinOpNN(OStates, *this, state, Ex, Op, L, R, T);
 }
 
-SVal GRExprEngine::EvalBinOp(BinaryOperator::Opcode Op, SVal L, SVal R) {
+SVal GRExprEngine::EvalBinOp(BinaryOperator::Opcode Op, SVal L, SVal R,
+                             QualType T) {
   
   if (L.isUndef() || R.isUndef())
     return UndefinedVal();
@@ -2926,7 +2928,7 @@ SVal GRExprEngine::EvalBinOp(BinaryOperator::Opcode Op, SVal L, SVal R) {
   }
   else
     return getTF().DetermEvalBinOpNN(*this, Op, cast<NonLoc>(L),
-                                     cast<NonLoc>(R));
+                                     cast<NonLoc>(R), T);
 }
 
 //===----------------------------------------------------------------------===//
index 22ccd7b8aa9199e59ffa245fd8dbaaf28ceb9cc8..3bd51ecd72cb569c29d067e4c2d1361efb5ab4db 100644 (file)
@@ -131,7 +131,8 @@ static unsigned char LNotOpMap[] = {
 
 SVal GRSimpleVals::DetermEvalBinOpNN(GRExprEngine& Eng,
                                      BinaryOperator::Opcode Op,
-                                     NonLoc L, NonLoc R)  {
+                                     NonLoc L, NonLoc R,
+                                     QualType T)  {
 
   BasicValueFactory& BasicVals = Eng.getBasicVals();
   unsigned subkind = L.getSubKind();
@@ -173,34 +174,35 @@ SVal GRSimpleVals::DetermEvalBinOpNN(GRExprEngine& Eng,
         }
       }
         
-      case nonloc::SymIntConstraintValKind: {
-        
+      case nonloc::SymExprValKind: {
         // Logical not?        
         if (!(Op == BinaryOperator::EQ && R.isZeroConstant()))
           return UnknownVal();
-        
-        const SymIntConstraint& C =
-          cast<nonloc::SymIntConstraintVal>(L).getConstraint();
-        
-        BinaryOperator::Opcode Opc = C.getOpcode();
-        
-        if (Opc < BinaryOperator::LT || Opc > BinaryOperator::NE)
-          return UnknownVal();
 
-        // For comparison operators, translate the constraint by
-        // changing the opcode.
+        const SymExpr &SE=*cast<nonloc::SymExprVal>(L).getSymbolicExpression();
         
-        int idx = (unsigned) Opc - (unsigned) BinaryOperator::LT;
+        // Only handle ($sym op constant) for now.
+        if (const SymIntExpr *E = dyn_cast<SymIntExpr>(&SE)) {
+          BinaryOperator::Opcode Opc = E->getOpcode();
         
-        assert (idx >= 0 && 
-                (unsigned) idx < sizeof(LNotOpMap)/sizeof(unsigned char));
+          if (Opc < BinaryOperator::LT || Opc > BinaryOperator::NE)
+            return UnknownVal();
+
+          // For comparison operators, translate the constraint by
+          // changing the opcode.        
+          int idx = (unsigned) Opc - (unsigned) BinaryOperator::LT;
         
-        Opc = (BinaryOperator::Opcode) LNotOpMap[idx];
+          assert (idx >= 0 && 
+                  (unsigned) idx < sizeof(LNotOpMap)/sizeof(unsigned char));
         
-        const SymIntConstraint& CNew =
-          BasicVals.getConstraint(C.getSymbol(), Opc, C.getInt());
+          Opc = (BinaryOperator::Opcode) LNotOpMap[idx];          
+          assert(E->getType(Eng.getContext()) == T);
+          E = Eng.getSymbolManager().getSymIntExpr(E->getLHS(), Opc,
+                                                   E->getRHS(), T);
+          return nonloc::SymExprVal(E);
+        }
         
-        return nonloc::SymIntConstraintVal(CNew);
+        return UnknownVal();
       }
         
       case nonloc::ConcreteIntKind:
@@ -231,14 +233,18 @@ SVal GRSimpleVals::DetermEvalBinOpNN(GRExprEngine& Eng,
       case nonloc::SymbolValKind:
         if (isa<nonloc::ConcreteInt>(R)) {
           if (Op >= BinaryOperator::LT && Op <= BinaryOperator::NE) {
-            const SymIntConstraint& C =
-              BasicVals.getConstraint(cast<nonloc::SymbolVal>(L).getSymbol(), 
-                                   Op, cast<nonloc::ConcreteInt>(R).getValue());
-            return nonloc::SymIntConstraintVal(C);
+            const SymIntExpr *SE =
+              Eng.getSymbolManager().getSymIntExpr(
+                                     cast<nonloc::SymbolVal>(L).getSymbol(), Op,
+                                     cast<nonloc::ConcreteInt>(R).getValue(),T);
+
+            
+            return nonloc::SymExprVal(SE);
           } else {
             return NonLoc::MakeVal(Eng.getSymbolManager(),
                                    cast<nonloc::SymbolVal>(L).getSymbol(),
-                                   Op, cast<nonloc::ConcreteInt>(R).getValue());
+                                   Op, cast<nonloc::ConcreteInt>(R).getValue(),
+                                   T);
           }
         }
         else
@@ -308,25 +314,28 @@ TryAgain:
       }
       else if (isa<loc::SymbolVal>(R)) {
         
-        const SymIntConstraint& C =
-          BasicVals.getConstraint(cast<loc::SymbolVal>(R).getSymbol(),
-                               BinaryOperator::EQ,
-                               cast<loc::ConcreteInt>(L).getValue());
+        const SymIntExpr *SE =
+          Eng.getSymbolManager().getSymIntExpr(cast<loc::SymbolVal>(R).getSymbol(),
+                                               BinaryOperator::EQ,
+                                               cast<loc::ConcreteInt>(L).getValue(),
+                                               Eng.getContext().IntTy);
         
-        return nonloc::SymIntConstraintVal(C);
+        return nonloc::SymExprVal(SE);
       }
       
       break;
       
     case loc::SymbolValKind: {
 
-      if (isa<loc::ConcreteInt>(R)) {          
-        const SymIntConstraint& C =
-          BasicVals.getConstraint(cast<loc::SymbolVal>(L).getSymbol(),
-                               BinaryOperator::EQ,
-                               cast<loc::ConcreteInt>(R).getValue());
+      if (isa<loc::ConcreteInt>(R)) {
+        const SymIntExpr *SE =
+          Eng.getSymbolManager().getSymIntExpr(
+                                            cast<loc::SymbolVal>(L).getSymbol(),
+                                            BinaryOperator::EQ,
+                                            cast<loc::ConcreteInt>(R).getValue(),
+                                            Eng.getContext().IntTy);
         
-        return nonloc::SymIntConstraintVal(C);
+        return nonloc::SymExprVal(SE);
       }
       
       // FIXME: Implement == for lval Symbols.  This is mainly useful
@@ -378,25 +387,27 @@ TryAgain:
         
         return NonLoc::MakeIntTruthVal(BasicVals, b);
       }
-      else if (isa<loc::SymbolVal>(R)) {        
-        const SymIntConstraint& C =
-          BasicVals.getConstraint(cast<loc::SymbolVal>(R).getSymbol(),
-                                  BinaryOperator::NE,
-                                  cast<loc::ConcreteInt>(L).getValue());
-        
-        return nonloc::SymIntConstraintVal(C);
+      else if (isa<loc::SymbolVal>(R)) {
+        const SymIntExpr * SE =
+        Eng.getSymbolManager().getSymIntExpr(
+                                    cast<loc::SymbolVal>(R).getSymbol(),
+                                    BinaryOperator::NE,
+                                    cast<loc::ConcreteInt>(L).getValue(),
+                                    Eng.getContext().IntTy);
+        return nonloc::SymExprVal(SE);
       }
       
       break;
 
     case loc::SymbolValKind: {
-      if (isa<loc::ConcreteInt>(R)) {          
-        const SymIntConstraint& C =
-          BasicVals.getConstraint(cast<loc::SymbolVal>(L).getSymbol(),
-                                  BinaryOperator::NE,
-                                  cast<loc::ConcreteInt>(R).getValue());
-        
-        return nonloc::SymIntConstraintVal(C);
+      if (isa<loc::ConcreteInt>(R)) {
+        const SymIntExpr *SE = 
+          Eng.getSymbolManager().getSymIntExpr(
+                                          cast<loc::SymbolVal>(L).getSymbol(),
+                                          BinaryOperator::NE,
+                                          cast<loc::ConcreteInt>(R).getValue(),
+                                          Eng.getContext().IntTy);
+        return nonloc::SymExprVal(SE);
       }
       
       // FIXME: Implement != for lval Symbols.  This is mainly useful
index 6848ced2be70f03ece8b96669d294d5649b59032..efe7c631ab2e001c99df186a58b0d2a704c83cf1 100644 (file)
@@ -29,7 +29,7 @@ protected:
   
   virtual SVal DetermEvalBinOpNN(GRExprEngine& Eng,
                                  BinaryOperator::Opcode Op,
-                                 NonLoc L, NonLoc R);
+                                 NonLoc L, NonLoc R, QualType T);
   
 public:
   GRSimpleVals() {}
index c08bd8f0b19b27d42bd35f9eb738c7ba6ae40132..69c09d9a2ec5a1dc85465e87acb1605124643fe7 100644 (file)
@@ -21,7 +21,8 @@ void GRTransferFuncs::EvalBinOpNN(GRStateSet& OStates,
                                   GRExprEngine& Eng,
                                   const GRState *St, Expr* Ex,
                                   BinaryOperator::Opcode Op,
-                                  NonLoc L, NonLoc R) {
+                                  NonLoc L, NonLoc R, QualType T) {
   
-  OStates.Add(Eng.getStateManager().BindExpr(St, Ex, DetermEvalBinOpNN(Eng, Op, L, R)));
+  OStates.Add(Eng.getStateManager().BindExpr(St, Ex,
+                                          DetermEvalBinOpNN(Eng, Op, L, R, T)));
 }
index 5bfc989eb8051c3cae9cef280d322384ccffeed6..738e8c67d69346a2e9ffd9cf9183a3eb54699ab7 100644 (file)
@@ -112,10 +112,8 @@ void ElementRegion::Profile(llvm::FoldingSetNodeID& ID) const {
 //===----------------------------------------------------------------------===//
 
 QualType SymbolicRegion::getRValueType(ASTContext& C) const {
-  const SymbolData& data = SymMgr.getSymbolData(sym);
-
   // Get the type of the symbol.
-  QualType T = data.getType(C);
+  QualType T = sym->getType(C);
 
   if (const PointerType* PTy = T->getAsPointerType())
     return PTy->getPointeeType();
@@ -132,8 +130,7 @@ QualType SymbolicRegion::getRValueType(ASTContext& C) const {
 }
 
 QualType SymbolicRegion::getLValueType(ASTContext& C) const {
-  const SymbolData& data = SymMgr.getSymbolData(sym);
-  return data.getType(C);
+  return sym->getType(C);
 }
 
 QualType ElementRegion::getRValueType(ASTContext& C) const {
@@ -332,12 +329,9 @@ MemRegionManager::getElementRegion(SVal Idx, const TypedRegion* superRegion){
 }
 
 /// getSymbolicRegion - Retrieve or create a "symbolic" memory region.
-SymbolicRegion* MemRegionManager::getSymbolicRegion(const SymbolRef sym,
-                                                    const SymbolManager& mgr) {
-  
+SymbolicRegion* MemRegionManager::getSymbolicRegion(SymbolRef sym) {
   llvm::FoldingSetNodeID ID;
   SymbolicRegion::ProfileRegion(ID, sym);
-  
   void* InsertPos;
   MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
   SymbolicRegion* R = cast_or_null<SymbolicRegion>(data);
@@ -345,7 +339,7 @@ SymbolicRegion* MemRegionManager::getSymbolicRegion(const SymbolRef sym,
   if (!R) {
     R = (SymbolicRegion*) A.Allocate<SymbolicRegion>();
     // SymbolicRegion's storage class is usually unknown.
-    new (R) SymbolicRegion(sym, mgr, getUnknownRegion());
+    new (R) SymbolicRegion(sym, getUnknownRegion());
     Regions.InsertNode(R, InsertPos);
   }
   
index 78dda87392d9db3d36498f2c48c2ac7ccd36dd96..f23369c8e1141bfa7a1e00ed6f5f95dd04accb54 100644 (file)
@@ -367,8 +367,7 @@ SVal RegionStoreManager::getLValueFieldOrIvar(const GRState* St, SVal Base,
     break;
 
   case loc::SymbolValKind:
-    BaseR = MRMgr.getSymbolicRegion(cast<loc::SymbolVal>(&BaseL)->getSymbol(),
-                                    StateMgr.getSymbolManager());
+    BaseR = MRMgr.getSymbolicRegion(cast<loc::SymbolVal>(&BaseL)->getSymbol());
     break;
   
   case loc::GotoLabelKind:
@@ -412,11 +411,9 @@ SVal RegionStoreManager::getLValueElement(const GRState* St,
 
   const TypedRegion* BaseRegion = 0;
 
-  if (isa<loc::SymbolVal>(Base))
-    BaseRegion = MRMgr.getSymbolicRegion(cast<loc::SymbolVal>(Base).getSymbol(),
-                                         StateMgr.getSymbolManager());
-  else
-    BaseRegion = cast<TypedRegion>(cast<loc::MemRegionVal>(Base).getRegion());
+  BaseRegion = isa<loc::SymbolVal>(Base)
+               ? MRMgr.getSymbolicRegion(cast<loc::SymbolVal>(Base).getSymbol())
+               : cast<TypedRegion>(cast<loc::MemRegionVal>(Base).getRegion());
 
   // Pointer of any type can be cast and used as array base.
   const ElementRegion *ElemR = dyn_cast<ElementRegion>(BaseRegion);
@@ -862,8 +859,7 @@ Store RegionStoreManager::Remove(Store store, Loc L) {
   if (isa<loc::MemRegionVal>(L))
     R = cast<loc::MemRegionVal>(L).getRegion();
   else if (isa<loc::SymbolVal>(L))
-    R = MRMgr.getSymbolicRegion(cast<loc::SymbolVal>(L).getSymbol(),
-                                StateMgr.getSymbolManager());
+    R = MRMgr.getSymbolicRegion(cast<loc::SymbolVal>(L).getSymbol());
   
   if (R) {
     RegionBindingsTy B = GetRegionBindings(store);  
index 0f345602a22dd2f13910eb0623ad75afaf5db1f3..9225f994d3f0f0412b8bf698938d1a5767a32e3b 100644 (file)
@@ -22,37 +22,13 @@ using llvm::cast;
 using llvm::APSInt;
 
 //===----------------------------------------------------------------------===//
-// Symbol Iteration.
+// Symbol iteration within an SVal.
 //===----------------------------------------------------------------------===//
 
-SVal::symbol_iterator SVal::symbol_begin() const {
-  // FIXME: This is a rat's nest.  Cleanup.
-
-  if (isa<loc::SymbolVal>(this))
-    return symbol_iterator(SymbolRef((uintptr_t)Data));
-  else if (isa<nonloc::SymbolVal>(this))
-    return symbol_iterator(SymbolRef((uintptr_t)Data));
-  else if (isa<nonloc::SymIntConstraintVal>(this)) {
-    const SymIntConstraint& C =
-      cast<nonloc::SymIntConstraintVal>(this)->getConstraint();    
-    return symbol_iterator(C.getSymbol());
-  }
-  else if (isa<nonloc::LocAsInteger>(this)) {
-    const nonloc::LocAsInteger& V = cast<nonloc::LocAsInteger>(*this);
-    return V.getPersistentLoc().symbol_begin();
-  }
-  else if (isa<loc::MemRegionVal>(this)) {
-    const MemRegion* R = cast<loc::MemRegionVal>(this)->getRegion();
-    if (const SymbolicRegion* S = dyn_cast<SymbolicRegion>(R))
-      return symbol_iterator(S->getSymbol());
-  }
-  
-  return symbol_iterator();
-}
 
-SVal::symbol_iterator SVal::symbol_end() const {
-  return symbol_iterator();
-}
+//===----------------------------------------------------------------------===//
+// Utility methods.
+//===----------------------------------------------------------------------===//
 
 /// getAsLocSymbol - If this SVal is a location (subclasses Loc) and 
 ///  wraps a symbol, return that SymbolRef.  Otherwise return a SymbolRef
@@ -78,7 +54,7 @@ SymbolRef SVal::getAsLocSymbol() const {
     }
   }
   
-  return SymbolRef();
+  return 0;
 }
 
 /// getAsSymbol - If this Sval wraps a symbol return that SymbolRef.
@@ -87,9 +63,66 @@ SymbolRef SVal::getAsSymbol() const {
   if (const nonloc::SymbolVal *X = dyn_cast<nonloc::SymbolVal>(this))
     return X->getSymbol();
   
+  if (const nonloc::SymExprVal *X = dyn_cast<nonloc::SymExprVal>(this))
+    if (SymbolRef Y = dyn_cast<SymbolData>(X->getSymbolicExpression()))
+      return Y;
+  
   return getAsLocSymbol();
 }
 
+/// getAsSymbolicExpression - If this Sval wraps a symbolic expression then
+///  return that expression.  Otherwise return NULL.
+const SymExpr *SVal::getAsSymbolicExpression() const {
+  if (const nonloc::SymExprVal *X = dyn_cast<nonloc::SymExprVal>(this))
+    return X->getSymbolicExpression();
+  
+  return getAsSymbol();
+}
+
+bool SVal::symbol_iterator::operator==(const symbol_iterator &X) const {
+  return itr == X.itr;
+}
+
+bool SVal::symbol_iterator::operator!=(const symbol_iterator &X) const {
+  return itr != X.itr;
+}
+
+SVal::symbol_iterator::symbol_iterator(const SymExpr *SE) {
+  itr.push_back(SE);
+  while (!isa<SymbolData>(itr.back())) expand();  
+}
+
+SVal::symbol_iterator& SVal::symbol_iterator::operator++() {
+  assert(!itr.empty() && "attempting to iterate on an 'end' iterator");
+  assert(isa<SymbolData>(itr.back()));
+  itr.pop_back();         
+  if (!itr.empty())
+    while (!isa<SymbolData>(itr.back())) expand();
+  return *this;
+}
+
+SymbolRef SVal::symbol_iterator::operator*() {
+  assert(!itr.empty() && "attempting to dereference an 'end' iterator");
+  return cast<SymbolData>(itr.back());
+}
+
+void SVal::symbol_iterator::expand() {
+  const SymExpr *SE = itr.back();
+  itr.pop_back();
+    
+  if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(SE)) {
+    itr.push_back(SIE->getLHS());
+    return;
+  }  
+  else if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(SE)) {
+    itr.push_back(SSE->getLHS());
+    itr.push_back(SSE->getRHS());
+    return;
+  }
+  
+  assert(false && "unhandled expansion case");
+}
+
 //===----------------------------------------------------------------------===//
 // Other Iterators.
 //===----------------------------------------------------------------------===//
@@ -168,7 +201,7 @@ SVal loc::ConcreteInt::EvalBinOp(BasicValueFactory& BasicVals,
     return UndefinedVal();
 }
 
-NonLoc Loc::EQ(BasicValueFactory& BasicVals, const Loc& R) const {
+NonLoc Loc::EQ(SymbolManager& SymMgr, const Loc& R) const {
   
   switch (getSubKind()) {
     default:
@@ -180,49 +213,48 @@ NonLoc Loc::EQ(BasicValueFactory& BasicVals, const Loc& R) const {
         bool b = cast<loc::ConcreteInt>(this)->getValue() ==
                  cast<loc::ConcreteInt>(R).getValue();
         
-        return NonLoc::MakeIntTruthVal(BasicVals, b);
+        return NonLoc::MakeIntTruthVal(SymMgr.getBasicVals(), b);
       }
       else if (isa<loc::SymbolVal>(R)) {
-        
-        const SymIntConstraint& C =
-          BasicVals.getConstraint(cast<loc::SymbolVal>(R).getSymbol(),
+        const SymIntExpr *SE =
+          SymMgr.getSymIntExpr(cast<loc::SymbolVal>(R).getSymbol(),
                                BinaryOperator::EQ,
-                               cast<loc::ConcreteInt>(this)->getValue());
+                               cast<loc::ConcreteInt>(this)->getValue(),
+                               SymMgr.getContext().IntTy);
         
-        return nonloc::SymIntConstraintVal(C);        
+        return nonloc::SymExprVal(SE);        
       }
       
       break;
       
       case loc::SymbolValKind: {
         if (isa<loc::ConcreteInt>(R)) {
-          
-          const SymIntConstraint& C =
-            BasicVals.getConstraint(cast<loc::SymbolVal>(this)->getSymbol(),
+          const SymIntExpr *SE =
+            SymMgr.getSymIntExpr(cast<loc::SymbolVal>(this)->getSymbol(),
                                  BinaryOperator::EQ,
-                                 cast<loc::ConcreteInt>(R).getValue());
+                                 cast<loc::ConcreteInt>(R).getValue(),
+                                 SymMgr.getContext().IntTy);
           
-          return nonloc::SymIntConstraintVal(C);
+          return nonloc::SymExprVal(SE);
         }
-        
-        assert (!isa<loc::SymbolVal>(R) && "FIXME: Implement unification.");
-        
+                                 
+        assert (!isa<loc::SymbolVal>(R) && "FIXME: Implement unification.");        
         break;
       }
       
       case loc::MemRegionKind:
       if (isa<loc::MemRegionVal>(R)) {        
         bool b = cast<loc::MemRegionVal>(*this) == cast<loc::MemRegionVal>(R);
-        return NonLoc::MakeIntTruthVal(BasicVals, b);
+        return NonLoc::MakeIntTruthVal(SymMgr.getBasicVals(), b);
       }
       
       break;
   }
   
-  return NonLoc::MakeIntTruthVal(BasicVals, false);
+  return NonLoc::MakeIntTruthVal(SymMgr.getBasicVals(), false);
 }
 
-NonLoc Loc::NE(BasicValueFactory& BasicVals, const Loc& R) const {
+NonLoc Loc::NE(SymbolManager& SymMgr, const Loc& R) const {
   switch (getSubKind()) {
     default:
       assert(false && "NE not implemented for this Loc.");
@@ -233,46 +265,43 @@ NonLoc Loc::NE(BasicValueFactory& BasicVals, const Loc& R) const {
         bool b = cast<loc::ConcreteInt>(this)->getValue() !=
                  cast<loc::ConcreteInt>(R).getValue();
         
-        return NonLoc::MakeIntTruthVal(BasicVals, b);
+        return NonLoc::MakeIntTruthVal(SymMgr.getBasicVals(), b);
       }
       else if (isa<loc::SymbolVal>(R)) {
-        
-        const SymIntConstraint& C =
-        BasicVals.getConstraint(cast<loc::SymbolVal>(R).getSymbol(),
-                             BinaryOperator::NE,
-                             cast<loc::ConcreteInt>(this)->getValue());
-        
-        return nonloc::SymIntConstraintVal(C);        
+        const SymIntExpr *SE =
+          SymMgr.getSymIntExpr(cast<loc::SymbolVal>(R).getSymbol(),
+                               BinaryOperator::NE,
+                               cast<loc::ConcreteInt>(this)->getValue(),
+                               SymMgr.getContext().IntTy);
+        return nonloc::SymExprVal(SE);
       }
-      
       break;
       
       case loc::SymbolValKind: {
         if (isa<loc::ConcreteInt>(R)) {
+          const SymIntExpr *SE =
+            SymMgr.getSymIntExpr(cast<loc::SymbolVal>(this)->getSymbol(),
+                                 BinaryOperator::NE,
+                                 cast<loc::ConcreteInt>(R).getValue(),
+                                 SymMgr.getContext().IntTy);
           
-          const SymIntConstraint& C =
-          BasicVals.getConstraint(cast<loc::SymbolVal>(this)->getSymbol(),
-                               BinaryOperator::NE,
-                               cast<loc::ConcreteInt>(R).getValue());
-          
-          return nonloc::SymIntConstraintVal(C);
+          return nonloc::SymExprVal(SE);
         }
         
         assert (!isa<loc::SymbolVal>(R) && "FIXME: Implement sym !=.");
-        
         break;
       }
       
       case loc::MemRegionKind:
         if (isa<loc::MemRegionVal>(R)) {        
           bool b = cast<loc::MemRegionVal>(*this)==cast<loc::MemRegionVal>(R);
-          return NonLoc::MakeIntTruthVal(BasicVals, b);
+          return NonLoc::MakeIntTruthVal(SymMgr.getBasicVals(), b);
         }
       
         break;
   }
   
-  return NonLoc::MakeIntTruthVal(BasicVals, true);
+  return NonLoc::MakeIntTruthVal(SymMgr.getBasicVals(), true);
 }
 
 //===----------------------------------------------------------------------===//
@@ -283,21 +312,21 @@ NonLoc NonLoc::MakeVal(SymbolRef sym) {
   return nonloc::SymbolVal(sym);
 }
 
-NonLoc NonLoc::MakeVal(SymbolManager& SymMgr, SymbolRef lhs, 
-                       BinaryOperator::Opcode op, const APSInt& v) {
+NonLoc NonLoc::MakeVal(SymbolManager& SymMgr, const SymExpr *lhs, 
+                       BinaryOperator::Opcode op, const APSInt& v, QualType T) {
   // The Environment ensures we always get a persistent APSInt in
   // BasicValueFactory, so we don't need to get the APSInt from
   // BasicValueFactory again.
-
-  SymbolRef sym = SymMgr.getSymIntExpr(lhs, op, v, SymMgr.getType(lhs));
-  return nonloc::SymbolVal(sym);
+  assert(!Loc::IsLocType(T));
+  return nonloc::SymExprVal(SymMgr.getSymIntExpr(lhs, op, v, T));
 }
 
-NonLoc NonLoc::MakeVal(SymbolManager& SymMgr, SymbolRef lhs, 
-                       BinaryOperator::Opcode op, SymbolRef rhs) {
+NonLoc NonLoc::MakeVal(SymbolManager& SymMgr, const SymExpr *lhs, 
+                       BinaryOperator::Opcode op, const SymExpr *rhs,
+QualType T) {
   assert(SymMgr.getType(lhs) == SymMgr.getType(rhs));
-  SymbolRef sym = SymMgr.getSymSymExpr(lhs, op, rhs, SymMgr.getType(lhs));
-  return nonloc::SymbolVal(sym);
+  assert(!Loc::IsLocType(T));
+  return nonloc::SymExprVal(SymMgr.getSymSymExpr(lhs, op, rhs, T));
 }
 
 NonLoc NonLoc::MakeIntVal(BasicValueFactory& BasicVals, uint64_t X, 
@@ -419,30 +448,6 @@ void SVal::print(llvm::raw_ostream& Out) const {
   }
 }
 
-static void printOpcode(llvm::raw_ostream& Out, BinaryOperator::Opcode Op) {
-  
-  switch (Op) {      
-    case BinaryOperator::Mul: Out << '*'  ; break;
-    case BinaryOperator::Div: Out << '/'  ; break;
-    case BinaryOperator::Rem: Out << '%'  ; break;
-    case BinaryOperator::Add: Out << '+'  ; break;
-    case BinaryOperator::Sub: Out << '-'  ; break;
-    case BinaryOperator::Shl: Out << "<<" ; break;
-    case BinaryOperator::Shr: Out << ">>" ; break;
-    case BinaryOperator::LT:  Out << "<"  ; break;
-    case BinaryOperator::GT:  Out << '>'  ; break;
-    case BinaryOperator::LE:  Out << "<=" ; break;
-    case BinaryOperator::GE:  Out << ">=" ; break;    
-    case BinaryOperator::EQ:  Out << "==" ; break;
-    case BinaryOperator::NE:  Out << "!=" ; break;
-    case BinaryOperator::And: Out << '&'  ; break;
-    case BinaryOperator::Xor: Out << '^'  ; break;
-    case BinaryOperator::Or:  Out << '|'  ; break;
-      
-    default: assert(false && "Not yet implemented.");
-  }        
-}
-
 void NonLoc::print(llvm::raw_ostream& Out) const {
 
   switch (getSubKind()) {  
@@ -459,17 +464,10 @@ void NonLoc::print(llvm::raw_ostream& Out) const {
       Out << '$' << cast<nonloc::SymbolVal>(this)->getSymbol();
       break;
      
-    case nonloc::SymIntConstraintValKind: {
-      const nonloc::SymIntConstraintVal& C = 
-        *cast<nonloc::SymIntConstraintVal>(this);
-      
-      Out << '$' << C.getConstraint().getSymbol() << ' ';
-      printOpcode(Out, C.getConstraint().getOpcode());
-      Out << ' ' << C.getConstraint().getInt().getZExtValue();
-      
-      if (C.getConstraint().getInt().isUnsigned())
-        Out << 'U';
-      
+    case nonloc::SymExprValKind: {
+      const nonloc::SymExprVal& C = *cast<nonloc::SymExprVal>(this);
+      const SymExpr *SE = C.getSymbolicExpression();
+      Out << SE;
       break;
     }
     
index 50552c11440d1aa09c1c62de4fa5fb4f4e7b3abf..904479c4c3af5987033e2ad9589c7723d1f3e340 100644 (file)
@@ -21,11 +21,35 @@ namespace clang {
 SimpleConstraintManager::~SimpleConstraintManager() {}
 
 bool SimpleConstraintManager::canReasonAbout(SVal X) const {
-  if (nonloc::SymbolVal* SymVal = dyn_cast<nonloc::SymbolVal>(&X)) {
-    const SymbolData& data 
-      = getSymbolManager().getSymbolData(SymVal->getSymbol());
-    return !(data.getKind() == SymbolData::SymIntKind || 
-             data.getKind() == SymbolData::SymSymKind );
+  if (nonloc::SymExprVal *SymVal = dyn_cast<nonloc::SymExprVal>(&X)) {
+    const SymExpr *SE = SymVal->getSymbolicExpression();
+    
+    if (isa<SymbolData>(SE))
+      return true;
+    
+    if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(SE)) {
+      switch (SIE->getOpcode()) {
+          // We don't reason yet about bitwise-constraints on symbolic values.
+        case BinaryOperator::And:
+        case BinaryOperator::Or:
+        case BinaryOperator::Xor:
+          return false;
+        // We don't reason yet about arithmetic constraints on symbolic values.
+        case BinaryOperator::Mul:
+        case BinaryOperator::Div:
+        case BinaryOperator::Rem:
+        case BinaryOperator::Add:
+        case BinaryOperator::Sub:
+        case BinaryOperator::Shl:
+        case BinaryOperator::Shr:
+          return false;
+        // All other cases.
+        default:
+          return true;
+      }      
+    }
+
+    return false;
   }
 
   return true;
@@ -150,11 +174,14 @@ SimpleConstraintManager::AssumeAux(const GRState* St,NonLoc Cond,
       return AssumeSymEQ(St, sym, BasicVals.getValue(0, T), isFeasible);
   }
 
-  case nonloc::SymIntConstraintValKind:
-    return
-      AssumeSymInt(St, Assumption,
-                   cast<nonloc::SymIntConstraintVal>(Cond).getConstraint(),
-                   isFeasible);
+  case nonloc::SymExprValKind: {
+    nonloc::SymExprVal V = cast<nonloc::SymExprVal>(Cond);
+    if (const SymIntExpr *SE = dyn_cast<SymIntExpr>(V.getSymbolicExpression()))
+      return AssumeSymInt(St, Assumption, SE, isFeasible);
+    
+    isFeasible = true;
+    return St;
+  }
 
   case nonloc::ConcreteIntKind: {
     bool b = cast<nonloc::ConcreteInt>(Cond).getValue() != 0;
@@ -170,50 +197,43 @@ SimpleConstraintManager::AssumeAux(const GRState* St,NonLoc Cond,
 
 const GRState*
 SimpleConstraintManager::AssumeSymInt(const GRState* St, bool Assumption,
-                                      const SymIntConstraint& C,
-                                      bool& isFeasible) {
+                                      const SymIntExpr *SE, bool& isFeasible) {
+
 
-  switch (C.getOpcode()) {
+  // Here we assume that LHS is a symbol.  This is consistent with the
+  // rest of the constraint manager logic.
+  SymbolRef Sym = cast<SymbolData>(SE->getLHS());
+  const llvm::APSInt &Int = SE->getRHS();
+  
+  switch (SE->getOpcode()) {
   default:
     // No logic yet for other operators.
     isFeasible = true;
     return St;
 
   case BinaryOperator::EQ:
-    if (Assumption)
-      return AssumeSymEQ(St, C.getSymbol(), C.getInt(), isFeasible);
-    else
-      return AssumeSymNE(St, C.getSymbol(), C.getInt(), isFeasible);
+    return Assumption ? AssumeSymEQ(St, Sym, Int, isFeasible)
+                      : AssumeSymNE(St, Sym, Int, isFeasible);
 
   case BinaryOperator::NE:
-    if (Assumption)
-      return AssumeSymNE(St, C.getSymbol(), C.getInt(), isFeasible);
-    else
-      return AssumeSymEQ(St, C.getSymbol(), C.getInt(), isFeasible);
+    return Assumption ? AssumeSymNE(St, Sym, Int, isFeasible)
+                      : AssumeSymEQ(St, Sym, Int, isFeasible);
 
   case BinaryOperator::GT:
-    if (Assumption)
-      return AssumeSymGT(St, C.getSymbol(), C.getInt(), isFeasible);
-    else
-      return AssumeSymLE(St, C.getSymbol(), C.getInt(), isFeasible);
+    return Assumption ? AssumeSymGT(St, Sym, Int, isFeasible)
+                      : AssumeSymLE(St, Sym, Int, isFeasible);
 
   case BinaryOperator::GE:
-    if (Assumption)
-      return AssumeSymGE(St, C.getSymbol(), C.getInt(), isFeasible);
-    else
-      return AssumeSymLT(St, C.getSymbol(), C.getInt(), isFeasible);
+    return Assumption ? AssumeSymGE(St, Sym, Int, isFeasible)
+                      : AssumeSymLT(St, Sym, Int, isFeasible);
 
   case BinaryOperator::LT:
-    if (Assumption)
-      return AssumeSymLT(St, C.getSymbol(), C.getInt(), isFeasible);
-    else
-      return AssumeSymGE(St, C.getSymbol(), C.getInt(), isFeasible);
+    return Assumption ? AssumeSymLT(St, Sym, Int, isFeasible)
+                      : AssumeSymGE(St, Sym, Int, isFeasible);
       
   case BinaryOperator::LE:
-    if (Assumption)
-      return AssumeSymLE(St, C.getSymbol(), C.getInt(), isFeasible);
-    else
-      return AssumeSymGT(St, C.getSymbol(), C.getInt(), isFeasible);
+      return Assumption ? AssumeSymLE(St, Sym, Int, isFeasible)
+                        : AssumeSymGT(St, Sym, Int, isFeasible);
   } // end switch
 }
 
index 8195c8ed36ed1781e005dfbb5f7019f3e239f877..fb41e2f1dab24fed520dd77cddb695acfdf59028 100644 (file)
@@ -45,7 +45,7 @@ public:
                            bool& isFeasible);
 
   const GRState* AssumeSymInt(const GRState* St, bool Assumption,
-                              const SymIntConstraint& C, bool& isFeasible);
+                              const SymIntExpr *SE, bool& isFeasible);
 
   virtual const GRState* AssumeSymNE(const GRState* St, SymbolRef sym,
                                      const llvm::APSInt& V,
index 33d6a5722e25ba5f0ed0ab45a63dea1b28cb68ab..f8e2db72688813bdcefc39d6117aa8667defcfaf 100644 (file)
 
 using namespace clang;
 
-llvm::raw_ostream& llvm::operator<<(llvm::raw_ostream& os,
-                                    clang::SymbolRef sym)  {
-  if (sym.isValid())
-    os << sym.getNumber();
-  else
-    os << "(Invalid)";
+static void print(llvm::raw_ostream& os, const SymExpr *SE);
+
+static void print(llvm::raw_ostream& os, BinaryOperator::Opcode Op) {  
+  switch (Op) {
+    default:
+      assert(false && "operator printing not implemented");
+      break;
+    case BinaryOperator::Mul: os << '*'  ; break;
+    case BinaryOperator::Div: os << '/'  ; break;
+    case BinaryOperator::Rem: os << '%'  ; break;
+    case BinaryOperator::Add: os << '+'  ; break;
+    case BinaryOperator::Sub: os << '-'  ; break;
+    case BinaryOperator::Shl: os << "<<" ; break;
+    case BinaryOperator::Shr: os << ">>" ; break;
+    case BinaryOperator::LT:  os << "<"  ; break;
+    case BinaryOperator::GT:  os << '>'  ; break;
+    case BinaryOperator::LE:  os << "<=" ; break;
+    case BinaryOperator::GE:  os << ">=" ; break;    
+    case BinaryOperator::EQ:  os << "==" ; break;
+    case BinaryOperator::NE:  os << "!=" ; break;
+    case BinaryOperator::And: os << '&'  ; break;
+    case BinaryOperator::Xor: os << '^'  ; break;
+    case BinaryOperator::Or:  os << '|'  ; break;
+  }        
+}
+
+static void print(llvm::raw_ostream& os, const SymIntExpr *SE) {
+  os << '(';
+  print(os, SE->getLHS());
+  os << ") ";
+  print(os, SE->getOpcode());
+  os << ' ' << SE->getRHS().getZExtValue();
+  if (SE->getRHS().isUnsigned()) os << 'U';
+}
   
+static void print(llvm::raw_ostream& os, const SymSymExpr *SE) {
+  os << '(';
+  print(os, SE->getLHS());
+  os << ") ";
+  os << '(';
+  print(os, SE->getRHS());
+  os << ')';  
+}
+
+static void print(llvm::raw_ostream& os, const SymExpr *SE) {
+  switch (SE->getKind()) {
+    case SymExpr::BEGIN_SYMBOLS:
+    case SymExpr::RegionRValue:
+    case SymExpr::ConjuredKind:
+    case SymExpr::END_SYMBOLS:
+      os << '$' << cast<SymbolData>(SE)->getSymbolID();
+      return;
+    case SymExpr::SymIntKind:
+      print(os, cast<SymIntExpr>(SE));
+      return;
+    case SymExpr::SymSymKind:
+      print(os, cast<SymSymExpr>(SE));
+      return;
+  }
+}
+
+
+llvm::raw_ostream& llvm::operator<<(llvm::raw_ostream& os, const SymExpr *SE) {
+  print(os, SE);
   return os;
 }
 
-std::ostream& std::operator<<(std::ostream& os, clang::SymbolRef sym) {
-  if (sym.isValid())
-    os << sym.getNumber();
-  else
-    os << "(Invalid)";
-  
+std::ostream& std::operator<<(std::ostream& os, const SymExpr *SE) {
+  llvm::raw_os_ostream O(os);
+  print(O, SE);
   return os;
 }
 
-SymbolRef SymbolManager::getRegionRValueSymbol(const MemRegion* R) {  
+const SymbolRegionRValue* 
+SymbolManager::getRegionRValueSymbol(const MemRegion* R) {
   llvm::FoldingSetNodeID profile;
-
   SymbolRegionRValue::Profile(profile, R);
   void* InsertPos;  
-  SymbolData* SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);    
-  if (SD) return SD->getSymbol();
+  SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);    
+  if (!SD) {  
+    SD = (SymExpr*) BPAlloc.Allocate<SymbolRegionRValue>();
+    new (SD) SymbolRegionRValue(SymbolCounter, R);  
+    DataSet.InsertNode(SD, InsertPos);
+    ++SymbolCounter;
+  }
   
-  SD = (SymbolData*) BPAlloc.Allocate<SymbolRegionRValue>();
-  new (SD) SymbolRegionRValue(SymbolCounter, R);  
-  DataSet.InsertNode(SD, InsertPos);
-  DataMap[SymbolCounter] = SD;  
-  return SymbolCounter++;
+  return cast<SymbolRegionRValue>(SD);
 }
 
-SymbolRef SymbolManager::getConjuredSymbol(const Stmt* E, QualType T,
-                                           unsigned Count,
-                                           const void* SymbolTag) {
+const SymbolConjured*
+SymbolManager::getConjuredSymbol(const Stmt* E, QualType T, unsigned Count,
+                                 const void* SymbolTag) {
   
   llvm::FoldingSetNodeID profile;
   SymbolConjured::Profile(profile, E, T, Count, SymbolTag);
-  void* InsertPos;
-  
-  SymbolData* SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
-  
-  if (SD)
-    return SD->getSymbol();
-  
-  SD = (SymbolData*) BPAlloc.Allocate<SymbolConjured>();
-  new (SD) SymbolConjured(SymbolCounter, E, T, Count, SymbolTag);
-  
-  DataSet.InsertNode(SD, InsertPos);  
-  DataMap[SymbolCounter] = SD;
+  void* InsertPos;  
+  SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);  
+  if (!SD) {  
+    SD = (SymExpr*) BPAlloc.Allocate<SymbolConjured>();
+    new (SD) SymbolConjured(SymbolCounter, E, T, Count, SymbolTag);  
+    DataSet.InsertNode(SD, InsertPos);  
+    ++SymbolCounter;
+  }
   
-  return SymbolCounter++;
+  return cast<SymbolConjured>(SD);
 }
 
-SymbolRef SymbolManager::getSymIntExpr(SymbolRef lhs,BinaryOperator::Opcode op, 
-                                       const llvm::APSInt& v, QualType t) {
+const SymIntExpr *SymbolManager::getSymIntExpr(const SymExpr *lhs,
+                                               BinaryOperator::Opcode op, 
+                                               const llvm::APSInt& v,
+                                               QualType t) {
   llvm::FoldingSetNodeID ID;
   SymIntExpr::Profile(ID, lhs, op, v, t);
-  void* InsertPos;
-
-  SymbolData* data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
-
-  if (data)
-    return data->getSymbol();
-
-  data = (SymIntExpr*) BPAlloc.Allocate<SymIntExpr>();
-  new (data) SymIntExpr(SymbolCounter, lhs, op, v, t);
-
-  DataSet.InsertNode(data, InsertPos);
-  DataMap[SymbolCounter] = data;
-
-  return SymbolCounter++;
+  void *InsertPos;
+  SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
+
+  if (!data) {
+    data = (SymIntExpr*) BPAlloc.Allocate<SymIntExpr>();
+    new (data) SymIntExpr(lhs, op, v, t);
+    DataSet.InsertNode(data, InsertPos);
+  }
+  
+  return cast<SymIntExpr>(data);
 }
 
-SymbolRef SymbolManager::getSymSymExpr(SymbolRef lhs, BinaryOperator::Opcode op,
-                                       SymbolRef rhs, QualType t) {
+const SymSymExpr *SymbolManager::getSymSymExpr(const SymExpr *lhs,
+                                               BinaryOperator::Opcode op,
+                                               const SymExpr *rhs,
+                                               QualType t) {
   llvm::FoldingSetNodeID ID;
   SymSymExpr::Profile(ID, lhs, op, rhs, t);
-  void* InsertPos;
-
-  SymbolData* data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
-
-  if (data)
-    return data->getSymbol();
-
-  data = (SymSymExpr*) BPAlloc.Allocate<SymSymExpr>();
-  new (data) SymSymExpr(SymbolCounter, lhs, op, rhs, t);
-
-  DataSet.InsertNode(data, InsertPos);
-  DataMap[SymbolCounter] = data;
-
-  return SymbolCounter++;
-}
-
-
-const SymbolData& SymbolManager::getSymbolData(SymbolRef Sym) const {  
-  DataMapTy::const_iterator I = DataMap.find(Sym);
-  assert (I != DataMap.end());  
-  return *I->second;
+  void *InsertPos;
+  SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
+
+  if (!data) {
+    data = (SymSymExpr*) BPAlloc.Allocate<SymSymExpr>();
+    new (data) SymSymExpr(lhs, op, rhs, t);
+    DataSet.InsertNode(data, InsertPos);
+  }
+  
+  return cast<SymSymExpr>(data);
 }
 
-
 QualType SymbolConjured::getType(ASTContext&) const {
   return T;
 }
@@ -158,7 +197,7 @@ bool SymbolReaper::isLive(SymbolRef sym) {
   
   // Interogate the symbol.  It may derive from an input value to
   // the analyzed function/method.
-  return isa<SymbolRegionRValue>(SymMgr.getSymbolData(sym));
+  return isa<SymbolRegionRValue>(sym);
 }
 
 SymbolVisitor::~SymbolVisitor() {}