Add GRState::getSimplifiedSVal(), which provides an API hook for doing symbol -> constant folding.  This isn't used yet, but
is prep for some pending optimizations in GRExprEngine.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@112929 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Checker/PathSensitive/GRState.h b/include/clang/Checker/PathSensitive/GRState.h
index 984118e..7d99890 100644
--- a/include/clang/Checker/PathSensitive/GRState.h
+++ b/include/clang/Checker/PathSensitive/GRState.h
@@ -257,11 +257,18 @@
 
   const llvm::APSInt *getSymVal(SymbolRef sym) const;
 
-  SVal getSVal(const Stmt* Ex) const;
-
+  /// Returns the SVal bound to the statement 'S' in the state's environment.
+  SVal getSVal(const Stmt* S) const;
+  
   SVal getSValAsScalarOrLoc(const Stmt *Ex) const;
 
   SVal getSVal(Loc LV, QualType T = QualType()) const;
+  
+  /// Returns a "simplified" SVal bound to the location 'LV' in the state's
+  /// store.  A simplified SVal will include optimizations such as
+  /// if the SVal is a symbol whose value is perfectly constrained then that
+  /// constant value is returned instead.
+  SVal getSimplifiedSVal(Loc LV, QualType T= QualType()) const;
 
   SVal getSVal(const MemRegion* R) const;
 
diff --git a/lib/Checker/GRState.cpp b/lib/Checker/GRState.cpp
index 024237c..2a7c6dc 100644
--- a/lib/Checker/GRState.cpp
+++ b/lib/Checker/GRState.cpp
@@ -169,6 +169,42 @@
   return UnknownVal();
 }
 
+SVal GRState::getSimplifiedSVal(Loc location, QualType T) const {
+  SVal V = getSVal(cast<Loc>(location), T);
+  
+  // If 'V' is a symbolic value that is *perfectly* constrained to
+  // be a constant value, use that value instead to lessen the burden
+  // on later analysis stages (so we have less symbolic values to reason
+  // about).
+  if (!T.isNull()) {
+    if (SymbolRef sym = V.getAsSymbol()) {
+      if (const llvm::APSInt *Int = getSymVal(sym)) {
+        // FIXME: Because we don't correctly model (yet) sign-extension
+        // and truncation of symbolic values, we need to convert
+        // the integer value to the correct signedness and bitwidth.
+        //
+        // This shows up in the following:
+        //
+        //   char foo();
+        //   unsigned x = foo();
+        //   if (x == 54)
+        //     ...
+        //
+        //  The symbolic value stored to 'x' is actually the conjured
+        //  symbol for the call to foo(); the type of that symbol is 'char',
+        //  not unsigned.
+        const llvm::APSInt &NewV = getBasicVals().Convert(T, *Int);
+        
+        if (isa<Loc>(V))
+          return loc::ConcreteInt(NewV);
+        else
+          return nonloc::ConcreteInt(NewV);
+      }
+    }
+  }
+  
+  return V;
+}
 
 const GRState *GRState::BindExpr(const Stmt* Ex, SVal V, bool Invalidate) const{
   Environment NewEnv = getStateManager().EnvMgr.BindExpr(Env, Ex, V,